401794606b839f68f291f9e22d193d9741b03771
[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 @Component
69 public class InstantiateDeploymentItemTask extends AbstractServiceTask {
70
71     private static final Logger logger = LoggerFactory.getLogger(InstantiateDeploymentItemTask.class);
72
73     private static final String KUBERNETES_RESOURCES_PARAM_NAME = "kubernetesResources";
74
75     private static final String IS_SUCCESSFUL_PARAM_NAME = "isSuccessful";
76     private static final String INSTANTIATE_REQUEST_PARAM_NAME = "request";
77
78     private final AaiServiceProvider aaiServiceProvider;
79     private final HelmClient helmClient;
80     private final KubernetesClientProvider kubernetesClientProvider;
81     private final KubernetesClient kubernetesClient;
82
83     @Autowired
84     protected InstantiateDeploymentItemTask(final DatabaseServiceProvider databaseServiceProvider,
85             final AaiServiceProvider aaiServiceProvider, final HelmClient helmClient,
86             final KubernetesClientProvider kubernetesClientProvider, final KubernetesClient kubernetesClient) {
87         super(databaseServiceProvider);
88         this.aaiServiceProvider = aaiServiceProvider;
89         this.helmClient = helmClient;
90         this.kubernetesClientProvider = kubernetesClientProvider;
91         this.kubernetesClient = kubernetesClient;
92     }
93
94     public void checkIfDeploymentItemExistsInDb(final DelegateExecution execution) {
95         logger.info("Executing checkIfDeploymentItemExistsInDb");
96         final InstantiateDeploymentItemRequest request =
97                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
98         logger.info("Instantiate request: {}", request);
99
100         final String asDeploymentItemInstId = request.getAsDeploymentItemInstId();
101         addJobStatus(execution, JobStatusEnum.IN_PROGRESS,
102                 "Checking if Deployment item record exists in database for asDeploymentItemInstId: "
103                         + asDeploymentItemInstId);
104
105         if (!databaseServiceProvider.isAsDeploymentItemExists(request.getAsDeploymentItemInstId())) {
106             abortOperation(execution, "Deployment Item does not exists in database for asDeploymentItemInstId: "
107                     + asDeploymentItemInstId);
108         }
109
110         logger.info("Finished executing checkIfDeploymentItemExistsInDb  ...");
111
112     }
113
114     public void createVfModuleInAai(final DelegateExecution execution) {
115         logger.info("Executing createVfModuleInAai  ...");
116         try {
117             final InstantiateDeploymentItemRequest request =
118                     (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
119
120             setJobStatus(execution, JobStatusEnum.IN_PROGRESS,
121                     "Creating Vf Module Instance in AAI for " + request.getAsDeploymentItemInstId());
122
123             final String asDeploymentItemInstId = request.getAsDeploymentItemInstId();
124
125             final VfModule vfModule = new VfModule();
126             vfModule.setVfModuleId(asDeploymentItemInstId);
127             vfModule.setVfModuleName(request.getAsDeploymentItemName());
128             vfModule.setIsBaseVfModule(true);
129             vfModule.setAutomatedAssignment(true);
130             vfModule.setOrchestrationStatus("Created");
131
132             aaiServiceProvider.createVfModule(request.getAsInstId(), asDeploymentItemInstId, vfModule);
133
134         } catch (final Exception exception) {
135             final String message = "Unable to Create Vf Module Instance in AAI";
136             logger.error(message, exception);
137             abortOperation(execution, message);
138         }
139         logger.info("Finished executing createVfModuleInAai  ...");
140
141     }
142
143     public void updateDeploymentItemStatusToInstantiated(final DelegateExecution execution) {
144         logger.info("Executing updateDeploymentItemStatusToInstantiated");
145         final InstantiateDeploymentItemRequest request =
146                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
147
148         updateDeploymentItemStatus(execution, request.getAsDeploymentItemInstId(), State.INSTANTIATED);
149
150         addJobStatus(execution, JobStatusEnum.FINISHED, "Successfully Instantiated Deployment Item: "
151                 + request.getAsDeploymentItemName() + " will set status to " + State.INSTANTIATED);
152
153         logger.info("Finished executing updateDeploymentItemStatusToInstantiated  ...");
154
155     }
156
157
158     public void runHelmInstallDryRun(final DelegateExecution execution) {
159         logger.info("Executing runHelmInstallDryRun");
160         final InstantiateDeploymentItemRequest request =
161                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
162
163         final String releaseName = request.getReleaseName();
164
165         try {
166             final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile());
167             final Path helmChartPath = Paths.get(request.getHelmArtifactFilePath());
168
169             logger.debug("Running helm install with dry run flag");
170             helmClient.runHelmChartInstallWithDryRunFlag(releaseName, kubeConfigFilePath, helmChartPath);
171         } catch (final Exception exception) {
172             final String message = "Unable to run helm install with dry run flag";
173             logger.error(message, exception);
174             abortOperation(execution, message);
175         }
176         logger.info("Finished executing runHelmInstallDryRun  ...");
177
178     }
179
180     public void retrieveKubeKinds(final DelegateExecution execution) {
181         logger.info("Executing retrieveKubeKinds");
182
183         final InstantiateDeploymentItemRequest request =
184                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
185
186         try {
187             final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile());
188             final Path helmChartPath = Paths.get(request.getHelmArtifactFilePath());
189             final String releaseName = request.getReleaseName();
190             final List<String> kubeKinds = helmClient.getKubeKinds(releaseName, kubeConfigFilePath, helmChartPath);
191
192             if (kubeKinds.isEmpty()) {
193                 abortOperation(execution,
194                         "Unable to retrieve kinds from chart / charts doesn't contains kinds: " + helmChartPath);
195             }
196
197             execution.setVariable(AS_DEPLOYMENT_ITEM_INST_ID_PARAM_NAME, request.getAsDeploymentItemInstId());
198             execution.setVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME, request.getKubeConfigFile());
199             execution.setVariable(KUBE_KINDS_PARAM_NAME, kubeKinds);
200
201             final Map<String, Boolean> result = new HashMap<>();
202             kubeKinds.forEach(kind -> result.put(kind, false));
203
204             execution.setVariable(KUBE_KINDS_RESULT_PARAM_NAME, result);
205         } catch (final BpmnError bpmnError) {
206             throw bpmnError;
207         } catch (final Exception exception) {
208             final String message = "Unable to retrieve kube kinds";
209             logger.error(message, exception);
210             abortOperation(execution, message);
211         }
212         logger.info("Finished executing retrieveKubeKinds  ...");
213
214     }
215
216     public void instantiateHelmChart(final DelegateExecution execution) {
217         logger.info("Executing instantiateHelmChart");
218
219         final InstantiateDeploymentItemRequest request =
220                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
221         final String releaseName = request.getReleaseName();
222         execution.setVariable(RELEASE_NAME_PARAM_NAME, releaseName);
223         try {
224             final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile());
225             final Path helmChartPath = Paths.get(request.getHelmArtifactFilePath());
226             final Map<String, String> lifeCycleParams = request.getLifeCycleParameters();
227
228             helmClient.installHelmChart(releaseName, kubeConfigFilePath, helmChartPath, lifeCycleParams);
229         } catch (final Exception exception) {
230             final String message = "Unable to install helm chart: " + request.getHelmArtifactFilePath()
231                     + " using kube-config file: " + request.getKubeConfigFile();
232             logger.error(message, exception);
233             abortOperation(execution, message);
234         }
235         logger.info("Finished executing instantiateHelmChart  ...");
236
237     }
238
239     public void checkIfHelmInstallWasSuccessful(final DelegateExecution execution) {
240         logger.info("Executing checkIfHelmInstallWasSuccessful");
241
242         @SuppressWarnings("unchecked")
243         final Map<String, Boolean> kubeKindResult =
244                 (Map<String, Boolean>) execution.getVariable(KUBE_KINDS_RESULT_PARAM_NAME);
245
246         execution.setVariable(IS_SUCCESSFUL_PARAM_NAME, true);
247
248         kubeKindResult.entrySet().forEach(entry -> {
249             logger.info("Checking if resource type {} was successfull Status: {}", entry.getKey(), entry.getValue());
250
251             if (Boolean.FALSE.equals(entry.getValue())) {
252                 logger.error("resource type {} failed", entry.getKey());
253                 execution.setVariable(IS_SUCCESSFUL_PARAM_NAME, false);
254             }
255         });
256
257         final String kubeConfigFile = (String) execution.getVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME);
258         kubernetesClientProvider.closeApiClient(kubeConfigFile);
259
260         logger.info("Finished executing checkIfHelmInstallWasSuccessful  ...");
261
262     }
263
264     public void retrieveKubernetesResources(final DelegateExecution execution) {
265         logger.info("Executing retrieveKubernetesResources");
266         final String releaseName = (String) execution.getVariable(RELEASE_NAME_PARAM_NAME);
267         final String kubeConfigFile = (String) execution.getVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME);
268         @SuppressWarnings("unchecked")
269         final List<String> kubeKinds = (List<String>) execution.getVariable(KUBE_KINDS_PARAM_NAME);
270
271         final String labelSelector = "app.kubernetes.io/instance=" + releaseName;
272
273         if (kubeKinds != null) {
274             final List<KubernetesResource> resources = new ArrayList<>();
275             kubeKinds.forEach(kind -> {
276                 try {
277                     final ApiClient apiClient = kubernetesClientProvider.getApiClient(kubeConfigFile);
278                     logger.debug("Will check if resource type: {} is ready using labelSelector: {}", kind,
279                             labelSelector);
280                     switch (kind) {
281                         case KIND_JOB:
282                             resources.addAll(kubernetesClient.getJobResources(apiClient, labelSelector));
283                             break;
284                         case KIND_POD:
285                             resources.addAll(kubernetesClient.getPodResources(apiClient, labelSelector));
286                             break;
287                         case KIND_SERVICE:
288                             resources.addAll(kubernetesClient.getServiceResources(apiClient, labelSelector));
289                             break;
290                         case KIND_DEPLOYMENT:
291                             resources.addAll(kubernetesClient.getDeploymentResources(apiClient, labelSelector));
292                             break;
293                         case KIND_REPLICA_SET:
294                             resources.addAll(kubernetesClient.getReplicaSetResources(apiClient, labelSelector));
295                             break;
296                         case KIND_DAEMON_SET:
297                             resources.addAll(kubernetesClient.getDaemonSetResources(apiClient, labelSelector));
298                             break;
299                         case KIND_STATEFUL_SET:
300                             resources.addAll(kubernetesClient.getStatefulSetResources(apiClient, labelSelector));
301                             break;
302                         default:
303                             logger.warn("Unknown resource type {} found skipping it ...", kind);
304                             break;
305                     }
306                 } catch (final Exception exception) {
307                     final String message = "Unable to query kubernetes for resource " + kind;
308                     logger.error(message, exception);
309                     abortOperation(execution, message);
310                 }
311             });
312             logger.debug("Found resources : {}", resources);
313
314             execution.setVariable(KUBERNETES_RESOURCES_PARAM_NAME, resources);
315
316         }
317
318         logger.info("Finished executing retrieveKubernetesResources  ...");
319
320     }
321
322     public void createK8sResourcesInAai(final DelegateExecution execution) {
323         logger.info("Executing createK8sResourcesInAai");
324         @SuppressWarnings("unchecked")
325         final List<KubernetesResource> resources =
326                 (List<KubernetesResource>) execution.getVariable(KUBERNETES_RESOURCES_PARAM_NAME);
327         if (resources == null) {
328             abortOperation(execution, "resources cannot be null");
329         }
330         final InstantiateDeploymentItemRequest request =
331                 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
332
333         setJobStatus(execution, JobStatusEnum.IN_PROGRESS,
334                 "Creating K8s Resource in AAI for " + request.getAsDeploymentItemInstId());
335
336         final AsInst asInst = getAsInst(execution);
337
338         resources.forEach(kubernetesResource -> {
339             try {
340                 final K8SResource k8sResource = new K8SResource();
341                 k8sResource.setId(kubernetesResource.getId());
342                 k8sResource.setName(kubernetesResource.getName());
343                 k8sResource.setGroup(kubernetesResource.getGroup());
344                 k8sResource.setVersion(kubernetesResource.getVersion());
345                 k8sResource.setKind(kubernetesResource.getKind());
346                 k8sResource.setNamespace(kubernetesResource.getNamespace());
347                 k8sResource.setDataSourceVersion(kubernetesResource.getResourceVersion());
348
349                 k8sResource.getLabels().addAll(kubernetesResource.getLabels());
350
351                 k8sResource.setDataOwner("so-cnfm");
352                 k8sResource.setDataSource("kubernetes");
353                 k8sResource.setSelflink("http://so-cnfm-lcm.onap:9888/query/");
354
355                 aaiServiceProvider.createK8sResource(kubernetesResource.getId(), asInst.getCloudOwner(),
356                         asInst.getCloudRegion(), asInst.getTenantId(), k8sResource);
357
358                 aaiServiceProvider.connectK8sResourceToVfModule(kubernetesResource.getId(), asInst.getCloudOwner(),
359                         asInst.getCloudRegion(), asInst.getTenantId(), request.getAsInstId(),
360                         request.getAsDeploymentItemInstId());
361
362                 aaiServiceProvider.connectK8sResourceToGenericVnf(kubernetesResource.getId(), asInst.getCloudOwner(),
363                         asInst.getCloudRegion(), asInst.getTenantId(), request.getAsInstId());
364
365
366             } catch (final Exception exception) {
367                 final String message = "Unable to Create K8s Resource in AAI for " + kubernetesResource;
368                 logger.error(message, exception);
369                 abortOperation(execution, message);
370             }
371         });
372
373         logger.info("Finished executing createK8sResourcesInAai  ...");
374
375     }
376
377     public void logTimeOut(final DelegateExecution execution) {
378         logger.error("Checking helm install status timedOut ...");
379
380         @SuppressWarnings("unchecked")
381         final Map<String, Boolean> kubeKindResult =
382                 (Map<String, Boolean>) execution.getVariable(KUBE_KINDS_RESULT_PARAM_NAME);
383
384         if (kubeKindResult != null) {
385             kubeKindResult.entrySet().forEach(
386                     entry -> logger.info("Current status {} of resource type: {}", entry.getValue(), entry.getKey()));
387         }
388
389         final String asInstId = (String) execution.getVariable(AS_INSTANCE_ID_PARAM_NAME);
390         final List<AsDeploymentItem> asDeploymentItems =
391                 databaseServiceProvider.getAsDeploymentItemByAsInstId(asInstId);
392         if (asDeploymentItems != null) {
393             asDeploymentItems.stream()
394                     .forEach(asDeploymentItem -> logger.info("Current status {} of asDeploymentItem: {}",
395                             asDeploymentItem.getStatus(), asDeploymentItem.getName()));
396         }
397     }
398
399 }