From 69fc40af690eee353d49f2127c9840888bfaae9f Mon Sep 17 00:00:00 2001 From: Adam Dyess Date: Tue, 25 Jun 2024 11:39:17 -0500 Subject: [PATCH] Pin cdk-addons to the charm's channel and warn about cdk-addons deprecations --- charmcraft.yaml | 7 +++ config.yaml | 7 +++ metadata.yaml | 3 ++ src/cdk_addons.py | 22 --------- src/charm.py | 106 +++++++++++++++++++++++++++++++++++------ templates/charm_branch | 2 + 6 files changed, 111 insertions(+), 36 deletions(-) create mode 100644 templates/charm_branch diff --git a/charmcraft.yaml b/charmcraft.yaml index d4b1c4a5..46ccd8c1 100644 --- a/charmcraft.yaml +++ b/charmcraft.yaml @@ -38,3 +38,10 @@ parts: build-packages: [git] prime: - templates/** + branch: + # save the branch name into the charm + after: [charm] + plugin: nil + source: ./ + override-prime: | + git -C $CRAFT_PART_SRC branch --show-current >> $CRAFT_PRIME/templates/charm_branch diff --git a/config.yaml b/config.yaml index 72a8a2de..6e8c5946 100644 --- a/config.yaml +++ b/config.yaml @@ -146,6 +146,13 @@ options: type: boolean default: true description: Deploy the Kubernetes Dashboard + enable-nvidia-plugin: + type: string + default: "false" + description: | + Deprecation notice: This option is deprecated and may be removed in a future release. + If set to anything other than "false", the charm will be blocked with an error message. + Consult https://ubuntu.com/kubernetes/docs/gpu-workers to learn how to deploy GPU workers. enable-metrics: type: boolean default: true diff --git a/metadata.yaml b/metadata.yaml index 5ad43318..6a308347 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -49,6 +49,9 @@ requires: interface: gcp-integration azure: interface: azure-integration + openstack: + # Remains for upgrade compatibility with a warning to remove after upgrade + interface: openstack-integration keystone-credentials: # Remains for upgrade compatibility with a warning to remove after upgrade interface: keystone-credentials diff --git a/src/cdk_addons.py b/src/cdk_addons.py index 71a9cac0..839a3e6d 100644 --- a/src/cdk_addons.py +++ b/src/cdk_addons.py @@ -48,36 +48,14 @@ def configure(self): args = [ "arch=" + arch(), - # "ceph-admin-key=" + (ceph.get("admin_key", "")), - # "ceph-fsid=" + (ceph.get("fsid", "")), - # "ceph-fsname=" + (ceph.get("fsname", "")), - # "ceph-kubernetes-key=" + (ceph.get("admin_key", "")), - # 'ceph-mon-hosts="' + (ceph.get("mon_hosts", "")) + '"', - # "ceph-user=" + hookenv.application_name(), - # "cephfs-mounter=" + cephfs_mounter, - # "cinder-availability-zone=" + hookenv.config("cinder-availability-zone"), "cluster-tag=" + self.charm.get_cluster_name(), "dashboard-auth=token", "default-storage=" + default_storage, "dns-domain=" + self.charm.model.config["dns_domain"], "dns-provider=" + self.get_dns_provider(), - # "enable-aws=" + enable_aws, - # "enable-azure=" + enable_azure, - # "enable-ceph=" + cephEnabled, - # "enable-cephfs=" + cephFsEnabled, "enable-dashboard=" + db_enabled, - # "enable-gcp=" + enable_gcp, - # "enable-gpu=" + str(gpuEnable).lower(), - # "enable-keystone=" + keystoneEnabled, "enable-metrics=" + metrics_enabled, - # "enable-openstack=" + enable_openstack, - # "keystone-cert-file=" + keystone.get("cert", ""), - # "keystone-key-file=" + keystone.get("key", ""), - # "keystone-server-ca=" + keystone.get("keystone-ca", ""), - # "keystone-server-url=" + keystone.get("url", ""), "kubeconfig=" + kubeconfig_path, - # "openstack-cloud-conf=", - # "openstack-endpoint-ca=", "registry=" + registry, ] check_call(["snap", "set", "cdk-addons"] + args) diff --git a/src/charm.py b/src/charm.py index 8676899b..87ab433b 100755 --- a/src/charm.py +++ b/src/charm.py @@ -51,6 +51,44 @@ OBSERVABILITY_ROLE = "system:cos" +def charm_track() -> str: + """Get the charm track based on the current charm branch. + + Read from the charm_branch file in the templates directory. If the file + exists, the last line should contain the branch name. If the branch name + exists and starts with "release_", the release ID is extracted and + returned. Otherwise, "latest" is returned. + + Returns: + str: The charm track based on the current charm branch. + """ + branch_name, branch_file = "", Path("templates/charm_branch") + if branch_file.exists(): + branch_content = branch_file.read_text().strip().splitlines(False) + branch_name = branch_content[-1] if branch_content else "" + log.info("Branch name from file: %s", branch_name) + if branch_name and branch_name.startswith("release_"): + rel_id = branch_name.split("_", 1)[-1] + if re.match(r"^\d+\.\d+$", rel_id): + return rel_id + else: + log.warning("Branch name is not a release branch: %s", branch_name) + return "latest" + + +def cdk_addons_channel(channel: str) -> str: + """cdk-addons channel based on the current charm branch and current snaps risk. + + Args: + channel: The current charm channel via config. (eg "edge", "1.29/stable") + + Returns: + str: The cdk-addons channel based on the charm track and snap risk. + """ + risk = channel.split("/")[-1] + return f"{charm_track()}/{risk}" + + class KubernetesControlPlaneCharm(ops.CharmBase): """Charmed Operator for Kubernetes Control Plane.""" @@ -164,16 +202,11 @@ def configure_auth_webhook(self): custom_authz_config_file=self.model.config["authorization-webhook-config-file"], ) - def warn_keystone_management(self): - relation = self.model.relations.get("keystone-credentials") - if relation and any(r.units for r in relation): - log.warning( - "------------------------------------------------------------\n" - "Keystone credential relation is no longer managed\n" - "Please remove the relation and manage keystone manually\n" - "Run `juju remove-relation kubernetes-control-plane:keystone-credentials keystone`" - ) - status.add(ops.BlockedStatus("Keystone credential relation is no longer managed")) + def deprecation_warnings(self): + self.warn_ceph_client() + self.warn_openstack_cloud() + self.warn_gpu_operator() + self.warn_keystone_management() def warn_ceph_client(self): relation = self.model.relations.get("ceph-client") @@ -182,9 +215,52 @@ def warn_ceph_client(self): "------------------------------------------------------------\n" "Ceph-client relation is no longer managed\n" "Please remove the relation and manage manually or with the ceph-csi charm\n" - "Run `juju remove-relation kubernetes-control-plane:ceph-csi ceph-mon`" + "Run `juju remove-relation %s:ceph-csi ceph-mon`", + self.app.name, + ) + status.add( + ops.BlockedStatus("ceph-client relation is no longer managed -- see debug log") + ) + + def warn_openstack_cloud(self): + relation = self.model.relations.get("openstack") + if relation and any(r.units for r in relation): + log.warning( + "------------------------------------------------------------\n" + "openstack relation is no longer managed\n" + "Please remove the relation and manage manually or with the following charms\n" + " * openstack-cloud-controller\n" + " * cinder-csi\n" + "Run `juju remove-relation %s:openstack openstack-integrator`", + self.app.name, + ) + status.add( + ops.BlockedStatus("openstack relation is no longer managed -- see debug log") ) - status.add(ops.BlockedStatus("Ceph-client relation is no longer managed")) + + def warn_gpu_operator(self): + enable_nvidia_plugin = self.model.config["enable-nvidia-plugin"].lower() + if enable_nvidia_plugin != "false": + log.warning( + "------------------------------------------------------------\n" + "Nvidia GPU operators are no longer managed\n" + "Please config enable-nvidia-plugin=false and manage manually or with the nvidia-gpu-operator charm\n" + "Run `juju config %s enable-nvidia-plugin=false`", + self.app.name, + ) + status.add(ops.BlockedStatus("nvidia-plugin is no longer managed -- see debug log")) + + def warn_keystone_management(self): + relation = self.model.relations.get("keystone-credentials") + if relation and any(r.units for r in relation): + log.warning( + "------------------------------------------------------------\n" + "Keystone credential relation is no longer managed\n" + "Please remove the relation and manage keystone manually\n" + "Run `juju remove-relation %s:keystone-credentials keystone`", + self.app.name, + ) + status.add(ops.BlockedStatus("Keystone credential relation is no longer managed")) @status.on_error(ops.WaitingStatus("Waiting for container runtime")) def configure_container_runtime(self): @@ -527,14 +603,16 @@ def reconcile(self, event): """Reconcile state change events.""" self.install_cni_binaries() kubernetes_snaps.install(channel=self.model.config["channel"], control_plane=True) + kubernetes_snaps.install_snap( + "cdk-addons", channel=cdk_addons_channel(self.model.config["channel"]) + ) kubernetes_snaps.configure_services_restart_always(control_plane=True) self.request_certificates() self.write_certificates() self.write_etcd_client_credentials() self.write_service_account_key() self.configure_auth_webhook() - self.warn_keystone_management() - self.warn_ceph_client() + self.deprecation_warnings() self.configure_loadbalancers() if self.api_dependencies_ready(): self.encryption_at_rest.prepare() diff --git a/templates/charm_branch b/templates/charm_branch new file mode 100644 index 00000000..97330b56 --- /dev/null +++ b/templates/charm_branch @@ -0,0 +1,2 @@ +## Automatically filled in by charmcraft.yaml on build +## the last line in this file represents the branch this charm is build from