blob: e7c2f82d4fe6d6e5575a24c7157a5d5a4d15026e [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 ]
garciadeblas29f8bcf2025-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")
garciadeblas167dde32025-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")
garciadeblas6347c8a2025-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", {})
garciadeblas58a6aee2025-12-18 12:14:58 +010070 if custom_env_vars is None:
71 custom_env_vars = {}
garciadeblas6347c8a2025-01-17 01:29:37 +010072 if "APPNAME" not in custom_env_vars:
73 custom_env_vars["APPNAME"] = ksu_name
74 if "TARGET_NS" not in custom_env_vars:
75 custom_env_vars["TARGET_NS"] = target_ns
garciadeblas167dde32025-02-14 00:44:58 +010076 if "KUSTOMIZATION_NS" not in custom_env_vars:
77 custom_env_vars["KUSTOMIZATION_NS"] = kustomization_ns
garciadeblas6347c8a2025-01-17 01:29:37 +010078 custom_env_vars_str = "|\n"
79 substitution_filter_list = []
80 for k, v in custom_env_vars.items():
81 custom_env_vars_str += " " * 10 + f"{k}={v}\n"
82 substitution_filter_list.append(f"${k}")
83 substitution_filter = ",".join(substitution_filter_list)
84 # TODO: add additional substitution filters
85 # substitution_filter = (
86 # f"{substitution_filter},{oka_params.get('substitution_filter', '')}".strip(",")
87 # )
garciadeblas1b2933c2024-10-16 11:43:36 +020088 inline_values = oka_params.get("inline_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +020089 if inline_values:
90 yaml_string = yaml.safe_dump(
91 inline_values, sort_keys=False, default_flow_style=False
92 )
93 inline_values = "|\n" + "\n".join(
94 [" " * 8 + line for line in yaml_string.splitlines()]
95 )
garciadeblasf7dfdb72024-09-25 12:15:40 +020096 else:
97 inline_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +020098 is_preexisting_cm = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +020099 cm_values = oka_params.get("configmap_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200100 if cm_values:
101 yaml_string = yaml.safe_dump(
102 cm_values, sort_keys=False, default_flow_style=False
103 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200104 cm_values = "|\n" + "\n".join(
garciadeblas96b94f52024-07-08 16:18:21 +0200105 [" " * 8 + line for line in yaml_string.splitlines()]
106 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200107 values_configmap_name = f"cm-{ksu_name}"
108 cm_key = "values.yaml"
109 else:
110 values_configmap_name = ""
111 cm_key = ""
112 cm_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +0200113 is_preexisting_secret = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +0200114 secret_values = oka_params.get("secret_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200115 if secret_values:
116 values_secret_name = f"secret-{ksu_name}"
117 reference_secret_for_values = f"ref-secret-{ksu_name}"
118 reference_key_for_values = f"ref-key-{ksu_name}"
119 secret_values = yaml.safe_dump(
120 secret_values, sort_keys=False, default_flow_style=False
121 )
122 else:
123 values_secret_name = ""
garciadeblasf7dfdb72024-09-25 12:15:40 +0200124 reference_secret_for_values = "this-secret-does-not-exist"
125 reference_key_for_values = "this-key-does-not-exist"
garciadeblas96b94f52024-07-08 16:18:21 +0200126 sync = "true"
127
128 if secret_values:
129 secret_namespace = "osm-workflows"
130 # Create secret
131 await self.create_secret(
132 reference_secret_for_values,
133 secret_namespace,
134 reference_key_for_values,
135 secret_values,
136 )
137
138 # Render workflow
139 manifest = self.render_jinja_template(
140 workflow_template,
141 output_file=None,
142 workflow_name=workflow_name,
garciadeblas56c3aa82025-05-26 15:29:46 +0200143 git_fleet_url=self._repo_fleet_url,
144 git_sw_catalogs_url=self._repo_sw_catalogs_url,
garciadeblas96b94f52024-07-08 16:18:21 +0200145 templates_path=oka_path,
146 substitute_environment=substitute_environment,
147 substitution_filter=substitution_filter,
garciadeblas6347c8a2025-01-17 01:29:37 +0100148 custom_env_vars=custom_env_vars_str,
garciadeblas96b94f52024-07-08 16:18:21 +0200149 kustomization_name=kustomization_name,
150 helmrelease_name=helmrelease_name,
151 inline_values=inline_values,
152 is_preexisting_secret=is_preexisting_secret,
153 target_ns=target_ns,
154 age_public_key=age_public_key,
155 values_secret_name=values_secret_name,
156 reference_secret_for_values=reference_secret_for_values,
157 reference_key_for_values=reference_key_for_values,
158 is_preexisting_cm=is_preexisting_cm,
159 values_configmap_name=values_configmap_name,
garciadeblasf7dfdb72024-09-25 12:15:40 +0200160 cm_key=cm_key,
garciadeblas96b94f52024-07-08 16:18:21 +0200161 cm_values=cm_values,
162 ksu_name=ksu_name,
163 profile_name=profile_name,
164 profile_type=profile_type,
165 osm_project_name=osm_project_name,
166 sync=sync,
167 workflow_debug=self._workflow_debug,
168 workflow_dry_run=self._workflow_dry_run,
169 )
170 self.logger.debug(f"Workflow manifest: {manifest}")
171
172 # Submit workflow
173 self._kubectl.create_generic_object(
174 namespace="osm-workflows",
175 manifest_dict=yaml.safe_load(manifest),
176 api_group="argoproj.io",
177 api_plural="workflows",
178 api_version="v1alpha1",
179 )
garciadeblasadb81e82024-11-08 01:11:46 +0100180 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200181
182
183async def update_ksus(self, op_id, op_params_list, content_list):
garciadeblas9e532812024-10-22 14:04:36 +0200184 self.logger.info(f"update_ksus Enter. Operation {op_id}. Params: {op_params_list}")
185 # self.logger.debug(f"Content: {content_list}")
garciadeblas96b94f52024-07-08 16:18:21 +0200186
187 if len(content_list) > 1:
188 raise Exception("There is no ODU workflow yet able to manage multiple KSUs")
189 db_ksu = content_list[0]
190 ksu_params = op_params_list[0]
191 oka_list = ksu_params["oka"]
192 if len(oka_list) > 1:
193 raise Exception(
194 "There is no ODU workflow yet able to manage multiple OKAs for a KSU"
195 )
garciadeblas1b2933c2024-10-16 11:43:36 +0200196 oka_item = oka_list[0]
197 oka_params = oka_item.get("transformation", {})
198 if "sw_catalog_path" in oka_item:
199 oka_path = oka_item["sw_catalog_path"]
200 else:
garciadeblasa897d122024-12-09 13:31:06 +0100201 oka_type = MAP_PROFILE[
202 oka_item.get("profile_type", "infra_controller_profiles")
203 ]
garciadeblas29f8bcf2025-01-24 14:24:41 +0100204 oka_name = oka_item["git_name"].lower()
garciadeblas1b2933c2024-10-16 11:43:36 +0200205 oka_path = f"{oka_type}/{oka_name}/templates"
garciadeblas96b94f52024-07-08 16:18:21 +0200206
207 workflow_template = "launcher-update-ksu-hr.j2"
208 workflow_name = f"update-ksus-{op_id}"
209 ksu_name = db_ksu["git_name"].lower()
210
211 # Additional params for the workflow
212 osm_project_name = "osm_admin" # TODO: get project name from db_ksu
213 kustomization_name = ksu_name
214 helmrelease_name = ksu_name
garciadeblas96b94f52024-07-08 16:18:21 +0200215 profile_type = ksu_params.get("profile", {}).get("profile_type")
garciadeblasf7dfdb72024-09-25 12:15:40 +0200216 profile_type = MAP_PROFILE[profile_type]
garciadeblas96b94f52024-07-08 16:18:21 +0200217 profile_name = ksu_params.get("profile", {}).get("name")
218 age_public_key = ksu_params.get("profile", {}).get("age_pubkey")
garciadeblas167dde32025-02-14 00:44:58 +0100219 kustomization_ns = oka_params.get("kustomization_namespace", "flux-system")
garciadeblas1b2933c2024-10-16 11:43:36 +0200220 target_ns = oka_params.get("namespace", "default")
garciadeblas6347c8a2025-01-17 01:29:37 +0100221 substitute_environment = oka_params.get("substitute_environment", "true").lower()
222 custom_env_vars = oka_params.get("custom_env_vars", {})
garciadeblas58a6aee2025-12-18 12:14:58 +0100223 if custom_env_vars is None:
224 custom_env_vars = {}
garciadeblas6347c8a2025-01-17 01:29:37 +0100225 if "APPNAME" not in custom_env_vars:
226 custom_env_vars["APPNAME"] = ksu_name
227 if "TARGET_NS" not in custom_env_vars:
228 custom_env_vars["TARGET_NS"] = target_ns
garciadeblas167dde32025-02-14 00:44:58 +0100229 if "KUSTOMIZATION_NS" not in custom_env_vars:
230 custom_env_vars["KUSTOMIZATION_NS"] = kustomization_ns
garciadeblas6347c8a2025-01-17 01:29:37 +0100231 custom_env_vars_str = "|\n"
232 substitution_filter_list = []
233 for k, v in custom_env_vars.items():
234 custom_env_vars_str += " " * 10 + f"{k}={v}\n"
235 substitution_filter_list.append(f"${k}")
236 substitution_filter = ",".join(substitution_filter_list)
237 # TODO: add additional substitution filters
238 # substitution_filter = (
239 # f"{substitution_filter},{oka_params.get('substitution_filter', '')}".strip(",")
240 # )
garciadeblas1b2933c2024-10-16 11:43:36 +0200241 inline_values = oka_params.get("inline_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200242 if inline_values:
243 yaml_string = yaml.safe_dump(
244 inline_values, sort_keys=False, default_flow_style=False
245 )
246 inline_values = "|\n" + "\n".join(
247 [" " * 8 + line for line in yaml_string.splitlines()]
248 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200249 else:
250 inline_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +0200251 is_preexisting_cm = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +0200252 cm_values = oka_params.get("configmap_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200253 if cm_values:
254 yaml_string = yaml.safe_dump(
255 cm_values, sort_keys=False, default_flow_style=False
256 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200257 cm_values = "|\n" + "\n".join(
garciadeblas96b94f52024-07-08 16:18:21 +0200258 [" " * 8 + line for line in yaml_string.splitlines()]
259 )
garciadeblasf7dfdb72024-09-25 12:15:40 +0200260 values_configmap_name = f"cm-{ksu_name}"
261 cm_key = "values.yaml"
262 else:
263 values_configmap_name = ""
264 cm_key = ""
265 cm_values = '""'
garciadeblas96b94f52024-07-08 16:18:21 +0200266 is_preexisting_secret = "false"
garciadeblas1b2933c2024-10-16 11:43:36 +0200267 secret_values = oka_params.get("secret_values", "")
garciadeblas96b94f52024-07-08 16:18:21 +0200268 if secret_values:
269 values_secret_name = f"secret-{ksu_name}"
270 reference_secret_for_values = f"ref-secret-{ksu_name}"
271 reference_key_for_values = f"ref-key-{ksu_name}"
272 secret_values = yaml.safe_dump(
273 secret_values, sort_keys=False, default_flow_style=False
274 )
275 else:
276 values_secret_name = ""
garciadeblasf7dfdb72024-09-25 12:15:40 +0200277 reference_secret_for_values = "this-secret-does-not-exist"
278 reference_key_for_values = "this-key-does-not-exist"
garciadeblas96b94f52024-07-08 16:18:21 +0200279
280 if secret_values:
281 secret_namespace = "osm-workflows"
282 # Create secret
283 await self.create_secret(
284 reference_secret_for_values,
285 secret_namespace,
286 reference_key_for_values,
287 secret_values,
288 )
289
290 # Render workflow
291 manifest = self.render_jinja_template(
292 workflow_template,
293 output_file=None,
294 workflow_name=workflow_name,
garciadeblas56c3aa82025-05-26 15:29:46 +0200295 git_fleet_url=self._repo_fleet_url,
296 git_sw_catalogs_url=self._repo_sw_catalogs_url,
garciadeblas96b94f52024-07-08 16:18:21 +0200297 templates_path=oka_path,
298 substitute_environment=substitute_environment,
299 substitution_filter=substitution_filter,
garciadeblas6347c8a2025-01-17 01:29:37 +0100300 custom_env_vars=custom_env_vars_str,
garciadeblas96b94f52024-07-08 16:18:21 +0200301 kustomization_name=kustomization_name,
302 helmrelease_name=helmrelease_name,
303 inline_values=inline_values,
304 is_preexisting_secret=is_preexisting_secret,
305 target_ns=target_ns,
306 age_public_key=age_public_key,
307 values_secret_name=values_secret_name,
308 reference_secret_for_values=reference_secret_for_values,
309 reference_key_for_values=reference_key_for_values,
310 is_preexisting_cm=is_preexisting_cm,
311 values_configmap_name=values_configmap_name,
garciadeblasf7dfdb72024-09-25 12:15:40 +0200312 cm_key=cm_key,
garciadeblas96b94f52024-07-08 16:18:21 +0200313 cm_values=cm_values,
314 ksu_name=ksu_name,
315 profile_name=profile_name,
316 profile_type=profile_type,
317 osm_project_name=osm_project_name,
318 workflow_debug=self._workflow_debug,
319 workflow_dry_run=self._workflow_dry_run,
320 )
321 self.logger.debug(f"Workflow manifest: {manifest}")
322
323 # Submit workflow
324 self._kubectl.create_generic_object(
325 namespace="osm-workflows",
326 manifest_dict=yaml.safe_load(manifest),
327 api_group="argoproj.io",
328 api_plural="workflows",
329 api_version="v1alpha1",
330 )
garciadeblasadb81e82024-11-08 01:11:46 +0100331 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200332
333
334async def delete_ksus(self, op_id, op_params_list, content_list):
garciadeblas9e532812024-10-22 14:04:36 +0200335 self.logger.info(f"delete_ksus Enter. Operation {op_id}. Params: {op_params_list}")
336 # self.logger.debug(f"Content: {content_list}")
garciadeblas96b94f52024-07-08 16:18:21 +0200337
338 if len(content_list) > 1:
339 raise Exception("There is no ODU workflow yet able to manage multiple KSUs")
340 db_ksu = content_list[0]
341 ksu_params = op_params_list[0]
342
343 workflow_template = "launcher-delete-ksu.j2"
344 workflow_name = f"delete-ksus-{op_id}"
345 ksu_name = db_ksu["git_name"].lower()
346
347 # Additional params for the workflow
348 osm_project_name = "osm_admin" # TODO: get project name from db_ksu
349 profile_name = ksu_params.get("profile", {}).get("name")
350 profile_type = ksu_params.get("profile", {}).get("profile_type")
garciadeblasf7dfdb72024-09-25 12:15:40 +0200351 profile_type = MAP_PROFILE[profile_type]
garciadeblas96b94f52024-07-08 16:18:21 +0200352
353 # Render workflow
354 manifest = self.render_jinja_template(
355 workflow_template,
356 output_file=None,
357 workflow_name=workflow_name,
garciadeblas56c3aa82025-05-26 15:29:46 +0200358 git_fleet_url=self._repo_fleet_url,
359 git_sw_catalogs_url=self._repo_sw_catalogs_url,
garciadeblas96b94f52024-07-08 16:18:21 +0200360 ksu_name=ksu_name,
361 profile_name=profile_name,
362 profile_type=profile_type,
363 osm_project_name=osm_project_name,
364 workflow_debug=self._workflow_debug,
365 workflow_dry_run=self._workflow_dry_run,
366 )
367 self.logger.debug(f"Workflow manifest: {manifest}")
368
369 # Submit workflow
370 self._kubectl.create_generic_object(
371 namespace="osm-workflows",
372 manifest_dict=yaml.safe_load(manifest),
373 api_group="argoproj.io",
374 api_plural="workflows",
375 api_version="v1alpha1",
376 )
garciadeblasadb81e82024-11-08 01:11:46 +0100377 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200378
379
380async def clone_ksu(self, op_id, op_params, content):
garciadeblas9e532812024-10-22 14:04:36 +0200381 self.logger.info(f"clone_ksu Enter. Operation {op_id}. Params: {op_params}")
382 # self.logger.debug(f"Content: {content}")
garciadeblas96b94f52024-07-08 16:18:21 +0200383 workflow_name = f"clone-ksu-{content['_id']}"
garciadeblasadb81e82024-11-08 01:11:46 +0100384 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200385
386
387async def move_ksu(self, op_id, op_params, content):
garciadeblas9e532812024-10-22 14:04:36 +0200388 self.logger.info(f"move_ksu Enter. Operation {op_id}. Params: {op_params}")
389 # self.logger.debug(f"Content: {content}")
garciadeblas96b94f52024-07-08 16:18:21 +0200390 workflow_name = f"move-ksu-{content['_id']}"
garciadeblasadb81e82024-11-08 01:11:46 +0100391 return True, workflow_name
garciadeblas96b94f52024-07-08 16:18:21 +0200392
393
garciadeblasd8429852024-10-17 15:30:30 +0200394async def clean_items_ksu_create(self, op_id, op_params_list, content_list):
garciadeblasd8429852024-10-17 15:30:30 +0200395 self.logger.info(
garciadeblas9e532812024-10-22 14:04:36 +0200396 f"clean_items_ksu_create Enter. Operation {op_id}. Params: {op_params_list}"
garciadeblasd8429852024-10-17 15:30:30 +0200397 )
garciadeblas9e532812024-10-22 14:04:36 +0200398 # self.logger.debug(f"Content: {content_list}")
garciadeblasd8429852024-10-17 15:30:30 +0200399 try:
400 if len(content_list) > 1:
401 raise Exception("There is no ODU workflow yet able to manage multiple KSUs")
402 db_ksu = content_list[0]
403 ksu_name = db_ksu["git_name"].lower()
404 ksu_params = op_params_list[0]
405 oka_list = ksu_params["oka"]
406 if len(oka_list) > 1:
407 raise Exception(
408 "There is no ODU workflow yet able to manage multiple OKAs for a KSU"
409 )
410 oka_item = oka_list[0]
411 oka_params = oka_item.get("transformation", {})
412 secret_values = oka_params.get("secret_values", "")
413 if secret_values:
414 items = {
415 "secrets": [
416 {
417 "name": f"ref-secret-{ksu_name}",
418 "namespace": "osm-workflows",
419 }
420 ]
421 }
422 await self.clean_items(items)
423 return True, "OK"
424 except Exception as e:
425 return False, f"Error while cleaning items: {e}"
426
427
428async def clean_items_ksu_update(self, op_id, op_params_list, content_list):
garciadeblasd8429852024-10-17 15:30:30 +0200429 self.logger.info(
garciadeblas9e532812024-10-22 14:04:36 +0200430 f"clean_items_ksu_update Enter. Operation {op_id}. Params: {op_params_list}"
garciadeblasd8429852024-10-17 15:30:30 +0200431 )
garciadeblas9e532812024-10-22 14:04:36 +0200432 # self.logger.debug(f"Content: {content_list}")
garciadeblasd8429852024-10-17 15:30:30 +0200433 return await self.clean_items_ksu_create(op_id, op_params_list, content_list)
garciadeblasb23d2dc2025-02-21 10:15:49 +0100434
435
436async def clean_items_ksu_delete(self, op_id, op_params_list, content_list):
437 self.logger.info(
438 f"clean_items_ksu_delete Enter. Operation {op_id}. Params: {op_params_list}"
439 )
440 # self.logger.debug(f"Content: {content_list}")
441 return True, "OK"