Modify cluster (de)registration workflows to use new Jinja workflows 73/14573/3
authorgarciadeblas <gerardo.garciadeblas@telefonica.com>
Tue, 17 Sep 2024 11:25:06 +0000 (13:25 +0200)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Thu, 26 Sep 2024 09:39:05 +0000 (11:39 +0200)
Change-Id: I1ab2f7b4a356d2cdd0939fa037743127cc56d33b
Signed-off-by: garciadeblas <gerardo.garciadeblas@telefonica.com>
osm_lcm/k8s.py
osm_lcm/odu_libs/cluster_mgmt.py
osm_lcm/odu_libs/templates/launcher-bootstrap-cluster.j2 [new file with mode: 0644]
osm_lcm/odu_libs/templates/launcher-disconnect-flux-remote-cluster.j2 [new file with mode: 0644]
osm_lcm/odu_workflows.py

index a02e165..381195c 100644 (file)
@@ -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
index 719c7a8..935cc02 100644 (file)
@@ -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 (file)
index 0000000..a1ae75e
--- /dev/null
@@ -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 (file)
index 0000000..4a18237
--- /dev/null
@@ -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
index cb59d6b..2c9ed6a 100644 (file)
@@ -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,