From 50619616a9bd803bb9bb820fe83d999f26ba3f34 Mon Sep 17 00:00:00 2001 From: MichaelMorris Date: Fri, 16 Jul 2021 09:05:12 +0100 Subject: [PATCH] Import VSP top. template handling non SDC model Signed-off-by: MichaelMorris Issue-ID: SDC-3649 Change-Id: I2e2004187f5694f92d65b73139436fc990e7a6af --- .../csar/YamlTemplateParsingHandler.java | 5 + .../be/components/impl/ComponentBusinessLogic.java | 28 +- .../be/components/impl/ResourceBusinessLogic.java | 285 +++++++++++++++++---- .../be/components/impl/ServiceBusinessLogic.java | 17 -- .../impl/generic/GenericTypeBusinessLogic.java | 12 + .../be/tosca/CapabilityRequirementConverter.java | 73 ++++-- .../components/impl/ResourceBusinessLogicTest.java | 192 +++++++++++++- .../components/impl/ServiceBusinessLogicTest.java | 14 +- .../impl/utils/YamlTemplateParsingHandlerTest.java | 1 + .../src/test/resources/csars/nonOnapCsar.csar | Bin 0 -> 13948 bytes .../src/test/resources/csars/with_groups.csar | Bin 65799 -> 65647 bytes .../sdc/be/model/ParsedToscaYamlInfo.java | 1 + .../operations/NodeTemplateOperation.java | 3 +- .../operations/ToscaOperationFacade.java | 40 ++- .../elements/CapabilityDataDefinition.java | 5 +- .../elements/RequirementDataDefinition.java | 6 +- 16 files changed, 573 insertions(+), 109 deletions(-) create mode 100644 catalog-be/src/test/resources/csars/nonOnapCsar.csar diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java index 5d4549406c..6a56da2c4d 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java @@ -40,6 +40,7 @@ import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.IS_PASSWORD import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.MEMBERS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.NODE_TYPE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.POLICIES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.PROPERTIES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIREMENTS; @@ -64,6 +65,7 @@ import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -139,6 +141,9 @@ public class YamlTemplateParsingHandler { if (component instanceof Resource) { parsedToscaYamlInfo.setPolicies(getPolicies(fileName, mappedToscaTemplate, component.getModel())); } + if (getSubstitutionMappings(mappedToscaTemplate) != null) { + parsedToscaYamlInfo.setSubstitutionMappingNodeType((String) getSubstitutionMappings(mappedToscaTemplate).get(NODE_TYPE.getElementName())); + } log.debug("#parseResourceInfoFromYAML - The yaml {} has been parsed ", fileName); return parsedToscaYamlInfo; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java index 6007d0602e..7d4ba3bf77 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ComponentBusinessLogic.java @@ -686,14 +686,34 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { }); return componentNonGenericInputs; } + + protected void generatePropertiesFromGenericType(final Component component, final Resource genericType) { + if (CollectionUtils.isEmpty(genericType.getProperties())) { + return; + } + final List genericTypePropertyList = genericType.getProperties().stream().map(PropertyDefinition::new) + .peek(propertyDefinition -> propertyDefinition.setUniqueId(null)).collect(Collectors.toList()); + if (component.getProperties() == null) { + component.setProperties(new ArrayList<>(genericTypePropertyList)); + } else { + List servicePropertyList = component.getProperties(); + genericTypePropertyList.stream() + .filter(property -> servicePropertyList.stream().noneMatch(property1 -> property1.getName().equals(property.getName()))) + .forEach(servicePropertyList::add); + } + component.getProperties().forEach(propertyDefinition -> propertyDefinition.setUniqueId(null)); + } + protected Resource fetchAndSetDerivedFromGenericType(final T component) { + return fetchAndSetDerivedFromGenericType(component, null); + } - protected Resource fetchAndSetDerivedFromGenericType(T component) { - Either genericTypeEither = this.genericTypeBusinessLogic.fetchDerivedFromGenericType(component); + protected Resource fetchAndSetDerivedFromGenericType(final T component, final String toscaType) { + final Either genericTypeEither = this.genericTypeBusinessLogic.fetchDerivedFromGenericType(component, toscaType); if (genericTypeEither.isRight()) { log.debug("Failed to fetch latest generic type for component {} of type", component.getName(), component.assetType()); throw new ByActionStatusComponentException(ActionStatus.GENERIC_TYPE_NOT_FOUND, component.assetType()); } - Resource genericTypeResource = genericTypeEither.left().value(); + final Resource genericTypeResource = genericTypeEither.left().value(); component.setDerivedFromGenericInfo(genericTypeResource); return genericTypeResource; } @@ -855,7 +875,7 @@ public abstract class ComponentBusinessLogic extends BaseBusinessLogic { } public Either shouldUpgradeToLatestGeneric(Component clonedComponent) { - if (!clonedComponent.deriveFromGeneric()) { + if (!clonedComponent.deriveFromGeneric() || StringUtils.isNotEmpty(clonedComponent.getModel())) { return Either.left(false); } Boolean shouldUpgrade = false; diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java index f5b890e438..2435b5e937 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java @@ -29,9 +29,6 @@ import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaStr import static org.openecomp.sdc.be.components.impl.ImportUtils.getPropertyJsonStringValue; import static org.openecomp.sdc.be.tosca.CsarUtils.VF_NODE_TYPE_ARTIFACTS_PATH_PATTERN; import static org.openecomp.sdc.common.api.Constants.DEFAULT_GROUP_VF_MODULE; - -import com.google.common.annotations.VisibleForTesting; -import fj.data.Either; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -185,6 +182,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.Yaml; +import com.google.common.annotations.VisibleForTesting; +import fj.data.Either; @org.springframework.stereotype.Component("resourceBusinessLogic") public class ResourceBusinessLogic extends ComponentBusinessLogic { @@ -561,14 +560,15 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { preparedResource = updateExistingResourceByImport(newResource, oldResource, csarInfo.getModifier(), inTransaction, shouldLock, isNested).left; log.trace("YAML topology file found in CSAR, file name: {}, contents: {}", yamlFileName, yamlFileContent); - handleResourceGenericType(preparedResource); + handleResourceGenericType(preparedResource, yamlFileContent, uploadComponentInstanceInfoMap, uploadComponentInstanceInfoMap.getSubstitutionMappingNodeType()); handleNodeTypes(yamlFileName, preparedResource, yamlFileContent, shouldLock, nodeTypesArtifactsToHandle, createdArtifacts, nodeTypesInfo, - csarInfo, nodeName); + csarInfo, nodeName, newResource.getModel()); preparedResource = createInputsOnResource(preparedResource, uploadComponentInstanceInfoMap.getInputs()); Map existingNodeTypesByResourceNames = new HashMap<>(); - preparedResource = createResourceInstances(yamlFileName, preparedResource, oldResource, instances, csarInfo.getCreatedNodes(), + final Map instancesToCreate = getInstancesToCreate(uploadComponentInstanceInfoMap, newResource.getModel()); + preparedResource = createResourceInstances(yamlFileName, preparedResource, oldResource, instancesToCreate, csarInfo.getCreatedNodes(), existingNodeTypesByResourceNames); - preparedResource = createResourceInstancesRelations(csarInfo.getModifier(), yamlFileName, preparedResource, oldResource, instances, + preparedResource = createResourceInstancesRelations(csarInfo.getModifier(), yamlFileName, preparedResource, oldResource, instancesToCreate, existingNodeTypesByResourceNames); } catch (ComponentException e) { ResponseFormat responseFormat = @@ -714,15 +714,31 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } return Either.left(resource); } - + private Resource handleResourceGenericType(Resource resource) { Resource genericResource = fetchAndSetDerivedFromGenericType(resource); + if (resource.shouldGenerateInputs()) { generateAndAddInputsFromGenericTypeProperties(resource, genericResource); } return genericResource; } + private Resource handleResourceGenericType(final Resource resource, final String topologyTemplateYaml, final ParsedToscaYamlInfo parsedToscaYamlInfo, final String substitutionMappingNodeType) { + if (processSubstitutableAsNodeType(resource, parsedToscaYamlInfo)) { + final Map substitutableAsNodeType = getSubstitutableAsNodeTypeFromTemplate((Map) new Yaml().load(topologyTemplateYaml), substitutionMappingNodeType); + final Resource genericResource = fetchAndSetDerivedFromGenericType(resource, (String)substitutableAsNodeType.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName())); + + generatePropertiesFromGenericType(resource, genericResource); + generatePropertiesFromNodeType(resource, substitutableAsNodeType); + final String resourceId = resource.getUniqueId(); + resource.getProperties().forEach(propertyDefinition -> propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(resourceId, propertyDefinition.getName()))); + createResourcePropertiesOnGraph(resource); + return genericResource; + } + return handleResourceGenericType(resource); + } + private Either>>, ResponseFormat> findNodeTypesArtifactsToHandle( final Map nodeTypesInfo, final CsarInfo csarInfo, final Resource oldResource) { final Map>> nodeTypesArtifactsToHandle = new HashMap<>(); @@ -1072,20 +1088,33 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { boolean needLock, Map>> nodeTypesArtifactsToHandle, List nodeTypesNewCreatedArtifacts, - Map nodeTypesInfo, CsarInfo csarInfo) { + Map nodeTypesInfo, CsarInfo csarInfo, final String substitutableAsNodeType) { Either toscaVersion = findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION); if (toscaVersion.isRight()) { throw new ByActionStatusComponentException(ActionStatus.INVALID_TOSCA_TEMPLATE); } Map mapToConvert = new HashMap<>(); mapToConvert.put(TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION.getElementName(), toscaVersion.left().value()); - Map nodeTypes = getNodeTypesFromTemplate(mappedToscaTemplate); + final Map nodeTypes = getNodeTypesFromTemplate(mappedToscaTemplate, substitutableAsNodeType); createNodeTypes(yamlName, resource, needLock, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, mapToConvert, nodeTypes); return csarInfo.getCreatedNodes(); } - private Map getNodeTypesFromTemplate(Map mappedToscaTemplate) { + private Map getNodeTypesFromTemplate(final Map mappedToscaTemplate, final String substitutableAsNodeType) { + final Map nodeTypes = getAllNodeTypesInTemplate(mappedToscaTemplate); + if (StringUtils.isNotEmpty(substitutableAsNodeType)){ + nodeTypes.remove(substitutableAsNodeType); + } + return nodeTypes; + } + + @SuppressWarnings("unchecked") + private Map getSubstitutableAsNodeTypeFromTemplate(final Map mappedToscaTemplate, final String substitutableAsNodeType) { + return (Map)getAllNodeTypesInTemplate(mappedToscaTemplate).get(substitutableAsNodeType); + } + + private Map getAllNodeTypesInTemplate(final Map mappedToscaTemplate) { return ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES).left().orValue(HashMap::new); } @@ -1127,7 +1156,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map nestedVfcJsonMap = nodesInfo.get(nodeName).getMappedToscaTemplate(); log.debug("************* Going to create node types from yaml {}", yamlName); createResourcesFromYamlNodeTypesList(yamlName, resource, nestedVfcJsonMap, false, nodesArtifactsToHandle, createdArtifacts, - Collections.emptyMap(), csarInfo); + Collections.emptyMap(), csarInfo, resource.getModel()); log.debug("************* Finished to create node types from yaml {}", yamlName); if (nestedVfcJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE.getElementName())) { log.debug("************* Going to handle complex VFC from yaml {}", yamlName); @@ -1395,36 +1424,60 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { log.trace("************* createResourceFromYaml before full create resource {}", yamlName); loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, resource.getComponentMetadataForSupportLog(), StatusCode.STARTED, "Starting to add inputs from yaml: {}", yamlName); - final Resource genericResource = fetchAndSetDerivedFromGenericType(resource); - resource = createResourceTransaction(resource, csarInfo.getModifier(), isNormative); - log.trace("************* createResourceFromYaml after full create resource {}", yamlName); - log.trace("************* Going to add inputs from yaml {}", yamlName); - if (resource.shouldGenerateInputs()) { - generateAndAddInputsFromGenericTypeProperties(resource, genericResource); - } - final Map inputs = parsedToscaYamlInfo.getInputs(); - resource = createInputsOnResource(resource, inputs); - log.trace("************* Finish to add inputs from yaml {}", yamlName); - loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE, - "Finish to add inputs from yaml: {}", yamlName); - if (resource.getResourceType() == ResourceTypeEnum.PNF) { - log.trace("************* Adding generic properties to PNF"); - resource = (Resource) propertyBusinessLogic.copyPropertyToComponent(resource, genericResource.getProperties()); - log.trace("************* Adding software information to PNF"); - softwareInformationBusinessLogic.setSoftwareInformation(resource, csarInfo); - log.trace("************* Removing non-mano software information file from PNF"); - if (csarInfo.getSoftwareInformationPath().isPresent() && !softwareInformationBusinessLogic.removeSoftwareInformationFile(csarInfo)) { - log.warn(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ResourceBusinessLogic.class.getName(), "catalog-be", - "Could not remove the software information file."); + if (processSubstitutableAsNodeType(resource, parsedToscaYamlInfo)) { + final Map substitutableAsNodeType = getSubstitutableAsNodeTypeFromTemplate((Map) new Yaml().load(topologyTemplateYaml), parsedToscaYamlInfo.getSubstitutionMappingNodeType()); + resource.setToscaResourceName(parsedToscaYamlInfo.getSubstitutionMappingNodeType()); + final Resource genericResource = fetchAndSetDerivedFromGenericType(resource, (String)substitutableAsNodeType.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName())); + resource = createResourceTransaction(resource, csarInfo.getModifier(), isNormative); + generatePropertiesFromGenericType(resource, genericResource); + generatePropertiesFromNodeType(resource, substitutableAsNodeType); + final String resourceId = resource.getUniqueId(); + resource.getProperties().forEach(propertyDefinition -> propertyDefinition.setUniqueId(UniqueIdBuilder.buildPropertyUniqueId(resourceId, propertyDefinition.getName()))); + + createResourcePropertiesOnGraph(resource); + final Map instancesToCreate = getInstancesToCreate(parsedToscaYamlInfo, resource.getModel()); + + log.trace("************* Going to create nodes, RI's and Relations from yaml {}", yamlName); + loggerSupportability + .log(LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML, resource.getComponentMetadataForSupportLog(), StatusCode.STARTED, + "Start create nodes, RI and Relations from yaml: {}", yamlName); + resource = createRIAndRelationsFromYaml(yamlName, resource, instancesToCreate, topologyTemplateYaml, + nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeTypesArtifactsToCreate, nodeName, parsedToscaYamlInfo.getSubstitutionMappingNodeType()); + } else { + final Resource genericResource = fetchAndSetDerivedFromGenericType(resource, null); + resource = createResourceTransaction(resource, csarInfo.getModifier(), isNormative); + log.trace("************* createResourceFromYaml after full create resource {}", yamlName); + log.trace("************* Going to add inputs from yaml {}", yamlName); + if (resource.shouldGenerateInputs()) { + generateAndAddInputsFromGenericTypeProperties(resource, genericResource); } - } - final Map uploadComponentInstanceInfoMap = parsedToscaYamlInfo.getInstances(); - log.trace("************* Going to create nodes, RI's and Relations from yaml {}", yamlName); - loggerSupportability - .log(LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML, resource.getComponentMetadataForSupportLog(), StatusCode.STARTED, - "Start create nodes, RI and Relations from yaml: {}", yamlName); - resource = createRIAndRelationsFromYaml(yamlName, resource, uploadComponentInstanceInfoMap, topologyTemplateYaml, - nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeTypesArtifactsToCreate, nodeName); + final Map inputs = parsedToscaYamlInfo.getInputs(); + resource = createInputsOnResource(resource, inputs); + + log.trace("************* Finish to add inputs from yaml {}", yamlName); + loggerSupportability.log(LoggerSupportabilityActions.CREATE_INPUTS, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE, + "Finish to add inputs from yaml: {}", yamlName); + if (resource.getResourceType() == ResourceTypeEnum.PNF) { + log.trace("************* Adding generic properties to PNF"); + resource = (Resource) propertyBusinessLogic.copyPropertyToComponent(resource, genericResource.getProperties()); + log.trace("************* Adding software information to PNF"); + softwareInformationBusinessLogic.setSoftwareInformation(resource, csarInfo); + log.trace("************* Removing non-mano software information file from PNF"); + if (csarInfo.getSoftwareInformationPath().isPresent() && !softwareInformationBusinessLogic.removeSoftwareInformationFile(csarInfo)) { + log.warn(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, ResourceBusinessLogic.class.getName(), "catalog-be", + "Could not remove the software information file."); + } + } + final Map instancesToCreate = getInstancesToCreate(parsedToscaYamlInfo); + + log.trace("************* Going to create nodes, RI's and Relations from yaml {}", yamlName); + loggerSupportability + .log(LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML, resource.getComponentMetadataForSupportLog(), StatusCode.STARTED, + "Start create nodes, RI and Relations from yaml: {}", yamlName); + resource = createRIAndRelationsFromYaml(yamlName, resource, instancesToCreate, topologyTemplateYaml, + nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, nodeTypesArtifactsToCreate, nodeName, null); + } + log.trace("************* Finished to create nodes, RI and Relation from yaml {}", yamlName); loggerSupportability.log(LoggerSupportabilityActions.CREATE_RELATIONS, resource.getComponentMetadataForSupportLog(), StatusCode.COMPLETE, "Finished to create nodes, RI and Relation from yaml: {}", yamlName); @@ -1505,6 +1558,22 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } } } + + private boolean processSubstitutableAsNodeType(final Resource resource, final ParsedToscaYamlInfo parsedToscaYamlInfo) { + return !resource.getResourceType().isAtomicType() && StringUtils.isNotEmpty(resource.getModel()) && parsedToscaYamlInfo.getSubstitutionMappingNodeType() != null; + } + + private Map getInstancesToCreate(final ParsedToscaYamlInfo parsedToscaYamlInfo) { + return getInstancesToCreate(parsedToscaYamlInfo, null); + } + + private Map getInstancesToCreate(final ParsedToscaYamlInfo parsedToscaYamlInfo, final String model) { + if (StringUtils.isEmpty(model) || StringUtils.isEmpty(parsedToscaYamlInfo.getSubstitutionMappingNodeType())) { + return parsedToscaYamlInfo.getInstances(); + } + return parsedToscaYamlInfo.getInstances().entrySet().stream().filter(entry -> !parsedToscaYamlInfo.getSubstitutionMappingNodeType().equals(entry.getValue().getType())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } private void rollback(boolean inTransaction, Resource resource, List createdArtifacts, List nodeTypesNewCreatedArtifacts) { @@ -1689,6 +1758,41 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } return resource; } + + private Resource generatePropertiesFromNodeType(final Resource resource, final Map nodeType) { + final Either, ResultStatusEnum> properties = ImportUtils.getProperties(nodeType); + if (properties.isLeft()) { + final List propertiesList = new ArrayList<>(); + final Map value = properties.left().value(); + if (value != null) { + for (Entry entry : value.entrySet()) { + final String name = entry.getKey(); + final PropertyDefinition propertyDefinition = entry.getValue(); + propertyDefinition.setName(name); + propertiesList.add(propertyDefinition); + resource.getProperties().removeIf(p -> p.getName().equals(name)); + } + } + resource.getProperties().addAll(propertiesList); + } + return resource; + } + + private Resource createResourcePropertiesOnGraph(final Resource resource) { + final List resourceProperties = resource.getProperties(); + for (PropertyDefinition propertyDefinition: resourceProperties) { + final Either addPropertyEither = toscaOperationFacade + .addPropertyToComponent(propertyDefinition.getName(), propertyDefinition, resource); + + if (addPropertyEither.isRight()) { + final String error = String.format("failed to add properties from yaml: {}", addPropertyEither.right().value()); + loggerSupportability.log(LoggerSupportabilityActions.CREATE_PROPERTIES, resource.getComponentMetadataForSupportLog(), StatusCode.ERROR, + error); + throw new ByActionStatusComponentException(componentsUtils.convertFromStorageResponse(addPropertyEither.right().value()), error); + } + } + return resource; + } private List updateGroupsMembersUsingResource(Map groups, Resource component) { List result = new ArrayList<>(); @@ -1829,10 +1933,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { String topologyTemplateYaml, List nodeTypesNewCreatedArtifacts, Map nodeTypesInfo, CsarInfo csarInfo, Map>> nodeTypesArtifactsToCreate, - String nodeName) { + String nodeName, final String substitutableAsNodeType) { log.debug("************* Going to create all nodes {}", yamlName); handleNodeTypes(yamlName, resource, topologyTemplateYaml, false, nodeTypesArtifactsToCreate, nodeTypesNewCreatedArtifacts, nodeTypesInfo, - csarInfo, nodeName); + csarInfo, nodeName, substitutableAsNodeType); log.debug("************* Finished to create all nodes {}", yamlName); log.debug("************* Going to create all resource instances {}", yamlName); Map existingNodeTypesByResourceNames = new HashMap<>(); @@ -1864,7 +1968,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { private void handleNodeTypes(String yamlName, Resource resource, String topologyTemplateYaml, boolean needLock, Map>> nodeTypesArtifactsToHandle, List nodeTypesNewCreatedArtifacts, Map nodeTypesInfo, CsarInfo csarInfo, - String nodeName) { + String nodeName, String substitutableAsNodeType) { try { for (Entry nodeTypeEntry : nodeTypesInfo.entrySet()) { if (nodeTypeEntry.getValue().isNested() && !nodeTypeAlreadyExists(nodeTypeEntry.getKey())) { @@ -1881,7 +1985,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { mappedToscaTemplate = (Map) new Yaml().load(topologyTemplateYaml); } createResourcesFromYamlNodeTypesList(yamlName, resource, mappedToscaTemplate, needLock, nodeTypesArtifactsToHandle, - nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo); + nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, substitutableAsNodeType); } catch (ComponentException e) { ResponseFormat responseFormat = e.getResponseFormat() != null ? e.getResponseFormat() : componentsUtils.getResponseFormat(e.getActionStatus(), e.getParams()); @@ -2384,14 +2488,18 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } private void handleSubstitutionMappings(Resource resource, Map uploadResInstancesMap) { + Either getResourceRes = null; if (resource.getResourceType() == ResourceTypeEnum.CVFC) { - Either getResourceRes = updateCalculatedCapReqWithSubstitutionMappings(resource, uploadResInstancesMap); - if (getResourceRes.isRight()) { - ResponseFormat responseFormat = componentsUtils - .getResponseFormatByResource(componentsUtils.convertFromStorageResponse(getResourceRes.right().value()), resource); - throw new ByResponseFormatComponentException(responseFormat); - } + getResourceRes = updateCalculatedCapReqWithSubstitutionMappings(resource, uploadResInstancesMap); + } else if (StringUtils.isNotEmpty(resource.getModel()) && resource.getResourceType() == ResourceTypeEnum.VF) { + getResourceRes = updateCalculatedCapReqWithSubstitutionMappingsForVf(resource, uploadResInstancesMap); } + if (getResourceRes != null && getResourceRes.isRight()) { + ResponseFormat responseFormat = componentsUtils + .getResponseFormatByResource(componentsUtils.convertFromStorageResponse(getResourceRes.right().value()), resource); + throw new ByResponseFormatComponentException(responseFormat); + } + } private void addRelationsToRI(String yamlName, Resource resource, Map uploadResInstancesMap, @@ -2559,6 +2667,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Either updateRes = null; Map>> updatedInstCapabilities = new HashMap<>(); Map>> updatedInstRequirements = new HashMap<>(); + StorageOperationStatus status = toscaOperationFacade.deleteAllCalculatedCapabilitiesRequirements(resource.getUniqueId()); if (status != StorageOperationStatus.OK && status != StorageOperationStatus.NOT_FOUND) { log.debug("Failed to delete all calculated capabilities and requirements of resource {} upon update. Status is {}", @@ -2581,6 +2690,31 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } return updateRes; } + + private Either updateCalculatedCapReqWithSubstitutionMappingsForVf(final Resource resource, + final Map uploadResInstancesMap) { + Either updateRes = null; + final Map>> updatedInstCapabilities = new HashMap<>(); + final Map>> updatedInstRequirements = new HashMap<>(); + + resource.getComponentInstances().forEach(i -> { + setExternalCapabilities(updatedInstCapabilities, i, uploadResInstancesMap.get(i.getName()).getCapabilitiesNamesToUpdate()); + setExternalRequirements(updatedInstRequirements, i, uploadResInstancesMap.get(i.getName()).getRequirementsNamesToUpdate()); + }); + + final StorageOperationStatus status = toscaOperationFacade.updateCalculatedCapabilitiesRequirements(updatedInstCapabilities, updatedInstRequirements, resource); + if (status != StorageOperationStatus.OK) { + log.debug( + "Failed to update capabilities and requirements of resource {}. Status is {}", + resource.getUniqueId(), status); + updateRes = Either.right(status); + } + + if (updateRes == null) { + updateRes = Either.left(resource); + } + return updateRes; + } private void fillUpdatedInstCapabilitiesRequirements(List componentInstances, Map uploadResInstancesMap, @@ -2612,6 +2746,54 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { updatedInstRequirements.put(instance, updatedRequirements); } } + + private void setExternalRequirements( + final Map>> updatedInstRequirements, + final ComponentInstance instance, final Map requirementsNamesToUpdate) { + final Map> updatedRequirements = new HashMap<>(); + final Set updatedReqNames = new HashSet<>(); + if (isNotEmpty(requirementsNamesToUpdate)) { + for (Map.Entry> requirements : instance.getRequirements().entrySet()) { + updatedRequirements.put(requirements.getKey(), + requirements.getValue().stream() + .filter(r -> requirementsNamesToUpdate.containsKey(r.getName()) + && !updatedReqNames.contains(requirementsNamesToUpdate.get(r.getName()))) + .map(r -> { + r.setExternal(true); + r.setExternalName(requirementsNamesToUpdate.get(r.getName())); + updatedReqNames.add(r.getName()); + return r; + }).collect(toList())); + } + } + if (isNotEmpty(updatedRequirements)) { + updatedInstRequirements.put(instance, updatedRequirements); + } + } + + private void setExternalCapabilities( + final Map>> updatedInstCapabilties, + final ComponentInstance instance, Map capabilitiesNamesToUpdate) { + final Map> updatedCapabilities = new HashMap<>(); + final Set updatedCapNames = new HashSet<>(); + if (isNotEmpty(capabilitiesNamesToUpdate)) { + for (Map.Entry> requirements : instance.getCapabilities().entrySet()) { + updatedCapabilities.put(requirements.getKey(), + requirements.getValue().stream() + .filter(c -> capabilitiesNamesToUpdate.containsKey(c.getName()) + && !updatedCapNames.contains(capabilitiesNamesToUpdate.get(c.getName()))) + .map(c -> { + c.setExternal(true); + c.setExternalName(capabilitiesNamesToUpdate.get(c.getName())); + updatedCapNames.add(c.getName()); + return c; + }).collect(toList())); + } + } + if (isNotEmpty(updatedCapabilities)) { + updatedInstCapabilties.put(instance, updatedCapabilities); + } + } private void fillUpdatedInstCapabilities(Map>> updatedInstCapabilties, ComponentInstance instance, Map capabilitiesNamesToUpdate) { @@ -3383,6 +3565,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { newResource.setUUID(oldResource.getUUID()); newResource.setNormalizedName(oldResource.getNormalizedName()); newResource.setSystemName(oldResource.getSystemName()); + newResource.setModel(oldResource.getModel()); if (oldResource.getCsarUUID() != null) { newResource.setCsarUUID(oldResource.getCsarUUID()); } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java index ccaadbad76..21d27f3fa0 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogic.java @@ -737,23 +737,6 @@ public class ServiceBusinessLogic extends ComponentBusinessLogic { }); } - private void generatePropertiesFromGenericType(final Service service, final Resource genericType) { - if (CollectionUtils.isEmpty(genericType.getProperties())) { - return; - } - final List genericTypePropertyList = genericType.getProperties().stream().map(PropertyDefinition::new) - .peek(propertyDefinition -> propertyDefinition.setUniqueId(null)).collect(Collectors.toList()); - if (service.getProperties() == null) { - service.setProperties(new ArrayList<>(genericTypePropertyList)); - } else { - List servicePropertyList = service.getProperties(); - genericTypePropertyList.stream() - .filter(property -> servicePropertyList.stream().noneMatch(property1 -> property1.getName().equals(property.getName()))) - .forEach(servicePropertyList::add); - } - service.getProperties().forEach(propertyDefinition -> propertyDefinition.setUniqueId(null)); - } - @SuppressWarnings("unchecked") private void createServiceApiArtifactsData(Service service, User user) { // create mandatory artifacts diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogic.java index 313d345da1..6cf4327a99 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/generic/GenericTypeBusinessLogic.java @@ -78,6 +78,18 @@ public class GenericTypeBusinessLogic { Resource genericTypeResource = genericType.left().value(); return Either.left(genericTypeResource); } + + public Either fetchDerivedFromGenericType(final Component component, final String toscaType) { + if (StringUtils.isNotEmpty(toscaType)) { + final Either genericType = toscaOperationFacade.getLatestByToscaResourceNameAndModel(toscaType, component.getModel()); + if (genericType.isRight()) { + log.debug("Failed to fetch certified node type by tosca resource name {}", toscaType); + return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERIC_TYPE_NOT_FOUND, component.assetType(), toscaType)); + } + return Either.left(genericType.left().value()); + } + return fetchDerivedFromGenericType(component); + } /** * @param genericType the generic node type diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java index 88f3666305..8cc5868341 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CapabilityRequirementConverter.java @@ -301,9 +301,7 @@ public class CapabilityRequirementConverter { Map toscaRequirements = new HashMap<>(); Either, ToscaError> result = null; for (Map.Entry> entry : requirements.entrySet()) { - Optional failedToAddRequirement = entry.getValue().stream().filter(RequirementDefinition::isExternal).filter( - r -> !addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(r.getName(), r.getParentName(), ""), - r.getPreviousName(), r.getOwnerId(), r.getPath())).findAny(); + Optional failedToAddRequirement = addExternalToToscaRequirements(componentsCache, toscaRequirements, component, entry.getValue()); if (failedToAddRequirement.isPresent()) { logger.debug("Failed to convert requirement {} for substitution mappings section of a tosca template of the component {}. ", failedToAddRequirement.get().getName(), component.getName()); @@ -316,6 +314,18 @@ public class CapabilityRequirementConverter { } return result; } + + private Optional addExternalToToscaRequirements(final Map componentsCache, + final Map toscaRequirements, final Component component, final List requirements) { + return requirements.stream().filter(RequirementDefinition::isExternal).filter( + r -> ! + (StringUtils.isEmpty(r.getExternalName()) ? + addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(r.getName(), r.getParentName(), ""), + r.getPreviousName(), r.getOwnerId(), r.getPath()): + addEntry(componentsCache, toscaRequirements, component, new SubstitutionEntry(r.getExternalName(), r.getName(), ""), + r.getPreviousName(), r.getOwnerId(), r.getPath(), false)) + ).findAny(); + } private Either, ToscaError> buildAddSubstitutionMappingsCapabilities(Map componentsCache, Component component, @@ -323,11 +333,7 @@ public class CapabilityRequirementConverter { Map toscaCapabilities = new HashMap<>(); Either, ToscaError> result = null; for (Map.Entry> entry : capabilities.entrySet()) { - Optional failedToAddRequirement = entry.getValue().stream() - .filter(CapabilityDataDefinition::isExternal) - .filter( c -> !addEntry(componentsCache, toscaCapabilities, component, new SubstitutionEntry(c.getName(), c.getParentName(), "") - , c.getPreviousName(), c.getOwnerId(), c.getPath())) - .findAny(); + Optional failedToAddRequirement = addExternalToToscaCapabilities(componentsCache, toscaCapabilities, component, entry.getValue()); if (failedToAddRequirement.isPresent()) { logger.debug("Failed to convert capability {} for substitution mappings section of a tosca template of the component {}. ", failedToAddRequirement.get().getName(), component.getName()); @@ -340,18 +346,38 @@ public class CapabilityRequirementConverter { } return result; } + + private Optional addExternalToToscaCapabilities(final Map componentsCache, + final Map toscaCapabilities, final Component component, final List requirements) { + return requirements.stream() + .filter(CapabilityDataDefinition::isExternal) + .filter( c -> ! + (StringUtils.isEmpty(c.getExternalName()) ? + addEntry(componentsCache, toscaCapabilities, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""), + c.getPreviousName(), c.getOwnerId(), c.getPath()): + addEntry(componentsCache, toscaCapabilities, component, new SubstitutionEntry(c.getName(), c.getParentName(), ""), + c.getPreviousName(), c.getOwnerId(), c.getPath(), false)) + ).findAny(); + } private boolean addEntry(Map componentsCache, Map capReqMap, Component component, SubstitutionEntry entry, String previousName, String ownerId, List path) { - if (shouldBuildSubstitutionName(component, path) && !buildSubstitutedNamePerInstance(componentsCache, component, entry.getFullName(), - previousName, path, ownerId, entry)) { + return addEntry(componentsCache, capReqMap, component, entry, previousName, ownerId, path, shouldBuildSubstitutionName(component, path)); + } + + private boolean addEntry(final Map componentsCache, Map capReqMap, final Component component, + final SubstitutionEntry entry, final String previousName, final String ownerId, final List path, final boolean shouldBuildSubstitutionName) { + if (shouldBuildSubstitutionName && !buildSubstitutedNamePerInstance(componentsCache, + component, entry.getFullName(), previousName, path, ownerId, entry)) { return false; } - logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(), component.getUniqueId()); + logger.debug("The requirement/capability {} belongs to the component {} ", entry.getFullName(), + component.getUniqueId()); if (StringUtils.isNotEmpty(entry.getSourceName())) { addEntry(capReqMap, component, path, entry); } - logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(), component.getName()); + logger.debug("Finish convert the requirement/capability {} for the component {}. ", entry.getFullName(), + component.getName()); return true; } @@ -445,10 +471,16 @@ public class CapabilityRequirementConverter { private ImmutablePair convertRequirement(Map componentsCache, Component component, boolean isNodeType, RequirementDefinition r) { - String name = r.getName(); - if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) { - name = buildReqNamePerOwnerByPath(componentsCache, component, r); + String name; + if (StringUtils.isEmpty(r.getExternalName())){ + name = r.getName(); + if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) { + name = buildReqNamePerOwnerByPath(componentsCache, component, r); + } + } else { + name = r.getExternalName(); } + logger.debug("the requirement {} belongs to resource {} ", name, component.getUniqueId()); ToscaRequirement toscaRequirement = createToscaRequirement(r); return new ImmutablePair<>(name, toscaRequirement); @@ -546,9 +578,14 @@ public class CapabilityRequirementConverter { private void convertCapability(Map componentsCache, Component component, Map toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map dataTypes, String capabilityName) { - String name = isNoneBlank(capabilityName) ? capabilityName : c.getName(); - if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) { - name = buildCapNamePerOwnerByPath(componentsCache, c, component); + String name; + if (StringUtils.isEmpty(c.getExternalName())) { + name = isNoneBlank(capabilityName) ? capabilityName : c.getName(); + if (!isNodeType && ToscaUtils.isNotComplexVfc(component)) { + name = buildCapNamePerOwnerByPath(componentsCache, c, component); + } + } else { + name = c.getExternalName(); } logger.debug("The capability {} belongs to resource {} ", name, component.getUniqueId()); createToscaCapability(toscaCapabilities, c, dataTypes, name); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java index fe2f3ba983..f0900f7589 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java @@ -27,20 +27,28 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import fj.data.Either; +import java.io.File; import java.io.IOException; import java.lang.reflect.Method; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -58,10 +66,12 @@ import org.openecomp.sdc.be.components.ArtifactsResolver; import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarInfo; +import org.openecomp.sdc.be.components.csar.YamlTemplateParsingHandler; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.impl.generic.GenericTypeBusinessLogic; +import org.openecomp.sdc.be.components.impl.utils.YamlTemplateParsingHandlerTest; import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic; import org.openecomp.sdc.be.components.lifecycle.LifecycleChangeInfoWithAction; import org.openecomp.sdc.be.components.merge.resource.ResourceDataMergeBusinessLogic; @@ -91,6 +101,7 @@ import org.openecomp.sdc.be.impl.ComponentsUtils; import org.openecomp.sdc.be.impl.WebAppContextWrapper; import org.openecomp.sdc.be.model.ArtifactDefinition; import org.openecomp.sdc.be.model.Component; +import org.openecomp.sdc.be.model.ComponentInstance; import org.openecomp.sdc.be.model.ComponentParametersView; import org.openecomp.sdc.be.model.DataTypeDefinition; import org.openecomp.sdc.be.model.GroupDefinition; @@ -98,8 +109,12 @@ import org.openecomp.sdc.be.model.InputDefinition; import org.openecomp.sdc.be.model.LifeCycleTransitionEnum; import org.openecomp.sdc.be.model.LifecycleStateEnum; import org.openecomp.sdc.be.model.NodeTypeInfo; +import org.openecomp.sdc.be.model.ParsedToscaYamlInfo; import org.openecomp.sdc.be.model.PropertyDefinition; +import org.openecomp.sdc.be.model.RequirementDefinition; import org.openecomp.sdc.be.model.Resource; +import org.openecomp.sdc.be.model.UploadComponentInstanceInfo; +import org.openecomp.sdc.be.model.UploadReqInfo; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; @@ -134,6 +149,8 @@ import org.openecomp.sdc.common.impl.ExternalConfiguration; import org.openecomp.sdc.common.impl.FSConfigurationSource; import org.openecomp.sdc.common.util.GeneralUtility; import org.openecomp.sdc.common.util.ValidationUtils; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.exception.ResponseFormat; import org.springframework.web.context.WebApplicationContext; @@ -164,7 +181,8 @@ public class ResourceBusinessLogicTest { private final CatalogOperation catalogOperation = Mockito.mock(CatalogOperation.class); private final ICapabilityTypeOperation capabilityTypeOperation = Mockito.mock(ICapabilityTypeOperation.class); private final PropertyOperation propertyOperation = Mockito.mock(PropertyOperation.class); - private final ApplicationDataTypeCache applicationDataTypeCache = Mockito.mock(ApplicationDataTypeCache.class); + private final ApplicationDataTypeCache applicationDataTypeCache = Mockito.mock(ApplicationDataTypeCache.class); + private final ApplicationDataTypeCache dataTypeCache = Mockito.mock(ApplicationDataTypeCache.class); private final WebAppContextWrapper webAppContextWrapper = Mockito.mock(WebAppContextWrapper.class); private final UserValidations userValidations = Mockito.mock(UserValidations.class); private final WebApplicationContext webAppContext = Mockito.mock(WebApplicationContext.class); @@ -195,6 +213,7 @@ public class ResourceBusinessLogicTest { private final ToscaExportHandler toscaExportHandler = Mockito.mock(ToscaExportHandler.class); private final PolicyBusinessLogic policyBusinessLogic = Mockito.mock(PolicyBusinessLogic.class); + private YamlTemplateParsingHandler yamlTemplateParsingHandler = Mockito.mock(YamlTemplateParsingHandler.class); @InjectMocks ResponseFormatManager responseManager = null; private final GraphLockOperation graphLockOperation = Mockito.mock(GraphLockOperation.class); @@ -288,7 +307,8 @@ public class ResourceBusinessLogicTest { when(toscaOperationFacade.createToscaComponent(any(Resource.class))).thenReturn(eitherCreate); when(catalogOperation.updateCatalog(Mockito.any(), Mockito.any())).thenReturn(ActionStatus.OK); Map emptyDataTypes = new HashMap<>(); - when(applicationDataTypeCache.getAll()).thenReturn(Either.left(emptyDataTypes)); + when(applicationDataTypeCache.getAll()).thenReturn(Either.left(emptyDataTypes)); + when(dataTypeCache.getAll()).thenReturn(Either.left(emptyDataTypes)); when(mockJanusGraphDao.commit()).thenReturn(JanusGraphOperationStatus.OK); // BL object @@ -309,7 +329,8 @@ public class ResourceBusinessLogicTest { bl.setGraphLockOperation(graphLockOperation); bl.setPropertyOperation(propertyOperation); bl.setJanusGraphDao(mockJanusGraphDao); - bl.setApplicationDataTypeCache(applicationDataTypeCache); + bl.setApplicationDataTypeCache(applicationDataTypeCache); + bl.setDataTypeCache(dataTypeCache); bl.setGenericTypeBusinessLogic(genericTypeBusinessLogic); bl.setCatalogOperations(catalogOperation); toscaOperationFacade.setNodeTypeOperation(nodeTypeOperation); @@ -359,7 +380,7 @@ public class ResourceBusinessLogicTest { nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, - new CsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", ImportUtilsTest.loadFileNameToJsonString("normative-types-new-webServer.yml"),true)); + new CsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", ImportUtilsTest.loadFileNameToJsonString("normative-types-new-webServer.yml"),true), ""); } @Test @@ -419,6 +440,37 @@ public class ResourceBusinessLogicTest { } return resource; } + + private Resource createResourceObjectWithModel(boolean afterCreate) { + Resource resource = new Resource(); + resource.setName(RESOURCE_NAME); + resource.setToscaResourceName(RESOURCE_TOSCA_NAME); + resource.addCategory(RESOURCE_CATEGORY1, RESOURCE_SUBCATEGORY); + resource.setDescription("My short description"); + List tgs = new ArrayList<>(); + tgs.add("test"); + tgs.add(resource.getName()); + resource.setTags(tgs); + List template = new ArrayList<>(); + template.add("tosca.nodes.Root"); + resource.setDerivedFrom(template); + resource.setVendorName("Motorola"); + resource.setVendorRelease("1.0.0"); + resource.setContactId("ya5467"); + resource.setIcon("defaulticon"); + resource.setModel("Test Model"); + + if (afterCreate) { + resource.setName(resource.getName()); + resource.setVersion("0.1"); + resource.setUniqueId(resource.getName() + .toLowerCase() + ":" + resource.getVersion()); + resource.setCreatorUserId(user.getUserId()); + resource.setCreatorFullName(user.getFirstName() + " " + user.getLastName()); + resource.setLifecycleState(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); + } + return resource; + } private Resource createResourceObjectCsar(boolean afterCreate) { Resource resource = new Resource(); @@ -1402,6 +1454,132 @@ public class ResourceBusinessLogicTest { public void createResourceFromCsarTest() { bl.createResourceFromCsar(resourceResponse, user, new HashMap<>(), ""); } + + @Test() + public void testCreateResourceFromCsarWithModel() throws URISyntaxException, ZipException { + + final File csarFile = new File( + ResourceBusinessLogicTest.class.getClassLoader().getResource("csars/nonOnapCsar.csar").toURI()); + final Map csar = ZipUtils.readZip(csarFile, false); + + String resourceYml = new String(csar.get("Definitions/my_vnf.yaml")); + + YamlTemplateParsingHandler yamlTemplateParser = new YamlTemplateParsingHandler(mockJanusGraphDao, null, Mockito.mock(AnnotationBusinessLogic.class), null); + final ParsedToscaYamlInfo parsedToscaYamlInfo = yamlTemplateParser.parseResourceInfoFromYAML("Definitions/my_vnf.yml", resourceYml, Collections.EMPTY_MAP, Collections.EMPTY_MAP, "myVnf", resourceResponse); + + when(toscaOperationFacade.getLatestByToscaResourceName(anyString())).thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + Resource vduCp = new Resource(); + vduCp.setToscaResourceName("tosca.nodes.nfv.VduCp"); + vduCp.setState(LifecycleStateEnum.CERTIFIED); + vduCp.setUniqueId("tosca.nodes.nfv.VduCp"); + vduCp.setProperties(new ArrayList<>()); + Map> requirements = new HashMap<>(); + RequirementDefinition req = new RequirementDefinition(); + req.setName("virtual_link"); + List listReqs = new ArrayList<>(); + listReqs.add(req); + requirements.put("tosca.nodes.nfv.VduCp", listReqs); + vduCp.setRequirements(requirements); + PropertyDefinition bitrateProp = new PropertyDefinition(); + bitrateProp.setName("bitrate_requirement"); + bitrateProp.setType("integer"); + vduCp.getProperties().add(bitrateProp); + PropertyDefinition virtNiProp = new PropertyDefinition(); + virtNiProp.setName("virtual_network_interface_requirements"); + virtNiProp.setType("list"); + vduCp.getProperties().add(virtNiProp); + PropertyDefinition descriptionProp = new PropertyDefinition(); + descriptionProp.setName("description"); + descriptionProp.setType("string"); + vduCp.getProperties().add(descriptionProp); + PropertyDefinition roleProp = new PropertyDefinition(); + roleProp.setName("role"); + roleProp.setType("string"); + vduCp.getProperties().add(roleProp); + when(toscaOperationFacade.getByToscaResourceNameMatchingVendorRelease("tosca.nodes.nfv.VduCp", "1.0.0")).thenReturn(Either.left(vduCp)); + + + when(yamlTemplateParsingHandler.parseResourceInfoFromYAML(any(), any(), any(), any(), any(), any())).thenReturn(parsedToscaYamlInfo); + + UploadComponentInstanceInfo uploadComponentInstanceInfo = new UploadComponentInstanceInfo(); + uploadComponentInstanceInfo.setType("myType"); + resourceResponse.setUniqueId("myVnf"); + resourceResponse.setName("myVnf"); + resourceResponse.setSystemName("myVnf"); + resourceResponse.setModel("testModel"); + resourceResponse.setResourceType(ResourceTypeEnum.VF); + resourceResponse.setProperties(new ArrayList<>()); + + Resource derivedFrom = new Resource(); + List properties = new ArrayList<>(); + PropertyDefinition baseTypeProp = new PropertyDefinition(); + baseTypeProp.setName("propInBase"); + baseTypeProp.setType("string"); + properties.add(baseTypeProp); + derivedFrom.setProperties(properties ); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(any(), eq("tosca.nodes.nfv.VNF"))).thenReturn(Either.left(derivedFrom)); + + when(toscaOperationFacade + .validateComponentNameAndModelExists("myVnf", "testModel", ResourceTypeEnum.VF, ComponentTypeEnum.RESOURCE)).thenReturn(Either.left(false)); + + when(toscaOperationFacade.addPropertyToComponent(any(), any(), any())).thenReturn(Either.left(new PropertyDefinition())); + when(toscaOperationFacade.associateComponentInstancePropertiesToComponent(any(), any())).thenReturn(Either.left(Collections.emptyMap())); + when(toscaOperationFacade.associateArtifactsToInstances(any(), any())).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacade.associateDeploymentArtifactsToInstances(any(), any(), any())).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacade.associateInstAttributeToComponentToInstances(any(), any())).thenReturn(StorageOperationStatus.OK); + when(toscaOperationFacade.associateResourceInstances(any(Component.class), anyString(), anyList())).thenReturn(Either.left(Collections.EMPTY_LIST)); + + doAnswer(invocation -> { + Map>> instReqs = invocation.getArgument(1); + for (final Entry>> m: instReqs.entrySet()) { + m.getKey().setRequirements(m.getValue()); + } + return StorageOperationStatus.OK; + }). + when(toscaOperationFacade).associateOrAddCalculatedCapReq(any(), any(), any()); + + + when(toscaOperationFacade.updateCalculatedCapabilitiesRequirements(any(), any(), any())).thenReturn(StorageOperationStatus.OK); + when(groupBusinessLogic.validateUpdateVfGroupNames(any(), any())).thenReturn(Either.left(Collections.EMPTY_MAP)); + + ComponentInstance ci = new ComponentInstance(); + List cis = new ArrayList<>(); + cis.add(ci); + doAnswer(invocation -> { + List componentInstances = new ArrayList(((Map)invocation.getArgument(1)).keySet()); + ((Resource)invocation.getArgument(0)).setComponentInstances(componentInstances); + return null; + }).when(toscaOperationFacade).associateComponentInstancesToComponent(any(), any(), eq(false), eq(false)); + + doAnswer(invocation -> { + return Either.left(invocation.getArgument(0)); + }).when(csarArtifactsAndGroupsBusinessLogic).deleteVFModules(any(Resource.class), any(CsarInfo.class), eq(true), eq(false)); + + doAnswer(invocation -> { + return Either.left(resourceResponse); + }).when(toscaOperationFacade).getToscaFullElement("myVnf"); + + + Resource result = bl.createResourceFromCsar(resourceResponse, user, csar, "1234"); + + assertEquals("myDomain.myVnf", result.getToscaResourceName()); + List propIds = result.getProperties().stream().map(prop -> prop.getUniqueId()).collect(Collectors.toList()); + assertTrue(propIds.contains("myVnf.propInBase")); + assertTrue(propIds.contains("myVnf.descriptor_id")); + assertTrue(propIds.contains("myVnf.descriptor_version")); + assertTrue(propIds.contains("myVnf.flavour_description")); + assertTrue(propIds.contains("myVnf.flavour_id")); + assertTrue(propIds.contains("myVnf.product_name")); + assertTrue(propIds.contains("myVnf.provider")); + assertTrue(propIds.contains("myVnf.software_version")); + assertTrue(propIds.contains("myVnf.vnfm_info")); + + final List reqsName = new ArrayList<>(); + + final List cisWithExtReq = result.getComponentInstances().stream().filter(instance -> instance.getRequirements().get("tosca.nodes.nfv.VduCp").get(0).isExternal()).collect(Collectors.toList()); + cisWithExtReq.forEach(instance -> reqsName.add(instance.getRequirements().get("tosca.nodes.nfv.VduCp").get(0).getExternalName())); + assertEquals(3, cisWithExtReq.size()); + } @Test public void testResourceCategoryAfterCertify_UPDATE() { @@ -2097,7 +2275,7 @@ public class ResourceBusinessLogicTest { resource.setDerivedFrom(null); resource.setResourceType(ResourceTypeEnum.VF); when(toscaOperationFacade.createToscaComponent(resource)).thenReturn(Either.left(resource)); - when(genericTypeBusinessLogic.fetchDerivedFromGenericType(resource)).thenReturn(Either.left(genericVF)); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(resource, null)).thenReturn(Either.left(genericVF)); when(genericTypeBusinessLogic.generateInputsFromGenericTypeProperties(genericVF)).thenCallRealMethod(); when(genericTypeBusinessLogic.convertGenericTypePropertiesToInputsDefintion(genericVF.getProperties(), resource.getUniqueId())).thenCallRealMethod(); @@ -2125,7 +2303,7 @@ public class ResourceBusinessLogicTest { resource.setDerivedFrom(null); resource.setResourceType(ResourceTypeEnum.CR); when(toscaOperationFacade.createToscaComponent(resource)).thenReturn(Either.left(resource)); - when(genericTypeBusinessLogic.fetchDerivedFromGenericType(resource)).thenReturn(Either.left(genericCR)); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(resource, null)).thenReturn(Either.left(genericCR)); when(genericTypeBusinessLogic.generateInputsFromGenericTypeProperties(genericCR)).thenCallRealMethod(); when(genericTypeBusinessLogic.convertGenericTypePropertiesToInputsDefintion(genericCR.getProperties(), resource.getUniqueId())).thenCallRealMethod(); @@ -2146,7 +2324,7 @@ public class ResourceBusinessLogicTest { resource.setDerivedFrom(null); resource.setResourceType(ResourceTypeEnum.PNF); when(toscaOperationFacade.createToscaComponent(resource)).thenReturn(Either.left(resource)); - when(genericTypeBusinessLogic.fetchDerivedFromGenericType(resource)).thenReturn(Either.left(genericPNF)); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(resource, null)).thenReturn(Either.left(genericPNF)); when(genericTypeBusinessLogic.generateInputsFromGenericTypeProperties(genericPNF)).thenCallRealMethod(); when(genericTypeBusinessLogic.convertGenericTypePropertiesToInputsDefintion(genericPNF.getProperties(), resource.getUniqueId())).thenCallRealMethod(); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicTest.java index 42d24bbcd1..a64e3c1c85 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceBusinessLogicTest.java @@ -95,7 +95,7 @@ public class ServiceBusinessLogicTest extends ServiceBussinessLogicBaseTestSetup @Test public void testHappyScenario() { Service service = createServiceObject(false); - when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service)).thenReturn(Either.left(genericService)); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service, null)).thenReturn(Either.left(genericService)); Either createResponse = bl.createService(service, user); if (createResponse.isRight()) { @@ -107,7 +107,7 @@ public class ServiceBusinessLogicTest extends ServiceBussinessLogicBaseTestSetup @Test public void testServiceCreationPluginCall() { final Service service = createServiceObject(false); - when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service)).thenReturn(Either.left(genericService)); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service, null)).thenReturn(Either.left(genericService)); final List serviceCreationPlugins = new ArrayList<>(); serviceCreationPlugins.add(new ServiceCreationPlugin() { @Override @@ -143,7 +143,7 @@ public class ServiceBusinessLogicTest extends ServiceBussinessLogicBaseTestSetup final Resource genericTypeResource = mockGenericTypeResource(); - when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service)).thenReturn(Either.left(genericTypeResource)); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service, null)).thenReturn(Either.left(genericTypeResource)); final Service expectedService = createServiceObject(true); expectedService.setProperties(mockPropertyList()); when(toscaOperationFacade.createToscaComponent(service)).thenReturn(Either.left(expectedService)); @@ -168,7 +168,7 @@ public class ServiceBusinessLogicTest extends ServiceBussinessLogicBaseTestSetup final Resource genericTypeResource = mockGenericTypeResource(); - when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service)).thenReturn(Either.left(genericTypeResource)); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service, null)).thenReturn(Either.left(genericTypeResource)); final Service expectedService = createServiceObject(true); expectedService.setProperties(mockPropertyList()); expectedService.getProperties().add(serviceProperty); @@ -188,7 +188,7 @@ public class ServiceBusinessLogicTest extends ServiceBussinessLogicBaseTestSetup public void testHappyScenarioCRNullProjectCode() { Service service = createServiceObject(false); service.setProjectCode(null); - when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service)).thenReturn(Either.left(genericService)); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service, null)).thenReturn(Either.left(genericService)); Either createResponse = bl.createService(service, user); if (createResponse.isRight()) { @@ -202,7 +202,7 @@ public class ServiceBusinessLogicTest extends ServiceBussinessLogicBaseTestSetup createServiceValidator(); Service service = createServiceObject(false); service.setProjectCode(""); - when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service)).thenReturn(Either.left(genericService)); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service, null)).thenReturn(Either.left(genericService)); Either createResponse = bl.createService(service, user); if (createResponse.isRight()) { @@ -744,7 +744,7 @@ public class ServiceBusinessLogicTest extends ServiceBussinessLogicBaseTestSetup public void testDerivedFromGeneric() { Service service = createServiceObject(true); when(toscaOperationFacade.createToscaComponent(service)).thenReturn(Either.left(service)); - when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service)).thenReturn(Either.left(genericService)); + when(genericTypeBusinessLogic.fetchDerivedFromGenericType(service, null)).thenReturn(Either.left(genericService)); Either createResponse = bl.createService(service, user); assertTrue(createResponse.isLeft()); service = createResponse.left().value(); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java index 69367e962c..059dde3254 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java @@ -264,6 +264,7 @@ public class YamlTemplateParsingHandlerTest { .get(CAPABILITY_TYPE) .get(0).getProperties().get(0).getValue()).isEqualTo("success"); assertThat(parsedYaml.getGroups().get(MAIN_GROUP_NAME).getCapabilities()).isNotNull(); + assertThat(parsedYaml.getSubstitutionMappingNodeType()).isEqualTo("org.openecomp.resource.abstract.nodes.VF"); } private void stubGetGroupType() { diff --git a/catalog-be/src/test/resources/csars/nonOnapCsar.csar b/catalog-be/src/test/resources/csars/nonOnapCsar.csar new file mode 100644 index 0000000000000000000000000000000000000000..fcf6b7f2ae7653ec50c5d47f03674adb39038524 GIT binary patch literal 13948 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%0AS$?oSs&BU81cJ0F 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 literal 0 HcmV?d00001 diff --git a/catalog-be/src/test/resources/csars/with_groups.csar b/catalog-be/src/test/resources/csars/with_groups.csar index 3a9e9ab8e0a13b3cd978c6bea823654400e5ccbe..9259a81de07ea10407636680ada5f8b280a9abd6 100644 GIT binary patch delta 5221 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 delta 5364 zcmZ8_bx_o8v@pAbbnfEP-60_jA|<^nAPv&pr6}OiUGf7d>0aq(krV_30YSQyR2rpW zd$wBuNat8 zxpm1j#06v;i5|B2u_I*}50eI|(j)2(#s|L@_qJ6lebqrTTzDc?^=w1ji z%H}AmopHkPe0&JwNz?1JABZ>$zi&DeXl&}e#;F;$@7>u`kNA+Z0aE3g{gh0<7-J=` z-ly_2a%@411&CX+s@Dog&$AzsZ6aiwyzi6odh5V1E|f-eV<6MgHyD}4Jo0g1WcU>b zX|%@fgB@*|y*8J$q@s9vnK$FHq`3cy=)wncRw^9cJxov6ed8p%+|Op3a5O`_g!_BA zt)Mg`lk__#VrEMjyGoCari4pEm$z8P)b{~5EAp*hLZopp-kb5-eBs}zmpZ;~NUa|O`ER$rC1PE7g;H@sk)&$+ zTYer7#4{0wuvai#gSH5~Y=%G$sB5rmfo@C7(S`V zJm@pG2q6#Cy{H0xVe`DW^6Y+qbWIUNI@_94q_a^PK zm6b+i>1YKXO$idXU`aWtm9Ie(+kT@+KXm^ z-kLI%NNdN}*u2x>1ds&TW>&86c({ppzL-k$b*86=5 zNs26FJdvOiuX`CP{<;%w{S4B;IxB9}HPU3Qwu^Pm$h8*PcMkpiRywWy8}f;X{|a;9 z0p3M+qB4U{v)U69opDXsbc%t4?i}Xqmn<46EQL;GPLe^rNP8?@EIH-=Rt-?D0)s;Y zIGWVyl{w`@FjUHUNw&)94V?bnvAGxDH66Lr z@IZA2{gdz9_MYoe;x$Wk@1KbW=IT}hu*ebRXpdK#XDmXXH!82y^&e|TIB!Xh;8T2t z@KUsV@SRxYKAGBOFF-znKAMxT-hn7p5Q4aBl0(%yuk~eqy&O2Tu5+(=a3I~*|3c`N zBwU+VyD?eFmyLXnuTXAX$7vitj!vXqg?{tOe~w&9xB0W|6n5+p|0kiADY%ws!u?ij zu)fgIObAn~3W4EVS!`W>!m-~8rO8=Z@0)F~klZuV1)DXpDo12fta-n;lpd*aosxRo z!|?^we7omPm;OY$AZyB&3QiFcGDD6lin0ji``s8$hZS0oJ0SS?NFvsv2kksa!QG%& zOn2)aXGI(|g(6y^8YwV>k}Gv4$oht+wns6R7|`XOIr;OIf7yCdlKvZaDQ|zH#!14Q zNy>N@g`wrGZ9<|mo5!>sh@yvL3aRmZF=tb?$ahNdB^7k~IXN7%vda_VwwaOb`!(N% zC&Jj^t@hMC+-RJbRFXN1RaH}8fqY-P>nwVdlxbChBE2iA1#U~x9$ zpuXd?K=!9Kt(N^6=M3^cW^i6Xk$cOzc&n)JoSPms*SsIn@G_kIG zDmbFzra5i{??KO0!VH{W3Y443g~c&v5XD7Qz#AlWhT+EgGn1A2jFOoyS>*`N{iU?( zW6{)~eOkeIKd|OrE;e7k^bkJRAGjc4@2(_MHWpRt+O6*8n88}lZdN+iHizN_MiCQUSbK*v}&&QeRZB1`ze99 zm|ujJN>W&IJ4Pj9u@`X|BGu*sT%&GA|hI zc&dVLc8*bzZBHZ1{6@-_@7R1jmeLmkd(pxh)P)r7v10q^ZB&;V@JB&;^q5$PhA?2` zL!6ws^3_;MoMkjK;Yw&tfcq9~=`rTJ)buBE)d7EMf6hX9NErx9@S=f1eXZ_80J0zaCK*hZ6OTeEhQX$T#Dxbm8rz6MS>$y$|FzW7TjG9Q?zJ-`sh8`S$s?4l|8{)pu{k~o8W&UJIlM(@`L7Ik0A+7}F) z35XT`O;9*f&U-ekxoa3iTc^=VDqG)!wdaxH+deE;K8` zYw3$#-~3{=as3x2n_pJ0Lx@b#L$Q2JpO%q;DrF_xQPrfG{o#2^U&3Z-7J;c5_6Flf zBY)|aX{xWBz4@`d3n32O8aHHJ|I$ zDq~7y^){XQy>Toq?+EJ%GcMc5A2y#x`_6YGFRUI>l-hPV3Uge@b@5vfusNpX@`{6} zsRh~Sk_|-zA-zENG5${EZEPgW8*zkuLGYu&3Mc7SB<$o*pyH6Lg)+h{t&W}L?+?E5 z6QwJ%;YV2C1kJ~ERKqci=Ue;JUpgS?Vi~TYTiV&AvfEAEkY@$>msQg@fMMFRF?rGi z7P+xKk-&hoi6Pt6v&oCc+3cuy4c`KAE(ubrh&SI>SP2muDQ9VcAJpPveM9*mY5Zcu zq`vFjA8&d}BC+(H2GSA0IZ)C3ofb??WHhpcnX1lC`h!ZNTP6zOa?Kl4Rk58Y_#R*a zEC?Xx>($2tN3RW)6p%jo$%eC)AxTQ} z;{`qF$8Mbnn2ov?(TF+Wom(nGE@LR&SO_+=OWOzDmvJm63I;V~&vgpU7&W(U4#+xJ z?m|#;nLNq*{%zIKB~PO{uGYWnlBmm{diA^Df_I*Jbx*D>-#mzQEaJsr&VHPCbXXoT zt#*nXuFBn9U1M|(Q4?9`voDM!IOH#|jYGrzB6yBI`h*NWa&wAiwCh_$f+z8qIQt&C zEfdmC!IFP=dk%u3QUY1k+dr~!3fcqyY)#W~aMc>m;D&i~tZbgt9p%BF<>oU&Y-Z0| zhiwQDj=~?D-2VLb8N4xpli~3~yTU=&Th{{C%jO&C_?P$owkgQtk(6Csff*6!r;$}U zm+cDjx_j)GGT$f2cWNIXXRJ>wJ)5K<%=ZA#r+n=*L##4l&sks1Ag)Rf7($|JN#Q_W z-1w^5tNGt1Sq&p*%!Lr%_SOMumth|Nk@YDb3lW~;G_s1c_;^Sf^EjJ8HB9im1a5=k zr9zwwAMUHnu$w5N_L3VxV#8r^k!SJRr!`44WhuR;ZZ%2hvKCUL0l{endtHkr7q6P5 z);Xe4n@xn%j?Sz?FvrWQQ7f3>y&oE*yillzIHjf0t#Rr2;yD?pt@>^l*Z#A5sKq4( z+cY#yhjm_yeOP#JF-_gn(lqy-o&Iv_yDCGokH+>TKq5i?P7FnPz95&d$&(IYF5w&51*I*c|yz4pqyj0 zF_m$YN#NrIyo~U2pqhDe++y9|pF{E2@mH8p6j7x>9$iogFLEx)aZ5^V|4Vbs&=aB> z#>?yBC%>R;!uFw~mIc&X`u0p~X*_VUurI~O+W`lHlTrPy18>&`h5Vt=;yP8M`I4e}mJlxa{2b^zj6`MS^^; zGEVkN)>a@T!Let3oQ~qk#ayN;o$dv-m{7Tv`zE&uBdBwd&WBy%oa=vP%OgjH(w*EG z4f)KCh>M-}rvpAdOZ<~LQD7^!;#H+lYb3zI+=pa4jLrzcFCY^=_UhS4Ss~C^SHhN+ z66&e#mf`OSFSR@EfB&E}7PKQgCBxD3bDLc2H+G-26n)j59#*AP(smkw;&7}wH$SLR zkoKxTnl2+8I^@?1_nv$9htnK%#hjWRNZ3aDjqpkdI&K_Q)AkE$bG{lSsDwnY5cI3Q-axV-K;Q|*WGc8glNyIGW+8bzr{eoenM zH-wF1td`&^X;EBLX34bJc%A2`00nNW6x4-XjbhD`DO4fU;bVk*2y4CC%J`B~_O8|h z=dT0bZ`tJI+{&DMn#Q=5LO%tvfPswnC!a$NB~2`Q%dI$ETn!pW{5e|Q)sige2K(7f zn#$u1K^UeNW&`3VOG-Fsaw*YB#)$&8_pRxS-Bl%t{ou4`r<)kUzEo;wW7Ue}6yvz0 zH+?ROFE8Kn*p(`!K+*7DD%UeLYbvy$5j-*x$P?32I)iU%#=n-9&a7=u3@Rr|F40;} zKDBZb3yq}0WTp}FxEHl8q}{>lbxugC6lT$ zr!(n1;VyPZV*JRE!oR%v!IgFyj;twn%Y2Ljt~q;%vnp)KXA*|WC0?EHgFjiVQ_jb2 zS*cqhm!Y;$V(XfMNsk`rh_5w{wZ$B|)#)AOGM0z9v-q`_YLl+&&Tagp3_E6sbnj<< zgJ|JUX4lIE1fuoC7wE~U?Qrau!xENUEmJPXepD0U97Q8L=>Oy@nG;~|7^%iD&O&4@ z<2$-#C{*JEQ>b5jfX2%_GF_^!z!VQK46W&X>Ejqu6n6NN#q*9+MvI_r9z*jtP%UK{ z@|`_mk3P`$;nf-8!B|hg;OdrpoW{q&uE=8ZI=aL$lMbsqvBSUl^=xPTmY1DZ7RRDj zh? z61i@&k0m%$7ks-1t0#+&_KzNY*>lZP`x9#Je8S~UrDzWOlqScsWcb{4xPQKA}H_nahhJHmd z+#|-MIe)Ot(Olw!FfZ?Hxn+$vsVCrA7~TXY+4Z32VibTk)OeEu0@2$J zY~EKWZ5Cnb<{vn%WgLnhYK*pUakl4g6{+-8$@7mVU*S}o)03Fy?nOJlEip)N3dt0D z?FVJ&5=<0Z-_PsF`V>n<&b0s@Rn}#b2#GT8-nM>62vr^{v=cl&O}arg-m`wk+~^zD z#ssvVkphrp24F0-v=P6Ung!q}T7H912?+JGH%brGaRc!Ft;U^wDG+dcNDIgvk^(eG z7T|OW;1v}skbU&r5{imU;&J7;NXHGfN+@ot_V0N8KA|uf_J8YXp9?(064*T zgLUVDj(LW=%n%^+uQb?p8~C!#45-~Tjejc*p8N^O{^GbRMDSk`RoArOw0&UcTI;{$ gK;erpLXKLGd+=+ebN5Ak#k|J%s_0AO_`4*&oF diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ParsedToscaYamlInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ParsedToscaYamlInfo.java index a8de860b28..ce7c6deb91 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/ParsedToscaYamlInfo.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/ParsedToscaYamlInfo.java @@ -33,4 +33,5 @@ public class ParsedToscaYamlInfo { Map instances; Map groups; Map policies; + String substitutionMappingNodeType; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperation.java index 87bcda99d7..9db61e8ec3 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperation.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/NodeTemplateOperation.java @@ -1110,6 +1110,7 @@ public class NodeTemplateOperation extends BaseOperation { private void bindCapabilityDefinition(final CapabilityDataDefinition fromCapabilityDefinition, final CapabilityDataDefinition capabilityDefinitionToUpdate) { capabilityDefinitionToUpdate.setExternal(fromCapabilityDefinition.isExternal()); + capabilityDefinitionToUpdate.setExternalName(fromCapabilityDefinition.getExternalName()); } private Optional findComponentVertex(final String componentId) { @@ -1190,7 +1191,7 @@ public class NodeTemplateOperation extends BaseOperation { listRequirementDataDefinition.getListToscaDataDefinition().stream() .filter(e -> requirementDataDefinition.getOwnerId().equals(e.getOwnerId()) && requirementDataDefinition.getName().equals(e.getName())) - .forEach(r -> r.setExternal(requirementDataDefinition.isExternal())); + .forEach(r -> {r.setExternal(requirementDataDefinition.isExternal()); r.setExternalName(requirementDataDefinition.getExternalName());}); return updateCalculatedReqOnGraph(componentId, containerV, existingReqs); } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java index ec5721b95a..faedba5363 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java @@ -1871,6 +1871,36 @@ public class ToscaOperationFacade { updateInstancesCapAndReqOnComponentFromDB(component); return storageOperationStatus; } + + public StorageOperationStatus updateCalculatedCapabilitiesRequirements(final Map>> instCapabilties, + final Map>> instReg, + final Component component) { + StorageOperationStatus storageOperationStatus = StorageOperationStatus.OK; + if (instCapabilties != null) { + for (Entry>> entry : instCapabilties.entrySet()) { + final Map> cap = entry.getValue(); + for (List capabilityList: cap.values()) { + for (CapabilityDefinition capability: capabilityList) { + nodeTemplateOperation.updateComponentInstanceCapabilities(component.getUniqueId(), entry.getKey().getUniqueId(), capability); + } + } + } + } + if (instReg != null) { + for (Entry>> entry : instReg.entrySet()) { + final Map> req = entry.getValue(); + for (List requirementList: req.values()) { + for (RequirementDefinition requirement: requirementList) { + storageOperationStatus = nodeTemplateOperation.updateComponentInstanceRequirement(component.getUniqueId(), entry.getKey().getUniqueId(), requirement); + if (storageOperationStatus != StorageOperationStatus.OK) { + return storageOperationStatus; + } + } + } + } + } + return storageOperationStatus; + } private void updateInstancesCapAndReqOnComponentFromDB(Component component) { ComponentParametersView componentParametersView = new ComponentParametersView(true); @@ -1896,6 +1926,9 @@ public class ToscaOperationFacade { // include props hasProps.put(GraphPropertyEnum.COMPONENT_TYPE, ComponentTypeEnum.SERVICE.name()); hasProps.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + if (modelName != null) { + hasProps.put(GraphPropertyEnum.MODEL, modelName); + } // exclude props states.add(LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT); hasNotProps.put(GraphPropertyEnum.STATE, states); @@ -1912,7 +1945,7 @@ public class ToscaOperationFacade { List services = null; Map hasProps = new EnumMap<>(GraphPropertyEnum.class); Map hasNotProps = new EnumMap<>(GraphPropertyEnum.class); - fillPropsMap(hasProps, hasNotProps, internalComponentType, componentTypeEnum, isAbstract, vertexType); + fillPropsMap(hasProps, hasNotProps, internalComponentType, componentTypeEnum, isAbstract, vertexType, modelName); Either, JanusGraphOperationStatus> getRes = janusGraphDao .getByCriteria(vertexType, hasProps, hasNotProps, JsonParseFlagEnum.ParseMetadata); if (getRes.isRight() && !JanusGraphOperationStatus.NOT_FOUND.equals(getRes.right().value())) { @@ -2155,11 +2188,14 @@ public class ToscaOperationFacade { } private void fillPropsMap(Map hasProps, Map hasNotProps, String internalComponentType, - ComponentTypeEnum componentTypeEnum, boolean isAbstract, VertexTypeEnum internalVertexType) { + ComponentTypeEnum componentTypeEnum, boolean isAbstract, VertexTypeEnum internalVertexType, String modelName) { hasNotProps.put(GraphPropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT.name()); hasNotProps.put(GraphPropertyEnum.IS_DELETED, true); hasNotProps.put(GraphPropertyEnum.IS_ARCHIVED, true); hasProps.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true); + if (modelName != null) { + hasProps.put(GraphPropertyEnum.MODEL, modelName); + } if (VertexTypeEnum.NODE_TYPE == internalVertexType) { hasProps.put(GraphPropertyEnum.IS_ABSTRACT, isAbstract); if (internalComponentType != null) { diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CapabilityDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CapabilityDataDefinition.java index 3345c95946..a1dda0092c 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CapabilityDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/CapabilityDataDefinition.java @@ -40,7 +40,9 @@ public class CapabilityDataDefinition extends ToscaDataDefinition { @Getter @Setter private boolean external = false; - + @Getter + @Setter + private String externalName; /** * The default constructor initializing limits of the occurrences */ @@ -91,6 +93,7 @@ public class CapabilityDataDefinition extends ToscaDataDefinition { this.setSource(other.getSource()); this.setOwnerType(other.getOwnerType()); this.setExternal(other.isExternal()); + this.setExternalName(other.getExternalName()); } public CapabilityDataDefinition(CapabilityTypeDataDefinition other) { diff --git a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java index 4b7b6aa413..a7746fb22b 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/datatypes/elements/RequirementDataDefinition.java @@ -44,7 +44,10 @@ public class RequirementDataDefinition extends ToscaDataDefinition { @Getter @Setter - public boolean external = false; + private boolean external = false; + @Getter + @Setter + private String externalName; /** * The default constructor initializing limits of the occurrences @@ -80,6 +83,7 @@ public class RequirementDataDefinition extends ToscaDataDefinition { } this.setSource(other.getSource()); this.setExternal(other.isExternal()); + this.setExternalName(other.getExternalName()); } /** -- 2.16.6