blob: d1b95826530914c07430ef57ad8f112c80b1c407 [file] [log] [blame]
garciadeblas96b94f52024-07-08 16:18:21 +02001#######################################################################################
2# Copyright ETSI Contributors and Others.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13# implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#######################################################################################
17
18
19import asyncio
garciadeblas40811852024-10-22 11:35:17 +020020from math import ceil
garciadeblas96b94f52024-07-08 16:18:21 +020021
22
23async def check_workflow_status(self, workflow_name):
garciadeblas40811852024-10-22 11:35:17 +020024 self.logger.info(f"check_workflow_status Enter: {workflow_name}")
garciadeblasadb81e82024-11-08 01:11:46 +010025 if not workflow_name:
26 return False, "Workflow was not launched"
garciadeblasb33813b2024-10-22 11:56:37 +020027 try:
28 return await self.readiness_loop(
29 item="workflow",
garciadeblas96b94f52024-07-08 16:18:21 +020030 name=workflow_name,
garciadeblasb33813b2024-10-22 11:56:37 +020031 namespace="osm-workflows",
32 flag="Completed",
garciadeblasbc96f382025-01-22 16:02:18 +010033 deleted=False,
garciadeblasb33813b2024-10-22 11:56:37 +020034 timeout=300,
garciadeblas96b94f52024-07-08 16:18:21 +020035 )
garciadeblasb33813b2024-10-22 11:56:37 +020036 except Exception as e:
37 return False, f"Unexpected exception: {e}"
garciadeblas40811852024-10-22 11:35:17 +020038
39
garciadeblasbc96f382025-01-22 16:02:18 +010040async def readiness_loop(
41 self, item, name, namespace, flag, deleted, timeout, kubectl=None
42):
43 if kubectl is None:
44 kubectl = self._kubectl
garciadeblas40811852024-10-22 11:35:17 +020045 self.logger.info("readiness_loop Enter")
46 self.logger.info(
garciadeblasbc96f382025-01-22 16:02:18 +010047 f"{item} {name}. Namespace: '{namespace}'. Flag: {flag}. Deleted: {deleted}. Timeout: {timeout}"
garciadeblas40811852024-10-22 11:35:17 +020048 )
49 item_api_map = {
garciadeblasb33813b2024-10-22 11:56:37 +020050 "workflow": {
51 "api_group": "argoproj.io",
52 "api_plural": "workflows",
53 "api_version": "v1alpha1",
54 },
garciadeblas40811852024-10-22 11:35:17 +020055 "kustomization": {
56 "api_group": "kustomize.toolkit.fluxcd.io",
57 "api_plural": "kustomizations",
58 "api_version": "v1",
59 },
60 "cluster_aws": {
61 "api_group": "eks.aws.upbound.io",
62 "api_plural": "clusters",
63 "api_version": "v1beta1",
64 },
65 "cluster_azure": {
66 "api_group": "containerservice.azure.upbound.io",
67 "api_plural": "kubernetesclusters",
68 "api_version": "v1beta1",
69 },
70 "cluster_gcp": {
71 "api_group": "container.gcp.upbound.io",
72 "api_plural": "clusters",
73 "api_version": "v1beta2",
74 },
garciadeblasceaa19d2024-10-24 12:52:11 +020075 "nodepool_aws": {
76 "api_group": "eks.aws.upbound.io",
77 "api_plural": "nodegroups",
78 "api_version": "v1beta1",
79 },
80 "nodepool_gcp": {
81 "api_group": "container.gcp.upbound.io",
82 "api_plural": "nodepools",
83 "api_version": "v1beta2",
84 },
garciadeblas40811852024-10-22 11:35:17 +020085 }
86 counter = 1
87 retry_time = self._odu_checkloop_retry_time
88 max_iterations = ceil(timeout / retry_time)
garciadeblasb33813b2024-10-22 11:56:37 +020089 api_group = item_api_map[item]["api_group"]
90 api_plural = item_api_map[item]["api_plural"]
91 api_version = item_api_map[item]["api_version"]
garciadeblas40811852024-10-22 11:35:17 +020092
93 while counter <= max_iterations:
garciadeblasbc96f382025-01-22 16:02:18 +010094 try:
95 self.logger.info(f"Iteration {counter}/{max_iterations}")
96 generic_object = await kubectl.get_generic_object(
97 api_group=api_group,
98 api_plural=api_plural,
99 api_version=api_version,
100 namespace=namespace,
101 name=name,
garciadeblasceaa19d2024-10-24 12:52:11 +0200102 )
garciadeblasbc96f382025-01-22 16:02:18 +0100103 if deleted:
104 if generic_object:
105 self.logger.info(
106 f"Found {api_plural}. Name: {name}. Namespace: '{namespace}'. API: {api_group}/{api_version}"
107 )
108 else:
109 self.logger.info(
110 f"{item} {name} deleted after {counter} iterations (aprox {counter*retry_time} seconds)"
111 )
112 return True, "COMPLETED"
113 else:
114 if not flag:
115 return True, "Nothing to check"
116 if generic_object:
117 # self.logger.debug(f"{yaml.safe_dump(generic_object)}")
118 conditions = generic_object.get("status", {}).get("conditions", [])
119 self.logger.info(f"{item} status conditions: {conditions}")
120 else:
121 self.logger.info(
122 f"Could not find {api_plural}. Name: {name}. Namespace: '{namespace}'. API: {api_group}/{api_version}"
123 )
124 conditions = []
125 result = next((item for item in conditions if item["type"] == flag), {})
126 if result.get("status", "False") == "True":
127 self.logger.info(
128 f"{item} {name} reached the status {flag} in {counter} iterations (aprox {counter*retry_time} seconds)"
129 )
130 return True, "COMPLETED"
131 # TODO: Implement generic condition with jsonpath filter
132 # jsonpath_expr = parse(condition["jsonpath_filter"])
133 # match = jsonpath_expr.find(generic_object)
134 # if match:
135 # value = match[0].value
136 # if condition["function"](value, condition["value"]):
137 # return True, "COMPLETED"
138 except Exception as e:
139 self.logger.error(f"Exception: {e}")
garciadeblas40811852024-10-22 11:35:17 +0200140 await asyncio.sleep(retry_time)
141 counter += 1
142 return (
143 False,
144 "{item} {name} was not ready after {max_iterations} iterations (aprox {timeout} seconds)",
145 )