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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.so.cnfm.lcm.bpmn.flows.tasks;
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;
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;
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;
65 * @author Waqas Ikram (waqas.ikram@est.tech)
70 public class InstantiateDeploymentItemTask extends AbstractServiceTask {
72 private static final Logger logger = LoggerFactory.getLogger(InstantiateDeploymentItemTask.class);
74 private static final String KUBERNETES_RESOURCES_PARAM_NAME = "kubernetesResources";
76 private static final String IS_SUCCESSFUL_PARAM_NAME = "isSuccessful";
77 private static final String INSTANTIATE_REQUEST_PARAM_NAME = "request";
79 private final AaiServiceProvider aaiServiceProvider;
80 private final HelmClient helmClient;
81 private final KubernetesClientProvider kubernetesClientProvider;
82 private final KubernetesClient kubernetesClient;
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;
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);
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);
106 if (!databaseServiceProvider.isAsDeploymentItemExists(request.getAsDeploymentItemInstId())) {
107 abortOperation(execution, "Deployment Item does not exists in database for asDeploymentItemInstId: "
108 + asDeploymentItemInstId);
111 logger.info("Finished executing checkIfDeploymentItemExistsInDb ...");
115 public void createVfModuleInAai(final DelegateExecution execution) {
116 logger.info("Executing createVfModuleInAai ...");
118 final InstantiateDeploymentItemRequest request =
119 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
121 setJobStatus(execution, JobStatusEnum.IN_PROGRESS,
122 "Creating Vf Module Instance in AAI for " + request.getAsDeploymentItemInstId());
124 final String asDeploymentItemInstId = request.getAsDeploymentItemInstId();
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");
133 aaiServiceProvider.createVfModule(request.getAsInstId(), asDeploymentItemInstId, vfModule);
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);
140 logger.info("Finished executing createVfModuleInAai ...");
144 public void updateDeploymentItemStatusToInstantiated(final DelegateExecution execution) {
145 logger.info("Executing updateDeploymentItemStatusToInstantiated");
146 final InstantiateDeploymentItemRequest request =
147 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
149 updateDeploymentItemStatus(execution, request.getAsDeploymentItemInstId(), State.INSTANTIATED);
151 addJobStatus(execution, JobStatusEnum.FINISHED, "Successfully Instantiated Deployment Item: "
152 + request.getAsDeploymentItemName() + " will set status to " + State.INSTANTIATED);
154 logger.info("Finished executing updateDeploymentItemStatusToInstantiated ...");
159 public void runHelmInstallDryRun(final DelegateExecution execution) {
160 logger.info("Executing runHelmInstallDryRun");
161 final InstantiateDeploymentItemRequest request =
162 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
164 final String releaseName = request.getReleaseName();
167 final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile());
168 final Path helmChartPath = Paths.get(request.getHelmArtifactFilePath());
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);
177 logger.info("Finished executing runHelmInstallDryRun ...");
181 public void retrieveKubeKinds(final DelegateExecution execution) {
182 logger.info("Executing retrieveKubeKinds");
184 final InstantiateDeploymentItemRequest request =
185 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
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);
193 if (kubeKinds.isEmpty()) {
194 abortOperation(execution,
195 "Unable to retrieve kinds from chart / charts doesn't contains kinds: " + helmChartPath);
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);
202 final Map<String, Boolean> result = new HashMap<>();
203 kubeKinds.forEach(kind -> {
204 result.put(kind, false);
207 execution.setVariable(KUBE_KINDS_RESULT_PARAM_NAME, result);
208 } catch (final BpmnError bpmnError) {
210 } catch (final Exception exception) {
211 final String message = "Unable to retrieve kube kinds";
212 logger.error(message, exception);
213 abortOperation(execution, message);
215 logger.info("Finished executing retrieveKubeKinds ...");
219 public void instantiateHelmChart(final DelegateExecution execution) {
220 logger.info("Executing instantiateHelmChart");
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);
227 final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile());
228 final Path helmChartPath = Paths.get(request.getHelmArtifactFilePath());
229 final Map<String, String> lifeCycleParams = request.getLifeCycleParameters();
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);
238 logger.info("Finished executing instantiateHelmChart ...");
242 public void checkIfHelmInstallWasSuccessful(final DelegateExecution execution) {
243 logger.info("Executing checkIfHelmInstallWasSuccessful");
245 @SuppressWarnings("unchecked")
246 final Map<String, Boolean> kubeKindResult =
247 (Map<String, Boolean>) execution.getVariable(KUBE_KINDS_RESULT_PARAM_NAME);
249 execution.setVariable(IS_SUCCESSFUL_PARAM_NAME, true);
251 kubeKindResult.entrySet().forEach(entry -> {
252 logger.info("Checking if resource type {} was successfull Status: {}", entry.getKey(), entry.getValue());
254 if (Boolean.FALSE.equals(entry.getValue())) {
255 logger.error("resource type {} failed", entry.getKey());
256 execution.setVariable(IS_SUCCESSFUL_PARAM_NAME, false);
260 final String kubeConfigFile = (String) execution.getVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME);
261 kubernetesClientProvider.closeApiClient(kubeConfigFile);
263 logger.info("Finished executing checkIfHelmInstallWasSuccessful ...");
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);
274 final String labelSelector = "app.kubernetes.io/instance=" + releaseName;
276 if (kubeKinds != null) {
277 final List<KubernetesResource> resources = new ArrayList<>();
278 kubeKinds.forEach(kind -> {
280 final ApiClient apiClient = kubernetesClientProvider.getApiClient(kubeConfigFile);
281 logger.debug("Will check if resource type: {} is ready using labelSelector: {}", kind,
285 resources.addAll(kubernetesClient.getJobResources(apiClient, labelSelector));
288 resources.addAll(kubernetesClient.getPodResources(apiClient, labelSelector));
291 resources.addAll(kubernetesClient.getServiceResources(apiClient, labelSelector));
293 case KIND_DEPLOYMENT:
294 resources.addAll(kubernetesClient.getDeploymentResources(apiClient, labelSelector));
296 case KIND_REPLICA_SET:
297 resources.addAll(kubernetesClient.getReplicaSetResources(apiClient, labelSelector));
299 case KIND_DAEMON_SET:
300 resources.addAll(kubernetesClient.getDaemonSetResources(apiClient, labelSelector));
302 case KIND_STATEFUL_SET:
303 resources.addAll(kubernetesClient.getStatefulSetResources(apiClient, labelSelector));
306 logger.warn("Unknown resource type {} setting {} skipping it", kind);
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);
315 logger.debug("Found resources : {}", resources);
317 execution.setVariable(KUBERNETES_RESOURCES_PARAM_NAME, resources);
321 logger.info("Finished executing retrieveKubernetesResources ...");
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");
333 final InstantiateDeploymentItemRequest request =
334 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
336 setJobStatus(execution, JobStatusEnum.IN_PROGRESS,
337 "Creating K8s Resource in AAI for " + request.getAsDeploymentItemInstId());
339 final AsInst asInst = getAsInst(execution);
341 resources.forEach(kubernetesResource -> {
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());
352 k8sResource.getLabels().addAll(kubernetesResource.getLabels());
354 k8sResource.setDataOwner("so-cnfm");
355 k8sResource.setDataSource("kubernetes");
356 k8sResource.setSelflink("http://so-cnfm-lcm.onap:9888/query/");
358 aaiServiceProvider.createK8sResource(kubernetesResource.getId(), asInst.getCloudOwner(),
359 asInst.getCloudRegion(), asInst.getTenantId(), k8sResource);
361 aaiServiceProvider.connectK8sResourceToVfModule(kubernetesResource.getId(), asInst.getCloudOwner(),
362 asInst.getCloudRegion(), asInst.getTenantId(), request.getAsInstId(),
363 request.getAsDeploymentItemInstId());
365 aaiServiceProvider.connectK8sResourceToGenericVnf(kubernetesResource.getId(), asInst.getCloudOwner(),
366 asInst.getCloudRegion(), asInst.getTenantId(), request.getAsInstId());
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);
377 logger.info("Finished executing createK8sResourcesInAai ...");
381 public void logTimeOut(final DelegateExecution execution) {
382 logger.error("Checking helm install status timedOut ...");
384 @SuppressWarnings("unchecked")
385 final Map<String, Boolean> kubeKindResult =
386 (Map<String, Boolean>) execution.getVariable(KUBE_KINDS_RESULT_PARAM_NAME);
388 if (kubeKindResult != null) {
389 kubeKindResult.entrySet().forEach(entry -> {
390 logger.info("Current status {} of resource type: {}", entry.getValue(), entry.getKey());
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());