From: garciadeblas Date: Tue, 17 Sep 2024 11:25:06 +0000 (+0200) Subject: Modify cluster (de)registration workflows to use new Jinja workflows X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=dde3a312ffc356d66543fccc04a960e13df5ea2e;p=osm%2FLCM.git Modify cluster (de)registration workflows to use new Jinja workflows Change-Id: I1ab2f7b4a356d2cdd0939fa037743127cc56d33b Signed-off-by: garciadeblas --- diff --git a/osm_lcm/k8s.py b/osm_lcm/k8s.py index a02e165..381195c 100644 --- a/osm_lcm/k8s.py +++ b/osm_lcm/k8s.py @@ -385,6 +385,14 @@ class ClusterLcm(LcmBase): db_cluster = self.update_operation_history(db_cluster, workflow_status, None) self.db.set_one("clusters", {"_id": db_cluster["_id"]}, db_cluster) + # Clean items used in the workflow, no matter if the workflow succeeded + clean_status, clean_msg = await self.odu.clean_items_workflow( + "register_cluster", op_id, op_params, content + ) + self.logger.info( + f"clean_status is :{clean_status} and clean_msg is :{clean_msg}" + ) + if workflow_status: resource_status, resource_msg = await self.odu.check_resource_status( "register_cluster", op_id, op_params, content diff --git a/osm_lcm/odu_libs/cluster_mgmt.py b/osm_lcm/odu_libs/cluster_mgmt.py index 719c7a8..935cc02 100644 --- a/osm_lcm/odu_libs/cluster_mgmt.py +++ b/osm_lcm/odu_libs/cluster_mgmt.py @@ -38,21 +38,17 @@ def generate_age_key(): return pubkey, privkey -async def create_cluster(self, op_id, op_params, content, bootstrap_only=False): +async def create_cluster(self, op_id, op_params, content): self.logger.info("Create cluster workflow Enter") self.logger.info(f"Operation {op_id}. Params: {op_params}. Content: {content}") db_cluster = content["cluster"] db_vim_account = content["vim_account"] - # workflow_template = "launcher-create-aks-cluster-and-bootstrap.j2" workflow_template = "launcher-create-crossplane-cluster-and-bootstrap.j2" workflow_name = f"create-cluster-{db_cluster['_id']}" - # cluster_name = db_cluster["name"].lower() cluster_name = db_cluster["git_name"].lower() - # Generate age key - # public_key_new_cluster, private_key_new_cluster = generate_age_key() # Get age key public_key_new_cluster, private_key_new_cluster = gather_age_key(db_cluster) self.logger.debug(f"public_key_new_cluster={public_key_new_cluster}") @@ -61,7 +57,7 @@ async def create_cluster(self, op_id, op_params, content, bootstrap_only=False): # Test kubectl connection self.logger.debug(self._kubectl._get_kubectl_version()) - # Create secret with agekey + # Create temporal secret with agekey secret_name = f"secret-age-{cluster_name}" secret_namespace = "osm-workflows" secret_key = "agekey" @@ -76,21 +72,17 @@ async def create_cluster(self, op_id, op_params, content, bootstrap_only=False): # Additional params for the workflow cluster_kustomization_name = cluster_name osm_project_name = "osm_admin" # TODO: get project name from content - if bootstrap_only: - cluster_type = "" - providerconfig_name = "" + vim_account_id = db_cluster["vim_account"] + providerconfig_name = f"{vim_account_id}-config" + vim_type = db_vim_account["vim_type"] + if vim_type == "azure": + cluster_type = "aks" + elif vim_type == "aws": + cluster_type = "eks" + elif vim_type == "gcp": + cluster_type = "gke" else: - vim_account_id = db_cluster["vim_account"] - providerconfig_name = f"{vim_account_id}-config" - vim_type = db_vim_account["vim_type"] - if vim_type == "azure": - cluster_type = "aks" - elif vim_type == "aws": - cluster_type = "eks" - elif vim_type == "gcp": - cluster_type = "gke" - else: - raise Exception("Not suitable VIM account to register cluster") + raise Exception("Not suitable VIM account to register cluster") # Render workflow # workflow_kwargs = { @@ -262,16 +254,21 @@ async def register_cluster(self, op_id, op_params, content): self.logger.info(f"Operation {op_id}. Params: {op_params}. Content: {content}") db_cluster = content["cluster"] - # cluster_name = db_cluster["name"].lower() cluster_name = db_cluster["git_name"].lower() - # Create secret with kubeconfig - secret_name = f"kubeconfig-{cluster_name}" - secret_namespace = "managed-resources" - secret_key = "kubeconfig" - secret_value = yaml.safe_dump( - db_cluster["credentials"], indent=4, default_flow_style=False, sort_keys=False - ) + workflow_template = "launcher-bootstrap-cluster.j2" + workflow_name = f"register-cluster-{db_cluster['_id']}" + + # Get age key + public_key_new_cluster, private_key_new_cluster = gather_age_key(db_cluster) + self.logger.debug(f"public_key_new_cluster={public_key_new_cluster}") + self.logger.debug(f"private_key_new_cluster={private_key_new_cluster}") + + # Create temporal secret with agekey + secret_name = f"secret-age-{cluster_name}" + secret_namespace = "osm-workflows" + secret_key = "agekey" + secret_value = private_key_new_cluster await self.create_secret( secret_name, secret_namespace, @@ -279,14 +276,90 @@ async def register_cluster(self, op_id, op_params, content): secret_value, ) - workflow_name = await self.create_cluster(op_id, op_params, content, True) + # Create secret with kubeconfig + secret_name2 = f"kubeconfig-{cluster_name}" + secret_namespace2 = "managed-resources" + secret_key2 = "kubeconfig" + secret_value2 = yaml.safe_dump( + db_cluster["credentials"], indent=4, default_flow_style=False, sort_keys=False + ) + await self.create_secret( + secret_name2, + secret_namespace2, + secret_key2, + secret_value2, + ) + + # Additional params for the workflow + cluster_kustomization_name = cluster_name + osm_project_name = "osm_admin" # TODO: get project name from content + vim_account_id = db_cluster["vim_account"] + providerconfig_name = f"{vim_account_id}-config" + + manifest = self.render_jinja_template( + workflow_template, + output_file=None, + workflow_name=workflow_name, + git_fleet_url=f"{self._repo_base_url}/{self._repo_user}/fleet-osm.git", + git_sw_catalogs_url=f"{self._repo_base_url}/{self._repo_user}/sw-catalogs-osm.git", + cluster_name=cluster_name, + cluster_kustomization_name=cluster_kustomization_name, + providerconfig_name=providerconfig_name, + public_key_mgmt=self._pubkey, + public_key_new_cluster=public_key_new_cluster, + secret_name_private_key_new_cluster=secret_name, + osm_project_name=osm_project_name, + workflow_debug=self._workflow_debug, + workflow_dry_run=self._workflow_dry_run, + ) + self.logger.debug(f"Workflow manifest: {manifest}") + + # Submit workflow + self._kubectl.create_generic_object( + namespace="osm-workflows", + manifest_dict=yaml.safe_load(manifest), + api_group="argoproj.io", + api_plural="workflows", + api_version="v1alpha1", + ) return workflow_name async def deregister_cluster(self, op_id, op_params, content): self.logger.info("Deregister cluster workflow Enter") self.logger.info(f"Operation {op_id}. Params: {op_params}. Content: {content}") - workflow_name = await self.delete_cluster(op_id, op_params, content) + + db_cluster = content["cluster"] + cluster_name = db_cluster["git_name"].lower() + + workflow_template = "launcher-disconnect-flux-remote-cluster.j2" + workflow_name = f"deregister-cluster-{db_cluster['_id']}" + + # Additional params for the workflow + cluster_kustomization_name = cluster_name + osm_project_name = "osm_admin" # TODO: get project name from DB + + # Render workflow + manifest = self.render_jinja_template( + workflow_template, + output_file=None, + workflow_name=workflow_name, + git_fleet_url=f"{self._repo_base_url}/{self._repo_user}/fleet-osm.git", + cluster_kustomization_name=cluster_kustomization_name, + osm_project_name=osm_project_name, + workflow_debug=self._workflow_debug, + workflow_dry_run=self._workflow_dry_run, + ) + self.logger.info(manifest) + + # Submit workflow + self._kubectl.create_generic_object( + namespace="osm-workflows", + manifest_dict=yaml.safe_load(manifest), + api_group="argoproj.io", + api_plural="workflows", + api_version="v1alpha1", + ) return workflow_name @@ -341,6 +414,26 @@ async def clean_items_cluster_update(self, op_id, op_params, content): return await self.clean_items_cluster_create(op_id, op_params, content) +async def clean_items_cluster_register(self, op_id, op_params, content): + self.logger.info("Clean items cluster_register Enter") + self.logger.info(f"Operation {op_id}. Params: {op_params}. Content: {content}") + # Clean secrets + cluster_name = content["cluster"]["git_name"].lower() + items = { + "secrets": [ + { + "name": f"secret-age-{cluster_name}", + "namespace": "osm-workflows", + }, + ] + } + + try: + await self.clean_items(items) + except Exception as e: + return False, f"Error while cleaning items: {e}" + + async def check_create_cluster(self, op_id, op_params, content): self.logger.info(f"Operation {op_id}. Params: {op_params}. Content: {content}") return True, "OK" @@ -362,5 +455,22 @@ async def check_register_cluster(self, op_id, op_params, content): async def check_deregister_cluster(self, op_id, op_params, content): + self.logger.info("check_deregister_cluster Enter") self.logger.info(f"Operation {op_id}. Params: {op_params}. Content: {content}") + # Clean secrets + self.logger.info("Cleaning kubeconfig") + cluster_name = content["cluster"]["git_name"].lower() + items = { + "secrets": [ + { + "name": f"kubeconfig-{cluster_name}", + "namespace": "managed-resources", + }, + ] + } + + try: + await self.clean_items(items) + except Exception as e: + return False, f"Error while cleaning items: {e}" return True, "OK" diff --git a/osm_lcm/odu_libs/templates/launcher-bootstrap-cluster.j2 b/osm_lcm/odu_libs/templates/launcher-bootstrap-cluster.j2 new file mode 100644 index 0000000..a1ae75e --- /dev/null +++ b/osm_lcm/odu_libs/templates/launcher-bootstrap-cluster.j2 @@ -0,0 +1,72 @@ +####################################################################################### +# Copyright ETSI Contributors and Others. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +####################################################################################### + +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + name: {{ workflow_name }} +spec: + arguments: + parameters: + + # Fleet repo + - name: git_fleet_url + value: "{{ git_fleet_url }}" + - name: fleet_destination_folder + value: "/fleet/fleet-osm" + - name: git_fleet_cred_secret + value: fleet-repo + + # SW-Catalogs repo + - name: git_sw_catalogs_url + value: "{{ git_sw_catalogs_url }}" + - name: sw_catalogs_destination_folder + value: "/sw-catalogs/sw-catalogs-osm" + - name: git_sw_catalogs_cred_secret + value: sw-catalogs + + # Specific parameters - Cluster bootstrap + - name: cluster_kustomization_name + value: {{ cluster_kustomization_name }} + - name: cluster_name + value: {{ cluster_name }} + - name: public_key_mgmt + value: "{{ public_key_mgmt }}" + - name: public_key_new_cluster + value: "{{ public_key_new_cluster }}" + - name: secret_name_private_age_key_for_new_cluster + value: "{{ secret_name_private_key_new_cluster }}" + - name: key_name_in_secret + value: "agekey" + - name: mgmt_project_name + value: "{{ osm_project_name }}" + + # Debug/dry run? + - name: debug + value: "{{ workflow_debug }}" + - name: dry_run + value: "{{ workflow_dry_run }}" + + + # Cleanup policy + ttlStrategy: + secondsAfterCompletion: 2000 # Time to live after workflow is completed, replaces ttlSecondsAfterFinished + secondsAfterSuccess: 1000 # Time to live after workflow is successful + secondsAfterFailure: 1000 # Time to live after workflow fails + + workflowTemplateRef: + name: full-bootstrap-cluster-wft diff --git a/osm_lcm/odu_libs/templates/launcher-disconnect-flux-remote-cluster.j2 b/osm_lcm/odu_libs/templates/launcher-disconnect-flux-remote-cluster.j2 new file mode 100644 index 0000000..4a18237 --- /dev/null +++ b/osm_lcm/odu_libs/templates/launcher-disconnect-flux-remote-cluster.j2 @@ -0,0 +1,54 @@ +####################################################################################### +# Copyright ETSI Contributors and Others. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +####################################################################################### + +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + name: {{ workflow_name }} +spec: + arguments: + parameters: + + # Fleet repo + - name: git_fleet_url + value: "{{ git_fleet_url }}" + - name: fleet_destination_folder + value: "/fleet/fleet-osm" + - name: git_fleet_cred_secret + value: fleet-repo + + # Specific parameters + - name: cluster_kustomization_name + value: {{ cluster_kustomization_name }} + - name: mgmt_project_name + value: "{{ osm_project_name }}" + + # Debug/dry run? + - name: debug + value: "{{ workflow_debug }}" + - name: dry_run + value: "{{ workflow_dry_run }}" + + + # Cleanup policy + ttlStrategy: + secondsAfterCompletion: 2000 # Time to live after workflow is completed, replaces ttlSecondsAfterFinished + secondsAfterSuccess: 1000 # Time to live after workflow is successful + secondsAfterFailure: 1000 # Time to live after workflow fails + + workflowTemplateRef: + name: full-disconnect-flux-remote-cluster-wft diff --git a/osm_lcm/odu_workflows.py b/osm_lcm/odu_workflows.py index cb59d6b..2c9ed6a 100644 --- a/osm_lcm/odu_workflows.py +++ b/osm_lcm/odu_workflows.py @@ -59,6 +59,7 @@ class OduWorkflow(LcmBase): }, "register_cluster": { "workflow_function": self.register_cluster, + "clean_function": self.clean_items_cluster_register, "check_resource_function": self.check_register_cluster, }, "deregister_cluster": { @@ -158,6 +159,7 @@ class OduWorkflow(LcmBase): deregister_cluster, clean_items_cluster_create, clean_items_cluster_update, + clean_items_cluster_register, check_create_cluster, check_update_cluster, check_delete_cluster,