summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml15
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java41
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java18
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/BaseServiceBusinessLogicTest.java5
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/ServiceDistributionBLTest.java4
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicBaseTestSetup.java4
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicTest.java40
-rw-r--r--catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java4
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java11
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java148
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ToscaOperationExceptionSupplier.java37
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java2
-rw-r--r--catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java157
13 files changed, 465 insertions, 21 deletions
diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
index 10cc6f6712..9e7939d58b 100644
--- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
+++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
@@ -2636,6 +2636,21 @@ errors:
}
#---------SVC4164-----------------------------
+ # %1 - Component name
+ COMPONENT_NOT_ARCHIVED: {
+ code: 403,
+ message: "Component '%1' is not archived",
+ messageId: "SVC4692"
+ }
+
+ #---------SVC4165-----------------------------
+ # %1 - List of services
+ COMPONENT_IN_USE_BY_ANOTHER_COMPONENT: {
+ code: 403,
+ message: "Component is in use by '%1'",
+ messageId: "SVC4693"
+ }
+ #---------SVC4164-----------------------------
# %1 - componentType
# %2 - component name
CANNOT_DELETE_SYSTEM_DEPLOYED_RESOURCES: {
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java
index aa011e91f4..8dac6ffc08 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java
@@ -102,6 +102,7 @@ import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.ModelTypeEnum;
import org.openecomp.sdc.be.externalapi.servlet.representation.ServiceDistributionReqInfo;
import org.openecomp.sdc.be.impl.ForwardingPathUtils;
import org.openecomp.sdc.be.impl.WebAppContextWrapper;
@@ -123,6 +124,7 @@ import org.openecomp.sdc.be.model.PropertyDefinition;
import org.openecomp.sdc.be.model.Resource;
import org.openecomp.sdc.be.model.Service;
import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.Model;
import org.openecomp.sdc.be.model.category.CategoryDefinition;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ForwardingPathOperation;
@@ -133,6 +135,7 @@ import org.openecomp.sdc.be.model.operations.api.IGroupOperation;
import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation;
+import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
import org.openecomp.sdc.be.model.operations.utils.ComponentValidationUtils;
import org.openecomp.sdc.be.plugins.ServiceCreationPlugin;
@@ -194,6 +197,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
private ServiceCategoryValidator serviceCategoryValidator;
@Autowired
private ServiceValidator serviceValidator;
+ private final ModelOperation modelOperation;
@Autowired
public ServiceBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, IGroupInstanceOperation groupInstanceOperation,
@@ -205,7 +209,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
ComponentContactIdValidator componentContactIdValidator, ComponentNameValidator componentNameValidator,
ComponentTagsValidator componentTagsValidator, ComponentValidator componentValidator,
ComponentIconValidator componentIconValidator, ComponentProjectCodeValidator componentProjectCodeValidator,
- ComponentDescriptionValidator componentDescriptionValidator) {
+ ComponentDescriptionValidator componentDescriptionValidator, ModelOperation modelOperation) {
super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, groupBusinessLogic, interfaceOperation,
interfaceLifecycleTypeOperation, artifactsBusinessLogic, artifactToscaOperation, componentContactIdValidator, componentNameValidator,
componentTagsValidator, componentValidator, componentIconValidator, componentProjectCodeValidator, componentDescriptionValidator);
@@ -214,6 +218,7 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
this.serviceDistributionValidation = serviceDistributionValidation;
this.forwardingPathValidator = forwardingPathValidator;
this.uiComponentDataConverter = uiComponentDataConverter;
+ this.modelOperation = modelOperation;
}
@Autowired
@@ -1301,7 +1306,39 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
return Either.left(serviceRelations);
}
- public ResponseFormat deleteService(String serviceId, User user) {
+ public void deleteServiceAllVersions(String serviceId, User user) {
+ validateUserExists(user);
+ Either<Service, StorageOperationStatus> serviceStatus = toscaOperationFacade.getToscaElement(serviceId);
+ if (serviceStatus.isRight()) {
+ log.debug("Failed to get service {}", serviceId);
+ componentException(serviceStatus.right().value());
+ }
+ Service service = serviceStatus.left().value();
+ if (Boolean.FALSE.equals(service.isArchived())) {
+ log.debug("The service, {}, requested for delete has not been archived.", serviceId);
+ throw new ComponentException(ActionStatus.COMPONENT_NOT_ARCHIVED, serviceId);
+ }
+ List<String> deletedServiceList = new ArrayList<>();
+ try {
+ String model = service.getModel();
+ final Optional<Model> modelOptional = modelOperation.findModelByName(model);
+ deletedServiceList = toscaOperationFacade.deleteService(service.getInvariantUUID(), true);
+ if (log.isDebugEnabled()) {
+ deletedServiceList.forEach(deletedS -> log.debug("Component {} was deleted.", deletedS));
+ }
+ if (modelOptional.isPresent() && modelOptional.get().getModelType() == ModelTypeEnum.NORMATIVE_EXTENSION) {
+ modelOperation.deleteModel(modelOptional.get(), false);
+ }
+ toscaOperationFacade.commitAndCheck(service.getUniqueId());
+ updateCatalog(service, ChangeTypeEnum.DELETE);
+ } catch (ComponentException exception) {
+ log.debug("Failed to delete service, {}, in ServiceServlet", serviceId);
+ janusGraphDao.rollback();
+ throw exception;
+ }
+ }
+
+ public ResponseFormat markServiceForDeletion(String serviceId, User user) {
ResponseFormat responseFormat;
validateUserExists(user);
Either<Service, StorageOperationStatus> serviceStatus = toscaOperationFacade.getToscaElement(serviceId);
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java
index bf171c2042..bcedc60d40 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ServiceServlet.java
@@ -52,6 +52,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
@@ -109,6 +110,8 @@ public class ServiceServlet extends AbstractValidationsServlet {
private final ElementBusinessLogic elementBusinessLogic;
private final ServiceBusinessLogic serviceBusinessLogic;
+ public enum Action {DELETE, MARK_AS_DELETE}
+
@Inject
public ServiceServlet(UserBusinessLogic userBusinessLogic, ComponentInstanceBusinessLogic componentInstanceBL, ComponentsUtils componentsUtils,
ServletUtils servletUtils, ResourceImportManager resourceImportManager, ServiceBusinessLogic serviceBusinessLogic,
@@ -269,7 +272,12 @@ public class ServiceServlet extends AbstractValidationsServlet {
@ApiResponse(responseCode = "400", description = "Invalid content / Missing content"),
@ApiResponse(responseCode = "404", description = "Service not found")})
@PermissionAllowed(AafPermission.PermNames.INTERNAL_ALL_VALUE)
- public Response deleteService(@PathParam("serviceId") final String serviceId, @Context final HttpServletRequest request) {
+ public Response deleteService(@PathParam("serviceId") final String serviceId,
+ @Parameter(description = "Optional parameter to determine the delete action: " +
+ "DELETE, which will permanently delete theService from the system or " +
+ "MARK_AS_DELETE, which will logically mark the service as deleted. Default action is to MARK_AS_DELETE")
+ @QueryParam("deleteAction") final Action deleteAction,
+ @Context final HttpServletRequest request) {
ServletContext context = request.getSession().getServletContext();
String url = request.getMethod() + " " + request.getRequestURI();
log.debug(START_HANDLE_REQUEST_OF, url);
@@ -284,7 +292,13 @@ public class ServiceServlet extends AbstractValidationsServlet {
.log(LoggerSupportabilityActions.DELETE_SERVICE, StatusCode.STARTED, "Starting to delete service {} by user {} ", serviceIdLower,
userId);
ServiceBusinessLogic businessLogic = getServiceBL(context);
- ResponseFormat actionResponse = businessLogic.deleteService(serviceIdLower, modifier);
+ ResponseFormat actionResponse;
+ if (Action.DELETE.equals(deleteAction)) {
+ businessLogic.deleteServiceAllVersions(serviceIdLower, modifier);
+ actionResponse = componentsUtils.getResponseFormat(ActionStatus.NO_CONTENT);
+ } else {
+ actionResponse = businessLogic.markServiceForDeletion(serviceIdLower, modifier);
+ }
if (actionResponse.getStatus() != HttpStatus.SC_NO_CONTENT) {
log.debug("failed to delete service");
return buildErrorResponse(actionResponse);
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/BaseServiceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/BaseServiceBusinessLogicTest.java
index ee37ea130d..692e8cce50 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/BaseServiceBusinessLogicTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/BaseServiceBusinessLogicTest.java
@@ -67,6 +67,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade
import org.openecomp.sdc.be.model.operations.api.IElementOperation;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
import org.openecomp.sdc.be.model.operations.impl.GraphLockOperation;
+import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
import org.openecomp.sdc.be.resources.data.auditing.ResourceAdminEvent;
import org.openecomp.sdc.be.user.Role;
import org.openecomp.sdc.be.user.UserBusinessLogic;
@@ -98,6 +99,7 @@ public abstract class BaseServiceBusinessLogicTest extends ComponentBusinessLogi
private ToscaOperationFacade toscaOperationFacade = Mockito.mock(ToscaOperationFacade.class);
private GenericTypeBusinessLogic genericTypeBusinessLogic = Mockito.mock(GenericTypeBusinessLogic.class);
private ForwardingPathOperation forwardingPathOperation = Mockito.mock(ForwardingPathOperation.class);
+ private final ModelOperation modelOperation = Mockito.mock(ModelOperation.class);
User user = null;
Service serviceResponse = null;
@@ -165,7 +167,8 @@ public abstract class BaseServiceBusinessLogicTest extends ComponentBusinessLogi
artifactsBusinessLogic, distributionEngine, componentInstanceBusinessLogic,
serviceDistributionValidation, forwardingPathValidator, uiComponentDataConverter,
artifactToscaOperation, componentContactIdValidator, componentNameValidator,
- componentTagsValidator, componentValidator, componentIconValidator, componentProjectCodeValidator, componentDescriptionValidator);
+ componentTagsValidator, componentValidator, componentIconValidator, componentProjectCodeValidator, componentDescriptionValidator,
+ modelOperation);
bl.setUserAdmin(mockUserAdmin);
bl.setGraphLockOperation(graphLockOperation);
bl.setJanusGraphDao(mockJanusGraphDao);
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/ServiceDistributionBLTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/ServiceDistributionBLTest.java
index 72cb51676b..0b3973e584 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/ServiceDistributionBLTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/ServiceDistributionBLTest.java
@@ -53,6 +53,7 @@ import org.openecomp.sdc.be.model.DistributionStatusEnum;
import org.openecomp.sdc.be.model.Service;
import org.openecomp.sdc.be.model.User;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
+import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
import org.openecomp.sdc.common.impl.ExternalConfiguration;
import org.openecomp.sdc.common.util.ThreadLocalsHolder;
import org.openecomp.sdc.exception.ResponseFormat;
@@ -66,6 +67,7 @@ class ServiceDistributionBLTest extends ComponentBusinessLogicMock {
private final ComponentInstanceBusinessLogic componentInstanceBusinessLogic = Mockito.mock(ComponentInstanceBusinessLogic.class);
private final ForwardingPathValidator forwardingPathValidator = Mockito.mock(ForwardingPathValidator.class);
private final UiComponentDataConverter uiComponentDataConverter = Mockito.mock(UiComponentDataConverter.class);
+ private final ModelOperation modelOperation = Mockito.mock(ModelOperation.class);
@InjectMocks
private final ServiceBusinessLogic bl = new ServiceBusinessLogic(elementDao, groupOperation, groupInstanceOperation,
@@ -74,7 +76,7 @@ class ServiceDistributionBLTest extends ComponentBusinessLogicMock {
serviceDistributionValidation, forwardingPathValidator, uiComponentDataConverter,
artifactToscaOperation, componentContactIdValidator,
componentNameValidator, componentTagsValidator, componentValidator, componentIconValidator,
- componentProjectCodeValidator, componentDescriptionValidator);
+ componentProjectCodeValidator, componentDescriptionValidator, modelOperation);
private Service serviceToActivate;
private ActivationRequestInformation activationRequestInformation;
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicBaseTestSetup.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicBaseTestSetup.java
index 44daa34aeb..5b4585136f 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicBaseTestSetup.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicBaseTestSetup.java
@@ -78,6 +78,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade
import org.openecomp.sdc.be.model.operations.api.IElementOperation;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
import org.openecomp.sdc.be.model.operations.impl.GraphLockOperation;
+import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
import org.openecomp.sdc.be.resources.data.auditing.DistributionDeployEvent;
import org.openecomp.sdc.be.resources.data.auditing.DistributionNotificationEvent;
import org.openecomp.sdc.be.resources.data.auditing.ResourceAdminEvent;
@@ -110,6 +111,7 @@ class ServiceBusinessLogicBaseTestSetup extends BaseBusinessLogicMock {
protected CatalogOperation catalogOperation = Mockito.mock(CatalogOperation.class);
protected ResourceAdminEvent auditArchive2 = Mockito.mock(ResourceAdminEvent.class);
protected ResourceAdminEvent auditRestore = Mockito.mock(ResourceAdminEvent.class);
+ protected ModelOperation modelOperation = Mockito.mock(ModelOperation.class);
IElementOperation mockElementDao = new ElementOperationMock();
DistributionEngine distributionEngine = Mockito.mock(DistributionEngine.class);
ServiceDistributionValidation serviceDistributionValidation = Mockito.mock(ServiceDistributionValidation.class);
@@ -209,7 +211,7 @@ class ServiceBusinessLogicBaseTestSetup extends BaseBusinessLogicMock {
serviceDistributionValidation, forwardingPathValidator, uiComponentDataConverter,
artifactToscaOperation, componentContactIdValidator,
componentNameValidator, componentTagsValidator, componentValidator,
- componentIconValidator, componentProjectCodeValidator, componentDescriptionValidator);
+ componentIconValidator, componentProjectCodeValidator, componentDescriptionValidator, modelOperation);
bl.setComponentContactIdValidator(componentContactIdValidator);
bl.setComponentIconValidator(componentIconValidator);
bl.setComponentTagsValidator(componentTagsValidator);
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicTest.java
index 5c074b0599..69938cd527 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicTest.java
@@ -28,6 +28,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Mockito.when;
@@ -41,7 +42,9 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.UUID;
+
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
@@ -51,16 +54,20 @@ import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.InterfaceInstanceDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.ListDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.ModelTypeEnum;
import org.openecomp.sdc.be.model.ArtifactDefinition;
import org.openecomp.sdc.be.model.Component;
import org.openecomp.sdc.be.model.ComponentInstance;
import org.openecomp.sdc.be.model.ComponentInstanceInterface;
import org.openecomp.sdc.be.model.GroupInstance;
+import org.openecomp.sdc.be.model.Model;
import org.openecomp.sdc.be.model.Operation;
import org.openecomp.sdc.be.model.PropertyDefinition;
import org.openecomp.sdc.be.model.Resource;
import org.openecomp.sdc.be.model.Service;
import org.openecomp.sdc.be.model.category.CategoryDefinition;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ToscaOperationException;
+import org.openecomp.sdc.be.model.operations.StorageException;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
import org.openecomp.sdc.be.plugins.ServiceCreationPlugin;
import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum;
@@ -659,6 +666,39 @@ class ServiceBusinessLogicTest extends ServiceBusinessLogicBaseTestSetup {
assertFalse(resourceIdList.contains(resourceInUse));
}
+ @Test
+ void testDeleteArchivedService_NotFound() {
+ Mockito.when(toscaOperationFacade.getToscaElement(Mockito.anyString())).thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+ assertThrows(StorageException.class, () -> bl.deleteServiceAllVersions("1", user));
+ }
+
+ @Test
+ void testDeleteArchivedService_NotArchived() {
+ String serviceId = "12345";
+ Either<Component, StorageOperationStatus> eitherService = Either.left(createNewService());
+ eitherService.left().value().setArchived(false);
+ Mockito.when(toscaOperationFacade.getToscaElement(Mockito.anyString())).thenReturn(eitherService);
+ final ComponentException actualException = assertThrows(ComponentException.class, () -> bl.deleteServiceAllVersions(serviceId, user));
+ assertEquals(actualException.getActionStatus(), ActionStatus.COMPONENT_NOT_ARCHIVED);
+ assertEquals(actualException.getParams()[0], serviceId);
+ }
+
+ @Test
+ void testDeleteArchivedService_DeleteServiceSpecificModel() throws ToscaOperationException {
+ String serviceId = "12345";
+ String model = "serviceSpecificModel";
+ List<String> deletedServcies= new ArrayList<>();
+ deletedServcies.add("54321");
+ Model normativeExtensionModel = new Model("normativeExtensionModel", ModelTypeEnum.NORMATIVE_EXTENSION);
+ Either<Component, StorageOperationStatus> eitherService = Either.left(createNewService());
+ eitherService.left().value().setArchived(true);
+ eitherService.left().value().setModel(model);
+ Mockito.when(toscaOperationFacade.getToscaElement(Mockito.anyString())).thenReturn(eitherService);
+ Mockito.when(toscaOperationFacade.deleteService(Mockito.anyString(), Mockito.eq(true))).thenReturn(deletedServcies);
+ Mockito.when(modelOperation.findModelByName(model)).thenReturn(Optional.of(normativeExtensionModel));
+ bl.deleteServiceAllVersions(serviceId, user);
+ Mockito.verify(modelOperation, Mockito.times(1)).deleteModel(normativeExtensionModel, false);
+ }
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
index 922853e8f0..3b5c9955d2 100644
--- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
+++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
@@ -62,7 +62,7 @@ public enum ActionStatus {
// Attribute related
ATTRIBUTE_ALREADY_EXIST, ATTRIBUTE_NOT_FOUND, INVALID_ATTRIBUTE,
// State related
- INVALID_SERVICE_STATE, COMPONENT_IN_CHECKOUT_STATE, ILLEGAL_COMPONENT_STATE, COMPONENT_IN_CERT_IN_PROGRESS_STATE, COMPONENT_SENT_FOR_CERTIFICATION, COMPONENT_VERSION_ALREADY_EXIST, COMPONENT_ALREADY_CHECKED_IN, COMPONENT_CHECKOUT_BY_ANOTHER_USER, COMPONENT_IN_USE, COMPONENT_HAS_NEWER_VERSION, COMPONENT_ALREADY_CERTIFIED, COMPONENT_NOT_READY_FOR_CERTIFICATION, COMPONENT_ARTIFACT_NOT_FOUND, COMPONENT_INSTANCE_NOT_FOUND, COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, SERVICE_NOT_FOUND, SERVICE_CATEGORY_CANNOT_BE_CHANGED, SERVICE_NAME_CANNOT_BE_CHANGED, SERVICE_ICON_CANNOT_BE_CHANGED, COMPONENT_TOO_MUCH_CATEGORIES, SERVICE_CANNOT_CONTAIN_SUBCATEGORY, RESOURCE_CATEGORY_CANNOT_BE_CHANGED, RESOURCE_NAME_CANNOT_BE_CHANGED, RESOURCE_ICON_CANNOT_BE_CHANGED, RESOURCE_VENDOR_NAME_CANNOT_BE_CHANGED, RESOURCE_TOO_MUCH_SUBCATEGORIES, SERVICE_ICON_EXCEEDS_LIMIT, RESOURCE_INSTANCE_NOT_FOUND, RESOURCE_INSTANCE_BAD_REQUEST, RESOURCE_INSTANCE_MATCH_NOT_FOUND, RESOURCE_INSTANCE_ALREADY_EXIST, RESOURCE_INSTANCE_RELATION_NOT_FOUND, COMPONENT_MISSING_SUBCATEGORY, COMPONENT_INVALID_SUBCATEGORY, ARTIFACT_TYPE_NOT_SUPPORTED, MISSING_ARTIFACT_TYPE, ARTIFACT_LOGICAL_NAME_CANNOT_BE_CHANGED, ARTIFACT_EXIST, ARTIFACT_NOT_FOUND, ARTIFACT_INVALID_MD5, MISSING_ARTIFACT_NAME, MISSING_PROJECT_CODE, INVALID_PROJECT_CODE, COMPONENT_MISSING_MANDATORY_ARTIFACTS, LIFECYCLE_TYPE_ALREADY_EXIST, SERVICE_NOT_AVAILABLE_FOR_DISTRIBUTION, MISSING_LIFECYCLE_TYPE, RESOURCE_VFCMT_LIFECYCLE_STATE_NOT_VALID,
+ INVALID_SERVICE_STATE, COMPONENT_IN_CHECKOUT_STATE, ILLEGAL_COMPONENT_STATE, COMPONENT_IN_CERT_IN_PROGRESS_STATE, COMPONENT_SENT_FOR_CERTIFICATION, COMPONENT_VERSION_ALREADY_EXIST, COMPONENT_ALREADY_CHECKED_IN, COMPONENT_CHECKOUT_BY_ANOTHER_USER, COMPONENT_IN_USE, COMPONENT_IN_USE_BY_ANOTHER_COMPONENT, COMPONENT_HAS_NEWER_VERSION, COMPONENT_ALREADY_CERTIFIED, COMPONENT_NOT_READY_FOR_CERTIFICATION, COMPONENT_ARTIFACT_NOT_FOUND, COMPONENT_INSTANCE_NOT_FOUND, COMPONENT_INSTANCE_NOT_FOUND_ON_CONTAINER, SERVICE_NOT_FOUND, SERVICE_CATEGORY_CANNOT_BE_CHANGED, SERVICE_NAME_CANNOT_BE_CHANGED, SERVICE_ICON_CANNOT_BE_CHANGED, COMPONENT_TOO_MUCH_CATEGORIES, SERVICE_CANNOT_CONTAIN_SUBCATEGORY, RESOURCE_CATEGORY_CANNOT_BE_CHANGED, RESOURCE_NAME_CANNOT_BE_CHANGED, RESOURCE_ICON_CANNOT_BE_CHANGED, RESOURCE_VENDOR_NAME_CANNOT_BE_CHANGED, RESOURCE_TOO_MUCH_SUBCATEGORIES, SERVICE_ICON_EXCEEDS_LIMIT, RESOURCE_INSTANCE_NOT_FOUND, RESOURCE_INSTANCE_BAD_REQUEST, RESOURCE_INSTANCE_MATCH_NOT_FOUND, RESOURCE_INSTANCE_ALREADY_EXIST, RESOURCE_INSTANCE_RELATION_NOT_FOUND, COMPONENT_MISSING_SUBCATEGORY, COMPONENT_INVALID_SUBCATEGORY, ARTIFACT_TYPE_NOT_SUPPORTED, MISSING_ARTIFACT_TYPE, ARTIFACT_LOGICAL_NAME_CANNOT_BE_CHANGED, ARTIFACT_EXIST, ARTIFACT_NOT_FOUND, ARTIFACT_INVALID_MD5, MISSING_ARTIFACT_NAME, MISSING_PROJECT_CODE, INVALID_PROJECT_CODE, COMPONENT_MISSING_MANDATORY_ARTIFACTS, LIFECYCLE_TYPE_ALREADY_EXIST, SERVICE_NOT_AVAILABLE_FOR_DISTRIBUTION, MISSING_LIFECYCLE_TYPE, RESOURCE_VFCMT_LIFECYCLE_STATE_NOT_VALID,
// Distribution
BAD_REQUEST_MISSING_RESOURCE, MISSING_USER_ID, MISSING_X_ECOMP_INSTANCE_ID, MISSING_PUBLIC_KEY, MISSING_ENV_NAME, DISTRIBUTION_ENV_DOES_NOT_EXIST, MISSING_BODY, ECOMP_RESEND_WITH_BASIC_AUTHENTICATION_CREDENTIALS, ECOMP_COMPONENT_NOT_AUTHORIZED, METHOD_NOT_ALLOWED_TO_DOWNLOAD_ARTIFACT, REGISTRATION_FAILED, DISTRIBUTION_ENVIRONMENT_NOT_AVAILABLE, DISTRIBUTION_ENVIRONMENT_NOT_FOUND, DISTRIBUTION_ENVIRONMENT_INVALID, DISTRIBUTION_REQUESTED_NOT_FOUND, DISTRIBUTION_REQUESTED_FAILED, DISTRIBUTION_NOT_FOUND, ADDITIONAL_INFORMATION_ALREADY_EXISTS, COMPONENT_VERSION_NOT_FOUND, ADDITIONAL_INFORMATION_MAX_NUMBER_REACHED, ADDITIONAL_INFORMATION_EMPTY_STRING_NOT_ALLOWED, ADDITIONAL_INFORMATION_EXCEEDS_LIMIT, ADDITIONAL_INFORMATION_KEY_NOT_ALLOWED_CHARACTERS, ADDITIONAL_INFORMATION_VALUE_NOT_ALLOWED_CHARACTERS, ADDITIONAL_INFORMATION_NOT_FOUND, ASDC_VERSION_NOT_FOUND, MISSING_DATA, EXCEEDS_LIMIT, UNSUPPORTED_ERROR, ARTIFACT_INVALID_TIMEOUT, SERVICE_IS_VNF_CANNOT_BE_CHANGED, RESOURCE_INSTANCE_NOT_FOUND_ON_SERVICE, WRONG_ARTIFACT_FILE_EXTENSION, INVALID_YAML, INVALID_XML, INVALID_JSON, INVALID_DEPLOYMENT_ARTIFACT_HEAT, INVALID_HEAT_PARAMETER_TYPE, INVALID_HEAT_PARAMETER_VALUE, DEPLOYMENT_ARTIFACT_OF_TYPE_ALREADY_EXISTS, DEPLOYMENT_ARTIFACT_NAME_ALREADY_EXISTS, MISSING_HEAT, MISMATCH_HEAT_VS_HEAT_ENV, CORRUPTED_FORMAT, MISMATCH_BETWEEN_ARTIFACT_TYPE_AND_COMPONENT_TYPE, INVALID_PARAMS_IN_HEAT_ENV_FILE, API_RESOURCE_NOT_FOUND,
//UEB
@@ -100,7 +100,7 @@ public enum ActionStatus {
//policies
RESOURCE_CANNOT_CONTAIN_POLICIES, POLICY_NOT_FOUND_ON_CONTAINER, INVALID_POLICY_NAME, POLICY_NAME_ALREADY_EXIST, EXCLUDED_POLICY_TYPE, POLICY_MISSING_POLICY_TYPE, POLICY_TYPE_IS_INVALID,
//External References Statuses
- EXT_REF_ALREADY_EXIST, EXT_REF_NOT_FOUND, POLICY_TARGET_DOES_NOT_EXIST, POLICY_TARGET_TYPE_DOES_NOT_EXIST, INPUTS_NOT_FOUND, RESOURCE_LIFECYCLE_STATE_NOT_VALID, COMPONENT_IS_ARCHIVED,
+ EXT_REF_ALREADY_EXIST, EXT_REF_NOT_FOUND, POLICY_TARGET_DOES_NOT_EXIST, POLICY_TARGET_TYPE_DOES_NOT_EXIST, INPUTS_NOT_FOUND, RESOURCE_LIFECYCLE_STATE_NOT_VALID, COMPONENT_IS_ARCHIVED, COMPONENT_NOT_ARCHIVED,
//Automated upgrade
COMPONENT_IS_NOT_HIHGEST_CERTIFIED, NO_INSTANCES_TO_UPGRADE, ARCHIVED_ORIGINS_FOUND, UPDATE_CATALOG_FAILED,
//Interface
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java
index 9e9b944fae..caedbeeb62 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaElementOperation.java
@@ -150,6 +150,17 @@ public abstract class ToscaElementOperation extends BaseOperation {
return Either.left(vertexG);
}
+ protected GraphVertex getHighestVersionFrom(GraphVertex v) {
+ Either<GraphVertex, JanusGraphOperationStatus> childVertexE = janusGraphDao
+ .getChildVertex(v, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse);
+ GraphVertex highestVersionVertex = v;
+ while (childVertexE.isLeft()) {
+ highestVersionVertex = childVertexE.left().value();
+ childVertexE = janusGraphDao.getChildVertex(highestVersionVertex, EdgeLabelEnum.VERSION, JsonParseFlagEnum.NoParse);
+ }
+ return highestVersionVertex;
+ }
+
public Either<ToscaElement, StorageOperationStatus> getToscaElement(String uniqueId) {
return getToscaElement(uniqueId, new ComponentParametersView());
}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
index 496fd0fe08..0546a91369 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
@@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
@@ -42,6 +43,7 @@ import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
+import java.util.TreeSet;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
@@ -79,6 +81,7 @@ import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.PromoteVersionEnum;
import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
@@ -114,8 +117,11 @@ import org.openecomp.sdc.be.model.catalog.CatalogComponent;
import org.openecomp.sdc.be.model.jsonjanusgraph.config.ContainerInstanceTypesData;
import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate;
import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
+import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElementTypeEnum;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.ToscaOperationExceptionSupplier;
import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
import org.openecomp.sdc.be.model.operations.StorageException;
+import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder;
@@ -144,6 +150,8 @@ public class ToscaOperationFacade {
private static final String COULDNT_FETCH_COMPONENT_WITH_AND_UNIQUE_ID_ERROR = "Couldn't fetch component with and unique id {}, error: {}";
private static final Logger log = Logger.getLogger(ToscaOperationFacade.class.getName());
@Autowired
+ private IGraphLockOperation graphLockOperation;
+ @Autowired
private NodeTypeOperation nodeTypeOperation;
@Autowired
private TopologyTemplateOperation topologyTemplateOperation;
@@ -992,21 +1000,122 @@ public class ToscaOperationFacade {
return Either.left(checkIfInUseAndDelete(allMarked));
}
- private List<String> checkIfInUseAndDelete(List<GraphVertex> allMarked) {
+ public List<String> deleteService(String invariantUUID, final boolean inTransaction) {
+ List<GraphVertex> allServiceVerticesToDelete = getVerticesForAllVersions(invariantUUID, ToscaElementTypeEnum.TOPOLOGY_TEMPLATE);
+ List<String> affectedComponentIds = new ArrayList<>();
+ try {
+ checkNotUsed( allServiceVerticesToDelete);
+ lockAllVerticesByNodeType(allServiceVerticesToDelete, NodeTypeEnum.Service);
+ for (GraphVertex elementV : allServiceVerticesToDelete) {
+ Either<ToscaElement, StorageOperationStatus> deleteToscaElement = deleteToscaElement(elementV);
+ if (deleteToscaElement.isRight()) {
+ log.debug("Failed to delete element UniqueID {}, Name {}, error {}", elementV.getUniqueId(),
+ elementV.getMetadataProperties().get(GraphPropertyEnum.NAME), deleteToscaElement.right().value());
+ throwStorageException(deleteToscaElement.right().value());
+ }
+ affectedComponentIds.add(elementV.getUniqueId());
+ }
+ if (!inTransaction) {
+ janusGraphDao.commit();
+ }
+ } catch (Exception exception) {
+ if (!inTransaction) {
+ janusGraphDao.rollback();
+ }
+ throw exception;
+ } finally {
+ unlockAllVerticesByNodeType(allServiceVerticesToDelete, NodeTypeEnum.Service);
+ }
+ return affectedComponentIds;
+ }
+
+ private void checkNotUsed(List<GraphVertex> vertices) {
+ boolean isInUse = isAnyComponentInUse(vertices);
+ if (isInUse) {
+ Set<GraphVertex> listOfVertices = getComponentsUsingComponents(vertices);
+ List<String> listOfStringComponents = new ArrayList<>();
+ for (GraphVertex componentVertex : listOfVertices) {
+ listOfStringComponents.add(
+ componentVertex.getMetadataJson().get(GraphPropertyEnum.COMPONENT_TYPE.getProperty()) + " "
+ + componentVertex.getMetadataJson().get(GraphPropertyEnum.NAME.getProperty())
+ );
+ }
+ String stringOfComponents = String.join(", ", listOfStringComponents);
+ throw ToscaOperationExceptionSupplier.componentInUse(stringOfComponents).get();
+ }
+ }
+
+ private List<GraphVertex> getVerticesForAllVersions(String invariantUUID, ToscaElementTypeEnum componentType){
+ Either<List<Component>, StorageOperationStatus> allComponents =
+ getComponentListByInvariantUuid(invariantUUID, null);
+ if (allComponents.isRight()) {
+ throwStorageException(allComponents.right().value());
+ }
+ List<GraphVertex> allComponentVertices = new ArrayList<>();
+ for (Component component : allComponents.left().value()) {
+ Either<GraphVertex, StorageOperationStatus> componentGraphVertex = topologyTemplateOperation
+ .getComponentByLabelAndId(component.getUniqueId(), componentType, JsonParseFlagEnum.ParseAll);
+ if (componentGraphVertex.isRight()) {
+ throwStorageException(componentGraphVertex.right().value());
+ }
+ allComponentVertices.add(componentGraphVertex.left().value());
+ }
+ return allComponentVertices;
+ }
+
+ public void commitAndCheck(String componentId) {
+ JanusGraphOperationStatus status = janusGraphDao.commit();
+ if (!status.equals(JanusGraphOperationStatus.OK)) {
+ log.debug("error occurred when trying to DELETE {}. Return code is: {}", componentId, status);
+ throwStorageException(DaoStatusConverter.convertJanusGraphStatusToStorageStatus(status));
+ }
+ }
+
+ private Set<GraphVertex> getComponentsUsingComponents(List<GraphVertex> componentVertices) {
+ Set<GraphVertex> inUseBy = new TreeSet<>(Comparator.comparing(GraphVertex::getUniqueId));
+ for (final GraphVertex elementV : componentVertices) {
+ List<GraphVertex> inUseByVertex = isInUse(elementV);
+ if (!inUseByVertex.isEmpty()) {
+ inUseBy.addAll(inUseByVertex);
+ }
+ }
+ return inUseBy;
+ }
+
+ private boolean isAnyComponentInUse(List<GraphVertex> componentVertices) {
+ boolean isComponentInUse = false;
+ if (log.isDebugEnabled()) {
+ for (final GraphVertex graphVertex : componentVertices) {
+ if (!isInUse(graphVertex).isEmpty()) {
+ isComponentInUse = true;
+ }
+ }
+ } else {
+ isComponentInUse = componentVertices.stream().anyMatch(vertex -> !isInUse(vertex).isEmpty());
+ }
+ return isComponentInUse;
+ }
+
+ private List<GraphVertex> isInUse(GraphVertex elementV) {
final List<EdgeLabelEnum> forbiddenEdgeLabelEnums = Arrays
- .asList(EdgeLabelEnum.INSTANCE_OF, EdgeLabelEnum.PROXY_OF, EdgeLabelEnum.ALLOTTED_OF);
- List<String> deleted = new ArrayList<>();
- for (GraphVertex elementV : allMarked) {
- boolean isAllowedToDelete = true;
- for (EdgeLabelEnum edgeLabelEnum : forbiddenEdgeLabelEnums) {
- Either<Edge, JanusGraphOperationStatus> belongingEdgeByCriteria = janusGraphDao
- .getBelongingEdgeByCriteria(elementV, edgeLabelEnum, null);
- if (belongingEdgeByCriteria.isLeft()) {
- log.debug("Marked element {} in use. don't delete it", elementV.getUniqueId());
- isAllowedToDelete = false;
- break;
+ .asList(EdgeLabelEnum.INSTANCE_OF, EdgeLabelEnum.PROXY_OF, EdgeLabelEnum.ALLOTTED_OF);
+ for (EdgeLabelEnum edgeLabelEnum : forbiddenEdgeLabelEnums) {
+ Either<List<GraphVertex>, JanusGraphOperationStatus> inUseBy =
+ janusGraphDao.getParentVertices(elementV, edgeLabelEnum, JsonParseFlagEnum.ParseAll);
+ if (inUseBy.isLeft()) {
+ if (log.isDebugEnabled()) {
+ log.debug("Element {} in use.", elementV.getUniqueId());
}
+ return inUseBy.left().value();
}
+ }
+ return Collections.emptyList();
+ }
+
+ private List<String> checkIfInUseAndDelete(List<GraphVertex> allMarked) {
+ List<String> deleted = new ArrayList<>();
+ for (GraphVertex elementV : allMarked) {
+ boolean isAllowedToDelete = !isInUse(elementV).isEmpty();
if (isAllowedToDelete) {
Either<ToscaElement, StorageOperationStatus> deleteToscaElement = deleteToscaElement(elementV);
if (deleteToscaElement.isRight()) {
@@ -1020,6 +1129,21 @@ public class ToscaOperationFacade {
return deleted;
}
+ private void lockAllVerticesByNodeType(List<GraphVertex> allVerticesToLock, NodeTypeEnum nodeType) {
+ for (GraphVertex graphVertex : allVerticesToLock) {
+ StorageOperationStatus storageOperationStatus = graphLockOperation.lockComponent(graphVertex.getUniqueId(), nodeType);
+ if (!storageOperationStatus.equals(StorageOperationStatus.OK)) {
+ throwStorageException(storageOperationStatus);
+ }
+ }
+ }
+
+ private void unlockAllVerticesByNodeType(List<GraphVertex> allVerticesToUnlock, NodeTypeEnum nodeType) {
+ for (GraphVertex graphVertex : allVerticesToUnlock) {
+ graphLockOperation.unlockComponent(graphVertex.getUniqueId(), nodeType);
+ }
+ }
+
public Either<List<String>, StorageOperationStatus> getAllComponentsMarkedForDeletion(ComponentTypeEnum componentType) {
Either<List<GraphVertex>, StorageOperationStatus> allComponentsMarkedForDeletion;
switch (componentType) {
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ToscaOperationExceptionSupplier.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ToscaOperationExceptionSupplier.java
new file mode 100644
index 0000000000..62d7e29b48
--- /dev/null
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/exception/ToscaOperationExceptionSupplier.java
@@ -0,0 +1,37 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 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.openecomp.sdc.be.model.jsonjanusgraph.operations.exception;
+
+import java.util.function.Supplier;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+
+public class ToscaOperationExceptionSupplier {
+
+ private ToscaOperationExceptionSupplier() {
+
+ }
+
+ public static Supplier<OperationException> componentInUse(final String stringOfServices) {
+ return () -> new OperationException(ActionStatus.COMPONENT_IN_USE_BY_ANOTHER_COMPONENT, stringOfServices);
+ }
+
+}
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java
index 4fbb5fbef3..491603081f 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/api/StorageOperationStatus.java
@@ -64,6 +64,8 @@ public enum StorageOperationStatus {
PROPERTY_NAME_ALREADY_EXISTS,
INVALID_PROPERTY,
COMPONENT_IS_ARCHIVED,
+ COMPONENT_NOT_ARCHIVED,
+ COMPONENT_IN_USE_BY_ANOTHER_COMPONENT,
DECLARED_INPUT_USED_BY_OPERATION;
// @formatter:on
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java
index c0c417a324..625ec39837 100644
--- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java
+++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacadeTest.java
@@ -36,6 +36,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyMap;
@@ -70,6 +71,8 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
+import org.openecomp.sdc.be.config.ComponentType;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphDao;
@@ -84,6 +87,7 @@ import org.openecomp.sdc.be.datatypes.elements.RequirementDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
+import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.PromoteVersionEnum;
import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
@@ -106,7 +110,10 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.NodeType;
import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate;
import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElementTypeEnum;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.exception.OperationException;
import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
+import org.openecomp.sdc.be.model.operations.StorageException;
+import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
@RunWith(MockitoJUnitRunner.class)
@@ -137,6 +144,9 @@ public class ToscaOperationFacadeTest {
@Mock
private NodeTemplateOperation nodeTemplateOperationMock;
+ @Mock
+ private IGraphLockOperation graphLockOperationMock;
+
@Before
public void setUp() throws Exception {
testInstance = new ToscaOperationFacade();
@@ -408,6 +418,153 @@ public class ToscaOperationFacadeTest {
}
@Test
+ public void testDeleteService_ServiceInUse() {
+ String invariantUUID = "12345";
+ String serviceUid = "1";
+ GraphVertex service1 = getTopologyTemplateVertex();
+ service1.setUniqueId(serviceUid);
+ List<GraphVertex> allResourcesToDelete = new ArrayList<>();
+ allResourcesToDelete.add(service1);
+ Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
+ propertiesToMatch.put(GraphPropertyEnum.INVARIANT_UUID, invariantUUID);
+ ToscaElement toscaElement = getToscaElementForTest();
+ toscaElement.setUniqueId(serviceUid);
+ String service2Name = "service2Name";
+ Map<String, Object> service2MetadataJson = new HashMap<>();
+ service2MetadataJson.put(GraphPropertyEnum.COMPONENT_TYPE.getProperty(), ComponentType.SERVICE);
+ service2MetadataJson.put(GraphPropertyEnum.NAME.getProperty(), service2Name);
+ String service2Uid = "2";
+ GraphVertex usingService = getTopologyTemplateVertex();
+ usingService.setUniqueId(service2Uid);
+ usingService.setMetadataJson(service2MetadataJson);
+ List<GraphVertex> inUseBy = new ArrayList<>();
+ inUseBy.add(usingService);
+
+ when(janusGraphDaoMock.getByCriteria(null, propertiesToMatch, JsonParseFlagEnum.ParseMetadata)).
+ thenReturn(Either.left(allResourcesToDelete));
+ doReturn(Either.left(toscaElement)).when(topologyTemplateOperationMock).getToscaElement(eq(service1), any(ComponentParametersView.class));
+ when(topologyTemplateOperationMock.
+ getComponentByLabelAndId(serviceUid, ToscaElementTypeEnum.TOPOLOGY_TEMPLATE, JsonParseFlagEnum.ParseAll)).
+ thenReturn(Either.left(service1));
+ when(janusGraphDaoMock.getParentVertices(any(GraphVertex.class), any(), eq(JsonParseFlagEnum.ParseAll))).
+ thenReturn(Either.left(inUseBy)).thenReturn(Either.left(inUseBy));
+ final OperationException actualException = assertThrows(OperationException.class, () -> testInstance.deleteService(invariantUUID, true));
+ assertEquals(actualException.getActionStatus(), ActionStatus.COMPONENT_IN_USE_BY_ANOTHER_COMPONENT);
+ assertEquals(actualException.getParams()[0], ComponentType.SERVICE + " " + service2Name);
+ }
+
+ @Test
+ public void testDeleteService_WithOneVersion() {
+ String invariantUUID = "12345";
+ String serviceUid = "1";
+ Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
+ propertiesToMatch.put(GraphPropertyEnum.INVARIANT_UUID, invariantUUID);
+ GraphVertex service1 = getTopologyTemplateVertex();
+ service1.setUniqueId(serviceUid);
+ List<GraphVertex> allResourcesToDelete = new ArrayList<>();
+ allResourcesToDelete.add(service1);
+ ToscaElement toscaElement = getToscaElementForTest();
+ toscaElement.setUniqueId(serviceUid);
+ List<String> affectedComponentIds = new ArrayList<>();
+ affectedComponentIds.add(service1.getUniqueId());
+
+ when(janusGraphDaoMock.getByCriteria(null, propertiesToMatch, JsonParseFlagEnum.ParseMetadata)).
+ thenReturn(Either.left(allResourcesToDelete));
+ doReturn(Either.left(toscaElement)).when(topologyTemplateOperationMock).getToscaElement(eq(service1), any(ComponentParametersView.class));
+ when(topologyTemplateOperationMock.
+ getComponentByLabelAndId(serviceUid, ToscaElementTypeEnum.TOPOLOGY_TEMPLATE, JsonParseFlagEnum.ParseAll)).
+ thenReturn(Either.left(service1));
+ when(janusGraphDaoMock.getParentVertices(eq(service1), any(), eq(JsonParseFlagEnum.ParseAll))).
+ thenReturn(Either.right(JanusGraphOperationStatus.OK));
+ when(graphLockOperationMock.lockComponent(service1.getUniqueId(), NodeTypeEnum.Service)).
+ thenReturn(StorageOperationStatus.OK);
+ when(topologyTemplateOperationMock.deleteToscaElement(service1)).thenReturn(Either.left(toscaElement));
+ assertEquals(affectedComponentIds, testInstance.deleteService(invariantUUID, true));
+ }
+
+ @Test
+ public void testDeleteService_WithTwoVersions() {
+ String invariantUUID = "12345";
+ String serviceUid = "1";
+ String service2Uid = "2";
+ GraphVertex service = getTopologyTemplateVertex();
+ service.setUniqueId(serviceUid);
+ GraphVertex serviceV2 = getTopologyTemplateVertex();
+ serviceV2.setUniqueId(service2Uid);
+ ToscaElement toscaElement = getToscaElementForTest();
+ toscaElement.setUniqueId(serviceUid);
+ ToscaElement toscaElement2 = getToscaElementForTest();
+ toscaElement2.setUniqueId(service2Uid);
+ List<String> affectedComponentIds = new ArrayList<>();
+ affectedComponentIds.add(service.getUniqueId());
+ affectedComponentIds.add(serviceV2.getUniqueId());
+ List<GraphVertex> allResourcesToDelete = new ArrayList<>();
+ allResourcesToDelete.add(service);
+ allResourcesToDelete.add(serviceV2);
+ Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
+ propertiesToMatch.put(GraphPropertyEnum.INVARIANT_UUID, invariantUUID);
+
+ when(janusGraphDaoMock.getByCriteria(null, propertiesToMatch, JsonParseFlagEnum.ParseMetadata)).
+ thenReturn(Either.left(allResourcesToDelete));
+ doReturn(Either.left(toscaElement)).when(topologyTemplateOperationMock).
+ getToscaElement(eq(service), any(ComponentParametersView.class));
+ doReturn(Either.left(toscaElement2)).when(topologyTemplateOperationMock).
+ getToscaElement(eq(serviceV2), any(ComponentParametersView.class));
+ when(topologyTemplateOperationMock.
+ getComponentByLabelAndId(serviceUid, ToscaElementTypeEnum.TOPOLOGY_TEMPLATE, JsonParseFlagEnum.ParseAll)).
+ thenReturn(Either.left(service));
+ when(topologyTemplateOperationMock.
+ getComponentByLabelAndId(service2Uid, ToscaElementTypeEnum.TOPOLOGY_TEMPLATE, JsonParseFlagEnum.ParseAll)).
+ thenReturn(Either.left(serviceV2));
+ when(janusGraphDaoMock.getParentVertices(any(GraphVertex.class), any(), eq(JsonParseFlagEnum.ParseAll))).
+ thenReturn(Either.right(JanusGraphOperationStatus.OK));
+ when(graphLockOperationMock.lockComponent(service.getUniqueId(), NodeTypeEnum.Service)).
+ thenReturn(StorageOperationStatus.OK);
+ when(graphLockOperationMock.lockComponent(serviceV2.getUniqueId(), NodeTypeEnum.Service)).
+ thenReturn(StorageOperationStatus.OK);
+ when(topologyTemplateOperationMock.deleteToscaElement(service)).thenReturn(Either.left(toscaElement));
+ when(topologyTemplateOperationMock.deleteToscaElement(serviceV2)).thenReturn(Either.left(toscaElement));
+ assertEquals(affectedComponentIds, testInstance.deleteService(invariantUUID, true));
+ }
+
+ @Test
+ public void testDeleteService_FailDelete() {
+ String invariantUUID = "12345";
+ String serviceUid = "1";
+ GraphVertex service = getTopologyTemplateVertex();
+ service.setUniqueId(serviceUid);
+ ToscaElement toscaElement = getToscaElementForTest();
+ toscaElement.setUniqueId(serviceUid);
+ List<GraphVertex> allResourcesToDelete = new ArrayList<>();
+ allResourcesToDelete.add(service);
+ Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
+ propertiesToMatch.put(GraphPropertyEnum.INVARIANT_UUID, invariantUUID);
+
+ when(janusGraphDaoMock.getByCriteria(null, propertiesToMatch, JsonParseFlagEnum.ParseMetadata)).
+ thenReturn(Either.left(allResourcesToDelete));
+ doReturn(Either.left(toscaElement)).when(topologyTemplateOperationMock).getToscaElement(eq(service), any(ComponentParametersView.class));
+ when(topologyTemplateOperationMock.getComponentByLabelAndId(serviceUid, ToscaElementTypeEnum.TOPOLOGY_TEMPLATE, JsonParseFlagEnum.ParseAll)).
+ thenReturn(Either.left(service));
+ when(janusGraphDaoMock.getParentVertices(eq(service), any(), eq(JsonParseFlagEnum.ParseAll))).
+ thenReturn(Either.right(JanusGraphOperationStatus.OK));
+ when(graphLockOperationMock.lockComponent(service.getUniqueId(), NodeTypeEnum.Service)).
+ thenReturn(StorageOperationStatus.OK);
+ when(topologyTemplateOperationMock.deleteToscaElement(service))
+ .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND));
+ assertThrows(StorageException.class, () -> testInstance.deleteService(invariantUUID, true));
+ }
+
+ @Test
+ public void testDeleteService_NotFound() {
+ String invariantUUID = "12345";
+ Map<GraphPropertyEnum, Object> propertiesToMatch = new EnumMap<>(GraphPropertyEnum.class);
+ propertiesToMatch.put(GraphPropertyEnum.INVARIANT_UUID, invariantUUID);
+ when(janusGraphDaoMock.getByCriteria(null, propertiesToMatch, JsonParseFlagEnum.ParseMetadata)).
+ thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND));
+ assertThrows(StorageException.class, () -> testInstance.deleteService(invariantUUID, true));
+ }
+
+ @Test
public void testMarkComponentToDelete() {
StorageOperationStatus result;
Component component = new Resource();