aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-be
diff options
context:
space:
mode:
authorMichaelMorris <michael.morris@est.tech>2020-06-23 09:15:48 +0100
committerSébastien Determe <sebastien.determe@intl.att.com>2020-09-04 14:42:04 +0000
commit032525a375681fb18cc498d8daed9d73faa21ec3 (patch)
tree20cf4c17f406b8d30c29ce904fe1f19ea4a2c989 /catalog-be
parentc16117e08b97da93da61be841c22f5759cdadd37 (diff)
Support for Nested/Hierarchical Services
Change-Id: I478cf2e1f9cf96443a3e35bf22ac2c9d72bca8f1 Issue-ID: SDC-3145 Signed-off-by: MichaelMorris <michael.morris@est.tech>
Diffstat (limited to 'catalog-be')
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/CategoriesImportManager.java5
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogic.java149
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java38
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/CategoriesImportManagerTest.java20
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ComponentInstanceBusinessLogicTest.java78
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java32
-rw-r--r--catalog-be/src/test/resources/types/categoryTypes.yml8
7 files changed, 276 insertions, 54 deletions
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<Component, StorageOperationStatus> 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<Component, StorageOperationStatus> 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<Component, StorageOperationStatus> getServiceResult = toscaOperationFacade.getToscaFullElement(resourceInstance.getComponentUid());
+ if (getServiceResult.isRight()) {
+ throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getServiceResult.right().value()));
+ }
+ final Component service = getServiceResult.left().value();
+
+ final Either<Component, StorageOperationStatus> 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<String, List<CapabilityDefinition>> capabilities = service.getCapabilities();
+ final Component service = serviceRes.left().value();
+ final Map<String, List<CapabilityDefinition>> capabilities = service.getCapabilities();
resourceInstance.setCapabilities(capabilities);
- Map<String, List<RequirementDefinition>> req = service.getRequirements();
+ final Map<String, List<RequirementDefinition>> req = service.getRequirements();
resourceInstance.setRequirements(req);
- Map<String, InterfaceDefinition> serviceInterfaces = service.getInterfaces();
+ final Map<String, InterfaceDefinition> serviceInterfaces = service.getInterfaces();
if(MapUtils.isNotEmpty(serviceInterfaces)) {
serviceInterfaces.forEach(resourceInstance::addInterface);
}
-
-
resourceInstance.setProperties(PropertiesUtils.getProperties(service));
- List<InputDefinition> serviceInputs = service.getInputs();
+ final List<InputDefinition> 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<Component, StorageOperationStatus> 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<Component, StorageOperationStatus> getServiceResult = toscaOperationFacade.getToscaFullElement(newComponentInstance.getComponentUid());
+ if (getServiceResult.isRight()) {
+ throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(getServiceResult.right().value()));
+ }
+ final Component service = getServiceResult.left().value();
+
+ final Either<Component, StorageOperationStatus> 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<Map<String, Object>, 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<Component, StorageOperationStatus> 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<String, Component> componentCache,
+ final Component container, final ToscaTemplate toscaNode) {
+ final List<ComponentInstance> componentInstances = container.getComponentInstances();
+
+ if (CollectionUtils.isEmpty(componentInstances)) {
+ return;
+ }
+ final List<ComponentInstance> 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<String, ToscaNodeType> nodeTypes = toscaNode.getNode_types() == null ? new HashMap<>() : toscaNode.getNode_types();
+ convertInterfaceNodeType(new HashMap<>(), componentCache.get(inst.getSourceModelUid()), toscaNode, nodeTypes, true);
+ }
+ }
+ }
private ToscaNodeType createProxyNodeType(Map<String, Component> 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<Map<String, List<CategoryDefinition>>, ResponseFormat> createCapabilityTypes = importManager.createCategories(ymlContent);
- assertTrue(createCapabilityTypes.isLeft());
+
+ assertTrue(createCapabilityTypes.isLeft());
+ final Map<String, List<CategoryDefinition>> categories = createCapabilityTypes.left().value();
+ final Optional<CategoryDefinition> categoryVoIPCallControl = categories.get("services").stream().filter(category -> category.getName().equals("VoIP Call Control")).findAny();
+ final Optional<CategoryDefinition> categoryWithServiceSubstitutionTrue = categories.get("services").stream().filter(category -> category.getName().equals("Category With Service Substitution True")).findAny();
+ final Optional<CategoryDefinition> 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<ComponentInstance, Resource> 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<String, Component> 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<ComponentInstance> 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"