Set default base type when none is provided 55/125855/5
authorandre.schmid <andre.schmid@est.tech>
Tue, 23 Nov 2021 21:35:12 +0000 (21:35 +0000)
committerMichael Morris <michael.morris@est.tech>
Fri, 26 Nov 2021 14:49:11 +0000 (14:49 +0000)
Sets a default base type (substitution type) when no base type is
provided during the creation of a service with a category that
requires a base type.
Previous to the introduction of the optional base type, the system
would always add a base type to a Service.

Change-Id: I32e892fc23719fd569062ee806eb0be7b5af4ac6
Issue-ID: SDC-3791
Signed-off-by: andre.schmid <andre.schmid@est.tech>
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogic.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogicTest.java
catalog-be/src/test/resources/config/catalog-be/configuration.yaml

index e51aeef..24ba0ea 100644 (file)
@@ -701,7 +701,8 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic {
             createMandatoryArtifactsData(service, user);
             createServiceApiArtifactsData(service, user);
             setToscaArtifactsPlaceHolders(service, user);
-            if (service.isSubstituteCandidate()) {
+
+            if (service.isSubstituteCandidate() || genericTypeBusinessLogic.hasMandatorySubstitutionType(service)) {
                 final Resource genericType = fetchAndSetDerivedFromGenericType(service);
                 generatePropertiesFromGenericType(service, genericType);
                 generateAndAddInputsFromGenericTypeProperties(service, genericType);
index 07d71ea..600f7fa 100644 (file)
@@ -22,9 +22,12 @@ package org.openecomp.sdc.be.components.impl.generic;
 import fj.data.Either;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.openecomp.sdc.be.config.CategoryBaseTypeConfig;
+import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.dao.api.ActionStatus;
 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
@@ -33,6 +36,7 @@ import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.be.model.category.CategoryDefinition;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
 import org.openecomp.sdc.common.log.wrappers.Logger;
@@ -42,7 +46,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 @org.springframework.stereotype.Component
 public class GenericTypeBusinessLogic {
 
-    private final static Logger log = Logger.getLogger(GenericTypeBusinessLogic.class);
+    private static final Logger log = Logger.getLogger(GenericTypeBusinessLogic.class);
     private final ComponentsUtils componentsUtils;
     private final ToscaOperationFacade toscaOperationFacade;
 
@@ -66,7 +70,7 @@ public class GenericTypeBusinessLogic {
         Either<Resource, StorageOperationStatus> genericType;
         if (StringUtils.isEmpty(component.getDerivedFromGenericVersion())){
             genericType = toscaOperationFacade
-            .getLatestCertifiedNodeTypeByToscaResourceName(genericTypeToscaName);
+                .getLatestCertifiedNodeTypeByToscaResourceName(genericTypeToscaName);
             if (genericType.isRight()) {
                 log.debug("Failed to fetch certified node type by tosca resource name {}", genericTypeToscaName);
                 return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERIC_TYPE_NOT_FOUND, component.assetType(), genericTypeToscaName));
@@ -91,6 +95,36 @@ public class GenericTypeBusinessLogic {
         return fetchDerivedFromGenericType(component);
     }
 
+    /**
+     * Checks if the component requires a substitution type.
+     *
+     * @param component the component to test
+     * @return {@code true} if the component requires a substitution type, {@code false} otherwise.
+     */
+    public boolean hasMandatorySubstitutionType(final Component component) {
+        if (!component.isService()) {
+            return true;
+        }
+
+        final Map<String, CategoryBaseTypeConfig> serviceBaseNodeTypes =
+            ConfigurationManager.getConfigurationManager().getConfiguration().getServiceBaseNodeTypes();
+        if (serviceBaseNodeTypes == null) {
+            return true;
+        }
+
+        if (CollectionUtils.isEmpty(component.getCategories())) {
+            throw new IllegalArgumentException("The Service must contain at least one category");
+        }
+        final CategoryDefinition categoryDefinition = component.getCategories().get(0);
+
+        final CategoryBaseTypeConfig categoryBaseTypeConfig = serviceBaseNodeTypes.get(categoryDefinition.getName());
+        if (categoryBaseTypeConfig == null) {
+            return true;
+        }
+
+        return categoryBaseTypeConfig.isRequired();
+    }
+
     /**
      * @param genericType the generic node type
      * @return the generic type properties as inputs
index 11b4fa0..564e02d 100644 (file)
  */
 package org.openecomp.sdc.be.components.impl.generic;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import fj.data.Either;
-import org.junit.Before;
-import org.junit.Test;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.openecomp.sdc.be.config.CategoryBaseTypeConfig;
+import org.openecomp.sdc.be.config.Configuration;
+import org.openecomp.sdc.be.config.ConfigurationManager;
 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
 import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.Component;
 import org.openecomp.sdc.be.model.InputDefinition;
 import org.openecomp.sdc.be.model.PropertyDefinition;
 import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.be.model.category.CategoryDefinition;
 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
 import org.openecomp.sdc.exception.ResponseFormat;
 
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.when;
-
-public class GenericTypeBusinessLogicTest {
+class GenericTypeBusinessLogicTest {
 
     @InjectMocks
     private GenericTypeBusinessLogic testInstance;
@@ -54,37 +61,52 @@ public class GenericTypeBusinessLogicTest {
     @Mock
     private ComponentsUtils componentsUtils;
 
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
+    @BeforeEach
+    public void setUp() {
+        MockitoAnnotations.openMocks(this);
         testInstance = new GenericTypeBusinessLogic(componentsUtils, toscaOperationFacadeMock);
+        final var configurationManager = new ConfigurationManager();
+
+        final var configuration = new Configuration();
+        CategoryBaseTypeConfig categoryBaseTypeConfig1 = new CategoryBaseTypeConfig();
+        categoryBaseTypeConfig1.setRequired(true);
+        CategoryBaseTypeConfig categoryBaseTypeConfig2 = new CategoryBaseTypeConfig();
+        categoryBaseTypeConfig2.setRequired(false);
+        Map<String, CategoryBaseTypeConfig> serviceBaseNodeTypeMap = Map.of(
+            "category1", categoryBaseTypeConfig1,
+            "category2", categoryBaseTypeConfig2
+        );
+        configuration.setServiceBaseNodeTypes(serviceBaseNodeTypeMap);
+        configurationManager.setConfiguration(configuration);
     }
 
     @Test
-    public void fetchDerivedFromGenericType_cvfv_getGenericResourceTypeFromDerivedFrom() throws Exception {
+    void fetchDerivedFromGenericType_cvfv_getGenericResourceTypeFromDerivedFrom() {
         Resource cvfc = new Resource();
         cvfc.setResourceType(ResourceTypeEnum.CVFC);
         cvfc.setDerivedFrom(Arrays.asList("genericType", "someOtherType"));
         cvfc.setDerivedFromGenericType("genericType");
         Resource genericResource = new Resource();
-        when(toscaOperationFacadeMock.getLatestCertifiedNodeTypeByToscaResourceName("genericType")).thenReturn(Either.left(genericResource));
+        when(toscaOperationFacadeMock.getLatestCertifiedNodeTypeByToscaResourceName(cvfc.getDerivedFromGenericType()))
+            .thenReturn(Either.left(genericResource));
         Either<Resource, ResponseFormat> fetchedGenericType = testInstance.fetchDerivedFromGenericType(cvfc);
         assertEquals(genericResource, fetchedGenericType.left().value());
     }
 
     @Test
-    public void fetchDerivedFromGenericType_getGenericResourceTypeFromConfiguration() throws Exception {
-        Resource resource = Mockito.mock(Resource.class);
+    void fetchDerivedFromGenericType_getGenericResourceTypeFromConfiguration() {
+        Resource resource = mock(Resource.class);
         when(resource.getResourceType()).thenReturn(ResourceTypeEnum.VF);
-        when(resource.fetchGenericTypeToscaNameFromConfig()).thenReturn("genericType");
+        final var genericType = "genericType";
+        when(resource.fetchGenericTypeToscaNameFromConfig()).thenReturn(genericType);
         Resource genericResource = new Resource();
-        when(toscaOperationFacadeMock.getLatestCertifiedNodeTypeByToscaResourceName("genericType")).thenReturn(Either.left(genericResource));
+        when(toscaOperationFacadeMock.getLatestCertifiedNodeTypeByToscaResourceName(genericType)).thenReturn(Either.left(genericResource));
         Either<Resource, ResponseFormat> fetchedGenericType = testInstance.fetchDerivedFromGenericType(resource);
         assertEquals(genericResource, fetchedGenericType.left().value());
     }
 
     @Test
-    public void generateInputsFromGenericTypeProperties() throws Exception {
+    void generateInputsFromGenericTypeProperties() {
         Resource genericNodeType = new Resource();
         genericNodeType.setUniqueId("genericUid");
         PropertyDefinition propertyDefinition = generatePropDefinition("prop1");
@@ -99,13 +121,66 @@ public class GenericTypeBusinessLogicTest {
     }
 
     @Test
-    public void generateInputsFromGenericTypeProperties_genericHasNoProps() throws Exception {
+    void generateInputsFromGenericTypeProperties_genericHasNoProps() {
         Resource genericNodeType = new Resource();
         assertTrue(testInstance.generateInputsFromGenericTypeProperties(genericNodeType).isEmpty());
     }
 
+    @Test
+    void hasMandatorySubstitutionForServiceTest() {
+        final var component = mock(Component.class);
+        when(component.isService()).thenReturn(true);
+        final var categoryDefinition = new CategoryDefinition();
+        categoryDefinition.setName("category1");
+        when(component.getCategories()).thenReturn(List.of(categoryDefinition));
+        assertTrue(testInstance.hasMandatorySubstitutionType(component));
+    }
+
+    @Test
+    void hasMandatorySubstitutionForServiceWithNotRequiredCategoryTest() {
+        final var component = mock(Component.class);
+        when(component.isService()).thenReturn(true);
+        final var categoryDefinition = new CategoryDefinition();
+        categoryDefinition.setName("category2");
+        when(component.getCategories()).thenReturn(List.of(categoryDefinition));
+        assertFalse(testInstance.hasMandatorySubstitutionType(component));
+    }
+
+    @Test
+    void hasMandatorySubstitutionForServiceWithNotConfiguredCategoryTest() {
+        final var component = mock(Component.class);
+        when(component.isService()).thenReturn(true);
+        final var categoryDefinition = new CategoryDefinition();
+        categoryDefinition.setName("category3");
+        when(component.getCategories()).thenReturn(List.of(categoryDefinition));
+        assertTrue(testInstance.hasMandatorySubstitutionType(component));
+    }
+
+    @Test
+    void hasMandatorySubstitutionForServiceWithNonExistentConfigTest() {
+        final var configurationManager = new ConfigurationManager();
+        configurationManager.setConfiguration(new Configuration());
+        final var component = mock(Component.class);
+        when(component.isService()).thenReturn(true);
+        assertTrue(testInstance.hasMandatorySubstitutionType(component));
+    }
+
+    @Test
+    void hasMandatorySubstitutionServiceMissingCategoryTest() {
+        final Component component = mock(Component.class);
+        when(component.isService()).thenReturn(true);
+        assertThrows(IllegalArgumentException.class, () -> testInstance.hasMandatorySubstitutionType(component));
+    }
+
+    @Test
+    void hasMandatorySubstitutionTypeForNonServiceComponentTest() {
+        final Component component = mock(Component.class);
+        when(component.isService()).thenReturn(false);
+        assertTrue(testInstance.hasMandatorySubstitutionType(component));
+    }
+
     private void assertInput(InputDefinition inputDefinition, PropertyDefinition propertyDefinition) {
-        assertEquals(inputDefinition.getOwnerId(), "genericUid");
+        assertEquals("genericUid", inputDefinition.getOwnerId());
         assertEquals(inputDefinition.getValue(), propertyDefinition.getValue());
         assertEquals(inputDefinition.getName(), propertyDefinition.getName());
     }
@@ -117,5 +192,4 @@ public class GenericTypeBusinessLogicTest {
         return propertyDefinition;
     }
 
-
 }
\ No newline at end of file
index 4692342..f332599 100644 (file)
@@ -417,6 +417,15 @@ genericAssetNodeTypes:
   PNF: org.openecomp.resource.abstract.nodes.PNF
   Service: org.openecomp.resource.abstract.nodes.service
 
+# Defines the base types for Services
+# <category name>:
+#   required: <boolean> //if the base type is mandatory or not
+#   baseTypes: <list of TOSCA types> //the base types. Required if the base type is required.
+#                                      If not provided, the category will have no base type.
+serviceBaseNodeTypes:
+  cat_name:
+    required: false
+
 workloadContext: Production
 
 environmentContext: