From e2293e81db8180fd03f87cadfcdad1eda1118680 Mon Sep 17 00:00:00 2001 From: Benjamin Schimke Date: Mon, 18 Nov 2024 20:25:26 +0100 Subject: [PATCH] Add cluster config through charm config --- charms/worker/k8s/charmcraft.yaml | 10 ++--- charms/worker/k8s/src/charm.py | 62 ++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/charms/worker/k8s/charmcraft.yaml b/charms/worker/k8s/charmcraft.yaml index 16fb21c7..e6a5e8bc 100644 --- a/charms/worker/k8s/charmcraft.yaml +++ b/charms/worker/k8s/charmcraft.yaml @@ -161,31 +161,29 @@ config: CIDR to use for Kubernetes services. After deployment it is only possible to increase the size of the IP range. It is not possible to change or shrink the address range after deployment. - local-storage.enabled: + local_storage_enabled: type: boolean - default: true description: | Enable local storage provisioning. This will create a storage class named "local-storage" that uses the hostPath provisioner. This is useful for development and testing purposes. It is not recommended for production use. - local-storage.local-path: + local_storage_local_path: type: string default: "" description: | The path on the host where local storage will be provisioned. This path must be writable by the kubelet. This is only used if local-storage.enabled is set to true. - local-storage.reclaim-policy: + local_storage_reclaim_policy: type: string description: | The reclaim policy for local storage. This can be either "Delete" or "Retain". If set to "Delete", the storage will be deleted when the PersistentVolumeClaim is deleted. If set to "Retain", the storage will be retained when the PersistentVolumeClaim is deleted. - local-storage.set-default: + local_storage_set_default: type: boolean - default: false description: | Set the local storage class as the default storage class. This is only used if local-storage.enabled is set to true. diff --git a/charms/worker/k8s/src/charm.py b/charms/worker/k8s/src/charm.py index 8d28884a..5ce82d55 100755 --- a/charms/worker/k8s/src/charm.py +++ b/charms/worker/k8s/src/charm.py @@ -133,7 +133,7 @@ def __init__(self, *args): self.labeller = LabelMaker( self, kubeconfig_path=self._internal_kubeconfig, kubectl=KUBECTL_PATH ) - self._stored.set_default(is_dying=False, cluster_name=str(), annotations={}) + self._stored.set_default(is_dying=False, cluster_name=str(), cluster_config={}) self.cos_agent = COSAgentProvider( self, @@ -296,7 +296,7 @@ def _bootstrap_k8s_snap(self): bootstrap_config = BootstrapConfig() self._configure_datastore(bootstrap_config) self._configure_cloud_provider(bootstrap_config) - self._configure_annotations(bootstrap_config) + self._configure_cluster_config(bootstrap_config) bootstrap_config.service_cidr = str(self.config["service-cidr"]) bootstrap_config.control_plane_taints = str(self.config["register-with-taints"]).split() bootstrap_config.extra_sans = [_get_public_address()] @@ -372,41 +372,59 @@ def _get_valid_annotations(self) -> Optional[dict]: return annotations - def _configure_annotations(self, config: BootstrapConfig): - """Configure the annotations for the Canonical Kubernetes cluster. + def _get_cluster_config_from_charm_config(self) -> UserFacingClusterConfig: + """Retrieve the cluster config from charm configuration. + + Returns: + UserFacingClusterConfig: The expected cluster configuration. + """ + local_storage = LocalStorageConfig( + enabled=self.config.get("local_storage_enabled"), + local_path=self.config.get("local_storage_local_path"), + reclaim_policy=self.config.get("local_storage_reclaim_policy"), + set_default=self.config.get("local_storage_set_default"), + ) + + return UserFacingClusterConfig( + local_storage=local_storage, + annotations=self._get_valid_annotations(), + ) + + def _configure_cluster_config(self, config: BootstrapConfig): + """Configure the cluster config for the Canonical Kubernetes cluster. Args: config (BootstrapConfig): Configuration object to bootstrap the cluster. """ - annotations = self._get_valid_annotations() - if annotations is None: - return - if not config.cluster_config: - config.cluster_config = UserFacingClusterConfig(annotations=annotations) + config.cluster_config = self._get_cluster_config_from_charm_config() else: - config.cluster_config.annotations = annotations + charm_cluster_config = self._get_cluster_config_from_charm_config() + # Merge the charm and user cluster configurations + # The existing configuration takes precedence over the charm configuration as + # this information is retrieved elsewhere (e.g. cloud-provider). + merged_data = {**charm_cluster_config.dict(), **config.cluster_config.dict()} + config.cluster_config = UserFacingClusterConfig(**merged_data) @status.on_error( - ops.BlockedStatus("Invalid Annotations"), + ops.BlockedStatus("Invalid Cluster configuration"), AssertionError, ) - def _update_annotations(self): - """Update the annotations for the Canonical Kubernetes cluster.""" - annotations = self._get_valid_annotations() - if annotations is None: - return + def _update_cluster_config(self): + """Update the cluster configuration for the Canonical Kubernetes cluster.""" + status.add(ops.MaintenanceStatus("Updating cluster configuration")) + log.info("Updating cluster configuration") - status.add(ops.MaintenanceStatus("Updating Annotations")) - log.info("Updating Annotations") + cluster_config = self._get_cluster_config_from_charm_config() - if self._stored.annotations == annotations: + if self._stored.cluster_config == cluster_config: return - config = UserFacingClusterConfig(annotations=annotations) - update_request = UpdateClusterConfigRequest(config=config) + update_request = UpdateClusterConfigRequest(config=cluster_config) self.api_manager.update_cluster_config(update_request) + self._stored.cluster_config = cluster_config + def _configure_datastore(self, config: Union[BootstrapConfig, UpdateClusterConfigRequest]): """Configure the datastore for the Kubernetes cluster. @@ -737,7 +755,7 @@ def _reconcile(self, event: ops.EventBase): self._k8s_info(event) self._bootstrap_k8s_snap() self._enable_functionalities() - self._update_annotations() + self._update_cluster_config() self._create_cluster_tokens() self._create_cos_tokens() self._apply_cos_requirements()