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
1diff --git a/src/charm.py b/src/charm.py
2index 55e1067..15bb57c 100755
3--- a/src/charm.py
4+++ b/src/charm.py
5@@ -17,6 +17,7 @@ from ops.charm import (
6 from ops.framework import (
7 EventBase,
8 EventSource,
9+ StoredState,
10 )
11 from ops.main import main
12 from ops.model import (
13@@ -28,9 +29,7 @@ from ops.model import (
14
15 from interface import pgsql
16
17-# Until https://github.com/canonical/operator/issues/317 is
18-# resolved, we'll directly manage charm state ourselves.
19-from charmstate import state_get, state_set
20+from charmstate import state_delete, state_get
21 from utils import extend_list_merging_dicts_matched_by_key
22
23 import logging
24@@ -96,23 +95,53 @@ def get_env_config(pod_spec, container_name):
25
26 class MattermostK8sCharm(CharmBase):
27
28+ state = StoredState()
29 on = MattermostCharmEvents()
30
31 def __init__(self, *args):
32 super().__init__(*args)
33
34+ self.framework.observe(self.on.upgrade_charm, self.migrate_to_native_state)
35+
36 self.framework.observe(self.on.start, self.configure_pod)
37 self.framework.observe(self.on.config_changed, self.configure_pod)
38 self.framework.observe(self.on.leader_elected, self.configure_pod)
39 self.framework.observe(self.on.upgrade_charm, self.configure_pod)
40
41 # database
42+ self.state.set_default(db_conn_str=None, db_uri=None, db_ro_uris=[])
43 self.db = pgsql.PostgreSQLClient(self, 'db')
44 self.framework.observe(self.db.on.database_relation_joined, self._on_database_relation_joined)
45 self.framework.observe(self.db.on.master_changed, self._on_master_changed)
46 self.framework.observe(self.db.on.standby_changed, self._on_standby_changed)
47 self.framework.observe(self.on.db_master_available, self.configure_pod)
48
49+ def migrate_to_native_state(self, event):
50+ """Migrate charm state from pre-0.7 charmstate.py to native StoredState.
51+ Assumes the framework was initialized with use_juju_for_storage=True."""
52+
53+ self.unit.status = MaintenanceStatus('Migrating charm state')
54+
55+ db_conn_str = state_get('db_conn_str')
56+ if db_conn_str:
57+ logging.info('Migrating db_conn_str to native StoredState.')
58+ self.state.db_conn_str = db_conn_str
59+ state_delete('db_conn_str')
60+
61+ db_uri = state_get('db_uri')
62+ if db_uri:
63+ logging.info('Migrating db_uri to native StoredState.')
64+ self.state.db_uri = db_uri
65+ state_delete('db_uri')
66+
67+ db_ro_uris = state_get('db_ro_uris')
68+ if db_ro_uris:
69+ logging.info('Migrating db_ro_uris to native StoredState.')
70+ self.state.db_ro_uris = json.loads(db_ro_uris)
71+ state_delete('db_ro_uris')
72+
73+ self.unit.status = ActiveStatus()
74+
75 def _on_database_relation_joined(self, event: pgsql.DatabaseRelationJoinedEvent):
76 """Handle db-relation-joined."""
77 if self.model.unit.is_leader():
78@@ -132,12 +161,8 @@ class MattermostK8sCharm(CharmBase):
79 # event, or risk connecting to an incorrect database.
80 return
81
82- state_set(
83- {
84- 'db_conn_str': None if event.master is None else event.master.conn_str,
85- 'db_uri': None if event.master is None else event.master.uri,
86- }
87- )
88+ self.state.db_conn_str = None if event.master is None else event.master.conn_str
89+ self.state.db_uri = None if event.master is None else event.master.uri
90
91 if event.master is None:
92 return
93@@ -151,7 +176,7 @@ class MattermostK8sCharm(CharmBase):
94 # event, or risk connecting to an incorrect database.
95 return
96
97- state_set({'db_ro_uris': json.dumps([c.uri for c in event.standbys])})
98+ self.state.db_ro_uris = [c.uri for c in event.standbys]
99
100 # TODO(pjdc): Emit event when we add support for read replicas.
101
102@@ -202,7 +227,7 @@ class MattermostK8sCharm(CharmBase):
103 """Return an envConfig with some core configuration."""
104 config = self.model.config
105 # https://github.com/mattermost/mattermost-server/pull/14666
106- db_uri = state_get('db_uri').replace('postgresql://', 'postgres://')
107+ db_uri = self.state.db_uri.replace('postgresql://', 'postgres://')
108 pod_config = {
109 'MATTERMOST_HTTPD_LISTEN_PORT': CONTAINER_PORT,
110 'MM_CONFIG': db_uri,
111@@ -511,7 +536,7 @@ class MattermostK8sCharm(CharmBase):
112
113 def configure_pod(self, event):
114 """Assemble the pod spec and apply it, if possible."""
115- if not state_get('db_uri'):
116+ if not self.state.db_uri:
117 self.unit.status = WaitingStatus('Waiting for database relation')
118 event.defer()
119 return
120@@ -542,4 +567,4 @@ class MattermostK8sCharm(CharmBase):
121
122
123 if __name__ == '__main__':
124- main(MattermostK8sCharm)
125+ main(MattermostK8sCharm, use_juju_for_storage=True)
126diff --git a/src/charmstate.py b/src/charmstate.py
127index 4a86efd..ebc30f9 100644
128--- a/src/charmstate.py
129+++ b/src/charmstate.py
130@@ -6,7 +6,11 @@
131 import subprocess
132 import yaml
133
134-from typing import Dict
135+
136+def _state_delete(attribute: str):
137+ """Delete attribute from controller-backed per-unit charm state."""
138+ cmd = ['state-delete', attribute]
139+ return yaml.safe_load(subprocess.check_output(cmd).decode('UTF-8'))
140
141
142 def _state_get(attribute: str):
143@@ -15,11 +19,5 @@ def _state_get(attribute: str):
144 return yaml.safe_load(subprocess.check_output(cmd).decode('UTF-8'))
145
146
147-def _state_set(settings: Dict[str, str]):
148- """Store settings in controller-backed per-unit charm state."""
149- cmd = ['state-set'] + ['{}={}'.format(k, v or '') for k, v in settings.items()]
150- subprocess.check_call(cmd)
151-
152-
153+state_delete = _state_delete
154 state_get = _state_get
155-state_set = _state_set

Subscribers

People subscribed via source and target branches