From 828f6451f9fe11240f16325d08131156d7f6be24 Mon Sep 17 00:00:00 2001
From: Liam Young <liam.young@canonical.com>
Date: Mon, 27 Feb 2023 07:14:48 +0000
Subject: [PATCH] Refactor configure_charm

* Switch to using new `configure_charm` structure
* Stop using deprecated use_juju_for_storage=True
* Treat db-sync in the same way as other charms

Depends-On: I6b46bae1dc700f5e8b597374c660c0af9c069172
Change-Id: I98b7576263bd431cebefc5188817fb56b9d62c0e
---
 charms/keystone-k8s/.zuul.yaml            |  4 ++
 charms/keystone-k8s/src/charm.py          | 45 +++++++++++++++--------
 charms/keystone-k8s/src/utils/manager.py  |  1 -
 charms/keystone-k8s/test-requirements.txt |  2 +-
 charms/keystone-k8s/tests/tests.yaml      |  2 +-
 5 files changed, 35 insertions(+), 19 deletions(-)

diff --git a/charms/keystone-k8s/.zuul.yaml b/charms/keystone-k8s/.zuul.yaml
index d0ef54cb..08d3cabf 100644
--- a/charms/keystone-k8s/.zuul.yaml
+++ b/charms/keystone-k8s/.zuul.yaml
@@ -5,3 +5,7 @@
       - microk8s-func-test
     vars:
       charm_build_name: keystone-k8s
+      juju_channel: 3.1/stable
+      juju_classic_mode: false
+      microk8s_channel: 1.26-strict/stable
+      microk8s_classic_mode: false
diff --git a/charms/keystone-k8s/src/charm.py b/charms/keystone-k8s/src/charm.py
index 05529929..339216a8 100755
--- a/charms/keystone-k8s/src/charm.py
+++ b/charms/keystone-k8s/src/charm.py
@@ -44,6 +44,8 @@ import ops.pebble
 import ops_sunbeam.charm as sunbeam_charm
 import ops_sunbeam.config_contexts as sunbeam_contexts
 import ops_sunbeam.core as sunbeam_core
+import ops_sunbeam.guard as sunbeam_guard
+import ops_sunbeam.job_ctrl as sunbeam_job_ctrl
 import ops_sunbeam.relation_handlers as sunbeam_rhandlers
 import pwgen
 from ops import (
@@ -325,6 +327,17 @@ class KeystoneOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
     wsgi_public_script = "/usr/bin/keystone-wsgi-public"
     service_port = 5000
     mandatory_relations = {"database", "ingress-public"}
+    db_sync_cmds = [
+        [
+            "sudo",
+            "-u",
+            "keystone",
+            "keystone-manage",
+            "--config-dir",
+            "/etc/keystone",
+            "db_sync",
+        ]
+    ]
 
     def __init__(self, framework):
         super().__init__(framework)
@@ -518,7 +531,7 @@ export OS_AUTH_VERSION=3
 
     def register_service(self, event):
         """Register service in keystone."""
-        if not self._state.bootstrapped:
+        if not self.bootstrapped():
             event.defer()
             return
         if not self.unit.is_leader():
@@ -827,7 +840,8 @@ export OS_AUTH_VERSION=3
         """Healthcheck HTTP URL for the service."""
         return f"http://localhost:{self.default_public_ingress_port}/v3"
 
-    def _do_bootstrap(self) -> bool:
+    @sunbeam_job_ctrl.run_once_per_unit("keystone_bootstrap")
+    def keystone_bootstrap(self) -> bool:
         """Starts the appropriate services in the order they are needed.
 
         If the service has not yet been bootstrapped, then this will
@@ -835,16 +849,13 @@ export OS_AUTH_VERSION=3
          2. Bootstrap the keystone users service
          3. Setup the fernet tokens
         """
-        if not super()._do_bootstrap():
-            return False
-
         if self.unit.is_leader():
             try:
                 self.keystone_manager.setup_keystone()
-            except (ops.pebble.ExecError, ops.pebble.ConnectionError) as error:
-                logger.exception("Failed to bootstrap")
-                logger.exception(error)
-                return False
+            except (ops.pebble.ExecError, ops.pebble.ConnectionError):
+                raise sunbeam_guard.BlockedExceptionError(
+                    "Failed to bootstrap"
+                )
 
             try:
                 self.keystone_manager.setup_initial_projects_and_users()
@@ -853,11 +864,15 @@ export OS_AUTH_VERSION=3
                 # sure of exact exceptions to be caught. List below that
                 # are observed:
                 # keystoneauth1.exceptions.connection.ConnectFailure
-                logger.exception("Failed to setup projects and users")
-                return False
-
+                raise sunbeam_guard.BlockedExceptionError(
+                    "Failed to setup projects and users"
+                )
         self.unit.status = model.MaintenanceStatus("Starting Keystone")
-        return True
+
+    def configure_app_leader(self, event):
+        """Configure the lead unit."""
+        self.keystone_bootstrap()
+        self.set_leader_ready()
 
     def _ingress_changed(self, event: ops.framework.EventBase) -> None:
         """Ingress changed callback.
@@ -872,6 +887,4 @@ export OS_AUTH_VERSION=3
 
 
 if __name__ == "__main__":
-    # Note: use_juju_for_storage=True required per
-    # https://github.com/canonical/operator/issues/506
-    main(KeystoneOperatorCharm, use_juju_for_storage=True)
+    main(KeystoneOperatorCharm)
diff --git a/charms/keystone-k8s/src/utils/manager.py b/charms/keystone-k8s/src/utils/manager.py
index c9f757db..9cd023fa 100644
--- a/charms/keystone-k8s/src/utils/manager.py
+++ b/charms/keystone-k8s/src/utils/manager.py
@@ -139,7 +139,6 @@ class KeystoneManager(framework.Object):
         keystone service.
         """
         with sunbeam_guard.guard(self.charm, "Initializing Keystone", False):
-            self._sync_database()
             self._fernet_setup()
             self._credential_setup()
             self._bootstrap()
diff --git a/charms/keystone-k8s/test-requirements.txt b/charms/keystone-k8s/test-requirements.txt
index ff99b735..f4b4552c 100644
--- a/charms/keystone-k8s/test-requirements.txt
+++ b/charms/keystone-k8s/test-requirements.txt
@@ -9,7 +9,7 @@ coverage
 mock
 flake8
 stestr
-git+https://github.com/openstack-charmers/zaza.git#egg=zaza
+git+https://github.com/openstack-charmers/zaza.git@libjuju-3.1#egg=zaza
 git+https://github.com/openstack-charmers/zaza-openstack-tests.git#egg=zaza.openstack
 git+https://opendev.org/openstack/tempest.git#egg=tempest
 ops
diff --git a/charms/keystone-k8s/tests/tests.yaml b/charms/keystone-k8s/tests/tests.yaml
index 18453a74..76254bde 100644
--- a/charms/keystone-k8s/tests/tests.yaml
+++ b/charms/keystone-k8s/tests/tests.yaml
@@ -6,7 +6,7 @@ configure:
   - zaza.openstack.charm_tests.keystone.setup.wait_for_all_endpoints
   - zaza.openstack.charm_tests.keystone.setup.add_tempest_roles
 tests:
-  - zaza.openstack.charm_tests.tempest.tests.TempestTestWithKeystoneV3
+  - zaza.openstack.charm_tests.tempest.tests.TempestTestWithKeystoneMinimal
 tests_options:
   trust:
     - smoke