Check kubernetes resources using generic condition with jsonpath filter 97/14897/4
authorgarciadeblas <gerardo.garciadeblas@telefonica.com>
Mon, 27 Jan 2025 15:53:45 +0000 (16:53 +0100)
committergarciadeblas <gerardo.garciadeblas@telefonica.com>
Mon, 27 Jan 2025 16:59:01 +0000 (17:59 +0100)
Change-Id: I1922a835e98db723829c0c9f8438fb5617496707
Signed-off-by: garciadeblas <gerardo.garciadeblas@telefonica.com>
osm_lcm/k8s.py
osm_lcm/odu_libs/workflows.py
requirements.in
requirements.txt

index e860a81..5d3cca4 100644 (file)
@@ -224,7 +224,7 @@ class GitOpsLcm(LcmBase):
                         item=checking["item"],
                         name=checking["name"],
                         namespace=checking["namespace"],
-                        flag=checking.get("flag"),
+                        condition=checking.get("condition"),
                         deleted=checking.get("deleted", False),
                         timeout=checking["timeout"],
                         kubectl=kubectl,
@@ -437,7 +437,10 @@ class ClusterLcm(GitOpsLcm):
                     "item": "kustomization",
                     "name": cluster_kustomization_name,
                     "namespace": "managed-resources",
-                    "flag": "Ready",
+                    "condition": {
+                        "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
+                        "value": "True",
+                    },
                     "timeout": 1500,
                     "enable": True,
                     "resourceState": "IN_PROGRESS.KUSTOMIZATION_READY",
@@ -446,7 +449,10 @@ class ClusterLcm(GitOpsLcm):
                     "item": f"cluster_{cloud_type}",
                     "name": cluster_name,
                     "namespace": "",
-                    "flag": "Synced",
+                    "condition": {
+                        "jsonpath_filter": "status.conditions[?(@.type=='Synced')].status",
+                        "value": "True",
+                    },
                     "timeout": self._checkloop_resource_timeout,
                     "enable": True,
                     "resourceState": "IN_PROGRESS.RESOURCE_SYNCED.CLUSTER",
@@ -455,7 +461,10 @@ class ClusterLcm(GitOpsLcm):
                     "item": f"cluster_{cloud_type}",
                     "name": cluster_name,
                     "namespace": "",
-                    "flag": "Ready",
+                    "condition": {
+                        "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
+                        "value": "True",
+                    },
                     "timeout": self._checkloop_resource_timeout,
                     "enable": True,
                     "resourceState": "IN_PROGRESS.RESOURCE_READY.CLUSTER",
@@ -464,7 +473,10 @@ class ClusterLcm(GitOpsLcm):
                     "item": "kustomization",
                     "name": f"{cluster_kustomization_name}-bstrp-fluxctrl",
                     "namespace": "managed-resources",
-                    "flag": "Ready",
+                    "condition": {
+                        "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
+                        "value": "True",
+                    },
                     "timeout": self._checkloop_resource_timeout,
                     "enable": bootstrap,
                     "resourceState": "IN_PROGRESS.BOOTSTRAP_OK",
@@ -477,7 +489,10 @@ class ClusterLcm(GitOpsLcm):
                 "item": f"nodepool_{cloud_type}",
                 "name": nodepool_name,
                 "namespace": "",
-                "flag": "Ready",
+                "condition": {
+                    "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
+                    "value": "True",
+                },
                 "timeout": self._checkloop_resource_timeout,
                 "enable": True,
                 "resourceState": "IN_PROGRESS.RESOURCE_READY.NODEPOOL",
@@ -961,7 +976,10 @@ class ClusterLcm(GitOpsLcm):
                 "item": "kustomization",
                 "name": f"{cluster_kustomization_name}-bstrp-fluxctrl",
                 "namespace": "managed-resources",
-                "flag": "Ready",
+                "condition": {
+                    "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
+                    "value": "True",
+                },
                 "timeout": self._checkloop_kustomization_timeout,
                 "enable": bootstrap,
                 "resourceState": "IN_PROGRESS.BOOTSTRAP_OK",
@@ -1138,7 +1156,7 @@ class ClusterLcm(GitOpsLcm):
 
         db_cluster["operatingState"] = "IDLE"
         # self.logger.info("db_cluster: {}".format(db_cluster))
-        # TODO: verify enxtcondition
+        # TODO: verify condition
         # For the moment, if the workflow completed successfully, then we update the db accordingly.
         if workflow_status:
             if "k8s_version" in op_params:
@@ -1168,7 +1186,10 @@ class ClusterLcm(GitOpsLcm):
         #         "item": "kustomization",
         #         "name": cluster_kustomization_name,
         #         "namespace": "managed-resources",
-        #         "flag": "Ready",
+        #         "condition": {
+        #             "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
+        #             "value": "True",
+        #         },
         #         "timeout": self._checkloop_kustomization_timeout,
         #         "enable": True,
         #         "resourceState": "IN_PROGRESS.KUSTOMIZATION_READY",
@@ -2004,7 +2025,10 @@ class KsuLcm(GitOpsLcm):
                         "item": "kustomization",
                         "name": kustomization_name,
                         "namespace": target_ns,
-                        "flag": "Ready",
+                        "condition": {
+                            "jsonpath_filter": "status.conditions[?(@.type=='Ready')].status",
+                            "value": "True",
+                        },
                         "timeout": self._checkloop_kustomization_timeout,
                         "enable": True,
                         "resourceState": "IN_PROGRESS.KUSTOMIZATION_READY",
index d1b9582..cf09e8f 100644 (file)
@@ -18,6 +18,7 @@
 
 import asyncio
 from math import ceil
+from jsonpath_ng.ext import parse
 
 
 async def check_workflow_status(self, workflow_name):
@@ -29,7 +30,10 @@ async def check_workflow_status(self, workflow_name):
             item="workflow",
             name=workflow_name,
             namespace="osm-workflows",
-            flag="Completed",
+            condition={
+                "jsonpath_filter": "status.conditions[?(@.type=='Completed')].status",
+                "value": "True",
+            },
             deleted=False,
             timeout=300,
         )
@@ -38,13 +42,13 @@ async def check_workflow_status(self, workflow_name):
 
 
 async def readiness_loop(
-    self, item, name, namespace, flag, deleted, timeout, kubectl=None
+    self, item, name, namespace, condition, deleted, timeout, kubectl=None
 ):
     if kubectl is None:
         kubectl = self._kubectl
     self.logger.info("readiness_loop Enter")
     self.logger.info(
-        f"{item} {name}. Namespace: '{namespace}'. Flag: {flag}. Deleted: {deleted}. Timeout: {timeout}"
+        f"{item} {name}. Namespace: '{namespace}'. Condition: {condition}. Deleted: {deleted}. Timeout: {timeout}"
     )
     item_api_map = {
         "workflow": {
@@ -111,7 +115,7 @@ async def readiness_loop(
                     )
                     return True, "COMPLETED"
             else:
-                if not flag:
+                if not condition:
                     return True, "Nothing to check"
                 if generic_object:
                     # self.logger.debug(f"{yaml.safe_dump(generic_object)}")
@@ -122,19 +126,16 @@ async def readiness_loop(
                         f"Could not find {api_plural}. Name: {name}. Namespace: '{namespace}'. API: {api_group}/{api_version}"
                     )
                     conditions = []
-                result = next((item for item in conditions if item["type"] == flag), {})
-                if result.get("status", "False") == "True":
-                    self.logger.info(
-                        f"{item} {name} reached the status {flag} in {counter} iterations (aprox {counter*retry_time} seconds)"
-                    )
-                    return True, "COMPLETED"
-                # TODO: Implement generic condition with jsonpath filter
-                # jsonpath_expr = parse(condition["jsonpath_filter"])
-                # match = jsonpath_expr.find(generic_object)
-                # if match:
-                #     value = match[0].value
-                #     if condition["function"](value, condition["value"]):
-                #         return True, "COMPLETED"
+                jsonpath_expr = parse(condition["jsonpath_filter"])
+                match = jsonpath_expr.find(generic_object)
+                if match:
+                    value = match[0].value
+                    condition_function = condition.get("function", lambda x, y: x == y)
+                    if condition_function(condition["value"], value):
+                        self.logger.info(
+                            f"{item} {name} met the condition {condition} in {counter} iterations (aprox {counter*retry_time} seconds)"
+                        )
+                        return True, "COMPLETED"
         except Exception as e:
             self.logger.error(f"Exception: {e}")
         await asyncio.sleep(retry_time)
index a4dd6a7..16cd246 100644 (file)
@@ -21,6 +21,7 @@ google-auth<2.18.0
 grpcio-tools
 grpclib
 jinja2
+jsonpath_ng
 juju==2.9.44.0
 kubernetes
 motor
index d219ace..8c451a7 100644 (file)
@@ -93,6 +93,8 @@ idna==3.10
     #   yarl
 jinja2==3.1.4
     # via -r requirements.in
+jsonpath-ng==1.7.0
+    # via -r requirements.in
 juju==2.9.44.0
     # via -r requirements.in
 jujubundlelib==0.5.7