From: garciadeblas Date: Mon, 27 Jan 2025 15:53:45 +0000 (+0100) Subject: Check kubernetes resources using generic condition with jsonpath filter X-Git-Tag: v17.0.1~18 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=6c82c3506df94bac477ecd1d0fa2d2fccb9b6fe4;p=osm%2FLCM.git Check kubernetes resources using generic condition with jsonpath filter Change-Id: I1922a835e98db723829c0c9f8438fb5617496707 Signed-off-by: garciadeblas --- diff --git a/osm_lcm/k8s.py b/osm_lcm/k8s.py index e860a812..5d3cca48 100644 --- a/osm_lcm/k8s.py +++ b/osm_lcm/k8s.py @@ -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", diff --git a/osm_lcm/odu_libs/workflows.py b/osm_lcm/odu_libs/workflows.py index d1b95826..cf09e8fa 100644 --- a/osm_lcm/odu_libs/workflows.py +++ b/osm_lcm/odu_libs/workflows.py @@ -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) diff --git a/requirements.in b/requirements.in index a4dd6a70..16cd2469 100644 --- a/requirements.in +++ b/requirements.in @@ -21,6 +21,7 @@ google-auth<2.18.0 grpcio-tools grpclib jinja2 +jsonpath_ng juju==2.9.44.0 kubernetes motor diff --git a/requirements.txt b/requirements.txt index d219ace5..8c451a74 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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