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)
69 public class InstantiateDeploymentItemTask extends AbstractServiceTask {
71 private static final Logger logger = LoggerFactory.getLogger(InstantiateDeploymentItemTask.class);
73 private static final String KUBERNETES_RESOURCES_PARAM_NAME = "kubernetesResources";
75 private static final String IS_SUCCESSFUL_PARAM_NAME = "isSuccessful";
76 private static final String INSTANTIATE_REQUEST_PARAM_NAME = "request";
78 private final AaiServiceProvider aaiServiceProvider;
79 private final HelmClient helmClient;
80 private final KubernetesClientProvider kubernetesClientProvider;
81 private final KubernetesClient kubernetesClient;
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;
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);
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);
105 if (!databaseServiceProvider.isAsDeploymentItemExists(request.getAsDeploymentItemInstId())) {
106 abortOperation(execution, "Deployment Item does not exists in database for asDeploymentItemInstId: "
107 + asDeploymentItemInstId);
110 logger.info("Finished executing checkIfDeploymentItemExistsInDb ...");
114 public void createVfModuleInAai(final DelegateExecution execution) {
115 logger.info("Executing createVfModuleInAai ...");
117 final InstantiateDeploymentItemRequest request =
118 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
120 setJobStatus(execution, JobStatusEnum.IN_PROGRESS,
121 "Creating Vf Module Instance in AAI for " + request.getAsDeploymentItemInstId());
123 final String asDeploymentItemInstId = request.getAsDeploymentItemInstId();
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");
132 aaiServiceProvider.createVfModule(request.getAsInstId(), asDeploymentItemInstId, vfModule);
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);
139 logger.info("Finished executing createVfModuleInAai ...");
143 public void updateDeploymentItemStatusToInstantiated(final DelegateExecution execution) {
144 logger.info("Executing updateDeploymentItemStatusToInstantiated");
145 final InstantiateDeploymentItemRequest request =
146 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
148 updateDeploymentItemStatus(execution, request.getAsDeploymentItemInstId(), State.INSTANTIATED);
150 addJobStatus(execution, JobStatusEnum.FINISHED, "Successfully Instantiated Deployment Item: "
151 + request.getAsDeploymentItemName() + " will set status to " + State.INSTANTIATED);
153 logger.info("Finished executing updateDeploymentItemStatusToInstantiated ...");
158 public void runHelmInstallDryRun(final DelegateExecution execution) {
159 logger.info("Executing runHelmInstallDryRun");
160 final InstantiateDeploymentItemRequest request =
161 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
163 final String releaseName = request.getReleaseName();
166 final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile());
167 final Path helmChartPath = Paths.get(request.getHelmArtifactFilePath());
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);
176 logger.info("Finished executing runHelmInstallDryRun ...");
180 public void retrieveKubeKinds(final DelegateExecution execution) {
181 logger.info("Executing retrieveKubeKinds");
183 final InstantiateDeploymentItemRequest request =
184 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
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);
192 if (kubeKinds.isEmpty()) {
193 abortOperation(execution,
194 "Unable to retrieve kinds from chart / charts doesn't contains kinds: " + helmChartPath);
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);
201 final Map<String, Boolean> result = new HashMap<>();
202 kubeKinds.forEach(kind -> result.put(kind, false));
204 execution.setVariable(KUBE_KINDS_RESULT_PARAM_NAME, result);
205 } catch (final BpmnError bpmnError) {
207 } catch (final Exception exception) {
208 final String message = "Unable to retrieve kube kinds";
209 logger.error(message, exception);
210 abortOperation(execution, message);
212 logger.info("Finished executing retrieveKubeKinds ...");
216 public void instantiateHelmChart(final DelegateExecution execution) {
217 logger.info("Executing instantiateHelmChart");
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);
224 final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile());
225 final Path helmChartPath = Paths.get(request.getHelmArtifactFilePath());
226 final Map<String, String> lifeCycleParams = request.getLifeCycleParameters();
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);
235 logger.info("Finished executing instantiateHelmChart ...");
239 public void checkIfHelmInstallWasSuccessful(final DelegateExecution execution) {
240 logger.info("Executing checkIfHelmInstallWasSuccessful");
242 @SuppressWarnings("unchecked")
243 final Map<String, Boolean> kubeKindResult =
244 (Map<String, Boolean>) execution.getVariable(KUBE_KINDS_RESULT_PARAM_NAME);
246 execution.setVariable(IS_SUCCESSFUL_PARAM_NAME, true);
248 kubeKindResult.entrySet().forEach(entry -> {
249 logger.info("Checking if resource type {} was successfull Status: {}", entry.getKey(), entry.getValue());
251 if (Boolean.FALSE.equals(entry.getValue())) {
252 logger.error("resource type {} failed", entry.getKey());
253 execution.setVariable(IS_SUCCESSFUL_PARAM_NAME, false);
257 final String kubeConfigFile = (String) execution.getVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME);
258 kubernetesClientProvider.closeApiClient(kubeConfigFile);
260 logger.info("Finished executing checkIfHelmInstallWasSuccessful ...");
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);
271 final String labelSelector = "app.kubernetes.io/instance=" + releaseName;
273 if (kubeKinds != null) {
274 final List<KubernetesResource> resources = new ArrayList<>();
275 kubeKinds.forEach(kind -> {
277 final ApiClient apiClient = kubernetesClientProvider.getApiClient(kubeConfigFile);
278 logger.debug("Will check if resource type: {} is ready using labelSelector: {}", kind,
282 resources.addAll(kubernetesClient.getJobResources(apiClient, labelSelector));
285 resources.addAll(kubernetesClient.getPodResources(apiClient, labelSelector));
288 resources.addAll(kubernetesClient.getServiceResources(apiClient, labelSelector));
290 case KIND_DEPLOYMENT:
291 resources.addAll(kubernetesClient.getDeploymentResources(apiClient, labelSelector));
293 case KIND_REPLICA_SET:
294 resources.addAll(kubernetesClient.getReplicaSetResources(apiClient, labelSelector));
296 case KIND_DAEMON_SET:
297 resources.addAll(kubernetesClient.getDaemonSetResources(apiClient, labelSelector));
299 case KIND_STATEFUL_SET:
300 resources.addAll(kubernetesClient.getStatefulSetResources(apiClient, labelSelector));
303 logger.warn("Unknown resource type {} found skipping it ...", kind);
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);
312 logger.debug("Found resources : {}", resources);
314 execution.setVariable(KUBERNETES_RESOURCES_PARAM_NAME, resources);
318 logger.info("Finished executing retrieveKubernetesResources ...");
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");
330 final InstantiateDeploymentItemRequest request =
331 (InstantiateDeploymentItemRequest) execution.getVariable(INSTANTIATE_REQUEST_PARAM_NAME);
333 setJobStatus(execution, JobStatusEnum.IN_PROGRESS,
334 "Creating K8s Resource in AAI for " + request.getAsDeploymentItemInstId());
336 final AsInst asInst = getAsInst(execution);
338 resources.forEach(kubernetesResource -> {
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());
349 k8sResource.getLabels().addAll(kubernetesResource.getLabels());
351 k8sResource.setDataOwner("so-cnfm");
352 k8sResource.setDataSource("kubernetes");
353 k8sResource.setSelflink("http://so-cnfm-lcm.onap:9888/query/");
355 aaiServiceProvider.createK8sResource(kubernetesResource.getId(), asInst.getCloudOwner(),
356 asInst.getCloudRegion(), asInst.getTenantId(), k8sResource);
358 aaiServiceProvider.connectK8sResourceToVfModule(kubernetesResource.getId(), asInst.getCloudOwner(),
359 asInst.getCloudRegion(), asInst.getTenantId(), request.getAsInstId(),
360 request.getAsDeploymentItemInstId());
362 aaiServiceProvider.connectK8sResourceToGenericVnf(kubernetesResource.getId(), asInst.getCloudOwner(),
363 asInst.getCloudRegion(), asInst.getTenantId(), request.getAsInstId());
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);
373 logger.info("Finished executing createK8sResourcesInAai ...");
377 public void logTimeOut(final DelegateExecution execution) {
378 logger.error("Checking helm install status timedOut ...");
380 @SuppressWarnings("unchecked")
381 final Map<String, Boolean> kubeKindResult =
382 (Map<String, Boolean>) execution.getVariable(KUBE_KINDS_RESULT_PARAM_NAME);
384 if (kubeKindResult != null) {
385 kubeKindResult.entrySet().forEach(
386 entry -> logger.info("Current status {} of resource type: {}", entry.getValue(), entry.getKey()));
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()));