Config. allowed instances in component composition 24/109824/5
authorandre.schmid <andre.schmid@est.tech>
Wed, 4 Mar 2020 16:28:05 +0000 (16:28 +0000)
committerJulien Bertozzi <julien.bertozzi@intl.att.com>
Wed, 29 Jul 2020 11:39:50 +0000 (11:39 +0000)
During the creation of Resource and Services components,
the allowed types to add in its composition are hard-coded.
This change allows those types to be configurable using the
configuration.yaml backend file.

Change-Id: If48849b57fe5124468db3d55f2f06391348935fb
Issue-ID: SDC-3177
Signed-off-by: andre.schmid <andre.schmid@est.tech>
20 files changed:
catalog-be/sdc-backend/chef-repo/cookbooks/sdc-catalog-be/templates/default/BE-configuration.yaml.erb
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/ContainerInstanceTypesData.java [deleted file]
catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ComponentInstanceServlet.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ArtifactsBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/externalapi/servlet/ExternalRefServletTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/servlets/ArchiveEndpointTest.java
catalog-be/src/test/resources/config/catalog-be/configuration.yaml
catalog-be/src/test/resources/paths/path-context.xml
catalog-model/pom.xml
catalog-model/src/main/java/org/openecomp/sdc/be/config/CatalogModelSpringConfig.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/config/ContainerInstanceTypesData.java [new file with mode: 0644]
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/config/ModelOperationsSpringConfig.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/config/ContainerInstanceTypesDataTest.java [new file with mode: 0644]
catalog-model/src/test/resources/application-context-test.xml
catalog-model/src/test/resources/config/configuration.yaml
common-app-api/src/main/java/org/openecomp/sdc/be/config/Configuration.java
common-be/src/main/java/org/openecomp/sdc/be/datatypes/enums/ResourceTypeEnum.java

index a8ebf06..d7a2d66 100644 (file)
@@ -133,6 +133,66 @@ resourceTypes: &allResourceTypes
   - VFCMT
   - Abstract
   - CVFC
+  - Configuration
+  - ServiceProxy
+  - PNF
+
+componentAllowedInstanceTypes:
+  Resource:
+    VF:
+      - VFC
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
+    CVFC:
+      - VFC
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - ServiceProxy
+      - Abstract
+    PNF:
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
+    CR:
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
+    VL:
+      - VL
+  Service:
+    "*":
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
 
 artifacts:
   - type: CONTROLLER_BLUEPRINT_ARCHIVE
index e9fc6a0..b0c9b30 100644 (file)
@@ -61,7 +61,7 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
 import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary;
-import org.openecomp.sdc.be.datamodel.utils.ContainerInstanceTypesData;
+import org.openecomp.sdc.be.model.jsonjanusgraph.config.ContainerInstanceTypesData;
 import org.openecomp.sdc.be.datatypes.elements.CINodeFilterDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
@@ -184,7 +184,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
     private ContainerInstanceTypesData containerInstanceTypesData;
 
     public ComponentInstance createComponentInstance(String containerComponentParam, String containerComponentId, String userId, ComponentInstance resourceInstance) {
-        return createComponentInstance(containerComponentParam, containerComponentId, userId, resourceInstance, false, true);
+        return createComponentInstance(containerComponentParam, containerComponentId, userId, resourceInstance, true);
     }
 
     public List<ComponentInstanceProperty> getComponentInstancePropertiesByInputId(org.openecomp.sdc.be.model.Component component, String inputId){
@@ -324,55 +324,54 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
     }
 
-    public ComponentInstance createComponentInstance(String containerComponentParam, String containerComponentId, String userId, ComponentInstance resourceInstance, boolean inTransaction, boolean needLock) {
-
-        Component origComponent = null;
-        User user;
-        org.openecomp.sdc.be.model.Component containerComponent = null;
-        ComponentTypeEnum containerComponentType;
-        try {
-            user = validateUserExists(userId);
-            validateUserNotEmpty(user, "Create component instance");
-            validateJsonBody(resourceInstance, ComponentInstance.class);
-            containerComponentType = validateComponentType(containerComponentParam);
-            containerComponent = validateComponentExists(containerComponentId, containerComponentType, null);
+    public ComponentInstance createComponentInstance(final String containerComponentParam,
+                                                     final String containerComponentId, final String userId,
+                                                     final ComponentInstance resourceInstance, final boolean needLock) {
+        final User user = validateUserExists(userId);
+        validateUserNotEmpty(user, "Create component instance");
+        validateJsonBody(resourceInstance, ComponentInstance.class);
+        final ComponentTypeEnum containerComponentType = validateComponentType(containerComponentParam);
+        final org.openecomp.sdc.be.model.Component containerComponent =
+            validateComponentExists(containerComponentId, containerComponentType, null);
 
-            if (ModelConverter.isAtomicComponent(containerComponent)) {
+        if (ModelConverter.isAtomicComponent(containerComponent)) {
+            if (log.isDebugEnabled()) {
                 log.debug("Cannot attach resource instances to container resource of type {}", containerComponent.assetType());
-                throw new ByActionStatusComponentException(ActionStatus.RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES, containerComponent.assetType());
             }
+            throw new ByActionStatusComponentException(ActionStatus.RESOURCE_CANNOT_CONTAIN_RESOURCE_INSTANCES, containerComponent.assetType());
+        }
 
-            validateCanWorkOnComponent(containerComponent, userId);
-
-            if (resourceInstance != null && containerComponentType != null) {
-                OriginTypeEnum originType = resourceInstance.getOriginType();
-                validateInstanceName(resourceInstance);
-                if (originType == OriginTypeEnum.ServiceProxy) {
-
-                    Either<Component, StorageOperationStatus> serviceProxyOrigin = toscaOperationFacade.getLatestByName("serviceProxy");
-                    if (isServiceProxyOrigin(serviceProxyOrigin)) {
-                        throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value()));
-                    }
-                    origComponent = serviceProxyOrigin.left().value();
+        validateCanWorkOnComponent(containerComponent, userId);
 
-                    StorageOperationStatus fillProxyRes = fillProxyInstanceData(resourceInstance, origComponent);
-                    if (isFillProxyRes(fillProxyRes)) {
-                        throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(fillProxyRes));
-                    }
+        Component origComponent = null;
+        if (resourceInstance != null && containerComponentType != null) {
+            final OriginTypeEnum originType = resourceInstance.getOriginType();
+            validateInstanceName(resourceInstance);
+            if (originType == OriginTypeEnum.ServiceProxy) {
+
+                final Either<Component, StorageOperationStatus> serviceProxyOrigin =
+                    toscaOperationFacade.getLatestByName("serviceProxy");
+                if (isServiceProxyOrigin(serviceProxyOrigin)) {
+                    throw new ByActionStatusComponentException(
+                        componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value()));
                 }
-                else {
-                    origComponent = getAndValidateOriginComponentOfComponentInstance(containerComponent, resourceInstance);
+                origComponent = serviceProxyOrigin.left().value();
+
+                final StorageOperationStatus fillProxyRes = fillProxyInstanceData(resourceInstance, origComponent);
+                if (isFillProxyRes(fillProxyRes)) {
+                    throw new ByActionStatusComponentException(
+                        componentsUtils.convertFromStorageResponse(fillProxyRes));
                 }
-                validateOriginAndResourceInstanceTypes(containerComponent, origComponent, originType);
-                validateResourceInstanceState(containerComponent, origComponent);
-                overrideFields(origComponent, resourceInstance);
-                compositionBusinessLogic.validateAndSetDefaultCoordinates(resourceInstance);
+            } else {
+                origComponent = getAndValidateOriginComponentOfComponentInstance(containerComponent,
+                    resourceInstance);
             }
-            return createComponent(needLock, containerComponent,origComponent, resourceInstance, user);
-
-        }catch (ComponentException e){
-            throw e;
+            validateOriginAndResourceInstanceTypes(containerComponent, origComponent, originType);
+            validateResourceInstanceState(containerComponent, origComponent);
+            overrideFields(origComponent, resourceInstance);
+            compositionBusinessLogic.validateAndSetDefaultCoordinates(resourceInstance);
         }
+        return createComponent(needLock, containerComponent, origComponent, resourceInstance, user);
     }
 
     private ComponentInstance createComponent(boolean needLock, Component containerComponent, Component origComponent, ComponentInstance resourceInstance, User user) {
@@ -426,10 +425,10 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         }
     }
 
-    private void validateOriginAndResourceInstanceTypes(Component containerComponent, Component origComponent, OriginTypeEnum originType) {
-        ResourceTypeEnum resourceType = null;
-        ResourceTypeEnum convertedOriginType;
-        resourceType = getResourceTypeEnumFromOriginComponent(origComponent, resourceType);
+    private void validateOriginAndResourceInstanceTypes(final Component containerComponent,
+                                                        final Component origComponent,
+                                                        final OriginTypeEnum originType) {
+        final ResourceTypeEnum resourceType = getResourceTypeEnumFromOriginComponent(origComponent);
         validateOriginType(originType, resourceType);
         validateOriginComponentIsValidForContainer(containerComponent, resourceType);
     }
@@ -437,13 +436,14 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
     private void validateOriginComponentIsValidForContainer(Component containerComponent, ResourceTypeEnum resourceType) {
         switch (containerComponent.getComponentType()) {
             case SERVICE:
-                if (!containerInstanceTypesData.getServiceContainerList().contains((resourceType))) {
+                if (!containerInstanceTypesData.isAllowedForServiceComponent(resourceType)) {
                     throw new ByActionStatusComponentException(ActionStatus.CONTAINER_CANNOT_CONTAIN_INSTANCE,
                             containerComponent.getComponentType().toString(), resourceType.name());
                 }
                 break;
             case RESOURCE:
-                if (!containerInstanceTypesData.getValidInstanceTypesInResourceContainer().get(((Resource) containerComponent).getResourceType()).contains(resourceType)) {
+                final ResourceTypeEnum componentResourceType = ((Resource) containerComponent).getResourceType();
+                if (!containerInstanceTypesData.isAllowedForResourceComponent(componentResourceType, resourceType)) {
                     throw new ByActionStatusComponentException(ActionStatus.CONTAINER_CANNOT_CONTAIN_INSTANCE,
                             containerComponent.getComponentType().toString(), resourceType.name());
                 }
@@ -465,18 +465,15 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         if (resourceType != convertedOriginType)  throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
     }
 
-    private ResourceTypeEnum getResourceTypeEnumFromOriginComponent(Component origComponent, ResourceTypeEnum resourceType) {
+    private ResourceTypeEnum getResourceTypeEnumFromOriginComponent(final Component origComponent) {
         switch (origComponent.getComponentType()) {
             case SERVICE:
-                resourceType = ResourceTypeEnum.ServiceProxy;
-                break;
+                return ResourceTypeEnum.ServiceProxy;
             case RESOURCE:
-                resourceType = ((Resource) origComponent).getResourceType();
-                break;
+                return ((Resource) origComponent).getResourceType();
             default:
                 throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
         }
-        return resourceType;
     }
 
     private ComponentInstance isNeedLock(boolean needLock, Component containerComponent) {
@@ -2730,7 +2727,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic {
         try {
 
             actionResponse = createComponentInstance(
-                    "services", containerComponentId, userId, inputComponentInstance, true, false);
+                    "services", containerComponentId, userId, inputComponentInstance, false);
 
         } catch (ComponentException e) {
             failed = true;
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/ContainerInstanceTypesData.java b/catalog-be/src/main/java/org/openecomp/sdc/be/datamodel/utils/ContainerInstanceTypesData.java
deleted file mode 100644 (file)
index 3ee9645..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * SDC
- * ================================================================================
- * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * 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.
- * ============LICENSE_END=========================================================
- */
-
-package org.openecomp.sdc.be.datamodel.utils;
-
-import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
-import org.springframework.stereotype.Component;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@Component
-public class ContainerInstanceTypesData {
-
-    private List<ResourceTypeEnum> validInstanceTypesInServiceContainer = Arrays.asList(ResourceTypeEnum.PNF,
-            ResourceTypeEnum.VF, ResourceTypeEnum.CP,
-            ResourceTypeEnum.VL, ResourceTypeEnum.CR,
-            ResourceTypeEnum.ServiceProxy,ResourceTypeEnum.Configuration);
-    private Map<ResourceTypeEnum,List<ResourceTypeEnum>> validInstanceTypesInResourceContainer = new HashMap<>();
-
-    private ContainerInstanceTypesData() {
-        List<ResourceTypeEnum> vfContainerInstances = Arrays.asList(ResourceTypeEnum.CP,
-                ResourceTypeEnum.VL, ResourceTypeEnum.Configuration,
-                ResourceTypeEnum.VFC);
-        List<ResourceTypeEnum> crContainerInstances = Arrays.asList(ResourceTypeEnum.CP,
-                ResourceTypeEnum.VL, ResourceTypeEnum.Configuration,
-                ResourceTypeEnum.VFC);
-        List<ResourceTypeEnum> pnfContainerInstances = Arrays.asList(ResourceTypeEnum.CP,
-                ResourceTypeEnum.VL, ResourceTypeEnum.Configuration,
-                ResourceTypeEnum.VFC);
-        validInstanceTypesInResourceContainer.put(ResourceTypeEnum.VF, vfContainerInstances);
-        validInstanceTypesInResourceContainer.put(ResourceTypeEnum.CR, crContainerInstances);
-        validInstanceTypesInResourceContainer.put(ResourceTypeEnum.PNF, pnfContainerInstances);
-    }
-
-    public List<ResourceTypeEnum> getServiceContainerList() {
-        return validInstanceTypesInServiceContainer;
-    }
-
-    public Map<ResourceTypeEnum, List<ResourceTypeEnum>> getValidInstanceTypesInResourceContainer() {
-        return validInstanceTypesInResourceContainer;
-    }
-}
index 34b261b..4f3120a 100644 (file)
@@ -166,24 +166,30 @@ public class ComponentInstanceServlet extends AbstractValidationsServlet {
             @Context final HttpServletRequest request) {
 
         validateNotEmptyBody(data);
-        ComponentInstance componentInstance = null;
+        final ComponentInstance componentInstance;
         try {
             componentInstance = RepresentationUtils.fromRepresentation(data, ComponentInstance.class);
             componentInstance.setInvariantName(null);
             componentInstance.setCreatedFrom(CreatedFrom.UI);
-        } catch (Exception e) {
+        } catch (final Exception e) {
             BeEcompErrorManager.getInstance().logBeRestApiGeneralError("Create Component Instance");
             log.debug("create component instance failed with exception", e);
             throw new ByActionStatusComponentException(ActionStatus.INVALID_CONTENT);
         }
-            loggerSupportability.log(LoggerSupportabilityActions.CREATE_INSTANCE, StatusCode.STARTED,"Starting to create component instance by {}",userId);
-            if (componentInstanceBusinessLogic == null) {
-                log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
-                return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
-            }
-            ComponentInstance actionResponse = componentInstanceBusinessLogic.createComponentInstance(containerComponentType, containerComponentId, userId, componentInstance);
-            loggerSupportability.log(LoggerSupportabilityActions.CREATE_INSTANCE,actionResponse.getComponentMetadataForSupportLog(),StatusCode.COMPLETE,"Ending to create component instance by user {}",userId);
-            return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse);
+
+        loggerSupportability.log(LoggerSupportabilityActions.CREATE_INSTANCE, StatusCode.STARTED,
+            "Starting to create component instance by {}", userId);
+        if (componentInstanceBusinessLogic == null) {
+            log.debug(UNSUPPORTED_COMPONENT_TYPE, containerComponentType);
+            return buildErrorResponse(
+                getComponentsUtils().getResponseFormat(ActionStatus.UNSUPPORTED_ERROR, containerComponentType));
+        }
+        final ComponentInstance actionResponse = componentInstanceBusinessLogic.
+            createComponentInstance(containerComponentType, containerComponentId, userId, componentInstance);
+        loggerSupportability
+            .log(LoggerSupportabilityActions.CREATE_INSTANCE, actionResponse.getComponentMetadataForSupportLog(),
+                StatusCode.COMPLETE, "Ending to create component instance by user {}", userId);
+        return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.CREATED), actionResponse);
 
     }
 
index c514565..d6995d1 100644 (file)
@@ -1182,7 +1182,7 @@ public class ArtifactsBusinessLogicTest extends BaseBusinessLogicMock {
         assertThat(artifactConfiguration1.getCategories()).contains(ArtifactGroupTypeEnum.INFORMATIONAL);
         assertThat(artifactConfiguration1.getComponentTypes()).hasSize(1);
         assertThat(artifactConfiguration1.getComponentTypes()).contains(ComponentType.RESOURCE);
-        assertThat(artifactConfiguration1.getResourceTypes()).hasSize(7);
+        assertThat(artifactConfiguration1.getResourceTypes()).hasSize(11);
         assertThat(artifactConfiguration1.getResourceTypes())
             .contains(ResourceTypeEnum.VFC.getValue(), ResourceTypeEnum.CP.getValue(), ResourceTypeEnum.VL.getValue(),
                 ResourceTypeEnum.VF.getValue(), ResourceTypeEnum.VFCMT.getValue(), "Abstract",
@@ -1946,8 +1946,8 @@ public class ArtifactsBusinessLogicTest extends BaseBusinessLogicMock {
     @Test(expected = ComponentException.class)
     public void validateDeploymentArtifact_unsupportedResourceType() {
         final ArtifactDefinition artifactDefinition = new ArtifactDefinition();
-        artifactDefinition.setArtifactType(ArtifactTypeEnum.YANG.getType());
-        artifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.INFORMATIONAL);
+        artifactDefinition.setArtifactType(ArtifactTypeEnum.ANSIBLE_PLAYBOOK.getType());
+        artifactDefinition.setArtifactGroupType(ArtifactGroupTypeEnum.DEPLOYMENT);
         final Resource resourceComponent = new Resource();
         resourceComponent.setComponentType(ComponentTypeEnum.RESOURCE);
         resourceComponent.setResourceType(ResourceTypeEnum.ServiceProxy);
index 8a005ff..127e1d9 100644 (file)
@@ -66,7 +66,6 @@ import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
 import org.openecomp.sdc.be.dao.jsongraph.JanusGraphDao;
 import org.openecomp.sdc.be.dao.jsongraph.types.JsonParseFlagEnum;
-import org.openecomp.sdc.be.datamodel.utils.ContainerInstanceTypesData;
 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathDataDefinition;
 import org.openecomp.sdc.be.datatypes.elements.ForwardingPathElementDataDefinition;
@@ -102,6 +101,7 @@ 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.cache.ApplicationDataTypeCache;
+import org.openecomp.sdc.be.model.jsonjanusgraph.config.ContainerInstanceTypesData;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ForwardingPathOperation;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
@@ -653,11 +653,11 @@ class ComponentInstanceBusinessLogicTest {
         createProperties();
         createInputs();
         createService();
-        createResource();
+        resource = createResource();
     }
 
-    private void createResource() {
-        resource = new Resource();
+    private Resource createResource() {
+        final Resource resource = new Resource();
         resource.setUniqueId(COMPONENT_ID);
         resource.setComponentInstancesRelations(Lists.newArrayList(relation));
         resource.setComponentInstances(Lists.newArrayList(toInstance, fromInstance));
@@ -665,6 +665,7 @@ class ComponentInstanceBusinessLogicTest {
         resource.setRequirements(fromInstance.getRequirements());
         resource.setComponentType(ComponentTypeEnum.RESOURCE);
         resource.setState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
+        return resource;
     }
 
     private void createService() {
@@ -879,7 +880,7 @@ class ComponentInstanceBusinessLogicTest {
     @Test
     void testValidateParent() {
         ComponentInstanceBusinessLogic testSubject;
-        createResource();
+        resource = createResource();
         String nodeTemplateId = "";
         boolean result;
 
@@ -945,7 +946,7 @@ class ComponentInstanceBusinessLogicTest {
     void testCreateOrUpdatePropertiesValues() {
         ComponentInstanceBusinessLogic testSubject;
         ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.RESOURCE;
-        createResource();
+        resource = createResource();
         String componentId = resource.getUniqueId();
         String resourceInstanceId = "";
         List<ComponentInstanceProperty> properties = new ArrayList<>();
@@ -979,7 +980,7 @@ class ComponentInstanceBusinessLogicTest {
         ComponentInstanceBusinessLogic testSubject;
         ComponentInstanceProperty property = new ComponentInstanceProperty();
         String newValue = "";
-        createResource();
+        resource = createResource();
         createInstances();
         String capabilityType = "";
         String capabilityName = "";
@@ -995,7 +996,7 @@ class ComponentInstanceBusinessLogicTest {
     void testCreateOrUpdateInstanceInputValues() {
         ComponentInstanceBusinessLogic testSubject;
         ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.RESOURCE;
-        createResource();
+        resource = createResource();
         String componentId = resource.getUniqueId();
         String resourceInstanceId = "";
         List<ComponentInstanceInput> inputs = new ArrayList<>();
@@ -1027,7 +1028,7 @@ class ComponentInstanceBusinessLogicTest {
     void testCreateOrUpdateGroupInstancePropertyValue() {
         ComponentInstanceBusinessLogic testSubject;
         ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.RESOURCE;
-        createResource();
+        resource = createResource();
         String componentId = resource.getUniqueId();
         String resourceInstanceId = "";
         String groupInstanceId = "";
@@ -1099,7 +1100,7 @@ class ComponentInstanceBusinessLogicTest {
     @Test
     void testGetResourceInstanceById() {
         ComponentInstanceBusinessLogic testSubject;
-        createResource();
+        resource = createResource();
         String instanceId = "";
         Either<ComponentInstance, StorageOperationStatus> result;
 
@@ -1113,7 +1114,7 @@ class ComponentInstanceBusinessLogicTest {
     void testUpdateInstanceCapabilityProperties_1() {
         ComponentInstanceBusinessLogic testSubject;
         ComponentTypeEnum componentTypeEnum = ComponentTypeEnum.RESOURCE;
-        createResource();
+        resource = createResource();
         String containerComponentId = resource.getUniqueId();
         String componentInstanceUniqueId = "";
         String capabilityType = "";
@@ -1664,7 +1665,7 @@ class ComponentInstanceBusinessLogicTest {
         when(toscaOperationFacade.getToscaFullElement(eq(ORIGIN_COMPONENT_ID)))
             .thenReturn(Either.left(originComponent));
 
-        ByActionStatusComponentException e = assertThrows(ByActionStatusComponentException.class, () -> {
+        final ByActionStatusComponentException e = assertThrows(ByActionStatusComponentException.class, () -> {
             componentInstanceBusinessLogic.createComponentInstance(ComponentTypeEnum.SERVICE_PARAM_NAME, COMPONENT_ID, USER_ID, ci);
         });
         assertThat(e.getActionStatus()).isEqualTo(ActionStatus.INVALID_CONTENT);
@@ -1672,9 +1673,9 @@ class ComponentInstanceBusinessLogicTest {
 
     @Test
     void testCreateComponentInstanceFailureCannotContainInstance() {
-        Pair<ComponentInstance, Resource> p = prepareResourcesForCreateComponentInstanceTest();
-        ComponentInstance ci = p.getLeft();
-        Resource originComponent = p.getRight();
+        final Pair<ComponentInstance, Resource> p = prepareResourcesForCreateComponentInstanceTest();
+        final ComponentInstance ci = p.getLeft();
+        final Resource originComponent = p.getRight();
 
         // Stub for getting component
         when(toscaOperationFacade.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
@@ -1682,21 +1683,38 @@ class ComponentInstanceBusinessLogicTest {
         when(toscaOperationFacade.getToscaFullElement(eq(ORIGIN_COMPONENT_ID)))
             .thenReturn(Either.left(originComponent));
         // Assume services cannot contain VF resource
-        when(containerInstanceTypeData.getServiceContainerList())
-            .thenReturn(Collections.singletonList(ResourceTypeEnum.VL));
+        when(containerInstanceTypeData.isAllowedForServiceComponent(eq(ResourceTypeEnum.VF)))
+            .thenReturn(false);
 
-        ByActionStatusComponentException e = assertThrows(ByActionStatusComponentException.class, () -> {
+        ByActionStatusComponentException actualException = assertThrows(ByActionStatusComponentException.class, () -> {
             componentInstanceBusinessLogic.createComponentInstance(ComponentTypeEnum.SERVICE_PARAM_NAME, COMPONENT_ID, USER_ID, ci);
         });
-        assertThat(e.getActionStatus()).isEqualTo(ActionStatus.CONTAINER_CANNOT_CONTAIN_INSTANCE);
-        verify(containerInstanceTypeData, times(1)).getServiceContainerList();
+        assertThat(actualException.getActionStatus()).isEqualTo(ActionStatus.CONTAINER_CANNOT_CONTAIN_INSTANCE);
+        verify(containerInstanceTypeData, times(1)).isAllowedForServiceComponent(eq(ResourceTypeEnum.VF));
+
+        //given
+        final Resource resource = createResource();
+        resource.setResourceType(ResourceTypeEnum.VF);
+        resource.setLastUpdaterUserId(USER_ID);
+        //when
+        when(toscaOperationFacade.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class)))
+            .thenReturn(Either.left(resource));
+        when(toscaOperationFacade.getToscaFullElement(eq(ORIGIN_COMPONENT_ID)))
+            .thenReturn(Either.left(originComponent));
+        when(containerInstanceTypeData.isAllowedForResourceComponent(eq(ResourceTypeEnum.VF), eq(ResourceTypeEnum.VF)))
+            .thenReturn(false);
+        actualException = assertThrows(ByActionStatusComponentException.class, () -> {
+            componentInstanceBusinessLogic.createComponentInstance(ComponentTypeEnum.RESOURCE_PARAM_NAME, COMPONENT_ID, USER_ID, ci);
+        });
+        //then
+        assertThat(actualException.getActionStatus()).isEqualTo(ActionStatus.CONTAINER_CANNOT_CONTAIN_INSTANCE);
     }
 
     @Test
     void testCreateComponentInstanceFailureAddToGraph() {
-        Pair<ComponentInstance, Resource> p = prepareResourcesForCreateComponentInstanceTest();
-        ComponentInstance ci = p.getLeft();
-        Resource originComponent = p.getRight();
+        final Pair<ComponentInstance, Resource> p = prepareResourcesForCreateComponentInstanceTest();
+        final ComponentInstance ci = p.getLeft();
+        final Resource originComponent = p.getRight();
 
         // TODO Refactor createComponentInstance() method and reduce these mocks
         //      not to target the internal details too much
@@ -1704,8 +1722,8 @@ class ComponentInstanceBusinessLogicTest {
             .thenReturn(Either.left(service));
         when(toscaOperationFacade.getToscaFullElement(eq(ORIGIN_COMPONENT_ID)))
             .thenReturn(Either.left(originComponent));
-        when(containerInstanceTypeData.getServiceContainerList())
-            .thenReturn(Collections.singletonList(ResourceTypeEnum.VF));
+        when(containerInstanceTypeData.isAllowedForServiceComponent(eq(ResourceTypeEnum.VF)))
+            .thenReturn(true);
         Mockito.doNothing().when(compositionBusinessLogic).validateAndSetDefaultCoordinates(ci);
         when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service))
             .thenReturn(StorageOperationStatus.OK);
@@ -1722,7 +1740,8 @@ class ComponentInstanceBusinessLogicTest {
         assertThrows(ByResponseFormatComponentException.class, () -> {
             componentInstanceBusinessLogic.createComponentInstance(ComponentTypeEnum.SERVICE_PARAM_NAME, COMPONENT_ID, USER_ID, ci);
         });
-        verify(containerInstanceTypeData, times(1)).getServiceContainerList();
+        verify(containerInstanceTypeData, times(1))
+            .isAllowedForServiceComponent(eq(ResourceTypeEnum.VF));
         verify(compositionBusinessLogic, times(1)).validateAndSetDefaultCoordinates(ci);
         verify(toscaOperationFacade, times(1))
             .addComponentInstanceToTopologyTemplate(service, originComponent, ci, false, user);
@@ -1731,11 +1750,11 @@ class ComponentInstanceBusinessLogicTest {
 
     @Test
     void testCreateComponentInstanceSuccess() {
-        Pair<ComponentInstance, Resource> p = prepareResourcesForCreateComponentInstanceTest();
-        ComponentInstance instanceToBeCreated = p.getLeft();
-        Resource originComponent = p.getRight();
+        final Pair<ComponentInstance, Resource> p = prepareResourcesForCreateComponentInstanceTest();
+        final ComponentInstance instanceToBeCreated = p.getLeft();
+        final Resource originComponent = p.getRight();
 
-        Service updatedService = new Service();
+        final Service updatedService = new Service();
         updatedService.setComponentInstances(Collections.singletonList(instanceToBeCreated));
         updatedService.setUniqueId(service.getUniqueId());
 
@@ -1745,8 +1764,8 @@ class ComponentInstanceBusinessLogicTest {
             .thenReturn(Either.left(service));
         when(toscaOperationFacade.getToscaFullElement(eq(ORIGIN_COMPONENT_ID)))
             .thenReturn(Either.left(originComponent));
-        when(containerInstanceTypeData.getServiceContainerList())
-            .thenReturn(Collections.singletonList(ResourceTypeEnum.VF));
+        when(containerInstanceTypeData.isAllowedForServiceComponent(eq(ResourceTypeEnum.VF)))
+            .thenReturn(true);
         Mockito.doNothing().when(compositionBusinessLogic).validateAndSetDefaultCoordinates(instanceToBeCreated);
         when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service))
             .thenReturn(StorageOperationStatus.OK);
@@ -1762,12 +1781,13 @@ class ComponentInstanceBusinessLogicTest {
         when(graphLockOperation.unlockComponent(COMPONENT_ID, NodeTypeEnum.Service))
             .thenReturn(StorageOperationStatus.OK);
 
-        ComponentInstance result = componentInstanceBusinessLogic.createComponentInstance(
+        final ComponentInstance result = componentInstanceBusinessLogic.createComponentInstance(
             ComponentTypeEnum.SERVICE_PARAM_NAME, COMPONENT_ID, USER_ID, instanceToBeCreated);
         assertThat(result).isEqualTo(instanceToBeCreated);
         assertThat(instanceToBeCreated.getComponentVersion()).isEqualTo(originComponent.getVersion());
         assertThat(instanceToBeCreated.getIcon()).isEqualTo(originComponent.getIcon());
-        verify(containerInstanceTypeData, times(1)).getServiceContainerList();
+        verify(containerInstanceTypeData, times(1))
+            .isAllowedForServiceComponent(eq(ResourceTypeEnum.VF));
         verify(compositionBusinessLogic, times(1)).validateAndSetDefaultCoordinates(instanceToBeCreated);
         verify(toscaOperationFacade, times(1))
             .addComponentInstanceToTopologyTemplate(service, originComponent, instanceToBeCreated, false, user);
index bdf986c..7482c69 100644 (file)
@@ -52,6 +52,7 @@ import org.openecomp.sdc.be.impl.ServletUtils;
 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
 import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.User;
+import org.openecomp.sdc.be.model.jsonjanusgraph.config.ContainerInstanceTypesData;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArchiveOperation;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.CategoryOperation;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ExternalReferencesOperation;
@@ -268,6 +269,10 @@ public class ExternalRefServletTest extends JerseyTest {
             return healingPipelineDao;
         }
 
+        @Bean
+        ContainerInstanceTypesData containerInstanceTypesData() {
+            return new ContainerInstanceTypesData();
+        }
 
         private void initGraphForTest() {
             if (!setupDone) {
index c670b51..009fa82 100644 (file)
@@ -60,6 +60,7 @@ import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.LifecycleStateEnum;
 import org.openecomp.sdc.be.model.User;
 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
+import org.openecomp.sdc.be.model.jsonjanusgraph.config.ContainerInstanceTypesData;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArchiveOperation;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.CategoryOperation;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.GroupsOperation;
@@ -251,6 +252,11 @@ public class ArchiveEndpointTest extends JerseyTest {
             return HEALING_PIPELINE_DAO;
         }
 
+        @Bean
+        ContainerInstanceTypesData containerInstanceTypesData() {
+            return new ContainerInstanceTypesData();
+        }
+
         private void initGraphForTest() {
             //Create Catalog Root
             catalogVertex = GraphTestUtils.createRootCatalogVertex(janusGraphDao);
index 484206c..0065d7b 100644 (file)
@@ -110,9 +110,70 @@ resourceTypes: &allResourceTypes
   - CP
   - VL
   - VF
+  - CR
   - VFCMT
   - Abstract
   - CVFC
+  - Configuration
+  - ServiceProxy
+  - PNF
+
+componentAllowedInstanceTypes:
+  Resource:
+    VF:
+      - VFC
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
+    CVFC:
+      - VFC
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - ServiceProxy
+      - Abstract
+    PNF:
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
+    CR:
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
+    VL:
+      - VL
+  Service:
+    "*":
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
 
 # validForResourceTypes usage
 #     validForResourceTypes:
index 0435d38..73f53f4 100644 (file)
@@ -51,6 +51,7 @@ Modifications copyright (c) 2018 Nokia
                org.openecomp.sdc.be.model.operations.impl,
                org.openecomp.sdc.be.model.jsonjanusgraph.operations,
                org.openecomp.sdc.be.model.jsonjanusgraph.utils,
+               org.openecomp.sdc.be.model.jsonjanusgraph.config,
                org.openecomp.sdc.be.components.csar,
                org.openecomp.sdc.be.datamodel.utils,
                org.openecomp.sdc.be.model.utils,
index 599bb91..6e30eac 100644 (file)
     </dependency>
     <!-- CASSANDRA END -->
 
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest</artifactId>
+      <version>${hamcrest.version}</version>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.hamcrest</groupId>
+      <artifactId>hamcrest-library</artifactId>
+      <version>${hamcrest.version}</version>
+      <scope>test</scope>
+    </dependency>
+
     <dependency>
       <groupId>org.junit.jupiter</groupId>
       <artifactId>junit-jupiter</artifactId>
       <artifactId>joda-time</artifactId>
       <version>${joda.time.version}</version>
     </dependency>
-               <dependency>
-                       <groupId>org.openecomp.sdc.core</groupId>
-                       <artifactId>openecomp-tosca-lib</artifactId>
-                       <version>${project.version}</version>
+    <dependency>
+      <groupId>org.openecomp.sdc.core</groupId>
+      <artifactId>openecomp-tosca-lib</artifactId>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <groupId>com.fasterxml.jackson.core</groupId>
index bd98076..061975b 100644 (file)
@@ -27,10 +27,11 @@ import org.springframework.context.annotation.Configuration;
 
 @Configuration
 @ComponentScan({"org.openecomp.sdc.be.model.operations.impl",
-                "org.openecomp.sdc.be.model.cache",
+    "org.openecomp.sdc.be.model.cache",
     "org.openecomp.sdc.be.model.jsonjanusgraph.utils",
     "org.openecomp.sdc.be.model.jsonjanusgraph.operations",
-                "org.openecomp.sdc.be.dao.cassandra"
+    "org.openecomp.sdc.be.model.jsonjanusgraph.config",
+    "org.openecomp.sdc.be.dao.cassandra"
 })
 public class CatalogModelSpringConfig {
 
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/config/ContainerInstanceTypesData.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/config/ContainerInstanceTypesData.java
new file mode 100644 (file)
index 0000000..903855b
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 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.config;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ContainerInstanceTypesData {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ContainerInstanceTypesData.class);
+    private static final String WILDCARD = "*";
+
+    private final ConfigurationManager configurationManager;
+
+    public ContainerInstanceTypesData() {
+        this.configurationManager = ConfigurationManager.getConfigurationManager();
+    }
+
+    /**
+     * Checks if a resource instance type is allowed in a Service component.
+     *
+     * @param resourceTypeToCheck the resource instance type that will be added to the container component
+     * @return {@code true} if the resource instance is allowed, {@code false} otherwise
+     */
+    public boolean isAllowedForServiceComponent(final ResourceTypeEnum resourceTypeToCheck) {
+        final List<String> allowedResourceInstanceTypeList =
+            getComponentAllowedList(ComponentTypeEnum.SERVICE, null);
+        if (CollectionUtils.isEmpty(allowedResourceInstanceTypeList)) {
+            return false;
+        }
+        return allowedResourceInstanceTypeList.contains(resourceTypeToCheck.getValue());
+    }
+
+    /**
+     * Checks if a resource instance type is allowed for a resource component.
+     *
+     * @param containerComponentResourceType the container component type that the instance will be added
+     * @param resourceToCheck the resource instance type that will be added to the container component
+     * @return {@code true} if the resource instance is allowed in the container component, {@code false} otherwise
+     */
+    public boolean isAllowedForResourceComponent(final ResourceTypeEnum containerComponentResourceType,
+                                                 final ResourceTypeEnum resourceToCheck) {
+        final List<String> allowedResourceInstanceTypeList =
+            getComponentAllowedList(ComponentTypeEnum.RESOURCE, containerComponentResourceType);
+        if (CollectionUtils.isEmpty(allowedResourceInstanceTypeList)) {
+            return false;
+        }
+        return allowedResourceInstanceTypeList.contains(resourceToCheck.getValue());
+    }
+
+    /**
+     * Gets the list of allowed component instances for a component type.
+     *
+     * @param componentType the component type
+     * @param resourceInstanceType the instance type to check, or null for any instance
+     * @return the list of allowed component instances for the given component
+     */
+    public List<String> getComponentAllowedList(final ComponentTypeEnum componentType,
+                                                final ResourceTypeEnum resourceInstanceType) {
+        final Map<String, List<String>> componentAllowedResourceTypeMap =
+            getComponentAllowedInstanceTypes().get(componentType.getValue());
+        if (MapUtils.isEmpty(componentAllowedResourceTypeMap)) {
+            final String resourceTypeString = resourceInstanceType == null ? WILDCARD : resourceInstanceType.getValue();
+            LOGGER.warn("No '{}' instance resource type configuration found for '{}'",
+                componentType.getValue(), resourceTypeString);
+            return Collections.emptyList();
+        }
+        return getAllowedInstanceType(resourceInstanceType, componentAllowedResourceTypeMap);
+    }
+
+    private Map<String, Map<String, List<String>>> getComponentAllowedInstanceTypes() {
+        return configurationManager.getConfiguration().getComponentAllowedInstanceTypes();
+    }
+
+    private List<String> getAllowedInstanceType(final ResourceTypeEnum resourceInstanceType,
+                                                final Map<String, List<String>> instanceAllowedResourceTypeMap) {
+        if (MapUtils.isEmpty(instanceAllowedResourceTypeMap)) {
+            return Collections.emptyList();
+        }
+        List<String> allowedInstanceResourceType = null;
+        if (resourceInstanceType == null) {
+            if (instanceAllowedResourceTypeMap.containsKey(WILDCARD)) {
+                allowedInstanceResourceType = instanceAllowedResourceTypeMap.get(WILDCARD);
+            }
+        } else {
+            allowedInstanceResourceType = instanceAllowedResourceTypeMap.get(resourceInstanceType.getValue());
+        }
+
+        if (CollectionUtils.isEmpty(allowedInstanceResourceType)) {
+            return Collections.emptyList();
+        }
+
+        return allowedInstanceResourceType;
+    }
+}
index cde3ef1..427939f 100644 (file)
@@ -27,6 +27,9 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.openecomp.sdc.be.config.Configuration;
+import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.be.model.jsonjanusgraph.config.ContainerInstanceTypesData;
 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
 import org.openecomp.sdc.be.dao.jsongraph.HealingJanusGraphDao;
@@ -40,8 +43,6 @@ import org.openecomp.sdc.be.model.*;
 import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
 import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
 import org.openecomp.sdc.be.model.CatalogUpdateTimestamp;
-import org.openecomp.sdc.be.datatypes.elements.MapCapabilityProperty;
-import org.openecomp.sdc.be.datatypes.elements.MapListCapabilityDataDefinition;
 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate;
 import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement;
@@ -91,6 +92,8 @@ public class ToscaOperationFacade {
     private GroupsOperation groupsOperation;
     @Autowired
     private HealingJanusGraphDao janusGraphDao;
+    @Autowired
+    private ContainerInstanceTypesData containerInstanceTypesData;
 
     private static final Logger log = Logger.getLogger(ToscaOperationFacade.class.getName());
     // endregion
@@ -1768,24 +1771,30 @@ public class ToscaOperationFacade {
         }
     }
 
-    private void fillNodeTypePropsMap(Map<GraphPropertyEnum, Object> hasProps, Map<GraphPropertyEnum, Object> hasNotProps, String internalComponentType) {
-        switch (internalComponentType.toLowerCase()) {
-            case "vf":
-                hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, Arrays.asList(ResourceTypeEnum.VFCMT.name()));
-                break;
-            case "cvfc":
-                hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, Arrays.asList(ResourceTypeEnum.VFCMT.name(), ResourceTypeEnum.Configuration.name()));
-                break;
-            case SERVICE:
-            case "pnf":
-            case "cr":
-                hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, Arrays.asList(ResourceTypeEnum.VFC.name(), ResourceTypeEnum.VFCMT.name()));
-                break;
-            case "vl":
-                hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, ResourceTypeEnum.VL.name());
-                break;
-            default:
-                break;
+    private void fillNodeTypePropsMap(final Map<GraphPropertyEnum, Object> hasProps,
+                                      final Map<GraphPropertyEnum, Object> hasNotProps,
+                                      final String internalComponentType) {
+        final Configuration configuration = ConfigurationManager.getConfigurationManager().getConfiguration();
+        final List<String> allowedTypes;
+
+        if (ComponentTypeEnum.SERVICE.getValue().equalsIgnoreCase(internalComponentType)) {
+            allowedTypes = containerInstanceTypesData.getComponentAllowedList(ComponentTypeEnum.SERVICE, null);
+        } else {
+            final ResourceTypeEnum resourceType = ResourceTypeEnum.getTypeIgnoreCase(internalComponentType);
+            allowedTypes = containerInstanceTypesData.getComponentAllowedList(ComponentTypeEnum.RESOURCE, resourceType);
+        }
+        final List<String> allResourceTypes = configuration.getResourceTypes();
+        if (allowedTypes == null) {
+            hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, allResourceTypes);
+            return;
+        }
+
+        if (ResourceTypeEnum.VL.getValue().equalsIgnoreCase(internalComponentType)) {
+            hasProps.put(GraphPropertyEnum.RESOURCE_TYPE, allowedTypes);
+        } else {
+            final List<String> notAllowedTypes = allResourceTypes.stream().filter(s -> !allowedTypes.contains(s))
+                .collect(Collectors.toList());
+            hasNotProps.put(GraphPropertyEnum.RESOURCE_TYPE, notAllowedTypes);
         }
     }
 
index a473e31..929441c 100644 (file)
@@ -28,6 +28,7 @@ import org.springframework.context.annotation.PropertySource;
 @ComponentScan({"org.openecomp.sdc.be.dao.cassandra", "org.openecomp.sdc.be.model.cache",
     "org.openecomp.sdc.be.model.jsonjanusgraph.operations",
     "org.openecomp.sdc.be.model.jsonjanusgraph.utils",
+    "org.openecomp.sdc.be.model.jsonjanusgraph.config",
         "org.openecomp.sdc.be.model.operations.impl"})
 @PropertySource("classpath:dao.properties")
 public class ModelOperationsSpringConfig { }
diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/config/ContainerInstanceTypesDataTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/config/ContainerInstanceTypesDataTest.java
new file mode 100644 (file)
index 0000000..5df7914
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 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.config;
+
+import static java.util.Collections.emptyList;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.is;
+
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
+import org.openecomp.sdc.common.impl.ExternalConfiguration;
+import org.openecomp.sdc.common.impl.FSConfigurationSource;
+
+public class ContainerInstanceTypesDataTest {
+
+    private ContainerInstanceTypesData containerInstanceTypesData;
+    private EnumSet<ResourceTypeEnum> serviceAllowedTypes;
+    private EnumMap<ResourceTypeEnum, EnumSet<ResourceTypeEnum>> resourceAllowedTypeConfig;
+    private EnumSet<ResourceTypeEnum> allResourceTypes;
+
+    @BeforeAll
+    public static void beforeClass() {
+        new ConfigurationManager(new FSConfigurationSource(ExternalConfiguration.getChangeListener(),
+            "src/test/resources/config"));
+    }
+
+    @BeforeEach
+    public void setUp() {
+        containerInstanceTypesData = new ContainerInstanceTypesData();
+
+        allResourceTypes = EnumSet.allOf(ResourceTypeEnum.class);
+
+        serviceAllowedTypes = EnumSet.of(ResourceTypeEnum.VF,
+            ResourceTypeEnum.CR,
+            ResourceTypeEnum.CP,
+            ResourceTypeEnum.PNF,
+            ResourceTypeEnum.CVFC,
+            ResourceTypeEnum.VL,
+            ResourceTypeEnum.Configuration,
+            ResourceTypeEnum.ServiceProxy,
+            ResourceTypeEnum.ABSTRACT
+        );
+
+        resourceAllowedTypeConfig =
+            new EnumMap<>(ResourceTypeEnum.class);
+
+        resourceAllowedTypeConfig.put(ResourceTypeEnum.VF,
+            EnumSet.of(ResourceTypeEnum.VFC,
+                ResourceTypeEnum.VF,
+                ResourceTypeEnum.CR,
+                ResourceTypeEnum.CP,
+                ResourceTypeEnum.PNF,
+                ResourceTypeEnum.CVFC,
+                ResourceTypeEnum.VL,
+                ResourceTypeEnum.Configuration,
+                ResourceTypeEnum.ServiceProxy,
+                ResourceTypeEnum.ABSTRACT));
+
+        resourceAllowedTypeConfig.put(ResourceTypeEnum.CVFC,
+            EnumSet.of(ResourceTypeEnum.VFC,
+                ResourceTypeEnum.VF,
+                ResourceTypeEnum.CR,
+                ResourceTypeEnum.CP,
+                ResourceTypeEnum.PNF,
+                ResourceTypeEnum.CVFC,
+                ResourceTypeEnum.VL,
+                ResourceTypeEnum.ServiceProxy,
+                ResourceTypeEnum.ABSTRACT));
+
+        resourceAllowedTypeConfig.put(ResourceTypeEnum.PNF,
+            EnumSet.of(ResourceTypeEnum.VF,
+                ResourceTypeEnum.CR,
+                ResourceTypeEnum.CP,
+                ResourceTypeEnum.PNF,
+                ResourceTypeEnum.CVFC,
+                ResourceTypeEnum.VL,
+                ResourceTypeEnum.Configuration,
+                ResourceTypeEnum.ServiceProxy,
+                ResourceTypeEnum.ABSTRACT));
+
+        resourceAllowedTypeConfig.put(ResourceTypeEnum.CR,
+            EnumSet.of(ResourceTypeEnum.VF,
+                ResourceTypeEnum.CR,
+                ResourceTypeEnum.CP,
+                ResourceTypeEnum.PNF,
+                ResourceTypeEnum.CVFC,
+                ResourceTypeEnum.VL,
+                ResourceTypeEnum.Configuration,
+                ResourceTypeEnum.ServiceProxy,
+                ResourceTypeEnum.ABSTRACT));
+
+        resourceAllowedTypeConfig.put(ResourceTypeEnum.VL,
+            EnumSet.of(ResourceTypeEnum.VL));
+    }
+
+    @Test
+    public void isAllowedForServiceComponent() {
+        for (final ResourceTypeEnum allowedType : serviceAllowedTypes) {
+            assertThat(String.format("%s should be allowed", allowedType.getValue()),
+                containerInstanceTypesData.isAllowedForServiceComponent(allowedType), is(true));
+        }
+    }
+
+    @Test
+    public void isAllowedForResourceComponent() {
+        for (final ResourceTypeEnum componentResourceType : allResourceTypes) {
+            final EnumSet<ResourceTypeEnum> allowedResourceType = resourceAllowedTypeConfig.get(componentResourceType);
+            for (final ResourceTypeEnum resourceType : allResourceTypes) {
+                if (allowedResourceType == null) {
+                    final String msg = String
+                        .format("'%s' resource type should not be allowed", resourceType.getValue());
+                    assertThat(msg, containerInstanceTypesData
+                        .isAllowedForResourceComponent(componentResourceType, resourceType), is(false));
+                    continue;
+                }
+                final boolean isAllowed = allowedResourceType.contains(resourceType);
+                final String msg = String
+                    .format("'%s' resource type should %s be allowed", resourceType.getValue(), isAllowed ? "" : "not");
+                assertThat(msg, containerInstanceTypesData
+                    .isAllowedForResourceComponent(componentResourceType, resourceType), is(
+                    isAllowed));
+            }
+        }
+    }
+
+    @Test
+    public void getComponentAllowedListTest() {
+        List<String> actualAllowedList = containerInstanceTypesData
+            .getComponentAllowedList(ComponentTypeEnum.SERVICE, null);
+        assertThat("Allowed Instance Resource Type List should be as expected",
+            actualAllowedList, containsInAnyOrder(actualAllowedList.toArray()));
+
+        for (final ResourceTypeEnum resourceType : allResourceTypes) {
+            actualAllowedList = containerInstanceTypesData
+                .getComponentAllowedList(ComponentTypeEnum.RESOURCE, resourceType);
+            final EnumSet<ResourceTypeEnum> expectedAllowedSet = resourceAllowedTypeConfig.get(resourceType);
+            if (CollectionUtils.isEmpty(expectedAllowedSet)) {
+                assertThat("Allowed Instance Resource Type List should be as expected",
+                    actualAllowedList, is(empty()));
+                continue;
+            }
+            assertThat("Allowed Instance Resource Type List should be as expected",
+                actualAllowedList,
+                containsInAnyOrder(expectedAllowedSet.stream().map(ResourceTypeEnum::getValue).toArray()));
+        }
+    }
+
+    @Test
+    public void getComponentAllowedListTestEmptyList() {
+        List<String> actualAllowedList = containerInstanceTypesData
+            .getComponentAllowedList(ComponentTypeEnum.PRODUCT, null);
+        final String msg = "Allowed Instance Resource Type List should be empty";
+        assertThat(msg, actualAllowedList, is(emptyList()));
+
+        actualAllowedList = containerInstanceTypesData
+            .getComponentAllowedList(ComponentTypeEnum.SERVICE, ResourceTypeEnum.VF);
+        assertThat(msg, actualAllowedList, is(emptyList()));
+
+        actualAllowedList = containerInstanceTypesData
+            .getComponentAllowedList(ComponentTypeEnum.SERVICE, ResourceTypeEnum.ServiceProxy);
+        assertThat(msg, actualAllowedList, is(emptyList()));
+
+        actualAllowedList = containerInstanceTypesData
+            .getComponentAllowedList(ComponentTypeEnum.RESOURCE, null);
+        assertThat(msg, actualAllowedList, is(emptyList()));
+    }
+
+}
\ No newline at end of file
index 475760f..dc9d5ba 100644 (file)
@@ -12,8 +12,8 @@
        org.openecomp.sdc.be.model.cache,
                org.openecomp.sdc.be.dao.janusgraph,
                org.openecomp.sdc.be.dao.cassandra,
-               org.openecomp.sdc.be.model.jsonjanusgraph.utils
-        ">
+               org.openecomp.sdc.be.model.jsonjanusgraph.utils,
+    org.openecomp.sdc.be.model.jsonjanusgraph.config">
 
    
   </context:component-scan>
index 4e8bc0a..504c020 100644 (file)
@@ -97,9 +97,70 @@ resourceTypes: &allResourceTypes
   - CP
   - VL
   - VF
+  - CR
   - VFCMT
   - Abstract
   - CVFC
+  - Configuration
+  - ServiceProxy
+  - PNF
+
+componentAllowedInstanceTypes:
+  Resource:
+    VF:
+      - VFC
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
+    CVFC:
+      - VFC
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - ServiceProxy
+      - Abstract
+    PNF:
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
+    CR:
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
+    VL:
+      - VL
+  Service:
+    "*":
+      - VF
+      - CR
+      - CP
+      - PNF
+      - CVFC
+      - VL
+      - Configuration
+      - ServiceProxy
+      - Abstract
 
 # validForResourceTypes usage
 #     validForResourceTypes:
index b70a161..ddc941d 100644 (file)
@@ -159,6 +159,7 @@ public class Configuration extends BasicConfiguration {
     private List<GabConfig> gabConfig;
     private EcompPortalConfig ecompPortal;
     private List<ArtifactConfiguration> artifacts;
+    private Map<String, Map<String, List<String>>> componentAllowedInstanceTypes;
 
     public List<ArtifactConfiguration> getArtifacts() {
         return artifacts;
@@ -168,6 +169,15 @@ public class Configuration extends BasicConfiguration {
         this.artifacts = artifacts;
     }
 
+    public Map<String, Map<String, List<String>>> getComponentAllowedInstanceTypes() {
+        return componentAllowedInstanceTypes;
+    }
+
+    public void setComponentAllowedInstanceTypes(
+            final Map<String, Map<String, List<String>>> componentAllowedInstanceTypes) {
+        this.componentAllowedInstanceTypes = componentAllowedInstanceTypes;
+    }
+
     public String getAutoHealingOwner() {
         return autoHealingOwner;
     }
@@ -258,19 +268,19 @@ public class Configuration extends BasicConfiguration {
     public void setGenericAssetNodeTypes(Map<String, String> genericAssetNodeTypes) {
         this.genericAssetNodeTypes = genericAssetNodeTypes;
     }
-    
+
     public Map<String, String> getServiceNodeTypes(){
         return serviceNodeTypes ;
     }
-    
+
     public void setServiceNodeTypes(Map<String, String> serviceNodeTypes){
         this.serviceNodeTypes = serviceNodeTypes;
     }
-    
+
     public Map<String, Map<String, String>> getResourceNodeTypes(){
         return resourceNodeTypes;
     }
-    
+
     public void setResourceNodeTypes(Map<String, Map<String, String>> resourceNodeTypes){
         this.resourceNodeTypes = resourceNodeTypes;
     }
index bd32ace..4201b79 100644 (file)
@@ -15,6 +15,8 @@
 
 package org.openecomp.sdc.be.datatypes.enums;
 
+import java.util.Arrays;
+
 /**
  * Resource Type Enum
  *
@@ -32,12 +34,13 @@ public enum ResourceTypeEnum {
     VFCMT("VFCMT"/* (VFC Monitoring Template)"*/, true),
     Configuration("Configuration", true),
     ServiceProxy("ServiceProxy", true),
-    ABSTRACT("Abstract (Generic VFC/VF/PNF/Service Type)", true);
+    //Generic VFC/VF/PNF/Service Type
+    ABSTRACT("Abstract", true);
 
-    private String value;
-    private boolean isAtomicType;
+    private final String value;
+    private final boolean isAtomicType;
 
-    ResourceTypeEnum(String value, boolean isAtomicType) {
+    ResourceTypeEnum(final String value, final boolean isAtomicType) {
         this.value = value;
         this.isAtomicType = isAtomicType;
     }
@@ -50,69 +53,68 @@ public enum ResourceTypeEnum {
         return isAtomicType;
     }
 
-    public static ResourceTypeEnum getType(String type) {
-        for (ResourceTypeEnum e : ResourceTypeEnum.values()) {
-            if (e.name().equals(type)) {
-                return e;
-            }
+    public static ResourceTypeEnum getType(final String type) {
+        if (type == null) {
+            return null;
         }
-        return null;
+        return Arrays.stream(ResourceTypeEnum.values())
+            .filter(resourceTypeEnum -> resourceTypeEnum.name().equals(type))
+            .findFirst()
+            .orElse(null);
     }
 
-    public static ResourceTypeEnum getTypeByName(String type) {
-        for (ResourceTypeEnum e : ResourceTypeEnum.values()) {
-            if (e.name().equalsIgnoreCase(type)) {
-                return e;
-            }
+    public static ResourceTypeEnum getTypeByName(final String type) {
+        if (type == null) {
+            return null;
         }
-        return null;
+        return Arrays.stream(ResourceTypeEnum.values())
+            .filter(resourceTypeEnum -> resourceTypeEnum.name().equalsIgnoreCase(type))
+            .findFirst()
+            .orElse(null);
     }
 
     /**
      * Returns ResourceTypeEnum matching to received String ignore case
      *
-     * @param type
-     * @return
+     * @param type the resource type
+     * @return the resource type as a enum if found, {@code null} otherwise
      */
-    public static ResourceTypeEnum getTypeIgnoreCase(String type) {
-        for (ResourceTypeEnum e : ResourceTypeEnum.values()) {
-            if (e.name().toLowerCase().equals(type.toLowerCase())) {
-                return e;
-            }
+    public static ResourceTypeEnum getTypeIgnoreCase(final String type) {
+        if (type == null) {
+            return null;
         }
-        return null;
+        return Arrays.stream(ResourceTypeEnum.values())
+            .filter(resourceTypeEnum -> resourceTypeEnum.name().equalsIgnoreCase(type))
+            .findFirst()
+            .orElse(null);
     }
 
     /**
      * Checks if enum exist with given type
      *
-     * @param type
-     * @return
+     * @param type the resource type
+     * @return {@code true} if the given resource type exists, {@code false} otherwise
      */
-    public static boolean containsName(String type) {
-
-        for (ResourceTypeEnum e : ResourceTypeEnum.values()) {
-            if (e.name().equals(type)) {
-                return true;
-            }
+    public static boolean containsName(final String type) {
+        if (type == null) {
+            return false;
         }
-        return false;
+        return Arrays.stream(ResourceTypeEnum.values())
+            .anyMatch(resourceTypeEnum -> resourceTypeEnum.name().equals(type));
     }
 
     /**
      * Checks if enum exist with given type ignore case
      *
-     * @param type
-     * @return
+     * @param type the resource type
+     * @return {@code true} if the type exists, {@code false} otherwise
      */
-    public static boolean containsIgnoreCase(String type) {
-
-        for (ResourceTypeEnum e : ResourceTypeEnum.values()) {
-            if (e.name().toLowerCase().equals(type.toLowerCase())) {
-                return true;
-            }
+    public static boolean containsIgnoreCase(final String type) {
+        if (type == null) {
+            return false;
         }
-        return false;
+        return Arrays.stream(ResourceTypeEnum.values())
+            .anyMatch(resourceTypeEnum -> resourceTypeEnum.name().equalsIgnoreCase(type));
     }
 
 }