From 028954a29917555f9ba4099c372101fa20d27868 Mon Sep 17 00:00:00 2001 From: "waqas.ikram" Date: Tue, 7 Feb 2023 14:52:46 +0000 Subject: [PATCH] Adding Termination AS Change-Id: I200d007b6d36d9df6d6f891cb247bb4ec17bc78a Issue-ID: SO-4053 Signed-off-by: waqas.ikram --- .../kubernetes/KubernetesClientImpl.java | 14 +- .../tasks/MonitorHelmUnInstallStatusTask.java | 182 +++++++++++ .../cnfm/lcm/bpmn/flows/tasks/TerminateAsTask.java | 208 ++++++++++++ .../tasks/TerminateDeploymentItemRequest.java | 122 +++++++ .../flows/tasks/TerminateDeploymentItemTask.java | 198 ++++++++++++ .../main/resources/MonitorHelmUnInstallStatus.bpmn | 172 ++++++++++ .../src/main/resources/TerminateAs.bpmn | 352 +++++++++++++++++++++ .../main/resources/TerminateDeploymentItem.bpmn | 199 ++++++++++++ .../lcm/bpmn/flows/tasks/TerminateAsTaskTest.java | 267 ++++++++++++++++ 9 files changed, 1705 insertions(+), 9 deletions(-) create mode 100644 so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/MonitorHelmUnInstallStatusTask.java create mode 100644 so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateAsTask.java create mode 100644 so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateDeploymentItemRequest.java create mode 100644 so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateDeploymentItemTask.java create mode 100644 so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/MonitorHelmUnInstallStatus.bpmn create mode 100644 so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/TerminateAs.bpmn create mode 100644 so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/TerminateDeploymentItem.bpmn create mode 100644 so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateAsTaskTest.java diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/kubernetes/KubernetesClientImpl.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/kubernetes/KubernetesClientImpl.java index 15f6d83..06f0add 100644 --- a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/kubernetes/KubernetesClientImpl.java +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/extclients/kubernetes/KubernetesClientImpl.java @@ -709,20 +709,16 @@ public class KubernetesClientImpl implements KubernetesClient { private KubernetesResource getKubernetesResource(final String apiVersion, final String kind, final V1ObjectMeta metadata) { final GroupVersion groupVersion = GroupVersion.parse(apiVersion); - final KubernetesResource resource = - new KubernetesResource().id(metadata.getUid()).name(metadata.getName()).group(groupVersion.getGroup()) - .version(groupVersion.getVersion()).kind(kind).resourceVersion(metadata.getResourceVersion()) - .namespace(metadata.getNamespace() != null ? metadata.getNamespace() : "") - .labels(getLabels(metadata.getLabels())); - return resource; + return new KubernetesResource().id(metadata.getUid()).name(metadata.getName()).group(groupVersion.getGroup()) + .version(groupVersion.getVersion()).kind(kind).resourceVersion(metadata.getResourceVersion()) + .namespace(metadata.getNamespace() != null ? metadata.getNamespace() : "") + .labels(getLabels(metadata.getLabels())); } private List getLabels(final Map labels) { if (labels != null) { final List result = new ArrayList<>(); - labels.entrySet().forEach(entry -> { - result.add(entry.getKey() + "=" + entry.getValue()); - }); + labels.entrySet().forEach(entry -> result.add(entry.getKey() + "=" + entry.getValue())); return result; } return Collections.emptyList(); diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/MonitorHelmUnInstallStatusTask.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/MonitorHelmUnInstallStatusTask.java new file mode 100644 index 0000000..3f2a1bd --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/MonitorHelmUnInstallStatusTask.java @@ -0,0 +1,182 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.cnfm.lcm.bpmn.flows.tasks; + +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_DEPLOYMENT_ITEM_INST_ID_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.KIND_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.KUBE_CONFIG_FILE_PATH_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.KUBE_KINDS_RESULT_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.RELEASE_NAME_PARAM_NAME; + +import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_DAEMON_SET; +import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_DEPLOYMENT; +import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_JOB; +import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_POD; +import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_REPLICA_SET; +import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_SERVICE; +import static org.onap.so.cnfm.lcm.bpmn.flows.Constants.KIND_STATEFUL_SET; + +import io.kubernetes.client.openapi.ApiClient; +import java.util.Map; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.onap.so.cnfm.lcm.bpmn.flows.exceptions.KubernetesRequestTimeOut; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.kubernetes.KubernetesClient; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.kubernetes.KubernetesClientProvider; +import org.onap.so.cnfm.lcm.database.beans.JobStatusEnum; +import org.onap.so.cnfm.lcm.database.service.DatabaseServiceProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author Raviteja Karumuri (raviteja.karumuri@est.tech) + */ +@Component +public class MonitorHelmUnInstallStatusTask extends AbstractServiceTask { + + private static final Logger logger = LoggerFactory.getLogger(MonitorHelmUnInstallStatusTask.class); + private static final int MAX_RETRIES = 10; + private static final String IS_RESOURCE_DELETED_PARAM_NAME = "isResourceDeleted"; + private static final String RETRY_COUNTER_PARAM_NAME = "retryCounter"; + private final KubernetesClientProvider kubernetesClientProvider; + private final KubernetesClient kubernetesClient; + + @Autowired + protected MonitorHelmUnInstallStatusTask(final DatabaseServiceProvider databaseServiceProvider, + final KubernetesClientProvider kubernetesClientProvider, final KubernetesClient kubernetesClient) { + super(databaseServiceProvider); + this.kubernetesClientProvider = kubernetesClientProvider; + this.kubernetesClient = kubernetesClient; + } + + public void updateJobStatus(final DelegateExecution execution) { + logger.info("Executing updateJobStatus "); + final String kind = (String) execution.getVariable(KIND_PARAM_NAME); + final String asDeploymentItemInstId = (String) execution.getVariable(AS_DEPLOYMENT_ITEM_INST_ID_PARAM_NAME); + + addJobStatus(execution, JobStatusEnum.IN_PROGRESS, "Checking if resource: " + kind + + " is terminated for asDeploymentItemInstId: " + asDeploymentItemInstId); + + execution.setVariable(RETRY_COUNTER_PARAM_NAME, 0); + + logger.info("Finished updateJobStatus ..."); + } + + public void isResourceDeleted(final DelegateExecution execution) { + logger.info("Executing isResourceDeleted "); + final String kind = (String) execution.getVariable(KIND_PARAM_NAME); + final String releaseName = (String) execution.getVariable(RELEASE_NAME_PARAM_NAME); + final String kubeConfigFile = (String) execution.getVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME); + final String labelSelector = "app.kubernetes.io/instance=" + releaseName; + try { + final ApiClient apiClient = kubernetesClientProvider.getApiClient(kubeConfigFile); + boolean isDeleted = false; + logger.debug("Will check if resource type: {} is Deleted using labelSelector: {}", kind, labelSelector); + switch (kind) { + case KIND_JOB: + isDeleted = kubernetesClient.isJobDeleted(apiClient, labelSelector); + break; + case KIND_POD: + isDeleted = kubernetesClient.isPodDeleted(apiClient, labelSelector); + break; + case KIND_SERVICE: + isDeleted = kubernetesClient.isServiceDeleted(apiClient, labelSelector); + break; + case KIND_DEPLOYMENT: + isDeleted = kubernetesClient.isDeploymentDeleted(apiClient, labelSelector); + break; + case KIND_REPLICA_SET: + isDeleted = kubernetesClient.isReplicaSetDeleted(apiClient, labelSelector); + break; + case KIND_DAEMON_SET: + isDeleted = kubernetesClient.isDaemonSetDeleted(apiClient, labelSelector); + break; + case KIND_STATEFUL_SET: + isDeleted = kubernetesClient.isStatefulSetDeleted(apiClient, labelSelector); + break; + + default: + logger.warn("Unknown resource type {} setting {} flag to true", kind, + IS_RESOURCE_DELETED_PARAM_NAME); + isDeleted = true; + break; + } + + logger.debug("Resource '{}' isDeleted: {}", kind, isDeleted); + execution.setVariable(IS_RESOURCE_DELETED_PARAM_NAME, isDeleted); + + } catch (final KubernetesRequestTimeOut kubernetesRequestTimeOut) { + final Integer counter = (Integer) execution.getVariable(RETRY_COUNTER_PARAM_NAME); + if (counter > MAX_RETRIES) { + final String message = "Retries max out for resource: " + kind; + logger.error(message); + abortOperation(execution, message); + } + logger.debug("Current retries counter: {} will increament and try again", counter); + execution.setVariable(RETRY_COUNTER_PARAM_NAME, counter + 1); + execution.setVariable(IS_RESOURCE_DELETED_PARAM_NAME, false); + + } catch (final Exception exception) { + final String message = "Unable to preform delete status check for resource " + kind; + logger.error(message, exception); + abortOperation(execution, message); + } + logger.info("Finished isResourceDeleted ..."); + + } + + public void checkIfOperationWasSuccessful(final DelegateExecution execution) { + logger.info("Executing checkIfOperationWasSuccessful "); + + final String kind = (String) execution.getVariable(KIND_PARAM_NAME); + + @SuppressWarnings("unchecked") + final Map kubeKindResult = + (Map) execution.getVariable(KUBE_KINDS_RESULT_PARAM_NAME); + + final boolean isDeleted = (boolean) execution.getVariable(IS_RESOURCE_DELETED_PARAM_NAME); + logger.debug("{} delete status {}", kind, isDeleted ? "Successful" : "failed"); + kubeKindResult.put(kind, isDeleted); + + execution.setVariable(KUBE_KINDS_RESULT_PARAM_NAME, kubeKindResult); + + if (!isDeleted) { + final String message = "Status check failed for resource: {}" + kind; + logger.error(message); + abortOperation(execution, message); + } + + final String asDeploymentItemInstId = (String) execution.getVariable(AS_DEPLOYMENT_ITEM_INST_ID_PARAM_NAME); + addJobStatus(execution, JobStatusEnum.IN_PROGRESS, + "Resource " + kind + " is deleting for asDeploymentItemInstId: " + asDeploymentItemInstId); + logger.info("Finished checkIfOperationWasSuccessful ..."); + } + + public void timeOutLogFailue(final DelegateExecution execution) { + logger.info("Executing timeOutLogFailue "); + final String message = "Is Resource Deleted operation timed out"; + logger.error(message); + abortOperation(execution, message); + logger.info("Finished timeOutLogFailue ..."); + } + +} diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateAsTask.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateAsTask.java new file mode 100644 index 0000000..d834c4d --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateAsTask.java @@ -0,0 +1,208 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.cnfm.lcm.bpmn.flows.tasks; + +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_INSTANCE_ID_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.DEPLOYMENT_ITEM_TERMINATE_REQUESTS; +import static org.onap.so.cnfm.lcm.database.beans.JobStatusEnum.FINISHED; +import static org.onap.so.cnfm.lcm.database.beans.JobStatusEnum.IN_PROGRESS; +import static org.onap.so.cnfm.lcm.database.beans.JobStatusEnum.STARTED; + +import java.nio.file.Path; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.onap.so.beans.nsmf.OrchestrationStatusEnum; +import org.onap.so.cnfm.lcm.bpmn.flows.exceptions.KubeConfigFileNotFoundException; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.aai.AaiServiceProvider; +import org.onap.so.cnfm.lcm.bpmn.flows.service.KubConfigProvider; +import org.onap.so.cnfm.lcm.database.beans.AsDeploymentItem; +import org.onap.so.cnfm.lcm.database.beans.AsInst; +import org.onap.so.cnfm.lcm.database.beans.State; +import org.onap.so.cnfm.lcm.database.service.DatabaseServiceProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +@Component +public class TerminateAsTask extends AbstractServiceTask { + private static final Logger logger = LoggerFactory.getLogger(TerminateAsTask.class); + private final KubConfigProvider kubConfigProvider; + private final AaiServiceProvider aaiServiceProvider; + private static final String KUBE_CONFIG_FILE_PARAM_NAME = "kubeConfigFile"; + private static final String IS_AS_TERMINATION_SUCCESSFUL_PARAM_NAME = "isAsTerminationSuccessful"; + + @Autowired + protected TerminateAsTask(final DatabaseServiceProvider databaseServiceProvider, + final KubConfigProvider kubConfigProvider, final AaiServiceProvider aaiServiceProvider) { + super(databaseServiceProvider); + this.kubConfigProvider = kubConfigProvider; + this.aaiServiceProvider = aaiServiceProvider; + } + + public void setJobStatusToStarted(final DelegateExecution execution) { + setJobStatus(execution, STARTED, "Terminate AS workflow process started"); + } + + public void setJobStatusToFinished(final DelegateExecution execution) { + setJobStatus(execution, FINISHED, "Terminate AS workflow process finished"); + } + + public void setJobStatusToError(final DelegateExecution execution) { + setJobStatusToError(execution, "Terminate AS workflow process failed"); + } + + public void updateAsInstanceStatusToTerminating(final DelegateExecution execution) { + logger.info("Executing updateAsInstanceStatusToTerminating"); + setJobStatus(execution, IN_PROGRESS, "Updating AsInst Status to " + State.TERMINATING); + updateAsInstanceStatus(execution, State.TERMINATING); + logger.info("Finished executing updateAsInstanceStatusToTerminating ..."); + } + + public void updateAsInstanceStatusToNotInstantiated(final DelegateExecution execution) { + logger.info("Executing updateAsInstanceStatusToNotInstantiated"); + setJobStatus(execution, IN_PROGRESS, "Updating AsInst Status to " + State.NOT_INSTANTIATED); + updateAsInstanceStatus(execution, State.NOT_INSTANTIATED); + logger.info("Finished executing updateAsInstanceStatusToNotInstantiated ..."); + } + + public void logTimeOut(final DelegateExecution execution) { + logger.error("Deployment items Termination timedOut ..."); + final String asInstId = (String) execution.getVariable(AS_INSTANCE_ID_PARAM_NAME); + final List asDeploymentItems = + databaseServiceProvider.getAsDeploymentItemByAsInstId(asInstId); + if (asDeploymentItems != null) { + asDeploymentItems.stream().forEach(asDeploymentItem -> { + logger.info("Current status {} of terminating asDeploymentItem: {}", asDeploymentItem.getStatus(), + asDeploymentItem.getName()); + }); + } + } + + public void checkifKubConfigFileAvailable(final DelegateExecution execution) { + logger.info("Executing checkifKubConfigFileAvailable"); + try { + setJobStatus(execution, IN_PROGRESS, "Checking if kubeconfig file is available or not"); + final AsInst asInst = getAsInst(execution); + + final Path kubeConfigFile = kubConfigProvider.getKubeConfigFile(asInst.getCloudOwner(), + asInst.getCloudRegion(), asInst.getTenantId()); + + execution.setVariable(KUBE_CONFIG_FILE_PARAM_NAME, kubeConfigFile.toString()); + + } catch (final KubeConfigFileNotFoundException exception) { + final String message = "Unable to find kube-config file on filesystem"; + logger.error(message, exception); + abortOperation(execution, message); + + } + + logger.info("Finished executing checkifKubConfigFileAvailable ..."); + + } + + public void prepareTerminateDeploymentItemRequests(final DelegateExecution execution) { + logger.info("Executing prepareTerminateDeploymentItemRequests ..."); + setJobStatus(execution, IN_PROGRESS, "Preparing TerminateDeploymentItemRequest requests"); + + final String asInstId = (String) execution.getVariable(AS_INSTANCE_ID_PARAM_NAME); + final String kubeConfigFile = (String) execution.getVariable(KUBE_CONFIG_FILE_PARAM_NAME); + + final List asDeploymentItems = + databaseServiceProvider.getAsDeploymentItemByAsInstId(asInstId); + + final Set requests = new TreeSet<>(); + + asDeploymentItems.forEach(asDeploymentItem -> { + + final String asDeploymentItemInstId = asDeploymentItem.getAsDeploymentItemInstId(); + + final TerminateDeploymentItemRequest terminatedeploymentitemrequest = new TerminateDeploymentItemRequest(); + terminatedeploymentitemrequest.setAsInstId(asInstId); + terminatedeploymentitemrequest.setAsDeploymentItemInstId(asDeploymentItemInstId); + terminatedeploymentitemrequest.setDeploymentOrder(asDeploymentItem.getDeploymentOrder()); + terminatedeploymentitemrequest.setKubeConfigFile(kubeConfigFile); + terminatedeploymentitemrequest.setReleaseName(asDeploymentItem.getReleaseName()); + + requests.add(terminatedeploymentitemrequest); + + }); + + execution.setVariable(DEPLOYMENT_ITEM_TERMINATE_REQUESTS, requests); + + logger.info("Finished executing prepareTerminateDeploymentItemRequests ..."); + } + + public void checkIfDeploymentItemsTerminationWasSuccessful(final DelegateExecution execution) { + logger.info("Executing checkIfDeploymentItemsTerminationWasSuccessful"); + + @SuppressWarnings("unchecked") + final Set requests = + (Set) execution.getVariable(DEPLOYMENT_ITEM_TERMINATE_REQUESTS); + + final String asInstId = (String) execution.getVariable(AS_INSTANCE_ID_PARAM_NAME); + final List asDeploymentItems = + databaseServiceProvider.getAsDeploymentItemByAsInstId(asInstId); + + + if (asDeploymentItems == null || asDeploymentItems.isEmpty()) { + final String message = "Found empty asDeploymentItems"; + abortOperation(execution, message); + } else if (requests.size() != asDeploymentItems.size()) { + final String message = "Missing asDeploymentItems. Request triggered has: " + requests.size() + + " asDeploymentItems but database has: " + asDeploymentItems.size(); + abortOperation(execution, message); + } else { + execution.setVariable(IS_AS_TERMINATION_SUCCESSFUL_PARAM_NAME, true); + asDeploymentItems.forEach(asDeploymentItem -> { + logger.info("Checking AsDeploymentItem {} termination status: {}", + asDeploymentItem.getAsDeploymentItemInstId(), asDeploymentItem.getStatus()); + if (!State.NOT_INSTANTIATED.equals(asDeploymentItem.getStatus())) { + logger.error("AsDeploymentItem : {} {} termination failed", + asDeploymentItem.getAsDeploymentItemInstId(), asDeploymentItem.getName()); + execution.setVariable(IS_AS_TERMINATION_SUCCESSFUL_PARAM_NAME, false); + } + }); + } + logger.info("Finished executing checkIfDeploymentItemsTerminationWasSuccessful ..."); + } + + public void updateGenericVnfStatustoDeActivated(final DelegateExecution execution) { + + logger.debug("Executing updateGenericVnfStatustoDeActivated"); + final String asInstId = (String) execution.getVariable(AS_INSTANCE_ID_PARAM_NAME); + final boolean result = aaiServiceProvider.updateGenericVnfStatus(asInstId, + OrchestrationStatusEnum.DEACTIVATED); + if (!result) { + abortOperation(execution, "Failed to update GenericVnf status to Deactivated as there" + + "is no GenericVnf Found in AAI of ID: " + asInstId); + } + logger.info("Finished updating vnf status to Deactivated"); + } + +} diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateDeploymentItemRequest.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateDeploymentItemRequest.java new file mode 100644 index 0000000..b4fb233 --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateDeploymentItemRequest.java @@ -0,0 +1,122 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.cnfm.lcm.bpmn.flows.tasks; + +import static org.onap.so.cnfm.lcm.database.beans.utils.Utils.toIndentedString; + +import java.io.Serializable; +import java.util.Comparator; +import java.util.Objects; +import org.jetbrains.annotations.NotNull; + +/** + * + * @author Raviteja Karumuri (raviteja.karumuri@est.tech) + * + */ +public class TerminateDeploymentItemRequest implements Serializable, Comparable { + + private static final long serialVersionUID = 2953758424937589468L; + private String asInstId; + private String asDeploymentItemInstId; + private String kubeConfigFile; + private Integer deploymentOrder; + private String releaseName; + + private static final Comparator COMPARATOR = Comparator.nullsFirst(Integer::compare).reversed(); + + public String getAsInstId() { + return asInstId; + } + + public void setAsInstId(final String asInstId) { + this.asInstId = asInstId; + } + + public String getAsDeploymentItemInstId() { + return asDeploymentItemInstId; + } + + public void setAsDeploymentItemInstId(final String asDeploymentItemInstId) { + this.asDeploymentItemInstId = asDeploymentItemInstId; + } + + public String getKubeConfigFile() { + return kubeConfigFile; + } + + public void setKubeConfigFile(final String kubeConfigFile) { + this.kubeConfigFile = kubeConfigFile; + } + + public Integer getDeploymentOrder() { + return deploymentOrder; + } + + public void setDeploymentOrder(final Integer deploymentOrder) { + this.deploymentOrder = deploymentOrder; + } + + public String getReleaseName() { + return releaseName; + } + + public void setReleaseName(final String releaseName) { + this.releaseName = releaseName; + } + + @Override + public boolean equals(final Object obj) { + if (obj instanceof TerminateDeploymentItemRequest) { + final TerminateDeploymentItemRequest that = (TerminateDeploymentItemRequest) obj; + return Objects.equals(asInstId, that.asInstId) + && Objects.equals(asDeploymentItemInstId, that.asDeploymentItemInstId) + && Objects.equals(kubeConfigFile, that.kubeConfigFile) + && Objects.equals(deploymentOrder, that.deploymentOrder) + && Objects.equals(releaseName, that.releaseName); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(asInstId, asDeploymentItemInstId, kubeConfigFile, deploymentOrder, + releaseName); + } + + @Override + public int compareTo(@NotNull final TerminateDeploymentItemRequest terminateDeploymentItemRequest) { + return COMPARATOR.compare(this.getDeploymentOrder(), terminateDeploymentItemRequest.getDeploymentOrder()); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("class TerminateDeploymentItemRequest {\n"); + sb.append(" asInstId: ").append(toIndentedString(asInstId)).append("\n"); + sb.append(" asDeploymentItemInstId: ").append(toIndentedString(asDeploymentItemInstId)).append("\n"); + sb.append(" deploymentOrder: ").append(toIndentedString(deploymentOrder)).append("\n"); + sb.append(" kubeConfigFile: ").append(toIndentedString(kubeConfigFile)).append("\n"); + sb.append(" releaseName: ").append(toIndentedString(releaseName)).append("\n"); + sb.append("}"); + return sb.toString(); + } +} diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateDeploymentItemTask.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateDeploymentItemTask.java new file mode 100644 index 0000000..e78f8f0 --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateDeploymentItemTask.java @@ -0,0 +1,198 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.cnfm.lcm.bpmn.flows.tasks; + +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.AS_DEPLOYMENT_ITEM_INST_ID_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.KUBE_CONFIG_FILE_PATH_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.KUBE_KINDS_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.KUBE_KINDS_RESULT_PARAM_NAME; +import static org.onap.so.cnfm.lcm.bpmn.flows.CamundaVariableNameConstants.RELEASE_NAME_PARAM_NAME; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.aai.AaiServiceProvider; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.helm.HelmClient; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.kubernetes.KubernetesClientProvider; +import org.onap.so.cnfm.lcm.bpmn.flows.extclients.kubernetes.KubernetesResource; +import org.onap.so.cnfm.lcm.database.beans.AsInst; +import org.onap.so.cnfm.lcm.database.beans.JobStatusEnum; +import org.onap.so.cnfm.lcm.database.beans.State; +import org.onap.so.cnfm.lcm.database.service.DatabaseServiceProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * + * @author Raviteja karumuri (raviteja.karumuri@est.tech) + * + */ + +@Component +public class TerminateDeploymentItemTask extends AbstractServiceTask { + + private static final Logger logger = LoggerFactory.getLogger(TerminateDeploymentItemTask.class); + + private static final String IS_DELETED_PARAM_NAME = "isDeleted"; + private static final String TERMINATE_REQUEST_PARAM_NAME = "request"; + + private final AaiServiceProvider aaiServiceProvider; + private final HelmClient helmClient; + private final KubernetesClientProvider kubernetesClientProvider; + + @Autowired + protected TerminateDeploymentItemTask(final DatabaseServiceProvider databaseServiceProvider, + final AaiServiceProvider aaiServiceProvider, final HelmClient helmClient, + final KubernetesClientProvider kubernetesClientProvider) { + super(databaseServiceProvider); + this.aaiServiceProvider = aaiServiceProvider; + this.helmClient = helmClient; + this.kubernetesClientProvider = kubernetesClientProvider; + } + + public void checkIfDeploymentItemExistsInDb(final DelegateExecution execution) { + logger.info("Executing checkIfDeploymentItemExistsInDb"); + final TerminateDeploymentItemRequest request = + (TerminateDeploymentItemRequest) execution.getVariable(TERMINATE_REQUEST_PARAM_NAME); + logger.info("Terminate request: {}", request); + + final String asDeploymentItemInstId = request.getAsDeploymentItemInstId(); + addJobStatus(execution, JobStatusEnum.IN_PROGRESS, + "Checking if Deployment item record exists in database for asDeploymentItemInstId: " + + asDeploymentItemInstId); + + if (!databaseServiceProvider.isAsDeploymentItemExists(request.getAsDeploymentItemInstId())) { + abortOperation(execution, "Deployment Item does not exists in database for asDeploymentItemInstId: " + + asDeploymentItemInstId); + } + execution.setVariable(AS_DEPLOYMENT_ITEM_INST_ID_PARAM_NAME, request.getAsDeploymentItemInstId()); + execution.setVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME, request.getKubeConfigFile()); + logger.info("Finished executing checkIfDeploymentItemExistsInDb ..."); + + } + + public void unInstantiateHelmChart(final DelegateExecution execution) { + logger.info("Executing unInstantiateHelmChart"); + + final TerminateDeploymentItemRequest request = + (TerminateDeploymentItemRequest) execution.getVariable(TERMINATE_REQUEST_PARAM_NAME); + final String releaseName = request.getReleaseName(); + + try { + final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile()); + helmClient.unInstallHelmChart(releaseName, kubeConfigFilePath); + } catch (final Exception exception) { + final String message = "Failed to uninstall helm chart: " + " using kube-config file: " + + request.getKubeConfigFile() + "for reason: " + exception.getMessage(); + logger.error(message, exception); + abortOperation(execution, message); + } + logger.info("Finished executing unInstantiateHelmChart ..."); + + } + + + public void updateDeploymentItemStatusToNotInstantiated(final DelegateExecution execution) { + + logger.info("Executing updateDeploymentItemStatusToNotInstantiated"); + final TerminateDeploymentItemRequest request = + (TerminateDeploymentItemRequest) execution.getVariable(TERMINATE_REQUEST_PARAM_NAME); + + updateDeploymentItemStatus(execution, request.getAsDeploymentItemInstId(), State.NOT_INSTANTIATED); + + addJobStatus(execution, JobStatusEnum.FINISHED, "Successfully Terminated Deployment Item with " + + "releaseName: " + request.getReleaseName() + " and will set status to " + State.NOT_INSTANTIATED); + + logger.info("Finished executing updateDeploymentItemStatusToNotInstantiated ..."); + } + + public void getKubeKindsUsingManifestCommand(final DelegateExecution execution) { + + logger.info("Executing getKubeKindsFromReleaseHistory"); + + final TerminateDeploymentItemRequest request = + (TerminateDeploymentItemRequest) execution.getVariable(TERMINATE_REQUEST_PARAM_NAME); + final String releaseName = request.getReleaseName(); + final Path kubeConfigFilePath = Paths.get(request.getKubeConfigFile()); + final Map kubeKindsMap = new HashMap<>(); + final List kinds = helmClient.getKubeKindsUsingManifestCommand(releaseName, kubeConfigFilePath); + if (kinds.isEmpty()) { + abortOperation(execution, + "Unable to retrieve kinds from helm release history for releaseName: " + releaseName); + } + kinds.forEach(kind -> kubeKindsMap.put(kind, false)); + + execution.setVariable(RELEASE_NAME_PARAM_NAME, releaseName); + execution.setVariable(KUBE_KINDS_RESULT_PARAM_NAME, kubeKindsMap); + execution.setVariable(KUBE_KINDS_PARAM_NAME, kinds); + } + + public void checkIfHelmUnInstallWasSuccessful(final DelegateExecution execution) { + logger.info("Executing checkIfHelmUnInstallWasSuccessful"); + + @SuppressWarnings("unchecked") + final Map kubeKindResult = + (Map) execution.getVariable(KUBE_KINDS_RESULT_PARAM_NAME); + + execution.setVariable(IS_DELETED_PARAM_NAME, true); + + kubeKindResult.forEach((key, value) -> { + logger.info("Checking if resource type {} was deleted Status: {}", key, value); + + if (Boolean.FALSE.equals(value)) { + logger.error("resource type {} failed to delete", key); + execution.setVariable(IS_DELETED_PARAM_NAME, false); + } + }); + + final String kubeConfigFile = (String) execution.getVariable(KUBE_CONFIG_FILE_PATH_PARAM_NAME); + kubernetesClientProvider.closeApiClient(kubeConfigFile); + + logger.info("Finished executing checkIfHelmUnInstallWasSuccessful ..."); + + } + + public void deleteK8ResourcesinAAI(final DelegateExecution execution) { + logger.info("Executing deleteK8ResourcesinAai"); + final TerminateDeploymentItemRequest request = + (TerminateDeploymentItemRequest) execution.getVariable(TERMINATE_REQUEST_PARAM_NAME); + final List resources = + aaiServiceProvider.getK8sResources(request.getAsInstId(), request.getAsDeploymentItemInstId()); + final AsInst asInst = getAsInst(execution); + resources.forEach(resource -> aaiServiceProvider.deleteK8SResource(resource.getId(), asInst.getCloudOwner(), + asInst.getCloudRegion(), asInst.getTenantId())); + } + + public void deleteVFModuleinAai(final DelegateExecution execution) { + logger.info("Executing deleteVFModuleinAai"); + + final TerminateDeploymentItemRequest request = + (TerminateDeploymentItemRequest) execution.getVariable(TERMINATE_REQUEST_PARAM_NAME); + aaiServiceProvider.deleteVfModule(request.getAsInstId(), request.getAsDeploymentItemInstId()); + logger.info("Delete VfModule in AAi is Done"); + + } + +} diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/MonitorHelmUnInstallStatus.bpmn b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/MonitorHelmUnInstallStatus.bpmn new file mode 100644 index 0000000..8ea258e --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/MonitorHelmUnInstallStatus.bpmn @@ -0,0 +1,172 @@ + + + + + helm_uninstall_Flow_1f87oz7 + + + Flow_0f5dibe + helm_uninstall_Flow_1kpnioc + + helm_uninstall_Flow_1kekeh7 + + + helm_uninstall_Flow_0kdhub4 + helm_uninstall_Flow_1g3xchu + helm_uninstall_Flow_0n6qu57 + + + helm_uninstall_Flow_1g3xchu + helm_uninstall_Flow_0tqwb9b + + PT15S + + + + helm_uninstall_Flow_0n6qu57 + + + helm_uninstall_Flow_11mzqci + helm_uninstall_Flow_0tqwb9b + helm_uninstall_Flow_0kdhub4 + + + helm_uninstall_Flow_1kekeh7 + helm_uninstall_Flow_11mzqci + + + + + + + #{isResourceDeleted} + + + + + helm_uninstall_Flow_0qm63h0 + + + + helm_uninstall_Flow_1719q6v + helm_uninstall_Flow_0qm63h0 + + + helm_uninstall_Flow_1kpnioc + helm_uninstall_Flow_1f87oz7 + + + Flow_0f5dibe + + + helm_uninstall_Flow_1719q6v + + PT20M + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/TerminateAs.bpmn b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/TerminateAs.bpmn new file mode 100644 index 0000000..2cdb78d --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/TerminateAs.bpmn @@ -0,0 +1,352 @@ + + + + + Flow_0phigr7 + + + Flow_05pzpgq + + + + Flow_0phigr7 + Flow_06wp5ro + + + + + Flow_1xjr8hb + Flow_1ggg282 + + + Flow_1ah8wba + Flow_117o05v + + + Flow_117o05v + + + Flow_1xjr8hb + + + + + + + Flow_1ggg282 + Flow_1ah8wba + + + + + + Flow_0r7a1v7 + Flow_0762ta8 + + + Flow_1qhfzp9 + Flow_014quwi + + + Flow_014quwi + + + Flow_0r7a1v7 + + + + + + + + Flow_0762ta8 + Flow_1qhfzp9 + + + + Flow_1rn2equ + Flow_13oh37n + + + + Flow_06wp5ro + Flow_1b3sgnv + + + + Flow_1b3sgnv + Flow_08hpasa + + + + Flow_08hpasa + Flow_13hlp85 + + + Flow_03u3m4k + Flow_031y9cv + + + + + + + + Flow_13hlp85 + Flow_03u3m4k + + + + Flow_031y9cv + Flow_1va2hjh + Flow_1daazvp + + + Flow_1va2hjh + Flow_0i1vt5a + + + + + + #{not isAsTerminationSuccessful} + + + + #{isAsTerminationSuccessful} + + + + Flow_1daazvp + Flow_0vuf6k8 + + + Flow_13oh37n + Flow_05pzpgq + + + + Flow_0vuf6k8 + Flow_1rn2equ + + + + Flow_0do9jeh + Flow_0i1vt5a + + + + Flow_0do9jeh + + PT3H + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/TerminateDeploymentItem.bpmn b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/TerminateDeploymentItem.bpmn new file mode 100644 index 0000000..d5b2073 --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/main/resources/TerminateDeploymentItem.bpmn @@ -0,0 +1,199 @@ + + + + + Flow_11nr4yl + + + + Flow_1ey2cql + Flow_0hqyoqt + + + + Flow_11nr4yl + Flow_0ks1v6p + + + Flow_0gcia1l + + + Flow_044y6ke + Flow_0gcia1l + + + + + + + + + + + + + Flow_0hqyoqt + Flow_0tc7pv4 + + + + Flow_151tn6a + Flow_0mnd6tu + + + Flow_0tc7pv4 + Flow_0k6smfs + + + Flow_0mnd6tu + Flow_1v7gngy + + + + Flow_0k6smfs + Flow_1v7gngy + Flow_0pdqj64 + + + Flow_0pdqj64 + Flow_0rpkgfk + + + Flow_0rpkgfk + Flow_044y6ke + + + Flow_151tn6a + + PT1H + + + + + + + #{not isDeleted} + + + #{isDeleted} + + + + + + + Flow_0ks1v6p + Flow_1ey2cql + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateAsTaskTest.java b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateAsTaskTest.java new file mode 100644 index 0000000..832d675 --- /dev/null +++ b/so-cnfm/so-cnfm-lcm/so-cnfm-lcm-bpmn-flows/src/test/java/org/onap/so/cnfm/lcm/bpmn/flows/tasks/TerminateAsTaskTest.java @@ -0,0 +1,267 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.so.cnfm.lcm.bpmn.flows.tasks; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.ok; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.onap.aaiclient.client.aai.AAIVersion.V19; +import static org.springframework.http.HttpHeaders.CONTENT_TYPE; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +import com.google.gson.Gson; +import io.kubernetes.client.openapi.models.V1DaemonSetList; +import io.kubernetes.client.openapi.models.V1DeploymentList; +import io.kubernetes.client.openapi.models.V1JobList; +import io.kubernetes.client.openapi.models.V1PodList; +import io.kubernetes.client.openapi.models.V1ReplicaSetList; +import io.kubernetes.client.openapi.models.V1ServiceList; +import io.kubernetes.client.openapi.models.V1StatefulSetList; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.LocalDateTime; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import org.camunda.bpm.engine.history.HistoricProcessInstance; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.aai.domain.yang.GenericVnf; +import org.onap.so.beans.nsmf.OrchestrationStatusEnum; +import org.onap.so.cnfm.lcm.bpmn.flows.BaseTest; +import org.onap.so.cnfm.lcm.bpmn.flows.GsonProvider; +import org.onap.so.cnfm.lcm.bpmn.flows.service.JobExecutorService; +import org.onap.so.cnfm.lcm.database.beans.AsDeploymentItem; +import org.onap.so.cnfm.lcm.database.beans.AsInst; +import org.onap.so.cnfm.lcm.database.beans.AsLcmOpOcc; +import org.onap.so.cnfm.lcm.database.beans.Job; +import org.onap.so.cnfm.lcm.database.beans.OperationStateEnum; +import org.onap.so.cnfm.lcm.database.beans.State; +import org.onap.so.cnfm.lcm.model.TerminateAsRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +/** + * + * @author Waqas Ikram (waqas.ikram@est.tech) + * + */ +public class TerminateAsTaskTest extends BaseTest { + + private static final String AS_INST_ID = UUID.randomUUID().toString(); + private static final String AS_DEPLOYMENT_ITEM_ONE_INST_ID = UUID.randomUUID().toString(); + private static final String AS_DEPLOYMENT_ITEM_TWO_INST_ID = UUID.randomUUID().toString(); + + @Value("${cnfm.kube-configs-dir}") + private String kubeConfigsDir; + + @Autowired + private JobExecutorService objUnderTest; + + @Autowired + private MockedHelmClient mockedHelmClient; + + @Autowired + private MockedKubernetesClientProvider kubernetesClientProvider; + + @Autowired + private GsonProvider gsonProvider; + + private Gson gson; + + @Before + public void before() { + + wireMockServer.resetAll(); + try { + deleteFoldersAndFiles(Paths.get(kubeConfigsDir)); + Files.createDirectory(Paths.get(kubeConfigsDir)); + } catch (final IOException ioException) { + throw new RuntimeException( + "Failed to create/Delete Directory in TerminateAsTaskTest due to: " + ioException.getMessage()); + } + kubernetesClientProvider.setWireMockServer(wireMockServer); + + gson = gsonProvider.getGson(); + } + + @After + public void after() { + wireMockServer.resetAll(); + } + + @Test + public void testTerminateAsTask_SuccessfulCase() throws InterruptedException, IOException { + + mockKubernetesClientEndpoint(); + mockAAIEndPoints(); + addDummyAsToDatabase(AS_INST_ID); + + final String asLcmOpOccId = objUnderTest.runTerminateAsJob(AS_INST_ID, new TerminateAsRequest()); + + final Optional optional = getJobByResourceId(AS_INST_ID); + assertTrue(optional.isPresent()); + final Job job = optional.get(); + assertTrue(waitForProcessInstanceToFinish(job.getProcessInstanceId())); + + final HistoricProcessInstance historicProcessInstance = getHistoricProcessInstance(job.getProcessInstanceId()); + assertNotNull(historicProcessInstance); + assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState()); + + final Optional optionalAsInst = databaseServiceProvider.getAsInst(AS_INST_ID); + assertTrue(optionalAsInst.isPresent()); + final AsInst updatedAsInst = optionalAsInst.get(); + assertEquals(State.NOT_INSTANTIATED, updatedAsInst.getStatus()); + + final Optional optionalAsLcmOpOcc = databaseServiceProvider.getAsLcmOpOcc(asLcmOpOccId); + assertTrue(optionalAsLcmOpOcc.isPresent()); + final AsLcmOpOcc asLcmOpOcc = optionalAsLcmOpOcc.get(); + assertEquals(OperationStateEnum.COMPLETED, asLcmOpOcc.getOperationState()); + + final Map counter = mockedHelmClient.getUnInstallCounter(); + assertEquals(2, counter.size()); + } + + private void addDummyAsToDatabase(final String asInstanceId) throws IOException { + final String asInstName = "TerminateCnfService-" + System.currentTimeMillis(); + final AsInst asInst = new AsInst().asInstId(asInstanceId).name(asInstName).asdId(asInstanceId) + .asdInvariantId(asInstanceId).status(State.INSTANTIATED).statusUpdatedTime(LocalDateTime.now()) + .asApplicationName("asApplicationName").asApplicationVersion("asApplicationVersion") + .asProvider("asProvider").serviceInstanceId(SERVICE_INSTANCE_ID) + .serviceInstanceName(SERVICE_INSTANCE_NAME).cloudOwner("cloudOwner").cloudRegion("cloudRegion") + .tenantId("tenantId"); + + final String helmFile1 = "Artifacts/Deployment/HELM/sampleapp-db-operator-helm.tgz"; + final AsDeploymentItem dItemOne = new AsDeploymentItem().asDeploymentItemInstId(AS_DEPLOYMENT_ITEM_ONE_INST_ID) + .asInst(asInst).status(State.INSTANTIATED).name("sampleapp-db").itemId("1").deploymentOrder(1) + .artifactFilePath(helmFile1).createTime(LocalDateTime.now()).lastUpdateTime(LocalDateTime.now()) + .releaseName("testOne"); + + final String helmFile2 = "Artifacts/Deployment/HELM/sampleapp-services-helm.tgz"; + final AsDeploymentItem dItemTwo = new AsDeploymentItem().asDeploymentItemInstId(AS_DEPLOYMENT_ITEM_TWO_INST_ID) + .asInst(asInst).status(State.INSTANTIATED).name("sampleapp-services").itemId("2").deploymentOrder(2) + .artifactFilePath(helmFile2).createTime(LocalDateTime.now()).lastUpdateTime(LocalDateTime.now()) + .releaseName("testTwo"); + + asInst.asdeploymentItems(dItemOne); + asInst.asdeploymentItems(dItemTwo); + databaseServiceProvider.saveAsInst(asInst); + createKubeConfigFile(asInst); + } + + private void mockKubernetesClientEndpoint() { + + wireMockServer.stubFor(get(urlMatching("/apis/batch/v1/jobs\\?labelSelector.*&watch=false")) + .willReturn(aResponse().withBody(getJobList()).withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE))); + + wireMockServer.stubFor(get(urlMatching("/api/v1/pods\\?labelSelector.*&watch=false")) + .willReturn(aResponse().withBody(getPodList()).withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE))); + + wireMockServer.stubFor(get(urlMatching("/api/v1/services\\?labelSelector.*&watch=false")) + .willReturn(aResponse().withBody(getServiceList()).withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE))); + + wireMockServer.stubFor(get(urlMatching("/apis/apps/v1/deployments\\?labelSelector.*&watch=false")).willReturn( + aResponse().withBody(getDeploymentList()).withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE))); + + wireMockServer.stubFor(get(urlMatching("/apis/apps/v1/daemonsets\\?labelSelector.*&watch=false")) + .willReturn(aResponse().withBody(getDaemonList()).withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE))); + + wireMockServer.stubFor(get(urlMatching("/apis/apps/v1/replicasets\\?labelSelector.*&watch=false")).willReturn( + aResponse().withBody(getReplicaSetList()).withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE))); + + wireMockServer.stubFor(get(urlMatching("/apis/apps/v1/statefulsets\\?labelSelector.*&watch=false")).willReturn( + aResponse().withBody(getStatefulSetList()).withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE))); + } + + private void mockAAIEndPoints() { + + final String vnfEndPoint = "/aai/" + V19 + "/network/generic-vnfs/generic-vnf/" + AS_INST_ID; + + wireMockServer.stubFor(get(urlMatching(vnfEndPoint)).willReturn( + aResponse().withBody(gson.toJson(getGenericVnf())).withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE))); + wireMockServer.stubFor(post(urlMatching(vnfEndPoint)).willReturn(ok())); + } + + private String getServiceList() { + final V1ServiceList v1SeviceList = new V1ServiceList(); + v1SeviceList.setApiVersion("v1"); + v1SeviceList.setKind("ServiceList"); + return gson.toJson(v1SeviceList); + } + + private String getPodList() { + final V1PodList v1PodList = new V1PodList(); + v1PodList.setApiVersion("v1"); + v1PodList.setKind("PodList"); + return gson.toJson(v1PodList); + } + + private String getJobList() { + final V1JobList v1JobList = new V1JobList(); + v1JobList.setApiVersion("v1"); + v1JobList.setKind("JobList"); + return gson.toJson(v1JobList); + } + + private String getDeploymentList() { + final V1DeploymentList v1DeploymentList = new V1DeploymentList(); + v1DeploymentList.setApiVersion("v1"); + v1DeploymentList.setKind("DeploymentList"); + return gson.toJson(v1DeploymentList); + } + + private String getDaemonList() { + final V1DaemonSetList v1DaemonSetList = new V1DaemonSetList(); + v1DaemonSetList.setApiVersion("v1"); + v1DaemonSetList.setKind("DeploymentList"); + return gson.toJson(v1DaemonSetList); + } + + private String getStatefulSetList() { + final V1StatefulSetList v1StatefulSetList = new V1StatefulSetList(); + v1StatefulSetList.setApiVersion("v1"); + v1StatefulSetList.setKind("DeploymentList"); + return gson.toJson(v1StatefulSetList); + } + + private String getReplicaSetList() { + final V1ReplicaSetList v1ReplicaSetList = new V1ReplicaSetList(); + v1ReplicaSetList.setApiVersion("v1"); + v1ReplicaSetList.setKind("DeploymentList"); + return gson.toJson(v1ReplicaSetList); + } + + private GenericVnf getGenericVnf() { + final GenericVnf vnf = new GenericVnf(); + vnf.setVnfId(AS_INST_ID); + vnf.setOrchestrationStatus(OrchestrationStatusEnum.ACTIVATED.getValue()); + vnf.setResourceVersion("12345"); + return vnf; + } + +} -- 2.16.6