diff options
Diffstat (limited to 'catalog-be/src/main/java')
6 files changed, 330 insertions, 90 deletions
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<PropertyDefinition> 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<PropertyDefinition> 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 <T extends Component> Resource fetchAndSetDerivedFromGenericType(final T component) { + return fetchAndSetDerivedFromGenericType(component, null); + } - protected <T extends Component> Resource fetchAndSetDerivedFromGenericType(T component) { - Either<Resource, ResponseFormat> genericTypeEither = this.genericTypeBusinessLogic.fetchDerivedFromGenericType(component); + protected <T extends Component> Resource fetchAndSetDerivedFromGenericType(final T component, final String toscaType) { + final Either<Resource, ResponseFormat> 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<Boolean, ResponseFormat> 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<String, Resource> existingNodeTypesByResourceNames = new HashMap<>(); - preparedResource = createResourceInstances(yamlFileName, preparedResource, oldResource, instances, csarInfo.getCreatedNodes(), + final Map<String, UploadComponentInstanceInfo> 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<String, Object> substitutableAsNodeType = getSubstitutableAsNodeTypeFromTemplate((Map<String, Object>) 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<Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>>, ResponseFormat> findNodeTypesArtifactsToHandle( final Map<String, NodeTypeInfo> nodeTypesInfo, final CsarInfo csarInfo, final Resource oldResource) { final Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle = new HashMap<>(); @@ -1072,20 +1088,33 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { boolean needLock, Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle, List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, - Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo) { + Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, final String substitutableAsNodeType) { Either<String, ResultStatusEnum> toscaVersion = findFirstToscaStringElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION); if (toscaVersion.isRight()) { throw new ByActionStatusComponentException(ActionStatus.INVALID_TOSCA_TEMPLATE); } Map<String, Object> mapToConvert = new HashMap<>(); mapToConvert.put(TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION.getElementName(), toscaVersion.left().value()); - Map<String, Object> nodeTypes = getNodeTypesFromTemplate(mappedToscaTemplate); + final Map<String, Object> nodeTypes = getNodeTypesFromTemplate(mappedToscaTemplate, substitutableAsNodeType); createNodeTypes(yamlName, resource, needLock, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, mapToConvert, nodeTypes); return csarInfo.getCreatedNodes(); } - private Map<String, Object> getNodeTypesFromTemplate(Map<String, Object> mappedToscaTemplate) { + private Map<String, Object> getNodeTypesFromTemplate(final Map<String, Object> mappedToscaTemplate, final String substitutableAsNodeType) { + final Map<String, Object> nodeTypes = getAllNodeTypesInTemplate(mappedToscaTemplate); + if (StringUtils.isNotEmpty(substitutableAsNodeType)){ + nodeTypes.remove(substitutableAsNodeType); + } + return nodeTypes; + } + + @SuppressWarnings("unchecked") + private Map<String, Object> getSubstitutableAsNodeTypeFromTemplate(final Map<String, Object> mappedToscaTemplate, final String substitutableAsNodeType) { + return (Map<String, Object>)getAllNodeTypesInTemplate(mappedToscaTemplate).get(substitutableAsNodeType); + } + + private Map<String, Object> getAllNodeTypesInTemplate(final Map<String, Object> mappedToscaTemplate) { return ImportUtils.findFirstToscaMapElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES).left().orValue(HashMap::new); } @@ -1127,7 +1156,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Map<String, Object> 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<String, InputDefinition> 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<String, Object> substitutableAsNodeType = getSubstitutableAsNodeTypeFromTemplate((Map<String, Object>) 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<String, UploadComponentInstanceInfo> 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<String, UploadComponentInstanceInfo> 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<String, InputDefinition> 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<String, UploadComponentInstanceInfo> 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<String, UploadComponentInstanceInfo> getInstancesToCreate(final ParsedToscaYamlInfo parsedToscaYamlInfo) { + return getInstancesToCreate(parsedToscaYamlInfo, null); + } + + private Map<String, UploadComponentInstanceInfo> 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<ArtifactDefinition> createdArtifacts, List<ArtifactDefinition> nodeTypesNewCreatedArtifacts) { @@ -1689,6 +1758,41 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { } return resource; } + + private Resource generatePropertiesFromNodeType(final Resource resource, final Map<String, Object> nodeType) { + final Either<Map<String, PropertyDefinition>, ResultStatusEnum> properties = ImportUtils.getProperties(nodeType); + if (properties.isLeft()) { + final List<PropertyDefinition> propertiesList = new ArrayList<>(); + final Map<String, PropertyDefinition> value = properties.left().value(); + if (value != null) { + for (Entry<String, PropertyDefinition> 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<PropertyDefinition> resourceProperties = resource.getProperties(); + for (PropertyDefinition propertyDefinition: resourceProperties) { + final Either<PropertyDefinition, StorageOperationStatus> 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<GroupDefinition> updateGroupsMembersUsingResource(Map<String, GroupDefinition> groups, Resource component) { List<GroupDefinition> result = new ArrayList<>(); @@ -1829,10 +1933,10 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { String topologyTemplateYaml, List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>> 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<String, Resource> existingNodeTypesByResourceNames = new HashMap<>(); @@ -1864,7 +1968,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { private void handleNodeTypes(String yamlName, Resource resource, String topologyTemplateYaml, boolean needLock, Map<String, EnumMap<ArtifactOperationEnum, List<ArtifactDefinition>>> nodeTypesArtifactsToHandle, List<ArtifactDefinition> nodeTypesNewCreatedArtifacts, Map<String, NodeTypeInfo> nodeTypesInfo, CsarInfo csarInfo, - String nodeName) { + String nodeName, String substitutableAsNodeType) { try { for (Entry<String, NodeTypeInfo> nodeTypeEntry : nodeTypesInfo.entrySet()) { if (nodeTypeEntry.getValue().isNested() && !nodeTypeAlreadyExists(nodeTypeEntry.getKey())) { @@ -1881,7 +1985,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { mappedToscaTemplate = (Map<String, Object>) 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<String, UploadComponentInstanceInfo> uploadResInstancesMap) { + Either<Resource, StorageOperationStatus> getResourceRes = null; if (resource.getResourceType() == ResourceTypeEnum.CVFC) { - Either<Resource, StorageOperationStatus> 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<String, UploadComponentInstanceInfo> uploadResInstancesMap, @@ -2559,6 +2667,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { Either<Resource, StorageOperationStatus> updateRes = null; Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> updatedInstCapabilities = new HashMap<>(); Map<ComponentInstance, Map<String, List<RequirementDefinition>>> 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<Resource, StorageOperationStatus> updateCalculatedCapReqWithSubstitutionMappingsForVf(final Resource resource, + final Map<String, UploadComponentInstanceInfo> uploadResInstancesMap) { + Either<Resource, StorageOperationStatus> updateRes = null; + final Map<ComponentInstance, Map<String, List<CapabilityDefinition>>> updatedInstCapabilities = new HashMap<>(); + final Map<ComponentInstance, Map<String, List<RequirementDefinition>>> 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<ComponentInstance> componentInstances, Map<String, UploadComponentInstanceInfo> uploadResInstancesMap, @@ -2612,6 +2746,54 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { updatedInstRequirements.put(instance, updatedRequirements); } } + + private void setExternalRequirements( + final Map<ComponentInstance, Map<String, List<RequirementDefinition>>> updatedInstRequirements, + final ComponentInstance instance, final Map<String, String> requirementsNamesToUpdate) { + final Map<String, List<RequirementDefinition>> updatedRequirements = new HashMap<>(); + final Set<String> updatedReqNames = new HashSet<>(); + if (isNotEmpty(requirementsNamesToUpdate)) { + for (Map.Entry<String, List<RequirementDefinition>> 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<ComponentInstance, Map<String, List<CapabilityDefinition>>> updatedInstCapabilties, + final ComponentInstance instance, Map<String, String> capabilitiesNamesToUpdate) { + final Map<String, List<CapabilityDefinition>> updatedCapabilities = new HashMap<>(); + final Set<String> updatedCapNames = new HashSet<>(); + if (isNotEmpty(capabilitiesNamesToUpdate)) { + for (Map.Entry<String, List<CapabilityDefinition>> 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<ComponentInstance, Map<String, List<CapabilityDefinition>>> updatedInstCapabilties, ComponentInstance instance, Map<String, String> 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<PropertyDefinition> 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<PropertyDefinition> 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<Resource, ResponseFormat> fetchDerivedFromGenericType(final Component component, final String toscaType) { + if (StringUtils.isNotEmpty(toscaType)) { + final Either<Resource, StorageOperationStatus> 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<String, String[]> toscaRequirements = new HashMap<>(); Either<Map<String, String[]>, ToscaError> result = null; for (Map.Entry<String, List<RequirementDefinition>> entry : requirements.entrySet()) { - Optional<RequirementDefinition> 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<RequirementDefinition> 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<RequirementDefinition> addExternalToToscaRequirements(final Map<String, Component> componentsCache, + final Map<String, String[]> toscaRequirements, final Component component, final List<RequirementDefinition> 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<Map<String, String[]>, ToscaError> buildAddSubstitutionMappingsCapabilities(Map<String, Component> componentsCache, Component component, @@ -323,11 +333,7 @@ public class CapabilityRequirementConverter { Map<String, String[]> toscaCapabilities = new HashMap<>(); Either<Map<String, String[]>, ToscaError> result = null; for (Map.Entry<String, List<CapabilityDefinition>> entry : capabilities.entrySet()) { - Optional<CapabilityDefinition> 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<CapabilityDefinition> 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<CapabilityDefinition> addExternalToToscaCapabilities(final Map<String, Component> componentsCache, + final Map<String, String[]> toscaCapabilities, final Component component, final List<CapabilityDefinition> 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<String, Component> componentsCache, Map<String, String[]> capReqMap, Component component, SubstitutionEntry entry, String previousName, String ownerId, List<String> 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<String, Component> componentsCache, Map<String, String[]> capReqMap, final Component component, + final SubstitutionEntry entry, final String previousName, final String ownerId, final List<String> 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<String, ToscaRequirement> convertRequirement(Map<String, Component> 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<String, Component> componentsCache, Component component, Map<String, ToscaCapability> toscaCapabilities, boolean isNodeType, CapabilityDefinition c, Map<String, DataTypeDefinition> 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); |