From 032525a375681fb18cc498d8daed9d73faa21ec3 Mon Sep 17 00:00:00 2001 From: MichaelMorris Date: Tue, 23 Jun 2020 09:15:48 +0100 Subject: Support for Nested/Hierarchical Services Change-Id: I478cf2e1f9cf96443a3e35bf22ac2c9d72bca8f1 Issue-ID: SDC-3145 Signed-off-by: MichaelMorris --- .../components/impl/CategoriesImportManager.java | 5 + .../impl/ComponentInstanceBusinessLogic.java | 149 +++++++++++++++------ .../openecomp/sdc/be/tosca/ToscaExportHandler.java | 38 ++++-- .../impl/CategoriesImportManagerTest.java | 20 ++- .../impl/ComponentInstanceBusinessLogicTest.java | 78 ++++++++++- .../sdc/be/tosca/ToscaExportHandlerTest.java | 32 +++++ .../src/test/resources/types/categoryTypes.yml | 8 ++ 7 files changed, 276 insertions(+), 54 deletions(-) (limited to 'catalog-be') diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CategoriesImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CategoriesImportManager.java index 0eeb1a7086..4330c0de43 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CategoriesImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CategoriesImportManager.java @@ -22,6 +22,7 @@ package org.openecomp.sdc.be.components.impl; import fj.data.Either; import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.dao.neo4j.GraphPropertiesDictionary; import org.openecomp.sdc.be.datamodel.api.CategoryTypeEnum; import org.openecomp.sdc.be.datamodel.utils.NodeTypeConvertUtils; import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum; @@ -237,6 +238,10 @@ public class CategoriesImportManager { catDef.setIcons(icons); String normalizedName = ValidationUtils.normalizeCategoryName4Uniqueness(catName); catDef.setNormalizedName(normalizedName); + final Object useServiceSubstitutionForNestedServicesProperty = category.get("useServiceSubstitutionForNestedServices"); + final boolean useServiceSubstitutionForNestedServices = useServiceSubstitutionForNestedServicesProperty == null ? + false : (Boolean) useServiceSubstitutionForNestedServicesProperty; + catDef.setUseServiceSubstitutionForNestedServices(useServiceSubstitutionForNestedServices); categroiesDef.add(catDef); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java index e616ff87d3..ce1eed1a4c 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java @@ -349,30 +349,56 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { final OriginTypeEnum originType = resourceInstance.getOriginType(); validateInstanceName(resourceInstance); if (originType == OriginTypeEnum.ServiceProxy) { - - final Either serviceProxyOrigin = - toscaOperationFacade.getLatestByName("serviceProxy"); - if (isServiceProxyOrigin(serviceProxyOrigin)) { - throw new ByActionStatusComponentException( - componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value())); - } - origComponent = serviceProxyOrigin.left().value(); - - final StorageOperationStatus fillProxyRes = fillProxyInstanceData(resourceInstance, origComponent); - if (isFillProxyRes(fillProxyRes)) { - throw new ByActionStatusComponentException( - componentsUtils.convertFromStorageResponse(fillProxyRes)); + origComponent = getOrigComponentForServiceProxy(containerComponent, resourceInstance); + } else if (originType == OriginTypeEnum.ServiceSubstitution){ + origComponent = getOrigComponentForServiceSubstitution(resourceInstance); + } else { + origComponent = getAndValidateOriginComponentOfComponentInstance(containerComponent, resourceInstance); + validateOriginAndResourceInstanceTypes(containerComponent, origComponent, originType); } - } else { - origComponent = getAndValidateOriginComponentOfComponentInstance(containerComponent, - resourceInstance); + validateResourceInstanceState(containerComponent, origComponent); + overrideFields(origComponent, resourceInstance); + compositionBusinessLogic.validateAndSetDefaultCoordinates(resourceInstance); } - validateOriginAndResourceInstanceTypes(containerComponent, origComponent, originType); - validateResourceInstanceState(containerComponent, origComponent); - overrideFields(origComponent, resourceInstance); - compositionBusinessLogic.validateAndSetDefaultCoordinates(resourceInstance); + return createComponent(needLock, containerComponent,origComponent, resourceInstance, user); + + } + + private Component getOrigComponentForServiceProxy(org.openecomp.sdc.be.model.Component containerComponent, ComponentInstance resourceInstance) { + Either serviceProxyOrigin = toscaOperationFacade.getLatestByName("serviceProxy"); + if (isServiceProxyOrigin(serviceProxyOrigin)) { + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(serviceProxyOrigin.right().value())); + } + Component origComponent = serviceProxyOrigin.left().value(); + + StorageOperationStatus fillProxyRes = fillInstanceData(resourceInstance, origComponent); + if (isFillProxyRes(fillProxyRes)) { + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(fillProxyRes)); + } + validateOriginAndResourceInstanceTypes(containerComponent, origComponent, OriginTypeEnum.ServiceProxy); + return origComponent; + } + + private Component getOrigComponentForServiceSubstitution(ComponentInstance resourceInstance) { + final Either getServiceResult = toscaOperationFacade.getToscaFullElement(resourceInstance.getComponentUid()); + if (getServiceResult.isRight()) { + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getServiceResult.right().value())); + } + final Component service = getServiceResult.left().value(); + + final Either getServiceDerivedFromTypeResult = toscaOperationFacade.getLatestByToscaResourceName(service.getDerivedFromGenericType()); + if (getServiceDerivedFromTypeResult.isRight()) { + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getServiceResult.right().value())); + } + + Component origComponent = getServiceDerivedFromTypeResult.left().value(); + + final StorageOperationStatus fillProxyRes = fillInstanceData(resourceInstance, origComponent); + if (isFillProxyRes(fillProxyRes)) { + throw new ByActionStatusComponentException( + componentsUtils.convertFromStorageResponse(fillProxyRes)); } - return createComponent(needLock, containerComponent, origComponent, resourceInstance, user); + return origComponent; } private ComponentInstance createComponent(boolean needLock, Component containerComponent, Component origComponent, ComponentInstance resourceInstance, User user) { @@ -492,9 +518,8 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { return false; } - private StorageOperationStatus fillProxyInstanceData(ComponentInstance resourceInstance, Component proxyTemplate) { - resourceInstance.setIsProxy(true); - ComponentParametersView filter = new ComponentParametersView(true); + private StorageOperationStatus fillInstanceData(ComponentInstance resourceInstance, Component origComponent) { + final ComponentParametersView filter = new ComponentParametersView(true); filter.setIgnoreCapabilities(false); filter.setIgnoreCapabiltyProperties(false); filter.setIgnoreComponentInstances(false); @@ -507,38 +532,55 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { if (serviceRes.isRight()) { return serviceRes.right().value(); } - Component service = serviceRes.left().value(); - Map> capabilities = service.getCapabilities(); + final Component service = serviceRes.left().value(); + final Map> capabilities = service.getCapabilities(); resourceInstance.setCapabilities(capabilities); - Map> req = service.getRequirements(); + final Map> req = service.getRequirements(); resourceInstance.setRequirements(req); - Map serviceInterfaces = service.getInterfaces(); + final Map serviceInterfaces = service.getInterfaces(); if(MapUtils.isNotEmpty(serviceInterfaces)) { serviceInterfaces.forEach(resourceInstance::addInterface); } - - resourceInstance.setProperties(PropertiesUtils.getProperties(service)); - List serviceInputs = service.getInputs(); + final List serviceInputs = service.getInputs(); resourceInstance.setInputs(serviceInputs); - - String name = ValidationUtils.normalizeComponentInstanceName(service.getName()) + ToscaOperationFacade.PROXY_SUFFIX; - String toscaResourceName = ((Resource) proxyTemplate).getToscaResourceName(); - int lastIndexOf = toscaResourceName.lastIndexOf('.'); + resourceInstance.setSourceModelInvariant(service.getInvariantUUID()); + resourceInstance.setSourceModelName(service.getName()); + resourceInstance.setSourceModelUuid(service.getUUID()); + resourceInstance.setSourceModelUid(service.getUniqueId()); + resourceInstance.setComponentUid(origComponent.getUniqueId()); + resourceInstance.setComponentVersion(service.getVersion()); + + switch(resourceInstance.getOriginType()) { + case ServiceProxy: + return fillProxyInstanceData(resourceInstance, origComponent, service); + case ServiceSubstitution: + return fillServiceSubstitutableNodeTypeData(resourceInstance, service); + default: + return StorageOperationStatus.OK; + } + } + + private StorageOperationStatus fillProxyInstanceData(final ComponentInstance resourceInstance, final Component origComponent, final Component service) { + final String name = ValidationUtils.normalizeComponentInstanceName(service.getName()) + ToscaOperationFacade.PROXY_SUFFIX; + final String toscaResourceName = ((Resource) origComponent).getToscaResourceName(); + final int lastIndexOf = toscaResourceName.lastIndexOf('.'); if (lastIndexOf != -1) { - String proxyToscaName = toscaResourceName.substring(0, lastIndexOf + 1) + name; + final String proxyToscaName = toscaResourceName.substring(0, lastIndexOf + 1) + name; resourceInstance.setToscaComponentName(proxyToscaName); } resourceInstance.setName(name); resourceInstance.setIsProxy(true); - resourceInstance.setSourceModelInvariant(service.getInvariantUUID()); - resourceInstance.setSourceModelName(service.getName()); - resourceInstance.setSourceModelUuid(service.getUUID()); - resourceInstance.setSourceModelUid(service.getUniqueId()); - resourceInstance.setComponentUid(proxyTemplate.getUniqueId()); resourceInstance.setDescription("A Proxy for Service " + service.getName()); - resourceInstance.setComponentVersion(service.getVersion()); + return StorageOperationStatus.OK; + } + + private StorageOperationStatus fillServiceSubstitutableNodeTypeData(final ComponentInstance resourceInstance, final Component service) { + resourceInstance.setToscaComponentName("org.openecomp.service." + ValidationUtils.convertToSystemName(service.getName())); + resourceInstance.setName(ValidationUtils.normalizeComponentInstanceName(service.getName())); + resourceInstance.setIsProxy(false); + resourceInstance.setDescription("A substitutable node type for service " + service.getName()); return StorageOperationStatus.OK; } @@ -2348,6 +2390,7 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { Component origComponent = null; OriginTypeEnum originType = currentResourceInstance.getOriginType(); if (originType == OriginTypeEnum.ServiceProxy) { + newComponentInstance.setOriginType(originType); Either serviceProxyOrigin = toscaOperationFacade .getLatestByName("serviceProxy"); if (isServiceProxyOrigin(serviceProxyOrigin)) { @@ -2356,13 +2399,33 @@ public class ComponentInstanceBusinessLogic extends BaseBusinessLogic { } origComponent = serviceProxyOrigin.left().value(); - StorageOperationStatus fillProxyRes = fillProxyInstanceData(newComponentInstance, origComponent); + StorageOperationStatus fillProxyRes = fillInstanceData(newComponentInstance, origComponent); if (isFillProxyRes(fillProxyRes)) { throw new ByActionStatusComponentException( componentsUtils.convertFromStorageResponse(fillProxyRes)); } + } else if (originType == OriginTypeEnum.ServiceSubstitution){ newComponentInstance.setOriginType(originType); + + final Either getServiceResult = toscaOperationFacade.getToscaFullElement(newComponentInstance.getComponentUid()); + if (getServiceResult.isRight()) { + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getServiceResult.right().value())); + } + final Component service = getServiceResult.left().value(); + + final Either getServiceDerivedFromTypeResult = toscaOperationFacade.getLatestByToscaResourceName(service.getDerivedFromGenericType()); + if (getServiceDerivedFromTypeResult.isRight()) { + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getServiceResult.right().value())); + } + + origComponent = getServiceDerivedFromTypeResult.left().value(); + + final StorageOperationStatus fillProxyRes = fillInstanceData(newComponentInstance, origComponent); + if (isFillProxyRes(fillProxyRes)) { + throw new ByActionStatusComponentException( + componentsUtils.convertFromStorageResponse(fillProxyRes)); + } } else { origComponent = getOriginComponentFromComponentInstance(newComponentInstance); newComponentInstance.setName(resResourceInfo.getName()); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java index 518ed5726c..45db4f7365 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java @@ -25,10 +25,6 @@ import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import static org.apache.commons.collections.MapUtils.isNotEmpty; import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput; import static org.openecomp.sdc.be.tosca.InterfacesOperationsConverter.addInterfaceTypeElement; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import fj.data.Either; import java.beans.IntrospectionException; import java.util.ArrayList; import java.util.Collection; @@ -125,6 +121,9 @@ import org.yaml.snakeyaml.nodes.NodeTuple; import org.yaml.snakeyaml.nodes.Tag; import org.yaml.snakeyaml.representer.Represent; import org.yaml.snakeyaml.representer.Representer; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import fj.data.Either; @org.springframework.stereotype.Component("tosca-export-handler") public class ToscaExportHandler { @@ -282,6 +281,8 @@ public class ToscaExportHandler { if (nodeTypesMap != null && !nodeTypesMap.isEmpty()) { toscaNode.setNode_types(nodeTypesMap); } + + createServiceSubstitutionNodeTypes(componentCache, component, toscaNode); Either, ToscaError> proxyInterfaceTypesEither = createProxyInterfaceTypes(component); if (proxyInterfaceTypesEither.isRight()) { @@ -428,8 +429,11 @@ public class ToscaExportHandler { toscaMetadata.setSourceModelInvariant(componentInstance.getSourceModelInvariant()); toscaMetadata.setSourceModelUuid(componentInstance.getSourceModelUuid()); toscaMetadata.setSourceModelName(componentInstance.getSourceModelName()); - toscaMetadata.setName( - componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue()); + if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) { + toscaMetadata.setName(componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceProxy.getDisplayValue()); + } else if (componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) { + toscaMetadata.setName(componentInstance.getSourceModelName() + " " + OriginTypeEnum.ServiceSubstitution.getDisplayValue()); + } toscaMetadata.setDescription(componentInstance.getDescription()); } @@ -438,7 +442,7 @@ public class ToscaExportHandler { case RESOURCE: Resource resource = (Resource) component; - if (isInstance && componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) { + if (isInstance && (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution)) { toscaMetadata.setType(componentInstance.getOriginType().getDisplayValue()); } else { toscaMetadata.setType(resource.getResourceType().name()); @@ -546,7 +550,7 @@ public class ToscaExportHandler { final ComponentInstance componentInstance, final Component fetchedComponent) { componentCache.put(fetchedComponent.getUniqueId(), fetchedComponent); - if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) { + if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) { final Either sourceService = toscaOperationFacade .getToscaFullElement(componentInstance.getSourceModelUid()); if (sourceService.isRight() && (log.isDebugEnabled())) { @@ -1181,6 +1185,24 @@ public class ToscaExportHandler { return Either.left(nodeTypesMap); } + + private void createServiceSubstitutionNodeTypes(final Map componentCache, + final Component container, final ToscaTemplate toscaNode) { + final List componentInstances = container.getComponentInstances(); + + if (CollectionUtils.isEmpty(componentInstances)) { + return; + } + final List serviceSubstitutionInstanceList = componentInstances.stream() + .filter(p -> p.getOriginType().name().equals(OriginTypeEnum.ServiceSubstitution.name())) + .collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(serviceSubstitutionInstanceList)) { + for (ComponentInstance inst : serviceSubstitutionInstanceList) { + final Map nodeTypes = toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types(); + convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode, nodeTypes, true); + } + } + } private ToscaNodeType createProxyNodeType(Map componentCache, Component origComponent, Component proxyComponent, ComponentInstance instance) { diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CategoriesImportManagerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CategoriesImportManagerTest.java index 4be50e81ae..1d96272716 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CategoriesImportManagerTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CategoriesImportManagerTest.java @@ -43,7 +43,10 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Map; - +import java.util.Optional; +import java.util.stream.Stream; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; @@ -86,8 +89,21 @@ public class CategoriesImportManagerTest { public void importCategoriesTest() throws IOException { String ymlContent = getYmlContent(); Either>, ResponseFormat> createCapabilityTypes = importManager.createCategories(ymlContent); - assertTrue(createCapabilityTypes.isLeft()); + + assertTrue(createCapabilityTypes.isLeft()); + final Map> categories = createCapabilityTypes.left().value(); + final Optional categoryVoIPCallControl = categories.get("services").stream().filter(category -> category.getName().equals("VoIP Call Control")).findAny(); + final Optional categoryWithServiceSubstitutionTrue = categories.get("services").stream().filter(category -> category.getName().equals("Category With Service Substitution True")).findAny(); + final Optional categoryWithServiceSubstitutionFalse = categories.get("services").stream().filter(category -> category.getName().equals("Category With Service Substitution False")).findAny(); + + + assertTrue(categoryVoIPCallControl.isPresent()); + assertFalse(categoryVoIPCallControl.get().isUseServiceSubstitutionForNestedServices()); + assertTrue(categoryWithServiceSubstitutionTrue.isPresent()); + assertTrue(categoryWithServiceSubstitutionTrue.get().isUseServiceSubstitutionForNestedServices()); + assertTrue(categoryWithServiceSubstitutionFalse.isPresent()); + assertFalse(categoryWithServiceSubstitutionFalse.get().isUseServiceSubstitutionForNestedServices()); } private String getYmlContent() throws IOException { diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java index f213835406..d585c6f77a 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java @@ -1556,7 +1556,7 @@ class ComponentInstanceBusinessLogicTest { componentInst.setDeploymentArtifacts(component.getDeploymentArtifacts()); return componentInst; } - + // Prepare ComponentInstance & Resource objects used in createComponentInstance() tests private Pair prepareResourcesForCreateComponentInstanceTest() { ComponentInstance instanceToBeCreated = new ComponentInstance(); @@ -1802,4 +1802,80 @@ class ComponentInstanceBusinessLogicTest { // Check graph db change was committed verify(janusGraphDao, times(1)).commit(); } + + @Test + void testCreateComponentInstanceServiceSubstitutionSuccess() { + ComponentInstance instanceToBeCreated = createServiceSubstitutionComponentInstance(); + Service originService = createServiceSubstitutionOriginService(); + Component serviceBaseComponent = createServiceSubstitutionServiceDerivedFromComponent(); + + Service updatedService = new Service(); + updatedService.setComponentInstances(Collections.singletonList(instanceToBeCreated)); + updatedService.setUniqueId(service.getUniqueId()); + + when(toscaOperationFacade.getToscaElement(eq(COMPONENT_ID), any(ComponentParametersView.class))) + .thenReturn(Either.left(service)); + when(toscaOperationFacade.getToscaFullElement(eq(ORIGIN_COMPONENT_ID))) + .thenReturn(Either.left(originService)); + when(toscaOperationFacade.getLatestByToscaResourceName(eq(originService.getDerivedFromGenericType()))) + .thenReturn(Either.left(serviceBaseComponent)); + when(toscaOperationFacade.getToscaElement(eq(ORIGIN_COMPONENT_ID), any(ComponentParametersView.class))) + .thenReturn(Either.left(originService)); + Mockito.doNothing().when(compositionBusinessLogic).validateAndSetDefaultCoordinates(instanceToBeCreated); + when(graphLockOperation.lockComponent(COMPONENT_ID, NodeTypeEnum.Service)) + .thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacade.addComponentInstanceToTopologyTemplate(service, serviceBaseComponent, instanceToBeCreated, false, user)) + .thenReturn(Either.left(new ImmutablePair<>(updatedService, COMPONENT_INSTANCE_ID))); + when(artifactsBusinessLogic.getArtifacts( + "baseComponentId", NodeTypeEnum.Resource, ArtifactGroupTypeEnum.DEPLOYMENT, null)) + .thenReturn(Either.left(new HashMap<>())); + when(toscaOperationFacade + .addInformationalArtifactsToInstance(service.getUniqueId(), instanceToBeCreated, originService.getArtifacts())) + .thenReturn(StorageOperationStatus.OK); + when(janusGraphDao.commit()).thenReturn(JanusGraphOperationStatus.OK); + when(graphLockOperation.unlockComponent(COMPONENT_ID, NodeTypeEnum.Service)) + .thenReturn(StorageOperationStatus.OK); + + ComponentInstance result = componentInstanceBusinessLogic.createComponentInstance( + ComponentTypeEnum.SERVICE_PARAM_NAME, COMPONENT_ID, USER_ID, instanceToBeCreated); + assertThat(result).isEqualTo(instanceToBeCreated); + assertThat(instanceToBeCreated.getComponentVersion()).isEqualTo(originService.getVersion()); + assertThat(instanceToBeCreated.getIcon()).isEqualTo(originService.getIcon()); + verify(compositionBusinessLogic, times(1)).validateAndSetDefaultCoordinates(instanceToBeCreated); + verify(toscaOperationFacade, times(1)) + .addComponentInstanceToTopologyTemplate(service, serviceBaseComponent, instanceToBeCreated, false, user); + // Check graph db change was committed + verify(janusGraphDao, times(1)).commit(); + } + + private ComponentInstance createServiceSubstitutionComponentInstance() { + final ComponentInstance instanceToBeCreated = new ComponentInstance(); + instanceToBeCreated.setName(COMPONENT_INSTANCE_NAME); + instanceToBeCreated.setUniqueId(COMPONENT_INSTANCE_ID); + instanceToBeCreated.setComponentUid(ORIGIN_COMPONENT_ID); + instanceToBeCreated.setOriginType(OriginTypeEnum.ServiceSubstitution); + + return instanceToBeCreated; + } + + private Service createServiceSubstitutionOriginService() { + final Service originComponent = new Service(); + originComponent.setLifecycleState(LifecycleStateEnum.CERTIFIED); + originComponent.setVersion(ORIGIN_COMPONENT_VERSION); + originComponent.setIcon(ICON_NAME); + originComponent.setDerivedFromGenericType("org.openecomp.resource.abstract.nodes.service"); + originComponent.setName("myService"); + return originComponent; + } + + + private Component createServiceSubstitutionServiceDerivedFromComponent() { + final Resource component = new Resource(); + component.setLifecycleState(LifecycleStateEnum.CERTIFIED); + component.setVersion(ORIGIN_COMPONENT_VERSION); + component.setIcon(ICON_NAME); + component.setToscaResourceName("org.openecomp.resource.abstract.nodes.service"); + component.setUniqueId("baseComponentId"); + return component; + } } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java index 45cdbbdfaa..d54fc98c9a 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java @@ -997,6 +997,38 @@ public class ToscaExportHandlerTest extends BeConfDependentTest { result = Deencapsulation.invoke(testSubject, "createProxyNodeTypes", componentCache, container); Assert.assertNotNull(result); } + + @Test + public void testCreateServiceSubstitutionNodeTypes() throws Exception { + Map componentCache = new HashMap<>(); + + Component referencedService = getNewService(); + referencedService.setInvariantUUID("uuid"); + referencedService.setUUID("uuid"); + referencedService.setUniqueId("targetModelUid"); + referencedService.setDescription("desc"); + componentCache.put("targetModelUid", referencedService); + + Component containerService = new Service(); + List componentInstances = new ArrayList<>(); + ComponentInstance instance = new ComponentInstance(); + instance.setOriginType(OriginTypeEnum.ServiceSubstitution); + instance.setSourceModelUid("targetModelUid"); + + componentInstances.add(instance); + containerService.setComponentInstances(componentInstances); + + Mockito.when(interfaceLifecycleOperation.getAllInterfaceLifecycleTypes()) + .thenReturn(Either.left(Collections.emptyMap())); + Mockito.when(dataTypeCache.getAll()).thenReturn(Either.left(new HashMap<>())); + Mockito.when(capabiltyRequirementConvertor.convertRequirements(any(Map.class), any(Service.class), + any(ToscaNodeType.class))).thenReturn(Either.left(new ToscaNodeType())); + + ToscaTemplate toscaNode = new ToscaTemplate("1_1"); + + Deencapsulation.invoke(testSubject, "createServiceSubstitutionNodeTypes", componentCache, containerService, toscaNode); + Assert.assertNotNull(toscaNode.getNode_types()); + } @Test public void testCreateProxyNodeTypesWhenGetLatestByNameReturnValue() { diff --git a/catalog-be/src/test/resources/types/categoryTypes.yml b/catalog-be/src/test/resources/types/categoryTypes.yml index c853f9a52c..36268b1fff 100644 --- a/catalog-be/src/test/resources/types/categoryTypes.yml +++ b/catalog-be/src/test/resources/types/categoryTypes.yml @@ -11,6 +11,14 @@ services: VoIP_Call_Control: name: "VoIP Call Control" icons: ['call_controll'] + Category_With_ServiceSubstitution_True: + name: "Category With Service Substitution True" + icons: ['network_l_4'] + useServiceSubstitutionForNestedServices: true + Category_With_ServiceSubstitution_False: + name: "Category With Service Substitution False" + icons: ['network_l_4'] + useServiceSubstitutionForNestedServices: false resources: NetworkLayer23: name: "Network Layer 2-3" -- cgit 1.2.3-korg