a2cf9762a0acae12b2d2ab939f2f452f7f29fbbe
[so/adapters/so-cnf-adapter.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2023 Nordix Foundation.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.so.cnfm.lcm.bpmn.flows.tasks;
22
23 import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_DEPLOYMENT_ITEM_INST_ID_PARAM_NAME;
24 import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_INSTANCE_ID_PARAM_NAME;
25 import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.KUBE_CONFIG_FILE_PATH_PARAM_NAME;
26 import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.KUBE_KINDS_PARAM_NAME;
27 import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.KUBE_KINDS_RESULT_PARAM_NAME;
28 import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.RELEASE_NAME_PARAM_NAME;
29 import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_DAEMON_SET;
30 import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_DEPLOYMENT;
31 import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_JOB;
32 import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_POD;
33 import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_REPLICA_SET;
34 import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_SERVICE;
35 import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_STATEFUL_SET;
36
37 import io.kubernetes.client.openapi.ApiClient;
38 import java.nio.file.Path;
39 import java.nio.file.Paths;
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.List;
43 import java.util.Map;
44 import org.camunda.bpm.engine.delegate.BpmnError;
45 import org.camunda.bpm.engine.delegate.DelegateExecution;
46 import org.onap.aai.domain.yang.K8SResource;
47 import org.onap.aai.domain.yang.VfModule;
48 import org.onap.so.cnfm.lcm.bpmn.flows.extclients.aai.AaiServiceProvider;
49 import org.onap.so.cnfm.lcm.bpmn.flows.extclients.helm.HelmClient;
50 import org.onap.so.cnfm.lcm.bpmn.flows.extclients.kubernetes.KubernetesClient;
51 import org.onap.so.cnfm.lcm.bpmn.flows.extclients.kubernetes.KubernetesClientProvider;
52 import org.onap.so.cnfm.lcm.bpmn.flows.extclients.kubernetes.KubernetesResource;
53 import org.onap.so.cnfm.lcm.database.beans.AsDeploymentItem;
54 import org.onap.so.cnfm.lcm.database.beans.AsInst;
55 import org.onap.so.cnfm.lcm.database.beans.JobStatusEnum;
56 import org.onap.so.cnfm.lcm.database.beans.State;
57 import org.onap.so.cnfm.lcm.database.service.DatabaseServiceProvider;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60 import org.springframework.beans.factory.annotation.Autowired;
61 import org.springframework.stereotype.Component;
62
63 /**
64  *
65  * @author Waqas Ikram (waqas.ikram@est.tech)
66  *
67  */
68
69 @Component
70 public class InstantiateDeploymentItemTask extends AbstractServiceTask {
71
72     private static final Logger logger = LoggerFactory.getLogger(InstantiateDeploymentItemTask.class);
73
74     private static final String KUBERNETES_RESOURCES_PARAM_NAME = "kubernetesResources";
75
76     private static final String IS_SUCCESSFUL_PARAM_NAME = "isSuccessful";
77     private static final String INSTANTIATE_REQUEST_PARAM_NAME = "request";
78
79     private final AaiServiceProvider aaiServiceProvider;
80     private final HelmClient helmClient;
81     private final KubernetesClientProvider kubernetesClientProvider;
82     private final KubernetesClient kubernetesClient;
83
84     @Autowired
85     protected InstantiateDeploymentItemTask(final DatabaseServiceProvider databaseServiceProvider,
86             final AaiServiceProvider aaiServiceProvider, final HelmClient helmClient,
87             final KubernetesClientProvider kubernetesClientProvider, final KubernetesClient kubernetesClient) {
88         super(databaseServiceProvider);
89         this.aaiServiceProvider = aaiServiceProvider;
90         this.helmClient = helmClient;
91         this.kubernetesClientProvider = kubernetesClientProvider;
92         this.kubernetesClient = kubernetesClient;
93     }
94
95     public void checkIfDeploymentItemExistsInDb(final DelegateExecution execution) {
96         logger.info("Executing checkIfDeploymentItemExistsInDb");
97         final InstantiateDeploymentItemRequest request =
98                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
99         logger.info("Instantiate request: {}", request);
100
101         final String asDeploymentItemInstId = request.getAsDeploymentItemInstId();
102         addJobStatus(execution, JobStatusEnum.IN_PROGRESS,
103                 "Checking if Deployment item record exists in database for asDeploymentItemInstId: "
104                         + asDeploymentItemInstId);
105
106         if (!databaseServiceProvider.isAsDeploymentItemExists(request.getAsDeploymentItemInstId())) {
107             abortOperation(execution, "Deployment Item does not exists in database for asDeploymentItemInstId: "
108                     + asDeploymentItemInstId);
109         }
110
111         logger.info("Finished executing checkIfDeploymentItemExistsInDb  ...");
112
113     }
114
115     public void createVfModuleInAai(final DelegateExecution execution) {
116         logger.info("Executing createVfModuleInAai  ...");
117         try {
118             final InstantiateDeploymentItemRequest request =
119                     (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
120
121             setJobStatus(execution, JobStatusEnum.IN_PROGRESS,
122                     "Creating Vf Module Instance in AAI for " + request.getAsDeploymentItemInstId());
123
124             final String asDeploymentItemInstId = request.getAsDeploymentItemInstId();
125
126             final VfModule vfModule = new VfModule();
127             vfModule.setVfModuleId(asDeploymentItemInstId);
128             vfModule.setVfModuleName(request.getAsDeploymentItemName());
129             vfModule.setIsBaseVfModule(true);
130             vfModule.setAutomatedAssignment(true);
131             vfModule.setOrchestrationStatus("Created");
132
133             aaiServiceProvider.createVfModule(request.getAsInstId(), asDeploymentItemInstId, vfModule);
134
135         } catch (final Exception exception) {
136             final String message = "Unable to Create Vf Module Instance in AAI";
137             logger.error(message, exception);
138             abortOperation(execution, message);
139         }
140         logger.info("Finished executing createVfModuleInAai  ...");
141
142     }
143
144     public void updateDeploymentItemStatusToInstantiated(final DelegateExecution execution) {
145         logger.info("Executing updateDeploymentItemStatusToInstantiated");
146         final InstantiateDeploymentItemRequest request =
147                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
148
149         updateDeploymentItemStatus(execution, request.getAsDeploymentItemInstId(), State.INSTANTIATED);
150
151         addJobStatus(execution, JobStatusEnum.FINISHED, "Successfully Instantiated Deployment Item: "
152                 + request.getAsDeploymentItemName() + " will set status to " + State.INSTANTIATED);
153
154         logger.info("Finished executing updateDeploymentItemStatusToInstantiated  ...");
155
156     }
157
158
159     public void runHelmInstallDryRun(final DelegateExecution execution) {
160         logger.info("Executing runHelmInstallDryRun");
161         final InstantiateDeploymentItemRequest request =
162                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
163
164         final String releaseName = request.getReleaseName();
165
166         try {
167             final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile());
168             final Path helmChartPath = Paths.get(request.getHelmArtifactFilePath());
169
170             logger.debug("Running helm install with dry run flag");
171             helmClient.runHelmChartInstallWithDryRunFlag(releaseName, kubeConfigFilePath, helmChartPath);
172         } catch (final Exception exception) {
173             final String message = "Unable to run helm install with dry run flag";
174             logger.error(message, exception);
175             abortOperation(execution, message);
176         }
177         logger.info("Finished executing runHelmInstallDryRun  ...");
178
179     }
180
181     public void retrieveKubeKinds(final DelegateExecution execution) {
182         logger.info("Executing retrieveKubeKinds");
183
184         final InstantiateDeploymentItemRequest request =
185                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
186
187         try {
188             final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile());
189             final Path helmChartPath = Paths.get(request.getHelmArtifactFilePath());
190             final String releaseName = request.getReleaseName();
191             final List<String> kubeKinds = helmClient.getKubeKinds(releaseName, kubeConfigFilePath, helmChartPath);
192
193             if (kubeKinds.isEmpty()) {
194                 abortOperation(execution,
195                         "Unable to retrieve kinds from chart / charts doesn't contains kinds: " + helmChartPath);
196             }
197
198             execution.setVariable(AS_DEPLOYMENT_ITEM_INST_ID_PARAM_NAME, request.getAsDeploymentItemInstId());
199             execution.setVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME, request.getKubeConfigFile());
200             execution.setVariable(KUBE_KINDS_PARAM_NAME, kubeKinds);
201
202             final Map<String, Boolean> result = new HashMap<>();
203             kubeKinds.forEach(kind -> {
204                 result.put(kind, false);
205             });
206
207             execution.setVariable(KUBE_KINDS_RESULT_PARAM_NAME, result);
208         } catch (final BpmnError bpmnError) {
209             throw bpmnError;
210         } catch (final Exception exception) {
211             final String message = "Unable to retrieve kube kinds";
212             logger.error(message, exception);
213             abortOperation(execution, message);
214         }
215         logger.info("Finished executing retrieveKubeKinds  ...");
216
217     }
218
219     public void instantiateHelmChart(final DelegateExecution execution) {
220         logger.info("Executing instantiateHelmChart");
221
222         final InstantiateDeploymentItemRequest request =
223                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
224         final String releaseName = request.getReleaseName();
225         execution.setVariable(RELEASE_NAME_PARAM_NAME, releaseName);
226         try {
227             final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile());
228             final Path helmChartPath = Paths.get(request.getHelmArtifactFilePath());
229             final Map<String, String> lifeCycleParams = request.getLifeCycleParameters();
230
231             helmClient.installHelmChart(releaseName, kubeConfigFilePath, helmChartPath, lifeCycleParams);
232         } catch (final Exception exception) {
233             final String message = "Unable to install helm chart: " + request.getHelmArtifactFilePath()
234                     + " using kube-config file: " + request.getKubeConfigFile();
235             logger.error(message, exception);
236             abortOperation(execution, message);
237         }
238         logger.info("Finished executing instantiateHelmChart  ...");
239
240     }
241
242     public void checkIfHelmInstallWasSuccessful(final DelegateExecution execution) {
243         logger.info("Executing checkIfHelmInstallWasSuccessful");
244
245         @SuppressWarnings("unchecked")
246         final Map<String, Boolean> kubeKindResult =
247                 (Map<String, Boolean>) execution.getVariable(KUBE_KINDS_RESULT_PARAM_NAME);
248
249         execution.setVariable(IS_SUCCESSFUL_PARAM_NAME, true);
250
251         kubeKindResult.entrySet().forEach(entry -> {
252             logger.info("Checking if resource type {} was successfull Status: {}", entry.getKey(), entry.getValue());
253
254             if (Boolean.FALSE.equals(entry.getValue())) {
255                 logger.error("resource type {} failed", entry.getKey());
256                 execution.setVariable(IS_SUCCESSFUL_PARAM_NAME, false);
257             }
258         });
259
260         final String kubeConfigFile = (String) execution.getVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME);
261         kubernetesClientProvider.closeApiClient(kubeConfigFile);
262
263         logger.info("Finished executing checkIfHelmInstallWasSuccessful  ...");
264
265     }
266
267     public void retrieveKubernetesResources(final DelegateExecution execution) {
268         logger.info("Executing retrieveKubernetesResources");
269         final String releaseName = (String) execution.getVariable(RELEASE_NAME_PARAM_NAME);
270         final String kubeConfigFile = (String) execution.getVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME);
271         @SuppressWarnings("unchecked")
272         final List<String> kubeKinds = (List<String>) execution.getVariable(KUBE_KINDS_PARAM_NAME);
273
274         final String labelSelector = "app.kubernetes.io/instance=" + releaseName;
275
276         if (kubeKinds != null) {
277             final List<KubernetesResource> resources = new ArrayList<>();
278             kubeKinds.forEach(kind -> {
279                 try {
280                     final ApiClient apiClient = kubernetesClientProvider.getApiClient(kubeConfigFile);
281                     logger.debug("Will check if resource type: {} is ready using labelSelector: {}", kind,
282                             labelSelector);
283                     switch (kind) {
284                         case KIND_JOB:
285                             resources.addAll(kubernetesClient.getJobResources(apiClient, labelSelector));
286                             break;
287                         case KIND_POD:
288                             resources.addAll(kubernetesClient.getPodResources(apiClient, labelSelector));
289                             break;
290                         case KIND_SERVICE:
291                             resources.addAll(kubernetesClient.getServiceResources(apiClient, labelSelector));
292                             break;
293                         case KIND_DEPLOYMENT:
294                             resources.addAll(kubernetesClient.getDeploymentResources(apiClient, labelSelector));
295                             break;
296                         case KIND_REPLICA_SET:
297                             resources.addAll(kubernetesClient.getReplicaSetResources(apiClient, labelSelector));
298                             break;
299                         case KIND_DAEMON_SET:
300                             resources.addAll(kubernetesClient.getDaemonSetResources(apiClient, labelSelector));
301                             break;
302                         case KIND_STATEFUL_SET:
303                             resources.addAll(kubernetesClient.getStatefulSetResources(apiClient, labelSelector));
304                             break;
305                         default:
306                             logger.warn("Unknown resource type {} setting {} skipping it", kind);
307                             break;
308                     }
309                 } catch (final Exception exception) {
310                     final String message = "Unable to query kubernetes for resource " + kind;
311                     logger.error(message, exception);
312                     abortOperation(execution, message);
313                 }
314             });
315             logger.debug("Found resources : {}", resources);
316
317             execution.setVariable(KUBERNETES_RESOURCES_PARAM_NAME, resources);
318
319         }
320
321         logger.info("Finished executing retrieveKubernetesResources  ...");
322
323     }
324
325     public void createK8sResourcesInAai(final DelegateExecution execution) {
326         logger.info("Executing createK8sResourcesInAai");
327         @SuppressWarnings("unchecked")
328         final List<KubernetesResource> resources =
329                 (List<KubernetesResource>) execution.getVariable(KUBERNETES_RESOURCES_PARAM_NAME);
330         if (resources == null) {
331             abortOperation(execution, "resources cannot be null");
332         }
333         final InstantiateDeploymentItemRequest request =
334                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
335
336         setJobStatus(execution, JobStatusEnum.IN_PROGRESS,
337                 "Creating K8s Resource in AAI for " + request.getAsDeploymentItemInstId());
338
339         final AsInst asInst = getAsInst(execution);
340
341         resources.forEach(kubernetesResource -> {
342             try {
343                 final K8SResource k8sResource = new K8SResource();
344                 k8sResource.setId(kubernetesResource.getId());
345                 k8sResource.setName(kubernetesResource.getName());
346                 k8sResource.setGroup(kubernetesResource.getGroup());
347                 k8sResource.setVersion(kubernetesResource.getVersion());
348                 k8sResource.setKind(kubernetesResource.getKind());
349                 k8sResource.setNamespace(kubernetesResource.getNamespace());
350                 k8sResource.setDataSourceVersion(kubernetesResource.getResourceVersion());
351
352                 k8sResource.getLabels().addAll(kubernetesResource.getLabels());
353
354                 k8sResource.setDataOwner("so-cnfm");
355                 k8sResource.setDataSource("kubernetes");
356                 k8sResource.setSelflink("http://so-cnfm-lcm.onap:9888/query/");
357
358                 aaiServiceProvider.createK8sResource(kubernetesResource.getId(), asInst.getCloudOwner(),
359                         asInst.getCloudRegion(), asInst.getTenantId(), k8sResource);
360
361                 aaiServiceProvider.connectK8sResourceToVfModule(kubernetesResource.getId(), asInst.getCloudOwner(),
362                         asInst.getCloudRegion(), asInst.getTenantId(), request.getAsInstId(),
363                         request.getAsDeploymentItemInstId());
364
365                 aaiServiceProvider.connectK8sResourceToGenericVnf(kubernetesResource.getId(), asInst.getCloudOwner(),
366                         asInst.getCloudRegion(), asInst.getTenantId(), request.getAsInstId());
367
368
369             } catch (final Exception exception) {
370                 final String message = "Unable to Create K8s Resource in AAI for " + kubernetesResource;
371                 logger.error(message, exception);
372                 abortOperation(execution, message);
373             }
374         });
375
376
377         logger.info("Finished executing createK8sResourcesInAai  ...");
378
379     }
380
381     public void logTimeOut(final DelegateExecution execution) {
382         logger.error("Checking helm install status timedOut ...");
383
384         @SuppressWarnings("unchecked")
385         final Map<String, Boolean> kubeKindResult =
386                 (Map<String, Boolean>) execution.getVariable(KUBE_KINDS_RESULT_PARAM_NAME);
387
388         if (kubeKindResult != null) {
389             kubeKindResult.entrySet().forEach(entry -> {
390                 logger.info("Current status {} of resource type: {}", entry.getValue(), entry.getKey());
391             });
392         }
393
394
395         final String asInstId = (String) execution.getVariable(AS_INSTANCE_ID_PARAM_NAME);
396         final List<AsDeploymentItem> asDeploymentItems =
397                 databaseServiceProvider.getAsDeploymentItemByAsInstId(asInstId);
398         if (asDeploymentItems != null) {
399             asDeploymentItems.stream().forEach(asDeploymentItem -> {
400                 logger.info("Current status {} of asDeploymentItem: {}", asDeploymentItem.getStatus(),
401                         asDeploymentItem.getName());
402             });
403         }
404     }
405
406 }