Merge ~pjdc/charm-k8s-mattermost/+git/charm-k8s-mattermost:native-state into charm-k8s-mattermost:master

Proposed by Paul Collins
Status: Merged
Approved by: Paul Collins
Approved revision: c58d5f50bf9129cb7a0dfe03454f73195e300889
Merged at revision: 2b68f795ca392937568a21349d56c61e15892d49
Proposed branch: ~pjdc/charm-k8s-mattermost/+git/charm-k8s-mattermost:native-state
Merge into: charm-k8s-mattermost:master
Diff against target: 155 lines (+44/-21)
2 files modified
src/charm.py (+38/-13)
src/charmstate.py (+6/-8)
Reviewer Review Type Date Requested Status
Stuart Bishop (community) Approve
Mattermost Charmers Pending
Review via email: mp+389385@code.launchpad.net

Commit message

migrate back to StoredState, preserving existing data

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 :

This looks good.

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

Change successfully merged at revision 2b68f795ca392937568a21349d56c61e15892d49

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/src/charm.py b/src/charm.py
index 55e1067..15bb57c 100755
--- a/src/charm.py
+++ b/src/charm.py
@@ -17,6 +17,7 @@ from ops.charm import (
17from ops.framework import (17from ops.framework import (
18 EventBase,18 EventBase,
19 EventSource,19 EventSource,
20 StoredState,
20)21)
21from ops.main import main22from ops.main import main
22from ops.model import (23from ops.model import (
@@ -28,9 +29,7 @@ from ops.model import (
2829
29from interface import pgsql30from interface import pgsql
3031
31# Until https://github.com/canonical/operator/issues/317 is32from charmstate import state_delete, state_get
32# resolved, we'll directly manage charm state ourselves.
33from charmstate import state_get, state_set
34from utils import extend_list_merging_dicts_matched_by_key33from utils import extend_list_merging_dicts_matched_by_key
3534
36import logging35import logging
@@ -96,23 +95,53 @@ def get_env_config(pod_spec, container_name):
9695
97class MattermostK8sCharm(CharmBase):96class MattermostK8sCharm(CharmBase):
9897
98 state = StoredState()
99 on = MattermostCharmEvents()99 on = MattermostCharmEvents()
100100
101 def __init__(self, *args):101 def __init__(self, *args):
102 super().__init__(*args)102 super().__init__(*args)
103103
104 self.framework.observe(self.on.upgrade_charm, self.migrate_to_native_state)
105
104 self.framework.observe(self.on.start, self.configure_pod)106 self.framework.observe(self.on.start, self.configure_pod)
105 self.framework.observe(self.on.config_changed, self.configure_pod)107 self.framework.observe(self.on.config_changed, self.configure_pod)
106 self.framework.observe(self.on.leader_elected, self.configure_pod)108 self.framework.observe(self.on.leader_elected, self.configure_pod)
107 self.framework.observe(self.on.upgrade_charm, self.configure_pod)109 self.framework.observe(self.on.upgrade_charm, self.configure_pod)
108110
109 # database111 # database
112 self.state.set_default(db_conn_str=None, db_uri=None, db_ro_uris=[])
110 self.db = pgsql.PostgreSQLClient(self, 'db')113 self.db = pgsql.PostgreSQLClient(self, 'db')
111 self.framework.observe(self.db.on.database_relation_joined, self._on_database_relation_joined)114 self.framework.observe(self.db.on.database_relation_joined, self._on_database_relation_joined)
112 self.framework.observe(self.db.on.master_changed, self._on_master_changed)115 self.framework.observe(self.db.on.master_changed, self._on_master_changed)
113 self.framework.observe(self.db.on.standby_changed, self._on_standby_changed)116 self.framework.observe(self.db.on.standby_changed, self._on_standby_changed)
114 self.framework.observe(self.on.db_master_available, self.configure_pod)117 self.framework.observe(self.on.db_master_available, self.configure_pod)
115118
119 def migrate_to_native_state(self, event):
120 """Migrate charm state from pre-0.7 charmstate.py to native StoredState.
121 Assumes the framework was initialized with use_juju_for_storage=True."""
122
123 self.unit.status = MaintenanceStatus('Migrating charm state')
124
125 db_conn_str = state_get('db_conn_str')
126 if db_conn_str:
127 logging.info('Migrating db_conn_str to native StoredState.')
128 self.state.db_conn_str = db_conn_str
129 state_delete('db_conn_str')
130
131 db_uri = state_get('db_uri')
132 if db_uri:
133 logging.info('Migrating db_uri to native StoredState.')
134 self.state.db_uri = db_uri
135 state_delete('db_uri')
136
137 db_ro_uris = state_get('db_ro_uris')
138 if db_ro_uris:
139 logging.info('Migrating db_ro_uris to native StoredState.')
140 self.state.db_ro_uris = json.loads(db_ro_uris)
141 state_delete('db_ro_uris')
142
143 self.unit.status = ActiveStatus()
144
116 def _on_database_relation_joined(self, event: pgsql.DatabaseRelationJoinedEvent):145 def _on_database_relation_joined(self, event: pgsql.DatabaseRelationJoinedEvent):
117 """Handle db-relation-joined."""146 """Handle db-relation-joined."""
118 if self.model.unit.is_leader():147 if self.model.unit.is_leader():
@@ -132,12 +161,8 @@ class MattermostK8sCharm(CharmBase):
132 # event, or risk connecting to an incorrect database.161 # event, or risk connecting to an incorrect database.
133 return162 return
134163
135 state_set(164 self.state.db_conn_str = None if event.master is None else event.master.conn_str
136 {165 self.state.db_uri = None if event.master is None else event.master.uri
137 'db_conn_str': None if event.master is None else event.master.conn_str,
138 'db_uri': None if event.master is None else event.master.uri,
139 }
140 )
141166
142 if event.master is None:167 if event.master is None:
143 return168 return
@@ -151,7 +176,7 @@ class MattermostK8sCharm(CharmBase):
151 # event, or risk connecting to an incorrect database.176 # event, or risk connecting to an incorrect database.
152 return177 return
153178
154 state_set({'db_ro_uris': json.dumps([c.uri for c in event.standbys])})179 self.state.db_ro_uris = [c.uri for c in event.standbys]
155180
156 # TODO(pjdc): Emit event when we add support for read replicas.181 # TODO(pjdc): Emit event when we add support for read replicas.
157182
@@ -202,7 +227,7 @@ class MattermostK8sCharm(CharmBase):
202 """Return an envConfig with some core configuration."""227 """Return an envConfig with some core configuration."""
203 config = self.model.config228 config = self.model.config
204 # https://github.com/mattermost/mattermost-server/pull/14666229 # https://github.com/mattermost/mattermost-server/pull/14666
205 db_uri = state_get('db_uri').replace('postgresql://', 'postgres://')230 db_uri = self.state.db_uri.replace('postgresql://', 'postgres://')
206 pod_config = {231 pod_config = {
207 'MATTERMOST_HTTPD_LISTEN_PORT': CONTAINER_PORT,232 'MATTERMOST_HTTPD_LISTEN_PORT': CONTAINER_PORT,
208 'MM_CONFIG': db_uri,233 'MM_CONFIG': db_uri,
@@ -511,7 +536,7 @@ class MattermostK8sCharm(CharmBase):
511536
512 def configure_pod(self, event):537 def configure_pod(self, event):
513 """Assemble the pod spec and apply it, if possible."""538 """Assemble the pod spec and apply it, if possible."""
514 if not state_get('db_uri'):539 if not self.state.db_uri:
515 self.unit.status = WaitingStatus('Waiting for database relation')540 self.unit.status = WaitingStatus('Waiting for database relation')
516 event.defer()541 event.defer()
517 return542 return
@@ -542,4 +567,4 @@ class MattermostK8sCharm(CharmBase):
542567
543568
544if __name__ == '__main__':569if __name__ == '__main__':
545 main(MattermostK8sCharm)570 main(MattermostK8sCharm, use_juju_for_storage=True)
diff --git a/src/charmstate.py b/src/charmstate.py
index 4a86efd..ebc30f9 100644
--- a/src/charmstate.py
+++ b/src/charmstate.py
@@ -6,7 +6,11 @@
6import subprocess6import subprocess
7import yaml7import yaml
88
9from typing import Dict9
10def _state_delete(attribute: str):
11 """Delete attribute from controller-backed per-unit charm state."""
12 cmd = ['state-delete', attribute]
13 return yaml.safe_load(subprocess.check_output(cmd).decode('UTF-8'))
1014
1115
12def _state_get(attribute: str):16def _state_get(attribute: str):
@@ -15,11 +19,5 @@ def _state_get(attribute: str):
15 return yaml.safe_load(subprocess.check_output(cmd).decode('UTF-8'))19 return yaml.safe_load(subprocess.check_output(cmd).decode('UTF-8'))
1620
1721
18def _state_set(settings: Dict[str, str]):22state_delete = _state_delete
19 """Store settings in controller-backed per-unit charm state."""
20 cmd = ['state-set'] + ['{}={}'.format(k, v or '') for k, v in settings.items()]
21 subprocess.check_call(cmd)
22
23
24state_get = _state_get23state_get = _state_get
25state_set = _state_set

Subscribers

People subscribed via source and target branches