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 ++++-- 3 files changed, 141 insertions(+), 51 deletions(-) (limited to 'catalog-be/src/main') 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) { -- cgit 1.2.3-korg