From d5354323140bb69b9e0e4b2d7e4247f6c2e8afb3 Mon Sep 17 00:00:00 2001 From: Joseph Phillips Date: Fri, 12 Jan 2024 15:11:58 +0100 Subject: [PATCH] *** WIP. Roll Back. *** --- metadata.yaml | 2 +- src/charm.py | 59 +++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/metadata.yaml b/metadata.yaml index 6a7f1fe..832433a 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -2,7 +2,7 @@ # Licensed under the GPLv3, see LICENSE file for details. name: juju-controller assumes: -- juju >= 3.3 +- juju >= 4.0 description: | The Juju controller charm is used to expose various pieces of functionality of a Juju controller. diff --git a/src/charm.py b/src/charm.py index 5de7488..0fe2ce9 100755 --- a/src/charm.py +++ b/src/charm.py @@ -22,11 +22,14 @@ class JujuControllerCharm(CharmBase): DB_BIND_ADDR_KEY = 'db-bind-address' + ALL_BIND_ADDRS_KEY = 'db-bind-addresses' + _stored = StoredState() def __init__(self, *args): super().__init__(*args) + self.framework.observe(self.on.install, self._on_install) self.framework.observe(self.on.collect_unit_status, self._on_collect_status) self.framework.observe(self.on.config_changed, self._on_config_changed) self.framework.observe( @@ -34,7 +37,8 @@ def __init__(self, *args): self.framework.observe( self.on.website_relation_joined, self._on_website_relation_joined) - self._stored.set_default(db_bind_address='', last_bind_addresses=[], all_bind_addresses=dict()) + self._stored.set_default( + db_bind_address='', last_bind_addresses=[], all_bind_addresses=dict()) self.framework.observe( self.on.dbcluster_relation_changed, self._on_dbcluster_relation_changed) @@ -45,6 +49,9 @@ def __init__(self, *args): self.framework.observe( self.on.metrics_endpoint_relation_broken, self._on_metrics_endpoint_relation_broken) + def _on_collect_status(self, event: InstallEvent): + + def _on_collect_status(self, event: CollectStatusEvent): if len(self._stored.last_bind_addresses) > 1: event.add_status(BlockedStatus( @@ -133,12 +140,13 @@ def _on_metrics_endpoint_relation_broken(self, event: RelationDepartedEvent): self.control_socket.remove_metrics_user(username) def _on_dbcluster_relation_changed(self, event): - """Ensure that a bind address for Dqlite is set in relation data, - if we can determine a unique one from the relation's bound space. + """Maintain our own bind address in relation data. If we are the leader, aggregate the bind addresses for all the peers, and ensure the result is set in the application data bag. + If the aggregate addresses have changed, rewrite the config file. """ - self._ensure_db_bind_address(event) + relation = event.relation + self._ensure_db_bind_address(relation) if self.unit.is_leader(): # The event only has *other* units so include this @@ -146,19 +154,33 @@ def _on_dbcluster_relation_changed(self, event): ip = self._stored.db_bind_address all_bind_addresses = {self.unit.name: ip} if ip else dict() - for unit in event.relation.units: - unit_data = event.relation.data[unit] + for unit in relation.units: + unit_data = relation.data[unit] if self.DB_BIND_ADDR_KEY in unit_data: all_bind_addresses[unit.name] = unit_data[self.DB_BIND_ADDR_KEY] if self._stored.all_bind_addresses == all_bind_addresses: return - event.relation.data[self.app]['db-bind-addresses'] = json.dumps(all_bind_addresses) - self._stored.all_bind_addresses = all_bind_addresses + relation.data[self.app][self.ALL_BIND_ADDRS_KEY] = json.dumps(all_bind_addresses) + self._update_config_file(all_bind_addresses) + else: + app_data = relation.data[self.app] + if self.ALL_BIND_ADDRS_KEY in app_data: + all_bind_addresses = json.loads(app_data[self.ALL_BIND_ADDRS_KEY]) + else: + all_bind_addresses = dict() + + if self._stored.all_bind_addresses == all_bind_addresses: + return + + self._update_config_file(all_bind_addresses) - def _ensure_db_bind_address(self, event): - ips = [str(ip) for ip in self.model.get_binding(event.relation).network.ingress_addresses] + def _ensure_db_bind_address(self, relation): + """Ensure that a bind address for Dqlite is set in relation data, + if we can determine a unique one from the relation's bound space. + """ + ips = [str(ip) for ip in self.model.get_binding(relation).network.ingress_addresses] self._stored.last_bind_addresses = ips if len(ips) > 1: @@ -170,9 +192,24 @@ def _ensure_db_bind_address(self, event): if self._stored.db_bind_address == ip: return - event.relation.data[self.unit].update({self.DB_BIND_ADDR_KEY: ip}) + logger.info('setting new DB bind address: %s', ip) + relation.data[self.unit].update({self.DB_BIND_ADDR_KEY: ip}) self._stored.db_bind_address = ip + def _update_config_file(self, bind_addresses): + # Write this path on install. + + file_path = "something" + with open(file_path) as conf_file: + conf = yaml.safe_load(conf_file) + + conf['db-bind-addresses'] = bind-addresses + + with open(file_path, 'w') as conf_file: + yaml.dump(conf, conf_file) + + self._stored.all_bind_addresses = bind_addresses + def api_port(self) -> str: """Return the port on which the controller API server is listening.""" api_addresses = self._agent_conf('apiaddresses')