blob: 593792498e692e36e13dfd8baf95c671f7fa7247 [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 yaml
20
21
garciadeblasf7dfdb72024-09-25 12:15:40 +020022MAP_PROFILE = {
23 "infra_controller_profiles": "infra-controllers",
garciadeblasa897d122024-12-09 13:31:06 +010024 "infra_config_profiles": "infra-configs",
garciadeblasf7dfdb72024-09-25 12:15:40 +020025 "resource_profiles": "managed_resources",
26 "app_profiles": "apps",
27}
28
29
garciadeblas96b94f52024-07-08 16:18:21 +020030async def create_ksus(self, op_id, op_params_list, content_list):
garciadeblas9e532812024-10-22 14:04:36 +020031 self.logger.info(f"create_ksus Enter. Operation {op_id}. Params: {op_params_list}")
32 # self.logger.debug(f"Content: {content_list}")
garciadeblas96b94f52024-07-08 16:18:21 +020033
34 if len(content_list) > 1:
35 raise Exception("There is no ODU workflow yet able to manage multiple KSUs")
36 db_ksu = content_list[0]
37 ksu_params = op_params_list[0]
38 oka_list = ksu_params["oka"]
39 if len(oka_list) > 1:
40 raise Exception(
41 "There is no ODU workflow yet able to manage multiple OKAs for a KSU"
42 )
garciadeblasf7dfdb72024-09-25 12:15:40 +020043 oka_item = oka_list[0]
garciadeblas1b2933c2024-10-16 11:43:36 +020044 oka_params = oka_item.get("transformation", {})
garciadeblasf7dfdb72024-09-25 12:15:40 +020045 if "sw_catalog_path" in oka_item:
46 oka_path = oka_item["sw_catalog_path"]
47 else:
garciadeblasa897d122024-12-09 13:31:06 +010048 oka_type = MAP_PROFILE[
49 oka_item.get("profile_type", "infra_controller_profiles")
50 ]
garciadeblas1ad4e882025-01-24 14:24:41 +010051 oka_name = oka_item["git_name"].lower()
garciadeblasf7dfdb72024-09-25 12:15:40 +020052 oka_path = f"{oka_type}/{oka_name}/templates"
garciadeblas96b94f52024-07-08 16:18:21 +020053
54 workflow_template = "launcher-create-ksu-hr.j2"
55 workflow_name = f"create-ksus-{op_id}"
56 ksu_name = db_ksu["git_name"].lower()
57
58 # Additional params for the workflow
59 osm_project_name = "osm_admin" # TODO: get project name from db_ksu
60 kustomization_name = ksu_name
61 helmrelease_name = ksu_name
garciadeblas96b94f52024-07-08 16:18:21 +020062 profile_type = ksu_params.get("profile", {}).get("profile_type")
garciadeblasf7dfdb72024-09-25 12:15:40 +020063 profile_type = MAP_PROFILE[profile_type]
garciadeblas96b94f52024-07-08 16:18:21 +020064 profile_name = ksu_params.get("profile", {}).get("name")
65 age_public_key = ksu_params.get("profile", {}).get("age_pubkey")
garciadeblas1b2933c2024-10-16 11:43:36 +020066 target_ns = oka_params.get("namespace", "default")
garciadeblas1e12c302025-01-17 01:29:37 +010067 substitute_environment = oka_params.get("substitute_environment", "true").lower()
68 custom_env_vars = oka_params.get("custom_env_vars", {})
69 if "APPNAME" not in custom_env_vars:
70 custom_env_vars["APPNAME"] = ksu_name
71 if "TARGET_NS" not in custom_env_vars:
72 custom_env_vars["TARGET_NS"] = target_ns
73 custom_env_vars_str = "|\n"
74 substitution_filter_list = []
75 for k, v in custom_env_vars.items():
76 custom_env_vars_str += " " * 10 + f"{k}={v}\n"
77 substitution_filter_list.append(f"${k}")
78 substitution_filter = ",".join(substitution_filter_list)
79 # TODO: add additional substitution filters
80 # substitution_filter = (
81 # f"{substitution_filter},{oka_params.get('substitution_filter', '')}".strip(",")
82 # )
garciadeblas1b2933c2024-10-16 11:43:36 +020083 inline_values = oka_params.get("inline_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +020084 if inline_values:
85 yaml_string = yaml.safe_dump(
86 inline_values, sort_keys=False, default_flow_style=False
87 )
88 inline_values = "|\n" + "\n".join(
89 [" " * 8 + line for line in yaml_string.splitlines()]
90 )
garciadeblasf7dfdb72024-09-25 12:15:40 +020091 else:
92 inline_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +020093 is_preexisting_cm = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +020094 cm_values = oka_params.get("configmap_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +020095 if cm_values:
96 yaml_string = yaml.safe_dump(
97 cm_values, sort_keys=False, default_flow_style=False
98 )
garciadeblasf7dfdb72024-09-25 12:15:40 +020099 cm_values = "|\n" + "\n".join(
garciadeblas96b94f52024-07-08 16:18:21 +0200100 [" " * 8 + line for line in yaml_string.splitlines()]
101 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200102 values_configmap_name = f"cm-{ksu_name}"
103 cm_key = "values.yaml"
104 else:
105 values_configmap_name = ""
106 cm_key = ""
107 cm_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +0200108 is_preexisting_secret = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +0200109 secret_values = oka_params.get("secret_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200110 if secret_values:
111 values_secret_name = f"secret-{ksu_name}"
112 reference_secret_for_values = f"ref-secret-{ksu_name}"
113 reference_key_for_values = f"ref-key-{ksu_name}"
114 secret_values = yaml.safe_dump(
115 secret_values, sort_keys=False, default_flow_style=False
116 )
117 else:
118 values_secret_name = ""
garciadeblasf7dfdb72024-09-25 12:15:40 +0200119 reference_secret_for_values = "this-secret-does-not-exist"
120 reference_key_for_values = "this-key-does-not-exist"
garciadeblas96b94f52024-07-08 16:18:21 +0200121 sync = "true"
122
123 if secret_values:
124 secret_namespace = "osm-workflows"
125 # Create secret
126 await self.create_secret(
127 reference_secret_for_values,
128 secret_namespace,
129 reference_key_for_values,
130 secret_values,
131 )
132
133 # Render workflow
134 manifest = self.render_jinja_template(
135 workflow_template,
136 output_file=None,
137 workflow_name=workflow_name,
138 git_fleet_url=f"{self._repo_base_url}/{self._repo_user}/fleet-osm.git",
139 git_sw_catalogs_url=f"{self._repo_base_url}/{self._repo_user}/sw-catalogs-osm.git",
140 templates_path=oka_path,
141 substitute_environment=substitute_environment,
142 substitution_filter=substitution_filter,
garciadeblas1e12c302025-01-17 01:29:37 +0100143 custom_env_vars=custom_env_vars_str,
garciadeblas96b94f52024-07-08 16:18:21 +0200144 kustomization_name=kustomization_name,
145 helmrelease_name=helmrelease_name,
146 inline_values=inline_values,
147 is_preexisting_secret=is_preexisting_secret,
148 target_ns=target_ns,
149 age_public_key=age_public_key,
150 values_secret_name=values_secret_name,
151 reference_secret_for_values=reference_secret_for_values,
152 reference_key_for_values=reference_key_for_values,
153 is_preexisting_cm=is_preexisting_cm,
154 values_configmap_name=values_configmap_name,
garciadeblasf7dfdb72024-09-25 12:15:40 +0200155 cm_key=cm_key,
garciadeblas96b94f52024-07-08 16:18:21 +0200156 cm_values=cm_values,
157 ksu_name=ksu_name,
158 profile_name=profile_name,
159 profile_type=profile_type,
160 osm_project_name=osm_project_name,
161 sync=sync,
162 workflow_debug=self._workflow_debug,
163 workflow_dry_run=self._workflow_dry_run,
164 )
165 self.logger.debug(f"Workflow manifest: {manifest}")
166
167 # Submit workflow
168 self._kubectl.create_generic_object(
169 namespace="osm-workflows",
170 manifest_dict=yaml.safe_load(manifest),
171 api_group="argoproj.io",
172 api_plural="workflows",
173 api_version="v1alpha1",
174 )
garciadeblasadb81e82024-11-08 01:11:46 +0100175 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200176
177
178async def update_ksus(self, op_id, op_params_list, content_list):
garciadeblas9e532812024-10-22 14:04:36 +0200179 self.logger.info(f"update_ksus Enter. Operation {op_id}. Params: {op_params_list}")
180 # self.logger.debug(f"Content: {content_list}")
garciadeblas96b94f52024-07-08 16:18:21 +0200181
182 if len(content_list) > 1:
183 raise Exception("There is no ODU workflow yet able to manage multiple KSUs")
184 db_ksu = content_list[0]
185 ksu_params = op_params_list[0]
186 oka_list = ksu_params["oka"]
187 if len(oka_list) > 1:
188 raise Exception(
189 "There is no ODU workflow yet able to manage multiple OKAs for a KSU"
190 )
garciadeblas1b2933c2024-10-16 11:43:36 +0200191 oka_item = oka_list[0]
192 oka_params = oka_item.get("transformation", {})
193 if "sw_catalog_path" in oka_item:
194 oka_path = oka_item["sw_catalog_path"]
195 else:
garciadeblasa897d122024-12-09 13:31:06 +0100196 oka_type = MAP_PROFILE[
197 oka_item.get("profile_type", "infra_controller_profiles")
198 ]
garciadeblas1ad4e882025-01-24 14:24:41 +0100199 oka_name = oka_item["git_name"].lower()
garciadeblas1b2933c2024-10-16 11:43:36 +0200200 oka_path = f"{oka_type}/{oka_name}/templates"
garciadeblas96b94f52024-07-08 16:18:21 +0200201
202 workflow_template = "launcher-update-ksu-hr.j2"
203 workflow_name = f"update-ksus-{op_id}"
204 ksu_name = db_ksu["git_name"].lower()
205
206 # Additional params for the workflow
207 osm_project_name = "osm_admin" # TODO: get project name from db_ksu
208 kustomization_name = ksu_name
209 helmrelease_name = ksu_name
garciadeblas96b94f52024-07-08 16:18:21 +0200210 profile_type = ksu_params.get("profile", {}).get("profile_type")
garciadeblasf7dfdb72024-09-25 12:15:40 +0200211 profile_type = MAP_PROFILE[profile_type]
garciadeblas96b94f52024-07-08 16:18:21 +0200212 profile_name = ksu_params.get("profile", {}).get("name")
213 age_public_key = ksu_params.get("profile", {}).get("age_pubkey")
garciadeblas1b2933c2024-10-16 11:43:36 +0200214 target_ns = oka_params.get("namespace", "default")
garciadeblas1e12c302025-01-17 01:29:37 +0100215 substitute_environment = oka_params.get("substitute_environment", "true").lower()
216 custom_env_vars = oka_params.get("custom_env_vars", {})
217 if "APPNAME" not in custom_env_vars:
218 custom_env_vars["APPNAME"] = ksu_name
219 if "TARGET_NS" not in custom_env_vars:
220 custom_env_vars["TARGET_NS"] = target_ns
221 custom_env_vars_str = "|\n"
222 substitution_filter_list = []
223 for k, v in custom_env_vars.items():
224 custom_env_vars_str += " " * 10 + f"{k}={v}\n"
225 substitution_filter_list.append(f"${k}")
226 substitution_filter = ",".join(substitution_filter_list)
227 # TODO: add additional substitution filters
228 # substitution_filter = (
229 # f"{substitution_filter},{oka_params.get('substitution_filter', '')}".strip(",")
230 # )
garciadeblas1b2933c2024-10-16 11:43:36 +0200231 inline_values = oka_params.get("inline_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200232 if inline_values:
233 yaml_string = yaml.safe_dump(
234 inline_values, sort_keys=False, default_flow_style=False
235 )
236 inline_values = "|\n" + "\n".join(
237 [" " * 8 + line for line in yaml_string.splitlines()]
238 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200239 else:
240 inline_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +0200241 is_preexisting_cm = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +0200242 cm_values = oka_params.get("configmap_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200243 if cm_values:
244 yaml_string = yaml.safe_dump(
245 cm_values, sort_keys=False, default_flow_style=False
246 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200247 cm_values = "|\n" + "\n".join(
garciadeblas96b94f52024-07-08 16:18:21 +0200248 [" " * 8 + line for line in yaml_string.splitlines()]
249 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200250 values_configmap_name = f"cm-{ksu_name}"
251 cm_key = "values.yaml"
252 else:
253 values_configmap_name = ""
254 cm_key = ""
255 cm_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +0200256 is_preexisting_secret = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +0200257 secret_values = oka_params.get("secret_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200258 if secret_values:
259 values_secret_name = f"secret-{ksu_name}"
260 reference_secret_for_values = f"ref-secret-{ksu_name}"
261 reference_key_for_values = f"ref-key-{ksu_name}"
262 secret_values = yaml.safe_dump(
263 secret_values, sort_keys=False, default_flow_style=False
264 )
265 else:
266 values_secret_name = ""
garciadeblasf7dfdb72024-09-25 12:15:40 +0200267 reference_secret_for_values = "this-secret-does-not-exist"
268 reference_key_for_values = "this-key-does-not-exist"
garciadeblas96b94f52024-07-08 16:18:21 +0200269
270 if secret_values:
271 secret_namespace = "osm-workflows"
272 # Create secret
273 await self.create_secret(
274 reference_secret_for_values,
275 secret_namespace,
276 reference_key_for_values,
277 secret_values,
278 )
279
280 # Render workflow
281 manifest = self.render_jinja_template(
282 workflow_template,
283 output_file=None,
284 workflow_name=workflow_name,
285 git_fleet_url=f"{self._repo_base_url}/{self._repo_user}/fleet-osm.git",
286 git_sw_catalogs_url=f"{self._repo_base_url}/{self._repo_user}/sw-catalogs-osm.git",
287 templates_path=oka_path,
288 substitute_environment=substitute_environment,
289 substitution_filter=substitution_filter,
garciadeblas1e12c302025-01-17 01:29:37 +0100290 custom_env_vars=custom_env_vars_str,
garciadeblas96b94f52024-07-08 16:18:21 +0200291 kustomization_name=kustomization_name,
292 helmrelease_name=helmrelease_name,
293 inline_values=inline_values,
294 is_preexisting_secret=is_preexisting_secret,
295 target_ns=target_ns,
296 age_public_key=age_public_key,
297 values_secret_name=values_secret_name,
298 reference_secret_for_values=reference_secret_for_values,
299 reference_key_for_values=reference_key_for_values,
300 is_preexisting_cm=is_preexisting_cm,
301 values_configmap_name=values_configmap_name,
garciadeblasf7dfdb72024-09-25 12:15:40 +0200302 cm_key=cm_key,
garciadeblas96b94f52024-07-08 16:18:21 +0200303 cm_values=cm_values,
304 ksu_name=ksu_name,
305 profile_name=profile_name,
306 profile_type=profile_type,
307 osm_project_name=osm_project_name,
308 workflow_debug=self._workflow_debug,
309 workflow_dry_run=self._workflow_dry_run,
310 )
311 self.logger.debug(f"Workflow manifest: {manifest}")
312
313 # Submit workflow
314 self._kubectl.create_generic_object(
315 namespace="osm-workflows",
316 manifest_dict=yaml.safe_load(manifest),
317 api_group="argoproj.io",
318 api_plural="workflows",
319 api_version="v1alpha1",
320 )
garciadeblasadb81e82024-11-08 01:11:46 +0100321 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200322
323
324async def delete_ksus(self, op_id, op_params_list, content_list):
garciadeblas9e532812024-10-22 14:04:36 +0200325 self.logger.info(f"delete_ksus Enter. Operation {op_id}. Params: {op_params_list}")
326 # self.logger.debug(f"Content: {content_list}")
garciadeblas96b94f52024-07-08 16:18:21 +0200327
328 if len(content_list) > 1:
329 raise Exception("There is no ODU workflow yet able to manage multiple KSUs")
330 db_ksu = content_list[0]
331 ksu_params = op_params_list[0]
332
333 workflow_template = "launcher-delete-ksu.j2"
334 workflow_name = f"delete-ksus-{op_id}"
335 ksu_name = db_ksu["git_name"].lower()
336
337 # Additional params for the workflow
338 osm_project_name = "osm_admin" # TODO: get project name from db_ksu
339 profile_name = ksu_params.get("profile", {}).get("name")
340 profile_type = ksu_params.get("profile", {}).get("profile_type")
garciadeblasf7dfdb72024-09-25 12:15:40 +0200341 profile_type = MAP_PROFILE[profile_type]
garciadeblas96b94f52024-07-08 16:18:21 +0200342
343 # Render workflow
344 manifest = self.render_jinja_template(
345 workflow_template,
346 output_file=None,
347 workflow_name=workflow_name,
348 git_fleet_url=f"{self._repo_base_url}/{self._repo_user}/fleet-osm.git",
349 git_sw_catalogs_url=f"{self._repo_base_url}/{self._repo_user}/sw-catalogs-osm.git",
350 ksu_name=ksu_name,
351 profile_name=profile_name,
352 profile_type=profile_type,
353 osm_project_name=osm_project_name,
354 workflow_debug=self._workflow_debug,
355 workflow_dry_run=self._workflow_dry_run,
356 )
357 self.logger.debug(f"Workflow manifest: {manifest}")
358
359 # Submit workflow
360 self._kubectl.create_generic_object(
361 namespace="osm-workflows",
362 manifest_dict=yaml.safe_load(manifest),
363 api_group="argoproj.io",
364 api_plural="workflows",
365 api_version="v1alpha1",
366 )
garciadeblasadb81e82024-11-08 01:11:46 +0100367 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200368
369
370async def clone_ksu(self, op_id, op_params, content):
garciadeblas9e532812024-10-22 14:04:36 +0200371 self.logger.info(f"clone_ksu Enter. Operation {op_id}. Params: {op_params}")
372 # self.logger.debug(f"Content: {content}")
garciadeblas96b94f52024-07-08 16:18:21 +0200373 workflow_name = f"clone-ksu-{content['_id']}"
garciadeblasadb81e82024-11-08 01:11:46 +0100374 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200375
376
377async def move_ksu(self, op_id, op_params, content):
garciadeblas9e532812024-10-22 14:04:36 +0200378 self.logger.info(f"move_ksu Enter. Operation {op_id}. Params: {op_params}")
379 # self.logger.debug(f"Content: {content}")
garciadeblas96b94f52024-07-08 16:18:21 +0200380 workflow_name = f"move-ksu-{content['_id']}"
garciadeblasadb81e82024-11-08 01:11:46 +0100381 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200382
383
garciadeblasd8429852024-10-17 15:30:30 +0200384async def clean_items_ksu_create(self, op_id, op_params_list, content_list):
garciadeblasd8429852024-10-17 15:30:30 +0200385 self.logger.info(
garciadeblas9e532812024-10-22 14:04:36 +0200386 f"clean_items_ksu_create Enter. Operation {op_id}. Params: {op_params_list}"
garciadeblasd8429852024-10-17 15:30:30 +0200387 )
garciadeblas9e532812024-10-22 14:04:36 +0200388 # self.logger.debug(f"Content: {content_list}")
garciadeblasd8429852024-10-17 15:30:30 +0200389 try:
390 if len(content_list) > 1:
391 raise Exception("There is no ODU workflow yet able to manage multiple KSUs")
392 db_ksu = content_list[0]
393 ksu_name = db_ksu["git_name"].lower()
394 ksu_params = op_params_list[0]
395 oka_list = ksu_params["oka"]
396 if len(oka_list) > 1:
397 raise Exception(
398 "There is no ODU workflow yet able to manage multiple OKAs for a KSU"
399 )
400 oka_item = oka_list[0]
401 oka_params = oka_item.get("transformation", {})
402 secret_values = oka_params.get("secret_values", "")
403 if secret_values:
404 items = {
405 "secrets": [
406 {
407 "name": f"ref-secret-{ksu_name}",
408 "namespace": "osm-workflows",
409 }
410 ]
411 }
412 await self.clean_items(items)
413 return True, "OK"
414 except Exception as e:
415 return False, f"Error while cleaning items: {e}"
416
417
418async def clean_items_ksu_update(self, op_id, op_params_list, content_list):
garciadeblasd8429852024-10-17 15:30:30 +0200419 self.logger.info(
garciadeblas9e532812024-10-22 14:04:36 +0200420 f"clean_items_ksu_update Enter. Operation {op_id}. Params: {op_params_list}"
garciadeblasd8429852024-10-17 15:30:30 +0200421 )
garciadeblas9e532812024-10-22 14:04:36 +0200422 # self.logger.debug(f"Content: {content_list}")
garciadeblasd8429852024-10-17 15:30:30 +0200423 return await self.clean_items_ksu_create(op_id, op_params_list, content_list)