blob: 325ec5f026a7b9bf131d67f6eb81857bde758f58 [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")
garciadeblas4c9b4ab2025-02-14 00:44:58 +010066 kustomization_ns = oka_params.get("kustomization_namespace", "flux-system")
garciadeblas1b2933c2024-10-16 11:43:36 +020067 target_ns = oka_params.get("namespace", "default")
garciadeblas1e12c302025-01-17 01:29:37 +010068 substitute_environment = oka_params.get("substitute_environment", "true").lower()
69 custom_env_vars = oka_params.get("custom_env_vars", {})
70 if "APPNAME" not in custom_env_vars:
71 custom_env_vars["APPNAME"] = ksu_name
72 if "TARGET_NS" not in custom_env_vars:
73 custom_env_vars["TARGET_NS"] = target_ns
garciadeblas4c9b4ab2025-02-14 00:44:58 +010074 if "KUSTOMIZATION_NS" not in custom_env_vars:
75 custom_env_vars["KUSTOMIZATION_NS"] = kustomization_ns
garciadeblas1e12c302025-01-17 01:29:37 +010076 custom_env_vars_str = "|\n"
77 substitution_filter_list = []
78 for k, v in custom_env_vars.items():
79 custom_env_vars_str += " " * 10 + f"{k}={v}\n"
80 substitution_filter_list.append(f"${k}")
81 substitution_filter = ",".join(substitution_filter_list)
82 # TODO: add additional substitution filters
83 # substitution_filter = (
84 # f"{substitution_filter},{oka_params.get('substitution_filter', '')}".strip(",")
85 # )
garciadeblas1b2933c2024-10-16 11:43:36 +020086 inline_values = oka_params.get("inline_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +020087 if inline_values:
88 yaml_string = yaml.safe_dump(
89 inline_values, sort_keys=False, default_flow_style=False
90 )
91 inline_values = "|\n" + "\n".join(
92 [" " * 8 + line for line in yaml_string.splitlines()]
93 )
garciadeblasf7dfdb72024-09-25 12:15:40 +020094 else:
95 inline_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +020096 is_preexisting_cm = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +020097 cm_values = oka_params.get("configmap_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +020098 if cm_values:
99 yaml_string = yaml.safe_dump(
100 cm_values, sort_keys=False, default_flow_style=False
101 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200102 cm_values = "|\n" + "\n".join(
garciadeblas96b94f52024-07-08 16:18:21 +0200103 [" " * 8 + line for line in yaml_string.splitlines()]
104 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200105 values_configmap_name = f"cm-{ksu_name}"
106 cm_key = "values.yaml"
107 else:
108 values_configmap_name = ""
109 cm_key = ""
110 cm_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +0200111 is_preexisting_secret = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +0200112 secret_values = oka_params.get("secret_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200113 if secret_values:
114 values_secret_name = f"secret-{ksu_name}"
115 reference_secret_for_values = f"ref-secret-{ksu_name}"
116 reference_key_for_values = f"ref-key-{ksu_name}"
117 secret_values = yaml.safe_dump(
118 secret_values, sort_keys=False, default_flow_style=False
119 )
120 else:
121 values_secret_name = ""
garciadeblasf7dfdb72024-09-25 12:15:40 +0200122 reference_secret_for_values = "this-secret-does-not-exist"
123 reference_key_for_values = "this-key-does-not-exist"
garciadeblas96b94f52024-07-08 16:18:21 +0200124 sync = "true"
125
126 if secret_values:
127 secret_namespace = "osm-workflows"
128 # Create secret
129 await self.create_secret(
130 reference_secret_for_values,
131 secret_namespace,
132 reference_key_for_values,
133 secret_values,
134 )
135
136 # Render workflow
137 manifest = self.render_jinja_template(
138 workflow_template,
139 output_file=None,
140 workflow_name=workflow_name,
garciadeblas1c62c112025-05-26 15:29:46 +0200141 git_fleet_url=self._repo_fleet_url,
142 git_sw_catalogs_url=self._repo_sw_catalogs_url,
garciadeblas96b94f52024-07-08 16:18:21 +0200143 templates_path=oka_path,
144 substitute_environment=substitute_environment,
145 substitution_filter=substitution_filter,
garciadeblas1e12c302025-01-17 01:29:37 +0100146 custom_env_vars=custom_env_vars_str,
garciadeblas96b94f52024-07-08 16:18:21 +0200147 kustomization_name=kustomization_name,
148 helmrelease_name=helmrelease_name,
149 inline_values=inline_values,
150 is_preexisting_secret=is_preexisting_secret,
151 target_ns=target_ns,
152 age_public_key=age_public_key,
153 values_secret_name=values_secret_name,
154 reference_secret_for_values=reference_secret_for_values,
155 reference_key_for_values=reference_key_for_values,
156 is_preexisting_cm=is_preexisting_cm,
157 values_configmap_name=values_configmap_name,
garciadeblasf7dfdb72024-09-25 12:15:40 +0200158 cm_key=cm_key,
garciadeblas96b94f52024-07-08 16:18:21 +0200159 cm_values=cm_values,
160 ksu_name=ksu_name,
161 profile_name=profile_name,
162 profile_type=profile_type,
163 osm_project_name=osm_project_name,
164 sync=sync,
165 workflow_debug=self._workflow_debug,
166 workflow_dry_run=self._workflow_dry_run,
167 )
168 self.logger.debug(f"Workflow manifest: {manifest}")
169
170 # Submit workflow
171 self._kubectl.create_generic_object(
172 namespace="osm-workflows",
173 manifest_dict=yaml.safe_load(manifest),
174 api_group="argoproj.io",
175 api_plural="workflows",
176 api_version="v1alpha1",
177 )
garciadeblasadb81e82024-11-08 01:11:46 +0100178 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200179
180
181async def update_ksus(self, op_id, op_params_list, content_list):
garciadeblas9e532812024-10-22 14:04:36 +0200182 self.logger.info(f"update_ksus Enter. Operation {op_id}. Params: {op_params_list}")
183 # self.logger.debug(f"Content: {content_list}")
garciadeblas96b94f52024-07-08 16:18:21 +0200184
185 if len(content_list) > 1:
186 raise Exception("There is no ODU workflow yet able to manage multiple KSUs")
187 db_ksu = content_list[0]
188 ksu_params = op_params_list[0]
189 oka_list = ksu_params["oka"]
190 if len(oka_list) > 1:
191 raise Exception(
192 "There is no ODU workflow yet able to manage multiple OKAs for a KSU"
193 )
garciadeblas1b2933c2024-10-16 11:43:36 +0200194 oka_item = oka_list[0]
195 oka_params = oka_item.get("transformation", {})
196 if "sw_catalog_path" in oka_item:
197 oka_path = oka_item["sw_catalog_path"]
198 else:
garciadeblasa897d122024-12-09 13:31:06 +0100199 oka_type = MAP_PROFILE[
200 oka_item.get("profile_type", "infra_controller_profiles")
201 ]
garciadeblas1ad4e882025-01-24 14:24:41 +0100202 oka_name = oka_item["git_name"].lower()
garciadeblas1b2933c2024-10-16 11:43:36 +0200203 oka_path = f"{oka_type}/{oka_name}/templates"
garciadeblas96b94f52024-07-08 16:18:21 +0200204
205 workflow_template = "launcher-update-ksu-hr.j2"
206 workflow_name = f"update-ksus-{op_id}"
207 ksu_name = db_ksu["git_name"].lower()
208
209 # Additional params for the workflow
210 osm_project_name = "osm_admin" # TODO: get project name from db_ksu
211 kustomization_name = ksu_name
212 helmrelease_name = ksu_name
garciadeblas96b94f52024-07-08 16:18:21 +0200213 profile_type = ksu_params.get("profile", {}).get("profile_type")
garciadeblasf7dfdb72024-09-25 12:15:40 +0200214 profile_type = MAP_PROFILE[profile_type]
garciadeblas96b94f52024-07-08 16:18:21 +0200215 profile_name = ksu_params.get("profile", {}).get("name")
216 age_public_key = ksu_params.get("profile", {}).get("age_pubkey")
garciadeblas4c9b4ab2025-02-14 00:44:58 +0100217 kustomization_ns = oka_params.get("kustomization_namespace", "flux-system")
garciadeblas1b2933c2024-10-16 11:43:36 +0200218 target_ns = oka_params.get("namespace", "default")
garciadeblas1e12c302025-01-17 01:29:37 +0100219 substitute_environment = oka_params.get("substitute_environment", "true").lower()
220 custom_env_vars = oka_params.get("custom_env_vars", {})
221 if "APPNAME" not in custom_env_vars:
222 custom_env_vars["APPNAME"] = ksu_name
223 if "TARGET_NS" not in custom_env_vars:
224 custom_env_vars["TARGET_NS"] = target_ns
garciadeblas4c9b4ab2025-02-14 00:44:58 +0100225 if "KUSTOMIZATION_NS" not in custom_env_vars:
226 custom_env_vars["KUSTOMIZATION_NS"] = kustomization_ns
garciadeblas1e12c302025-01-17 01:29:37 +0100227 custom_env_vars_str = "|\n"
228 substitution_filter_list = []
229 for k, v in custom_env_vars.items():
230 custom_env_vars_str += " " * 10 + f"{k}={v}\n"
231 substitution_filter_list.append(f"${k}")
232 substitution_filter = ",".join(substitution_filter_list)
233 # TODO: add additional substitution filters
234 # substitution_filter = (
235 # f"{substitution_filter},{oka_params.get('substitution_filter', '')}".strip(",")
236 # )
garciadeblas1b2933c2024-10-16 11:43:36 +0200237 inline_values = oka_params.get("inline_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200238 if inline_values:
239 yaml_string = yaml.safe_dump(
240 inline_values, sort_keys=False, default_flow_style=False
241 )
242 inline_values = "|\n" + "\n".join(
243 [" " * 8 + line for line in yaml_string.splitlines()]
244 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200245 else:
246 inline_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +0200247 is_preexisting_cm = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +0200248 cm_values = oka_params.get("configmap_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200249 if cm_values:
250 yaml_string = yaml.safe_dump(
251 cm_values, sort_keys=False, default_flow_style=False
252 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200253 cm_values = "|\n" + "\n".join(
garciadeblas96b94f52024-07-08 16:18:21 +0200254 [" " * 8 + line for line in yaml_string.splitlines()]
255 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200256 values_configmap_name = f"cm-{ksu_name}"
257 cm_key = "values.yaml"
258 else:
259 values_configmap_name = ""
260 cm_key = ""
261 cm_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +0200262 is_preexisting_secret = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +0200263 secret_values = oka_params.get("secret_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200264 if secret_values:
265 values_secret_name = f"secret-{ksu_name}"
266 reference_secret_for_values = f"ref-secret-{ksu_name}"
267 reference_key_for_values = f"ref-key-{ksu_name}"
268 secret_values = yaml.safe_dump(
269 secret_values, sort_keys=False, default_flow_style=False
270 )
271 else:
272 values_secret_name = ""
garciadeblasf7dfdb72024-09-25 12:15:40 +0200273 reference_secret_for_values = "this-secret-does-not-exist"
274 reference_key_for_values = "this-key-does-not-exist"
garciadeblas96b94f52024-07-08 16:18:21 +0200275
276 if secret_values:
277 secret_namespace = "osm-workflows"
278 # Create secret
279 await self.create_secret(
280 reference_secret_for_values,
281 secret_namespace,
282 reference_key_for_values,
283 secret_values,
284 )
285
286 # Render workflow
287 manifest = self.render_jinja_template(
288 workflow_template,
289 output_file=None,
290 workflow_name=workflow_name,
garciadeblas1c62c112025-05-26 15:29:46 +0200291 git_fleet_url=self._repo_fleet_url,
292 git_sw_catalogs_url=self._repo_sw_catalogs_url,
garciadeblas96b94f52024-07-08 16:18:21 +0200293 templates_path=oka_path,
294 substitute_environment=substitute_environment,
295 substitution_filter=substitution_filter,
garciadeblas1e12c302025-01-17 01:29:37 +0100296 custom_env_vars=custom_env_vars_str,
garciadeblas96b94f52024-07-08 16:18:21 +0200297 kustomization_name=kustomization_name,
298 helmrelease_name=helmrelease_name,
299 inline_values=inline_values,
300 is_preexisting_secret=is_preexisting_secret,
301 target_ns=target_ns,
302 age_public_key=age_public_key,
303 values_secret_name=values_secret_name,
304 reference_secret_for_values=reference_secret_for_values,
305 reference_key_for_values=reference_key_for_values,
306 is_preexisting_cm=is_preexisting_cm,
307 values_configmap_name=values_configmap_name,
garciadeblasf7dfdb72024-09-25 12:15:40 +0200308 cm_key=cm_key,
garciadeblas96b94f52024-07-08 16:18:21 +0200309 cm_values=cm_values,
310 ksu_name=ksu_name,
311 profile_name=profile_name,
312 profile_type=profile_type,
313 osm_project_name=osm_project_name,
314 workflow_debug=self._workflow_debug,
315 workflow_dry_run=self._workflow_dry_run,
316 )
317 self.logger.debug(f"Workflow manifest: {manifest}")
318
319 # Submit workflow
320 self._kubectl.create_generic_object(
321 namespace="osm-workflows",
322 manifest_dict=yaml.safe_load(manifest),
323 api_group="argoproj.io",
324 api_plural="workflows",
325 api_version="v1alpha1",
326 )
garciadeblasadb81e82024-11-08 01:11:46 +0100327 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200328
329
330async def delete_ksus(self, op_id, op_params_list, content_list):
garciadeblas9e532812024-10-22 14:04:36 +0200331 self.logger.info(f"delete_ksus Enter. Operation {op_id}. Params: {op_params_list}")
332 # self.logger.debug(f"Content: {content_list}")
garciadeblas96b94f52024-07-08 16:18:21 +0200333
334 if len(content_list) > 1:
335 raise Exception("There is no ODU workflow yet able to manage multiple KSUs")
336 db_ksu = content_list[0]
337 ksu_params = op_params_list[0]
338
339 workflow_template = "launcher-delete-ksu.j2"
340 workflow_name = f"delete-ksus-{op_id}"
341 ksu_name = db_ksu["git_name"].lower()
342
343 # Additional params for the workflow
344 osm_project_name = "osm_admin" # TODO: get project name from db_ksu
345 profile_name = ksu_params.get("profile", {}).get("name")
346 profile_type = ksu_params.get("profile", {}).get("profile_type")
garciadeblasf7dfdb72024-09-25 12:15:40 +0200347 profile_type = MAP_PROFILE[profile_type]
garciadeblas96b94f52024-07-08 16:18:21 +0200348
349 # Render workflow
350 manifest = self.render_jinja_template(
351 workflow_template,
352 output_file=None,
353 workflow_name=workflow_name,
garciadeblas1c62c112025-05-26 15:29:46 +0200354 git_fleet_url=self._repo_fleet_url,
355 git_sw_catalogs_url=self._repo_sw_catalogs_url,
garciadeblas96b94f52024-07-08 16:18:21 +0200356 ksu_name=ksu_name,
357 profile_name=profile_name,
358 profile_type=profile_type,
359 osm_project_name=osm_project_name,
360 workflow_debug=self._workflow_debug,
361 workflow_dry_run=self._workflow_dry_run,
362 )
363 self.logger.debug(f"Workflow manifest: {manifest}")
364
365 # Submit workflow
366 self._kubectl.create_generic_object(
367 namespace="osm-workflows",
368 manifest_dict=yaml.safe_load(manifest),
369 api_group="argoproj.io",
370 api_plural="workflows",
371 api_version="v1alpha1",
372 )
garciadeblasadb81e82024-11-08 01:11:46 +0100373 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200374
375
376async def clone_ksu(self, op_id, op_params, content):
garciadeblas9e532812024-10-22 14:04:36 +0200377 self.logger.info(f"clone_ksu Enter. Operation {op_id}. Params: {op_params}")
378 # self.logger.debug(f"Content: {content}")
garciadeblas96b94f52024-07-08 16:18:21 +0200379 workflow_name = f"clone-ksu-{content['_id']}"
garciadeblasadb81e82024-11-08 01:11:46 +0100380 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200381
382
383async def move_ksu(self, op_id, op_params, content):
garciadeblas9e532812024-10-22 14:04:36 +0200384 self.logger.info(f"move_ksu Enter. Operation {op_id}. Params: {op_params}")
385 # self.logger.debug(f"Content: {content}")
garciadeblas96b94f52024-07-08 16:18:21 +0200386 workflow_name = f"move-ksu-{content['_id']}"
garciadeblasadb81e82024-11-08 01:11:46 +0100387 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200388
389
garciadeblasd8429852024-10-17 15:30:30 +0200390async def clean_items_ksu_create(self, op_id, op_params_list, content_list):
garciadeblasd8429852024-10-17 15:30:30 +0200391 self.logger.info(
garciadeblas9e532812024-10-22 14:04:36 +0200392 f"clean_items_ksu_create Enter. Operation {op_id}. Params: {op_params_list}"
garciadeblasd8429852024-10-17 15:30:30 +0200393 )
garciadeblas9e532812024-10-22 14:04:36 +0200394 # self.logger.debug(f"Content: {content_list}")
garciadeblasd8429852024-10-17 15:30:30 +0200395 try:
396 if len(content_list) > 1:
397 raise Exception("There is no ODU workflow yet able to manage multiple KSUs")
398 db_ksu = content_list[0]
399 ksu_name = db_ksu["git_name"].lower()
400 ksu_params = op_params_list[0]
401 oka_list = ksu_params["oka"]
402 if len(oka_list) > 1:
403 raise Exception(
404 "There is no ODU workflow yet able to manage multiple OKAs for a KSU"
405 )
406 oka_item = oka_list[0]
407 oka_params = oka_item.get("transformation", {})
408 secret_values = oka_params.get("secret_values", "")
409 if secret_values:
410 items = {
411 "secrets": [
412 {
413 "name": f"ref-secret-{ksu_name}",
414 "namespace": "osm-workflows",
415 }
416 ]
417 }
418 await self.clean_items(items)
419 return True, "OK"
420 except Exception as e:
421 return False, f"Error while cleaning items: {e}"
422
423
424async def clean_items_ksu_update(self, op_id, op_params_list, content_list):
garciadeblasd8429852024-10-17 15:30:30 +0200425 self.logger.info(
garciadeblas9e532812024-10-22 14:04:36 +0200426 f"clean_items_ksu_update Enter. Operation {op_id}. Params: {op_params_list}"
garciadeblasd8429852024-10-17 15:30:30 +0200427 )
garciadeblas9e532812024-10-22 14:04:36 +0200428 # self.logger.debug(f"Content: {content_list}")
garciadeblasd8429852024-10-17 15:30:30 +0200429 return await self.clean_items_ksu_create(op_id, op_params_list, content_list)
garciadeblasc1c67892025-02-21 10:15:49 +0100430
431
432async def clean_items_ksu_delete(self, op_id, op_params_list, content_list):
433 self.logger.info(
434 f"clean_items_ksu_delete Enter. Operation {op_id}. Params: {op_params_list}"
435 )
436 # self.logger.debug(f"Content: {content_list}")
437 return True, "OK"