Merge ~mthaddon/charm-k8s-discourse/+git/charm-k8s-discourse:redis-relation into charm-k8s-discourse:master

Proposed by Tom Haddon
Status: Merged
Approved by: Tom Haddon
Approved revision: 8635ad01c30596a19ce219a4a470c96e81ed218b
Merged at revision: ab22995f6d560f85d94adec0d2a9d4d1b8813221
Proposed branch: ~mthaddon/charm-k8s-discourse/+git/charm-k8s-discourse:redis-relation
Merge into: charm-k8s-discourse:master
Diff against target: 506 lines (+173/-38)
12 files modified
Makefile (+2/-2)
README.md (+7/-16)
config.yaml (+4/-4)
lib/charms/redis_k8s/v0/redis.py (+97/-0)
metadata.yaml (+4/-1)
src/charm.py (+42/-7)
tests/unit/fixtures/config_valid_complete.yaml (+4/-3)
tests/unit/fixtures/config_valid_no_saml_fingerprint.yaml (+1/-0)
tests/unit/fixtures/config_valid_no_saml_target_url.yaml (+1/-0)
tests/unit/fixtures/config_valid_no_tls.yaml (+4/-3)
tests/unit/fixtures/config_valid_with_tls.yaml (+1/-0)
tests/unit/test_charm.py (+6/-2)
Reviewer Review Type Date Requested Status
Joel Sing (community) +1 Approve
🤖 prod-jenkaas-is (community) continuous-integration Approve
Canonical IS Reviewers Pending
Review via email: mp+402637@code.launchpad.net

Commit message

Add a redis relation, using the new redis-k8s library, but continue to support static redis config as well

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
🤖 prod-jenkaas-is (prod-jenkaas-is) wrote :

A CI job is currently in progress. A follow up comment will be added when it completes.

Revision history for this message
🤖 prod-jenkaas-is (prod-jenkaas-is) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
🤖 prod-jenkaas-is (prod-jenkaas-is) wrote :

A CI job is currently in progress. A follow up comment will be added when it completes.

Revision history for this message
🤖 prod-jenkaas-is (prod-jenkaas-is) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
🤖 prod-jenkaas-is (prod-jenkaas-is) wrote :

A CI job is currently in progress. A follow up comment will be added when it completes.

Revision history for this message
🤖 prod-jenkaas-is (prod-jenkaas-is) wrote :
review: Approve (continuous-integration)
Revision history for this message
Joel Sing (jsing) wrote :

LGTM - see various minor comments inline.

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

Change successfully merged at revision ab22995f6d560f85d94adec0d2a9d4d1b8813221

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/Makefile b/Makefile
index 95aa3b7..6a7bbe1 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ lint: blacken
1212
13# We actually use the build directory created by charmcraft,13# We actually use the build directory created by charmcraft,
14# but the .charm file makes a much more convenient sentinel.14# but the .charm file makes a much more convenient sentinel.
15unittest: discourse.charm15unittest: discourse-k8s.charm
16 @tox -e unit16 @tox -e unit
1717
18test: lint unittest18test: lint unittest
@@ -21,7 +21,7 @@ clean:
21 @echo "Cleaning files"21 @echo "Cleaning files"
22 @git clean -fXd22 @git clean -fXd
2323
24discourse.charm: src/*.py requirements.txt24discourse-k8s.charm: src/*.py requirements.txt
25 charmcraft build25 charmcraft build
2626
27build-image:27build-image:
diff --git a/README.md b/README.md
index 09898e4..b49813d 100644
--- a/README.md
+++ b/README.md
@@ -15,22 +15,13 @@ Discourse than the one currently deployed.
15For details on using Kubernetes with Juju [see here](https://juju.is/docs/kubernetes), and for15For details on using Kubernetes with Juju [see here](https://juju.is/docs/kubernetes), and for
16details on using Juju with MicroK8s for easy local testing [see here](https://juju.is/docs/microk8s-cloud).16details on using Juju with MicroK8s for easy local testing [see here](https://juju.is/docs/microk8s-cloud).
1717
18To get started with a test environment, first deploy Redis in an IaaS model:18To deploy into a Juju K8s model:
1919
20 juju deploy cs:~redis-charmers/redis # Note the deployed IP as ${REDIS_IP}20 juju deploy postgresql-k8s
2121 juju deploy redis-k8s
22Now deploy the Discourse and PostgreSQL charms within a Juju Kubernetes model22 juju deploy discourse-k8s
23as follows:23 juju relate discourse-k8s postgresql-k8s:db-admin
2424 juju relate discourse-k8s redis-k8s
25 juju deploy cs:~postgresql-charmers/postgresql-k8s postgresql
26 juju deploy cs:~discourse-charmers/discourse-k8s discourse \
27 --config redis_host=${REDIS_IP} \
28 --config developer_emails="user@foo.internal" \
29 --config external_hostname="foo.internal" \
30 --config smtp_address="127.0.0.1" \
31 --config smtp_domain="foo.internal"
32 juju add-relation discourse postgresql:db-admin
33 juju expose discourse
3425
35Once the deployment is completed and the "discourse" workload state in `juju26Once the deployment is completed and the "discourse" workload state in `juju
36status` has changed to "active" you can visit http://{$discourse_ip}:3000 in a27status` has changed to "active" you can visit http://{$discourse_ip}:3000 in a
diff --git a/config.yaml b/config.yaml
index a55dafd..85f0677 100644
--- a/config.yaml
+++ b/config.yaml
@@ -18,7 +18,7 @@ options:
18 external_hostname:18 external_hostname:
19 type: string19 type: string
20 description: "External hostname this discourse instance should respond to"20 description: "External hostname this discourse instance should respond to"
21 default: ""21 default: "foo.internal"
22 enable_cors:22 enable_cors:
23 type: boolean23 type: boolean
24 description: "Enable Cross-origin Resource Sharing (CORS) at the application level (required for SSO)"24 description: "Enable Cross-origin Resource Sharing (CORS) at the application level (required for SSO)"
@@ -30,15 +30,15 @@ options:
30 developer_emails:30 developer_emails:
31 type: string31 type: string
32 description: "Comma delimited list of email addresses that should have developer level access"32 description: "Comma delimited list of email addresses that should have developer level access"
33 default: ""33 default: "user@foo.internal"
34 smtp_domain:34 smtp_domain:
35 type: string35 type: string
36 description: "Hostname that email sent by this discourse should appear to come from"36 description: "Hostname that email sent by this discourse should appear to come from"
37 default: ""37 default: "foo.internal"
38 smtp_address:38 smtp_address:
39 type: string39 type: string
40 description: "Hostname / IP that should be used to send SMTP mail"40 description: "Hostname / IP that should be used to send SMTP mail"
41 default: ""41 default: "127.0.0.1"
42 smtp_port:42 smtp_port:
43 type: int43 type: int
44 description: "Port to use when connecting to SMTP server"44 description: "Port to use when connecting to SMTP server"
diff --git a/lib/charms/redis_k8s/v0/redis.py b/lib/charms/redis_k8s/v0/redis.py
45new file mode 10064445new file mode 100644
index 0000000..70787b6
--- /dev/null
+++ b/lib/charms/redis_k8s/v0/redis.py
@@ -0,0 +1,97 @@
1"""Library for the redis relation.
2
3This library contains the Requires and Provides classes for handling the
4redis interface.
5
6Import `RedisRequires` in your charm by adding the following to `src/charm.py`:
7```
8from charms.redis_k8s.v0.redis import RedisRequires
9
10# In your charm's `__init__` method.
11self.redis = RedisRequires(self, self._stored)
12```
13And then wherever you need to reference the relation data:
14```
15for redis_unit in self._stored.redis_relation:
16 redis_host = self._stored.redis_relation[redis_unit]["hostname"]
17 redis_port = self._stored.redis_relation[redis_unit]["port"]
18```
19"""
20import logging
21
22from ops.charm import CharmEvents
23from ops.framework import EventBase, EventSource, Object
24
25# The unique Charmhub library identifier, never change it
26LIBID = "fe18a608cec5465fa5153e419abcad7b"
27
28# Increment this major API version when introducing breaking changes
29LIBAPI = 0
30
31# Increment this PATCH version before using `charmcraft publish-lib` or reset
32# to 0 if you are raising the major API version
33LIBPATCH = 1
34
35logger = logging.getLogger(__name__)
36
37
38class RedisRelationUpdatedEvent(EventBase):
39 pass
40
41
42class RedisRelationCharmEvents(CharmEvents):
43 redis_relation_updated = EventSource(RedisRelationUpdatedEvent)
44
45
46class RedisRequires(Object):
47 def __init__(self, charm, _stored):
48 # Define a constructor that takes the charm and it's StoredState
49 super().__init__(charm, "redis")
50 self.framework.observe(charm.on.redis_relation_changed, self._on_relation_changed)
51 self.framework.observe(charm.on.redis_relation_broken, self._on_relation_broken)
52 self._stored = _stored
53 self.charm = charm
54
55 def _on_relation_changed(self, event):
56 if not event.unit:
57 return
58
59 hostname = event.relation.data[event.unit].get("hostname")
60 port = event.relation.data[event.unit].get("port")
61 # Store some data from the relation in local state
62 self._stored.redis_relation[event.relation.id] = {"hostname": hostname, "port": port}
63
64 # Trigger an event that our charm can react to.
65 self.charm.on.redis_relation_updated.emit()
66
67 def _on_relation_broken(self, event):
68 # Remove the unit data from local state
69 self._stored.redis_relation.pop(event.relation.id, None)
70
71 # Trigger an event that our charm can react to.
72 self.charm.on.redis_relation_updated.emit()
73
74
75class RedisProvides(Object):
76 def __init__(self, charm, port):
77 super().__init__(charm, "redis")
78 self.framework.observe(charm.on.redis_relation_changed, self._on_relation_changed)
79 self._port = port
80
81 def _on_relation_changed(self, event):
82 if not self.model.unit.is_leader():
83 logger.debug("Relation changes ignored by non-leader")
84 return
85
86 event.relation.data[self.model.unit]['hostname'] = str(self._bind_address(event))
87 event.relation.data[self.model.unit]['port'] = str(self._port)
88 # The reactive Redis charm exposes also 'password'. When tackling
89 # https://github.com/canonical/redis-operator/issues/7 add 'password'
90 # field so that it matches the exposed interface information from it.
91 # event.relation.data[self.unit]['password'] = ''
92
93 def _bind_address(self, event):
94 relation = self.model.get_relation(event.relation.name, event.relation.id)
95 if address := self.model.get_binding(relation).network.bind_address:
96 return address
97 return self.app.name
diff --git a/metadata.yaml b/metadata.yaml
index 82e1aa8..0c8beb2 100644
--- a/metadata.yaml
+++ b/metadata.yaml
@@ -1,4 +1,5 @@
1name: discourse1name: discourse-k8s
2display-name: Discourse
2summary: Discourse is the 100% open source discussion platform built for the next decade of the Internet.3summary: Discourse is the 100% open source discussion platform built for the next decade of the Internet.
3description: |4description: |
4 Discourse is the 100% open source discussion platform built for the next decade of the Internet.5 Discourse is the 100% open source discussion platform built for the next decade of the Internet.
@@ -15,6 +16,8 @@ series:
15 - kubernetes16 - kubernetes
16min-juju-version: 2.8.017min-juju-version: 2.8.0
17requires:18requires:
19 redis:
20 interface: redis
18 db:21 db:
19 interface: pgsql22 interface: pgsql
20 limit: 123 limit: 1
diff --git a/src/charm.py b/src/charm.py
index d8f210b..0ef9f01 100755
--- a/src/charm.py
+++ b/src/charm.py
@@ -2,7 +2,13 @@
2# Copyright 2020 Canonical Ltd.2# Copyright 2020 Canonical Ltd.
3# See LICENSE file for licensing details.3# See LICENSE file for licensing details.
44
5import logging
6
5import ops.lib7import ops.lib
8from charms.redis_k8s.v0.redis import (
9 RedisRelationCharmEvents,
10 RedisRequires,
11)
6from ops.charm import CharmBase12from ops.charm import CharmBase
7from ops.main import main13from ops.main import main
8from ops.framework import StoredState14from ops.framework import StoredState
@@ -10,6 +16,9 @@ from ops.framework import StoredState
10from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus, WaitingStatus16from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus, WaitingStatus
1117
1218
19logger = logging.getLogger(__name__)
20
21
13pgsql = ops.lib.use("pgsql", 1, "postgresql-charmers@lists.launchpad.net")22pgsql = ops.lib.use("pgsql", 1, "postgresql-charmers@lists.launchpad.net")
1423
15THROTTLE_LEVELS = {24THROTTLE_LEVELS = {
@@ -52,7 +61,7 @@ def create_discourse_pod_config(config):
52 'DISCOURSE_SMTP_USER_NAME': config['smtp_username'],61 'DISCOURSE_SMTP_USER_NAME': config['smtp_username'],
53 'DISCOURSE_SMTP_PASSWORD': config['smtp_password'],62 'DISCOURSE_SMTP_PASSWORD': config['smtp_password'],
54 'DISCOURSE_REDIS_HOST': config['redis_host'],63 'DISCOURSE_REDIS_HOST': config['redis_host'],
55 'DISCOURSE_REDIS_PORT': 6379,64 'DISCOURSE_REDIS_PORT': config['redis_port'],
56 'DISCOURSE_ENABLE_CORS': config['enable_cors'],65 'DISCOURSE_ENABLE_CORS': config['enable_cors'],
57 'DISCOURSE_CORS_ORIGIN': config['cors_origin'],66 'DISCOURSE_CORS_ORIGIN': config['cors_origin'],
58 'DISCOURSE_REFRESH_MAXMIND_DB_DURING_PRECOMPILE_DAYS': "0",67 'DISCOURSE_REFRESH_MAXMIND_DB_DURING_PRECOMPILE_DAYS': "0",
@@ -161,7 +170,7 @@ def get_pod_spec(app_name, config):
161 return pod_spec170 return pod_spec
162171
163172
164def check_for_config_problems(config):173def check_for_config_problems(config, stored):
165 """Check if there are issues with the juju config.174 """Check if there are issues with the juju config.
166175
167 - Primarily looks for missing config options using check_for_missing_config_fields()176 - Primarily looks for missing config options using check_for_missing_config_fields()
@@ -169,7 +178,7 @@ def check_for_config_problems(config):
169 - Returns a list of errors if any were found.178 - Returns a list of errors if any were found.
170 """179 """
171 errors = []180 errors = []
172 missing_fields = check_for_missing_config_fields(config)181 missing_fields = check_for_missing_config_fields(config, stored)
173182
174 if missing_fields:183 if missing_fields:
175 errors.append('Required configuration missing: {}'.format(" ".join(missing_fields)))184 errors.append('Required configuration missing: {}'.format(" ".join(missing_fields)))
@@ -183,7 +192,7 @@ def check_for_config_problems(config):
183 return errors192 return errors
184193
185194
186def check_for_missing_config_fields(config):195def check_for_missing_config_fields(config, stored):
187 """Check for missing fields in juju config.196 """Check for missing fields in juju config.
188197
189 - Returns a list of required fields that are either not present198 - Returns a list of required fields that are either not present
@@ -194,13 +203,18 @@ def check_for_missing_config_fields(config):
194 needed_fields = [203 needed_fields = [
195 'db_name',204 'db_name',
196 'smtp_address',205 'smtp_address',
197 'redis_host',
198 'cors_origin',206 'cors_origin',
199 'developer_emails',207 'developer_emails',
200 'smtp_domain',208 'smtp_domain',
201 'discourse_image',209 'discourse_image',
202 'external_hostname',210 'external_hostname',
203 ]211 ]
212 # See if Redis connection information has been provided via a relation.
213 redis_hostname = None
214 for redis_unit in stored.redis_relation:
215 redis_hostname = stored.redis_relation[redis_unit]["hostname"]
216 if not redis_hostname:
217 needed_fields.append("redis_host")
204 for key in needed_fields:218 for key in needed_fields:
205 if not config.get(key):219 if not config.get(key):
206 missing_fields.append(key)220 missing_fields.append(key)
@@ -209,6 +223,7 @@ def check_for_missing_config_fields(config):
209223
210224
211class DiscourseCharm(CharmBase):225class DiscourseCharm(CharmBase):
226 on = RedisRelationCharmEvents()
212 stored = StoredState()227 stored = StoredState()
213228
214 def __init__(self, *args):229 def __init__(self, *args):
@@ -220,7 +235,13 @@ class DiscourseCharm(CharmBase):
220 super().__init__(*args)235 super().__init__(*args)
221236
222 self.stored.set_default(237 self.stored.set_default(
223 db_name=None, db_user=None, db_password=None, db_host=None, has_db_relation=False, has_db_credentials=False238 db_name=None,
239 db_user=None,
240 db_password=None,
241 db_host=None,
242 has_db_relation=False,
243 has_db_credentials=False,
244 redis_relation={},
224 )245 )
225 self.framework.observe(self.on.leader_elected, self.configure_pod)246 self.framework.observe(self.on.leader_elected, self.configure_pod)
226 self.framework.observe(self.on.config_changed, self.configure_pod)247 self.framework.observe(self.on.config_changed, self.configure_pod)
@@ -230,6 +251,9 @@ class DiscourseCharm(CharmBase):
230 self.framework.observe(self.db.on.database_relation_joined, self.on_database_relation_joined)251 self.framework.observe(self.db.on.database_relation_joined, self.on_database_relation_joined)
231 self.framework.observe(self.db.on.master_changed, self.on_database_changed)252 self.framework.observe(self.db.on.master_changed, self.on_database_changed)
232253
254 self.redis = RedisRequires(self, self.stored)
255 self.framework.observe(self.on.redis_relation_updated, self.configure_pod)
256
233 def check_config_is_valid(self, config):257 def check_config_is_valid(self, config):
234 """Check that the provided config is valid.258 """Check that the provided config is valid.
235259
@@ -238,7 +262,7 @@ class DiscourseCharm(CharmBase):
238 - Sets model status as appropriate.262 - Sets model status as appropriate.
239 """263 """
240 valid_config = True264 valid_config = True
241 errors = check_for_config_problems(config)265 errors = check_for_config_problems(config, self.stored)
242266
243 # Set status if we have a bad config.267 # Set status if we have a bad config.
244 if errors:268 if errors:
@@ -266,6 +290,15 @@ class DiscourseCharm(CharmBase):
266290
267 - Configures pod using pod_spec generated from config.291 - Configures pod using pod_spec generated from config.
268 """292 """
293 # Get redis connection information from config but allow overriding
294 # via a relation.
295 redis_hostname = self.config["redis_host"]
296 redis_port = 6379
297 for redis_unit in self.stored.redis_relation:
298 redis_hostname = self.stored.redis_relation[redis_unit]["hostname"]
299 redis_port = self.stored.redis_relation[redis_unit]["port"]
300 logging.debug("Got redis connection details from relation of %s:%s", redis_hostname, redis_port)
301
269 # Set our status while we get configured.302 # Set our status while we get configured.
270 self.model.unit.status = MaintenanceStatus('Configuring pod')303 self.model.unit.status = MaintenanceStatus('Configuring pod')
271304
@@ -282,6 +315,8 @@ class DiscourseCharm(CharmBase):
282 config["db_user"] = self.stored.db_user315 config["db_user"] = self.stored.db_user
283 config["db_password"] = self.stored.db_password316 config["db_password"] = self.stored.db_password
284 config["db_host"] = self.stored.db_host317 config["db_host"] = self.stored.db_host
318 config["redis_host"] = redis_hostname
319 config["redis_port"] = redis_port
285 # Get our spec definition.320 # Get our spec definition.
286 if self.check_config_is_valid(config):321 if self.check_config_is_valid(config):
287 # Get pod spec using our app name and config322 # Get pod spec using our app name and config
diff --git a/tests/unit/fixtures/config_valid_complete.yaml b/tests/unit/fixtures/config_valid_complete.yaml
index 7815983..946388d 100644
--- a/tests/unit/fixtures/config_valid_complete.yaml
+++ b/tests/unit/fixtures/config_valid_complete.yaml
@@ -12,6 +12,7 @@ config:
12 image_user: 'someuser'12 image_user: 'someuser'
13 max_body_size: 2513 max_body_size: 25
14 redis_host: 10.9.89.19714 redis_host: 10.9.89.197
15 redis_port: 6379
15 smtp_address: 167.89.123.5816 smtp_address: 167.89.123.58
16 smtp_authentication: login17 smtp_authentication: login
17 smtp_domain: example.com18 smtp_domain: example.com
@@ -51,7 +52,7 @@ pod_config:
51pod_spec:52pod_spec:
52 version: 353 version: 3
53 containers:54 containers:
54 - name: discourse55 - name: discourse-k8s
55 envConfig:56 envConfig:
56 DISCOURSE_CORS_ORIGIN: '*'57 DISCOURSE_CORS_ORIGIN: '*'
57 DISCOURSE_DEVELOPER_EMAILS: some.person@example.com58 DISCOURSE_DEVELOPER_EMAILS: some.person@example.com
@@ -100,14 +101,14 @@ pod_spec:
100 nginx.ingress.kubernetes.io/session-cookie-max-age: '3600'101 nginx.ingress.kubernetes.io/session-cookie-max-age: '3600'
101 nginx.ingress.kubernetes.io/session-cookie-name: 'DISCOURSE_AFFINITY'102 nginx.ingress.kubernetes.io/session-cookie-name: 'DISCOURSE_AFFINITY'
102 nginx.ingress.kubernetes.io/session-cookie-samesite: 'Lax'103 nginx.ingress.kubernetes.io/session-cookie-samesite: 'Lax'
103 name: discourse-ingress104 name: discourse-k8s-ingress
104 spec:105 spec:
105 rules:106 rules:
106 - host: discourse.local107 - host: discourse.local
107 http:108 http:
108 paths:109 paths:
109 - backend:110 - backend:
110 serviceName: discourse111 serviceName: discourse-k8s
111 servicePort: 3000112 servicePort: 3000
112 path: '/'113 path: '/'
113 tls:114 tls:
diff --git a/tests/unit/fixtures/config_valid_no_saml_fingerprint.yaml b/tests/unit/fixtures/config_valid_no_saml_fingerprint.yaml
index 4f7365a..cc76606 100644
--- a/tests/unit/fixtures/config_valid_no_saml_fingerprint.yaml
+++ b/tests/unit/fixtures/config_valid_no_saml_fingerprint.yaml
@@ -11,6 +11,7 @@ config:
11 image_pass: ''11 image_pass: ''
12 image_user: ''12 image_user: ''
13 redis_host: 10.9.89.19713 redis_host: 10.9.89.197
14 redis_port: 6379
14 smtp_address: 167.89.123.5815 smtp_address: 167.89.123.58
15 smtp_authentication: login16 smtp_authentication: login
16 smtp_domain: example.com17 smtp_domain: example.com
diff --git a/tests/unit/fixtures/config_valid_no_saml_target_url.yaml b/tests/unit/fixtures/config_valid_no_saml_target_url.yaml
index 2f31a4f..1364998 100644
--- a/tests/unit/fixtures/config_valid_no_saml_target_url.yaml
+++ b/tests/unit/fixtures/config_valid_no_saml_target_url.yaml
@@ -11,6 +11,7 @@ config:
11 image_pass: ''11 image_pass: ''
12 image_user: ''12 image_user: ''
13 redis_host: 10.9.89.19713 redis_host: 10.9.89.197
14 redis_port: 6379
14 smtp_address: 167.89.123.5815 smtp_address: 167.89.123.58
15 smtp_authentication: login16 smtp_authentication: login
16 smtp_domain: example.com17 smtp_domain: example.com
diff --git a/tests/unit/fixtures/config_valid_no_tls.yaml b/tests/unit/fixtures/config_valid_no_tls.yaml
index 1f7e021..8179e1a 100644
--- a/tests/unit/fixtures/config_valid_no_tls.yaml
+++ b/tests/unit/fixtures/config_valid_no_tls.yaml
@@ -12,6 +12,7 @@ config:
12 image_user: ''12 image_user: ''
13 max_body_size: 2013 max_body_size: 20
14 redis_host: 10.9.89.19714 redis_host: 10.9.89.197
15 redis_port: 6379
15 smtp_address: 167.89.123.5816 smtp_address: 167.89.123.58
16 smtp_authentication: login17 smtp_authentication: login
17 smtp_domain: example.com18 smtp_domain: example.com
@@ -51,7 +52,7 @@ pod_config:
51pod_spec:52pod_spec:
52 version: 353 version: 3
53 containers:54 containers:
54 - name: discourse55 - name: discourse-k8s
55 envConfig:56 envConfig:
56 DISCOURSE_CORS_ORIGIN: '*'57 DISCOURSE_CORS_ORIGIN: '*'
57 DISCOURSE_DEVELOPER_EMAILS: some.person@example.com58 DISCOURSE_DEVELOPER_EMAILS: some.person@example.com
@@ -99,13 +100,13 @@ pod_spec:
99 nginx.ingress.kubernetes.io/session-cookie-name: 'DISCOURSE_AFFINITY'100 nginx.ingress.kubernetes.io/session-cookie-name: 'DISCOURSE_AFFINITY'
100 nginx.ingress.kubernetes.io/session-cookie-samesite: 'Lax'101 nginx.ingress.kubernetes.io/session-cookie-samesite: 'Lax'
101 nginx.ingress.kubernetes.io/ssl-redirect: 'false'102 nginx.ingress.kubernetes.io/ssl-redirect: 'false'
102 name: discourse-ingress103 name: discourse-k8s-ingress
103 spec:104 spec:
104 rules:105 rules:
105 - host: discourse.local106 - host: discourse.local
106 http:107 http:
107 paths:108 paths:
108 - backend:109 - backend:
109 serviceName: discourse110 serviceName: discourse-k8s
110 servicePort: 3000111 servicePort: 3000
111 path: '/'112 path: '/'
diff --git a/tests/unit/fixtures/config_valid_with_tls.yaml b/tests/unit/fixtures/config_valid_with_tls.yaml
index 8e9e225..a4eff75 100644
--- a/tests/unit/fixtures/config_valid_with_tls.yaml
+++ b/tests/unit/fixtures/config_valid_with_tls.yaml
@@ -11,6 +11,7 @@ config:
11 image_pass: 'discourse123'11 image_pass: 'discourse123'
12 image_user: 'discourse_role'12 image_user: 'discourse_role'
13 redis_host: 10.9.89.19713 redis_host: 10.9.89.197
14 redis_port: 6379
14 smtp_address: 167.89.123.5815 smtp_address: 167.89.123.58
15 smtp_authentication: login16 smtp_authentication: login
16 smtp_domain: example.com17 smtp_domain: example.com
diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py
index 20fe84e..40da7db 100644
--- a/tests/unit/test_charm.py
+++ b/tests/unit/test_charm.py
@@ -56,7 +56,7 @@ class TestDiscourseK8sCharmHooksDisabled(unittest.TestCase):
56 if config_key.startswith('config_valid_'):56 if config_key.startswith('config_valid_'):
57 config_valid = self.harness.charm.check_config_is_valid(self.configs[config_key]['config'])57 config_valid = self.harness.charm.check_config_is_valid(self.configs[config_key]['config'])
58 pod_config = create_discourse_pod_config(self.configs[config_key]['config'])58 pod_config = create_discourse_pod_config(self.configs[config_key]['config'])
59 self.assertEqual(config_valid, True, 'Valid config is not recognized as valid')59 self.assertEqual(config_valid, True, 'Valid config {} is not recognized as valid'.format(config_key))
60 self.assertEqual(60 self.assertEqual(
61 pod_config,61 pod_config,
62 self.configs[config_key]['pod_config'],62 self.configs[config_key]['pod_config'],
@@ -77,7 +77,9 @@ class TestDiscourseK8sCharmHooksDisabled(unittest.TestCase):
77 for config_key in self.configs:77 for config_key in self.configs:
78 if config_key.startswith('config_invalid_'):78 if config_key.startswith('config_invalid_'):
79 config_valid = self.harness.charm.check_config_is_valid(self.configs[config_key]['config'])79 config_valid = self.harness.charm.check_config_is_valid(self.configs[config_key]['config'])
80 missing_fields = check_for_missing_config_fields(self.configs[config_key]['config'])80 stored = SimpleNamespace()
81 stored.redis_relation = {}
82 missing_fields = check_for_missing_config_fields(self.configs[config_key]['config'], stored)
81 self.assertEqual(config_valid, False, 'Invalid config is not recognized as invalid')83 self.assertEqual(config_valid, False, 'Invalid config is not recognized as invalid')
82 self.assertEqual(84 self.assertEqual(
83 missing_fields,85 missing_fields,
@@ -91,6 +93,8 @@ class TestDiscourseK8sCharmHooksDisabled(unittest.TestCase):
91 test_config['db_user'] = 'discourse_m'93 test_config['db_user'] = 'discourse_m'
92 test_config['db_password'] = 'a_real_password'94 test_config['db_password'] = 'a_real_password'
93 test_config['db_host'] = '10.9.89.237'95 test_config['db_host'] = '10.9.89.237'
96 test_config['redis_host'] = '10.9.89.197'
97 test_config['redis_port'] = 6379
94 db_event = SimpleNamespace()98 db_event = SimpleNamespace()
95 db_event.master = SimpleNamespace()99 db_event.master = SimpleNamespace()
96 db_event.master.user = 'discourse_m'100 db_event.master.user = 'discourse_m'

Subscribers

People subscribed via source and target branches