Merge ~pjdc/charm-k8s-mattermost/+git/charm-k8s-mattermost:tls-ingress into charm-k8s-mattermost:master

Proposed by Paul Collins
Status: Merged
Approved by: Paul Collins
Approved revision: 9d239270fd5c6b29ea4634da2973cd009dda2894
Merged at revision: d855a543029c60512cba58eed2684fd0989f6634
Proposed branch: ~pjdc/charm-k8s-mattermost/+git/charm-k8s-mattermost:tls-ingress
Merge into: charm-k8s-mattermost:master
Prerequisite: ~pjdc/charm-k8s-mattermost/+git/charm-k8s-mattermost:siteurl
Diff against target: 169 lines (+91/-28)
2 files modified
config.yaml (+7/-4)
src/charm.py (+84/-24)
Reviewer Review Type Date Requested Status
Paul Collins me Approve
Stuart Bishop (community) Approve
Canonical IS Reviewers Pending
Review via email: mp+384520@code.launchpad.net

Commit message

create ingress ourselves so that we can enable TLS

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Stuart Bishop (stub) wrote :

Looks good. Needs a minor tweak to simplify some code, and consideration on if we actually want mattermost_port to be configurable. Is there any reason to choose non-default ports except to confuse people?

review: Approve
Revision history for this message
Tom Haddon (mthaddon) wrote :

One comment about non-leader status

Revision history for this message
Paul Collins (pjdc) :
Revision history for this message
Paul Collins (pjdc) wrote :

self-approving due to rebase

review: Approve (me)
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision d855a543029c60512cba58eed2684fd0989f6634

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/config.yaml b/config.yaml
2index 733c53d..1bb6bca 100644
3--- a/config.yaml
4+++ b/config.yaml
5@@ -1,8 +1,4 @@
6 options:
7- mattermost_port:
8- type: int
9- description: The port number for Mattermost to listen to.
10- default: 8000
11 open_server:
12 type: boolean
13 description: Allows users to sign up from the root page without an invite
14@@ -14,3 +10,10 @@ options:
15
16 For more information, see https://docs.mattermost.com/administration/config-settings.html#site-url
17 default: ''
18+ tls_secret_name:
19+ type: string
20+ description: |
21+ The name of the Kubernetes secret to be associated with the ingress resource.
22+
23+ This setting is ignored unless site_url begins with "https".
24+ default: ''
25diff --git a/src/charm.py b/src/charm.py
26index 230651c..5aae587 100755
27--- a/src/charm.py
28+++ b/src/charm.py
29@@ -3,6 +3,8 @@
30 import sys
31 sys.path.append('lib') # noqa: E402
32
33+from urllib.parse import urlparse
34+
35 from ops.charm import (
36 CharmBase,
37 CharmEvents,
38@@ -26,6 +28,7 @@ import logging
39 logger = logging.getLogger()
40
41
42+CONTAINER_PORT = 8000
43 DATABASE_NAME = 'mattermost'
44
45
46@@ -97,22 +100,27 @@ class MattermostK8sCharm(CharmBase):
47
48 # TODO(pjdc): Emit event when we add support for read replicas.
49
50- def configure_pod(self, event):
51- if not self.state.db_uri:
52- self.model.unit.status = WaitingStatus('Waiting for database relation')
53- event.defer()
54- return
55+ def _make_pod_spec(self):
56+ mattermost_image_details = self.mattermost_image.fetch()
57+ pod_spec = {
58+ 'version': 2, # otherwise resources are ignored
59+ 'containers': [{
60+ 'name': self.app.name,
61+ 'imageDetails': mattermost_image_details,
62+ 'ports': [{
63+ 'containerPort': CONTAINER_PORT,
64+ 'protocol': 'TCP',
65+ }],
66+ 'config': self._make_pod_config(),
67+ }]
68+ }
69
70- if not self.framework.model.unit.is_leader():
71- self.model.unit.status = WaitingStatus('Not a leader')
72- return
73+ return pod_spec
74
75- mattermost_image_details = self.mattermost_image.fetch()
76- self.model.unit.status = MaintenanceStatus('Configuring pod')
77+ def _make_pod_config(self):
78 config = self.model.config
79-
80 pod_config = {
81- 'MATTERMOST_HTTPD_LISTEN_PORT': int(config['mattermost_port']),
82+ 'MATTERMOST_HTTPD_LISTEN_PORT': CONTAINER_PORT,
83 'MM_SQLSETTINGS_DATASOURCE': self.state.db_uri,
84 'MM_ENABLEOPENSERVER': config['open_server'],
85 }
86@@ -120,19 +128,71 @@ class MattermostK8sCharm(CharmBase):
87 if config['site_url']:
88 pod_config['MM_SERVICESETTINGS_SITEURL'] = config['site_url']
89
90- self.model.pod.set_spec({
91- 'containers': [{
92- 'name': self.framework.model.app.name,
93- 'imageDetails': mattermost_image_details,
94- 'ports': [{
95- 'containerPort': int(self.framework.model.config['mattermost_port']),
96- 'protocol': 'TCP',
97- }],
98- 'config': pod_config,
99- }]
100- })
101+ return pod_config
102+
103+ def _make_k8s_resources(self):
104+ site_url = self.model.config['site_url']
105+ if not site_url:
106+ return None
107+ parsed = urlparse(site_url)
108+
109+ if parsed.scheme.startswith('http'):
110+ ingress = {
111+ "name": self.app.name,
112+ "spec": {
113+ "rules": [{
114+ "host": parsed.hostname,
115+ "http": {
116+ "paths": [{
117+ "path": "/",
118+ "backend": {
119+ "serviceName": self.app.name,
120+ "servicePort": CONTAINER_PORT,
121+ }
122+ }]
123+ }
124+ }]
125+ }
126+ }
127+ if parsed.scheme == 'https':
128+ ingress['spec']['tls'] = [
129+ {
130+ 'hosts': [parsed.hostname],
131+ }
132+ ]
133+ tls_secret_name = self.model.config['tls_secret_name']
134+ if tls_secret_name:
135+ ingress['spec']['tls'][0]['secretName'] = tls_secret_name
136+
137+ return {
138+ "kubernetesResources": {
139+ "ingressResources": [ingress],
140+ }
141+ }
142+
143+ def configure_pod(self, event):
144+ if not self.state.db_uri:
145+ self.unit.status = WaitingStatus('Waiting for database relation')
146+ event.defer()
147+ return
148+
149+ if not self.unit.is_leader():
150+ self.unit.status = ActiveStatus()
151+ return
152+
153+ self.unit.status = MaintenanceStatus('Configuring pod')
154+
155+ pod_spec = self._make_pod_spec()
156+
157+ # Due to https://github.com/canonical/operator/issues/293 we
158+ # can't use pod.set_spec's k8s_resources argument.
159+ k8s_resources = self._make_k8s_resources()
160+ if k8s_resources:
161+ pod_spec.update(k8s_resources)
162+
163+ self.model.pod.set_spec(pod_spec)
164 self.state.is_started = True
165- self.model.unit.status = ActiveStatus()
166+ self.unit.status = ActiveStatus()
167
168
169 if __name__ == '__main__':

Subscribers

People subscribed via source and target branches