From: KrupaNagabhushan Date: Tue, 5 Jul 2022 17:43:07 +0000 (+0100) Subject: Service Import - Node Template Relationship Template X-Git-Tag: 1.11.7~16 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=7c7680d767bce8625c9c7ad69009fb73ae849809;p=sdc.git Service Import - Node Template Relationship Template Issue-ID: SDC-4083 Signed-off-by: KrupaNagabhushan Signed-off-by: andre.schmid Change-Id: Ia0f3635df969c44de5aba2d672fad34f0855e4e2 --- diff --git a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml index 58f3dc337c..50a7014f10 100644 --- a/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml +++ b/catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml @@ -2732,3 +2732,17 @@ errors: message: "Missing TOSCA function '%1'.", messageId: "SVC4172" } + + #-----------SVC4173--------------------------- + RELATIONSHIP_TEMPLATE_NOT_FOUND: { + code: 404, + message: "Relationship_templates entry not found in TOSCA CSAR.", + messageId: "SVC4173" + } + + #-----------SVC4174--------------------------- + RELATIONSHIP_TEMPLATE_DEFINITION_NOT_FOUND: { + code: 404, + message: "Relationship_templates definition not found in TOSCA CSAR.", + messageId: "SVC4174" + } 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 940363bce4..a68bbf3a2d 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 @@ -29,6 +29,8 @@ import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaLis import static org.openecomp.sdc.be.components.impl.ImportUtils.findFirstToscaMapElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement; import static org.openecomp.sdc.be.components.impl.ImportUtils.loadYamlAsStrictMap; +import static org.openecomp.sdc.be.datatypes.enums.MetadataKeyEnum.NAME; +import static org.openecomp.sdc.be.model.tosca.ToscaType.STRING; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.ARTIFACTS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.ATTRIBUTES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.CAPABILITIES; @@ -38,15 +40,20 @@ import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.DESCRIPTION import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.FILE; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.GET_INPUT; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.GROUPS; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.IMPLEMENTATION; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.INPUTS; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.INTERFACES; 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.OPERATIONS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.OUTPUTS; 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.RELATIONSHIP; +import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.RELATIONSHIP_TEMPLATES; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.REQUIREMENTS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_FILTERS; import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS; @@ -66,7 +73,9 @@ import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -108,6 +117,9 @@ import org.openecomp.sdc.be.model.UploadComponentInstanceInfo; import org.openecomp.sdc.be.model.UploadPropInfo; import org.openecomp.sdc.be.model.UploadReqInfo; import org.openecomp.sdc.be.model.tosca.ToscaPropertyType; +import org.openecomp.sdc.be.tosca.model.ToscaInterfaceDefinition; +import org.openecomp.sdc.be.ui.model.OperationUi; +import org.openecomp.sdc.be.ui.model.PropertyAssignmentUi; import org.openecomp.sdc.be.utils.TypeUtils; import org.openecomp.sdc.common.log.wrappers.Logger; import org.yaml.snakeyaml.parser.ParserException; @@ -140,9 +152,9 @@ public class YamlTemplateParsingHandler { Map nodeTypesInfo, String nodeName, Component component, String interfaceTemplateYaml) { log.debug("#parseResourceInfoFromYAML - Going to parse yaml {} ", fileName); - final Map mappedToscaTemplate = getMappedToscaTemplate(fileName, resourceYml, nodeTypesInfo, nodeName); - final ParsedToscaYamlInfo parsedToscaYamlInfo = new ParsedToscaYamlInfo(); - final Map mappedTopologyTemplate = (Map) findToscaElement(mappedToscaTemplate, TOPOLOGY_TEMPLATE, + Map mappedToscaTemplate = getMappedToscaTemplate(fileName, resourceYml, nodeTypesInfo, nodeName); + ParsedToscaYamlInfo parsedToscaYamlInfo = new ParsedToscaYamlInfo(); + Map mappedTopologyTemplate = (Map) findToscaElement(mappedToscaTemplate, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL).left().on(err -> failIfNotTopologyTemplate(fileName)); final Map mappedTopologyTemplateInputs = mappedTopologyTemplate.entrySet().stream() .filter(entry -> entry.getKey().equals(INPUTS.getElementName())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); @@ -151,6 +163,7 @@ public class YamlTemplateParsingHandler { parsedToscaYamlInfo.setInputs(getInputs(mappedTopologyTemplateInputs)); parsedToscaYamlInfo.setOutputs(getOutputs(mappedTopologyTemplateOutputs)); parsedToscaYamlInfo.setInstances(getInstances(mappedToscaTemplate, createdNodesToscaResourceNames)); + associateRelationshipTemplatesToInstances(parsedToscaYamlInfo.getInstances(), mappedTopologyTemplate); parsedToscaYamlInfo.setGroups(getGroups(mappedToscaTemplate, component.getModel())); parsedToscaYamlInfo.setPolicies(getPolicies(mappedToscaTemplate, component.getModel())); Map substitutionMappings = getSubstitutionMappings(mappedToscaTemplate); @@ -354,6 +367,102 @@ public class YamlTemplateParsingHandler { return null; } + private void associateRelationshipTemplatesToInstances(final Map instances, + final Map toscaJson) { + if (MapUtils.isEmpty(instances)) { + return; + } + for (UploadComponentInstanceInfo instance : instances.values()) { + final Map> operations = new HashMap<>(); + final Map> requirements = instance.getRequirements(); + if (MapUtils.isNotEmpty(requirements)) { + requirements.values() + .forEach(requirementInfoList -> requirementInfoList.stream() + .filter(requirement -> StringUtils.isNotEmpty(requirement.getRelationshipTemplate())) + .forEach(requirement -> operations.put(requirement.getRelationshipTemplate(), + getOperationsFromRelationshipTemplate(toscaJson, requirement.getRelationshipTemplate())))); + } + instance.setOperations(operations); + } + } + + private Map getRelationshipTemplates(final Map toscaJson, final String relationshipTemplate) { + final Either, ResultStatusEnum> eitherRelationshipTemplates = findFirstToscaMapElement(toscaJson, RELATIONSHIP_TEMPLATES); + if (eitherRelationshipTemplates.isRight()) { + throw new ByActionStatusComponentException(ActionStatus.RELATIONSHIP_TEMPLATE_NOT_FOUND); + } + final Map relationshipTemplateMap = eitherRelationshipTemplates.left().value(); + final Map> relationship = (Map>) relationshipTemplateMap.get(relationshipTemplate); + if (relationship == null) { + throw new ByActionStatusComponentException(ActionStatus.RELATIONSHIP_TEMPLATE_DEFINITION_NOT_FOUND); + } + return relationship.get(INTERFACES.getElementName()); + } + + private List buildToscaInterfacesFromRelationship(final Map interfaces) { + return interfaces.entrySet().stream() + .map(entry -> { + final var toscaInterfaceDefinition = new ToscaInterfaceDefinition(); + toscaInterfaceDefinition.setType(entry.getKey()); + final Map toscaInterfaceMap = (Map) entry.getValue(); + toscaInterfaceDefinition.setOperations((Map) toscaInterfaceMap.get(OPERATIONS.getElementName())); + return toscaInterfaceDefinition; + }) + .collect(toList()); + } + + private Optional getImplementation(final Map operationToscaMap) { + if (MapUtils.isEmpty(operationToscaMap) || !operationToscaMap.containsKey(IMPLEMENTATION.getElementName())) { + return Optional.empty(); + } + final Map implementationToscaMap = (Map) operationToscaMap.get(IMPLEMENTATION.getElementName()); + return Optional.ofNullable( + implementationToscaMap.computeIfPresent("toscaPresentation", (key, value) -> ((Map) value).get(NAME.getName())) + ); + } + + private List getOperationsInputs(final Map operationToscaMap) { + if (MapUtils.isEmpty(operationToscaMap) || !operationToscaMap.containsKey(INPUTS.getElementName())) { + return Collections.emptyList(); + } + final Map inputsMap = (Map) operationToscaMap.get(INPUTS.getElementName()); + return inputsMap.entrySet().stream().map(this::buildInputAssignment).collect(toList()); + } + + private PropertyAssignmentUi buildInputAssignment(final Entry inputAssignmentMap) { + var propertyAssignmentUi = new PropertyAssignmentUi(); + propertyAssignmentUi.setName(inputAssignmentMap.getKey()); + propertyAssignmentUi.setValue(inputAssignmentMap.getValue().toString()); + propertyAssignmentUi.setType(STRING.getType()); + return propertyAssignmentUi; + } + + private List getOperationsFromRelationshipTemplate(final Map toscaJson, final String relationshipTemplate) { + final List operationUiList = new ArrayList<>(); + final List interfaces = + buildToscaInterfacesFromRelationship(getRelationshipTemplates(toscaJson, relationshipTemplate)); + interfaces.stream() + .filter(interfaceDefinition -> MapUtils.isNotEmpty(interfaceDefinition.getOperations())) + .forEach(interfaceDefinition -> + interfaceDefinition.getOperations() + .forEach((operationType, operationValue) -> + operationUiList.add(buildOperation(interfaceDefinition.getType(), operationType, (Map) operationValue)) + )); + return operationUiList; + } + + private OperationUi buildOperation(final String interfaceType, final String operationType, final Map operationToscaMap) { + var operationUi = new OperationUi(); + operationUi.setInterfaceType(interfaceType); + operationUi.setOperationType(operationType); + getImplementation(operationToscaMap).ifPresent(operationUi::setImplementation); + final List operationsInputs = getOperationsInputs(operationToscaMap); + if (CollectionUtils.isNotEmpty(operationsInputs)) { + operationUi.setInputs(operationsInputs); + } + return operationUi; + } + @SuppressWarnings("unchecked") private Map getGroups(Map toscaJson, String model) { Map mappedTopologyTemplate = (Map) findToscaElement(toscaJson, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL) @@ -715,7 +824,7 @@ public class YamlTemplateParsingHandler { private void setRequirements(UploadComponentInstanceInfo nodeTemplateInfo, Map nodeTemplateJsonMap) { if (nodeTemplateJsonMap.containsKey(REQUIREMENTS.getElementName())) { - Map> regResponse = createReqModuleFromYaml(nodeTemplateJsonMap); + Map> regResponse = createReqModuleFromYaml(nodeTemplateJsonMap, nodeTemplateInfo.getName()); if (!regResponse.isEmpty()) { nodeTemplateInfo.setRequirements(regResponse); } @@ -746,14 +855,14 @@ public class YamlTemplateParsingHandler { } @SuppressWarnings("unchecked") - private Map> createReqModuleFromYaml(Map nodeTemplateJsonMap) { + private Map> createReqModuleFromYaml(Map nodeTemplateJsonMap, String nodeName) { Map> moduleRequirements = new HashMap<>(); Either, ResultStatusEnum> requirementsListRes = findFirstToscaListElement(nodeTemplateJsonMap, REQUIREMENTS); if (requirementsListRes.isLeft()) { for (Object jsonReqObj : requirementsListRes.left().value()) { String reqName = ((Map) jsonReqObj).keySet().iterator().next(); Object reqJson = ((Map) jsonReqObj).get(reqName); - addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName); + addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName, nodeName); } } else { Either, ResultStatusEnum> requirementsMapRes = findFirstToscaMapElement(nodeTemplateJsonMap, REQUIREMENTS); @@ -761,15 +870,15 @@ public class YamlTemplateParsingHandler { for (Map.Entry entry : requirementsMapRes.left().value().entrySet()) { String reqName = entry.getKey(); Object reqJson = entry.getValue(); - addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName); + addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName, nodeName); } } } return moduleRequirements; } - private void addModuleNodeTemplateReq(Map> moduleRequirements, Object requirementJson, String requirementName) { - UploadReqInfo requirement = buildModuleNodeTemplateReg(requirementJson); + private void addModuleNodeTemplateReq(Map> moduleRequirements, Object requirementJson, String requirementName, String nodeName) { + UploadReqInfo requirement = buildModuleNodeTemplateReg(requirementJson, nodeName); requirement.setName(requirementName); if (moduleRequirements.containsKey(requirementName)) { moduleRequirements.get(requirementName).add(requirement); @@ -911,7 +1020,7 @@ public class YamlTemplateParsingHandler { } @SuppressWarnings("unchecked") - private UploadReqInfo buildModuleNodeTemplateReg(Object regObject) { + private UploadReqInfo buildModuleNodeTemplateReg(Object regObject, String nodeName) { UploadReqInfo regTemplateInfo = new UploadReqInfo(); if (regObject instanceof String) { String nodeTemplateJsonString = (String) regObject; @@ -924,6 +1033,12 @@ public class YamlTemplateParsingHandler { if (nodeTemplateJsonMap.containsKey(CAPABILITY.getElementName())) { regTemplateInfo.setCapabilityName((String) nodeTemplateJsonMap.get(CAPABILITY.getElementName())); } + if (nodeTemplateJsonMap.containsKey(RELATIONSHIP.getElementName())) { + final String template = (String) nodeTemplateJsonMap.get(RELATIONSHIP.getElementName()); + if (StringUtils.isNotEmpty(nodeName) && template.contains(nodeName)) { + regTemplateInfo.setRelationshipTemplate(template); + } + } } return regTemplateInfo; } diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java index 225a6c4408..0850535108 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java @@ -40,6 +40,7 @@ import lombok.Getter; import lombok.Setter; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarBusinessLogic; @@ -132,6 +133,7 @@ import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.tosca.CsarUtils; +import org.openecomp.sdc.be.ui.model.OperationUi; import org.openecomp.sdc.be.utils.TypeUtils; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; import org.openecomp.sdc.common.api.ArtifactTypeEnum; @@ -1862,6 +1864,9 @@ public class ServiceImportBusinessLogic { reqAndRelationshipPair.setCapabilityOwnerId(aviableCapForRel.getOwnerId()); CapabilityRequirementRelationship capReqRel = new CapabilityRequirementRelationship(); capReqRel.setRelation(reqAndRelationshipPair); + if (StringUtils.isNotEmpty(uploadRegInfo.getRelationshipTemplate())) { + capReqRel.setOperations(getOperations(nodesInfoValue.getOperations(), uploadRegInfo.getRelationshipTemplate())); + } reqAndRelationshipPairList.add(capReqRel); regCapRelDef.setRelationships(reqAndRelationshipPairList); relations.add(regCapRelDef); @@ -1871,6 +1876,16 @@ public class ServiceImportBusinessLogic { return componentsUtils.getResponseFormat(ActionStatus.OK, yamlName); } + private List getOperations(final Map> operations, final String relationshipTemplate) { + final List operationUiList = new ArrayList<>(); + operations.forEach((operationKey, operationValues) -> { + if (operationKey.equals(relationshipTemplate)) { + operationUiList.addAll(operationValues); + } + }); + return operationUiList; + } + protected Service getResourceAfterCreateRelations(Service service) { ComponentParametersView parametersView = serviceImportParseLogic.getComponentFilterAfterCreateRelations(); Either eitherGetResource = toscaOperationFacade.getToscaElement(service.getUniqueId(), parametersView); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandlerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandlerTest.java index edf17b7e61..6d779a192e 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandlerTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandlerTest.java @@ -32,6 +32,7 @@ import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.ARTIFACTS; import java.io.File; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -40,6 +41,7 @@ import java.util.Optional; import java.util.stream.Collectors; import mockit.Deencapsulation; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang3.StringUtils; import org.assertj.core.util.Lists; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -65,8 +67,10 @@ import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.Service; import org.openecomp.sdc.be.model.UploadArtifactInfo; 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.operations.impl.AnnotationTypeOperations; +import org.openecomp.sdc.be.ui.model.OperationUi; import org.openecomp.sdc.common.zip.ZipUtils; import org.openecomp.sdc.common.zip.exception.ZipException; import org.springframework.test.util.ReflectionTestUtils; @@ -174,6 +178,31 @@ public class YamlTemplateParsingHandlerTest { assertTrue(parsedYaml.getProperties().containsKey("default_software_version")); } + @Test + void parseRelationshipTemplateInfoFromYamlTest() { + when(groupTypeBusinessLogic.getLatestGroupTypeByType(eq(HEAT_GROUP_TYPE), any())).thenReturn(heatGroupType); + String main_template_content = new String(csar.get(MAIN_TEMPLATE_NAME)); + CsarInfo csarInfo = new CsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME, + MAIN_TEMPLATE_NAME, main_template_content, true); + + Service service = new Service(); + ParsedToscaYamlInfo parsedYaml = handler.parseResourceInfoFromYAML(FILE_NAME, resourceYml, new HashMap<>(), + csarInfo.extractTypesInfo(), NODE_NAME, service, getInterfaceTemplateYaml(csarInfo).get()); + + assertThat(parsedYaml.getInstances()).isNotNull(); + final Map> operations = new HashMap<>(); + for (UploadComponentInstanceInfo instance : parsedYaml.getInstances().values()) { + final Map> requirements = instance.getRequirements(); + if (MapUtils.isNotEmpty(requirements)) { + requirements.values() + .forEach(requirementInfoList -> requirementInfoList.stream() + .filter(requirement -> StringUtils.isNotEmpty(requirement.getRelationshipTemplate())) + .forEach(requirement -> operations.putAll(instance.getOperations()))); + } + } + assertEquals(1, operations.size()); + } + @Test void parseResourceInfoFromYAMLTest() { stubGetGroupType(); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java index dcc0289822..1f45f77f3f 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java @@ -1571,6 +1571,7 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest any(ComponentInstance.class), any(UploadReqInfo.class))).thenReturn(capabilityDefinition); when(componentsUtils.getResponseFormat(any(ActionStatus.class), anyString())).thenReturn(responseFormat); Assertions.assertNotNull(sIBL.addRelationToRI(yamlName, service, nodesInfoValue, relations)); + Assertions.assertNotNull(relations.get(0).getRelationships().get(0).getOperations()); } @Test @@ -1584,7 +1585,6 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest List relations = new ArrayList<>(); when(componentsUtils.getResponseFormat(any(ActionStatus.class), anyString())).thenReturn(responseFormat); Assertions.assertNotNull(sIBL.addRelationToRI(yamlName, service, nodesInfoValue, relations)); - } @Test diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBussinessLogicBaseTestSetup.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBussinessLogicBaseTestSetup.java index beaa695fe4..c8fd87ca3b 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBussinessLogicBaseTestSetup.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBussinessLogicBaseTestSetup.java @@ -102,6 +102,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade import org.openecomp.sdc.be.model.operations.api.IElementOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.model.operations.impl.GraphLockOperation; +import org.openecomp.sdc.be.ui.model.OperationUi; import org.openecomp.sdc.be.user.Role; import org.openecomp.sdc.be.user.UserBusinessLogic; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; @@ -433,15 +434,26 @@ public class ServiceImportBussinessLogicBaseTestSetup extends BaseBusinessLogicM uploadReqInfo.setName("uploadReqInfo"); uploadReqInfo.setNode("zxjTestImportServiceAb"); uploadReqInfo.setCapabilityName("tosca.capabilities.Node"); + uploadReqInfo.setRelationshipTemplate("ExtCP 0.dependency.1"); uploadReqInfoList.add(uploadReqInfo); requirements.put("requirements", uploadReqInfoList); uploadNodeFilterInfo.setName("mme_ipu_vdu.virtualbinding"); uploadComponentInstanceInfo.setCapabilities(getCapabilities()); uploadComponentInstanceInfo.setRequirements(requirements); uploadComponentInstanceInfo.setName("zxjTestImportServiceAb"); + uploadComponentInstanceInfo.setOperations(getOperations()); return uploadComponentInstanceInfo; } + protected Map> getOperations() { + String relationshipTemplate = "ExtCP 0.dependency.1"; + OperationUi operationUi = new OperationUi(); + operationUi.setOperationType("change_external_connectivity_start"); + operationUi.setInterfaceType("tosca.interfaces.nfv.Vnflcm"); + operationUi.setImplementation("impl"); + return Map.of(relationshipTemplate, List.of(operationUi)); + } + protected Map> getCapabilities() { List uploadCapInfoList = new ArrayList<>(); UploadCapInfo uploadCapInfo = new UploadCapInfo(); diff --git a/catalog-be/src/test/resources/csars/with_groups.csar b/catalog-be/src/test/resources/csars/with_groups.csar index dd7f5dfb69..cd701a2078 100644 Binary files a/catalog-be/src/test/resources/csars/with_groups.csar and b/catalog-be/src/test/resources/csars/with_groups.csar differ diff --git a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java index 9c6ac18ef9..603f9ccf61 100644 --- a/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java +++ b/catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java @@ -140,4 +140,7 @@ public enum ActionStatus { TOSCA_GET_FUNCTION_PROPERTY_NOT_FOUND, TOSCA_GET_FUNCTION_INSTANCE_NOT_FOUND, TOSCA_FUNCTION_MISSING_ATTRIBUTE, + RELATIONSHIP_TEMPLATE_NOT_FOUND, + RELATIONSHIP_TEMPLATE_DEFINITION_NOT_FOUND + } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadComponentInstanceInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadComponentInstanceInfo.java index 57652ee162..ef9f1f17e8 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadComponentInstanceInfo.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadComponentInstanceInfo.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import lombok.Getter; import lombok.Setter; +import org.openecomp.sdc.be.ui.model.OperationUi; @Getter @Setter @@ -40,4 +41,5 @@ public class UploadComponentInstanceInfo { private Map requirementsNamesToUpdate; private Collection directives; private UploadNodeFilterInfo uploadNodeFilterInfo; + private Map> operations; } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadReqInfo.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadReqInfo.java index a3f927925f..b18a8e47a5 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadReqInfo.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadReqInfo.java @@ -19,6 +19,13 @@ */ package org.openecomp.sdc.be.model; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor public class UploadReqInfo extends UploadInfo { /** @@ -26,20 +33,6 @@ public class UploadReqInfo extends UploadInfo { */ private String capabilityName; private String node; + private String relationshipTemplate; - public String getCapabilityName() { - return capabilityName; - } - - public void setCapabilityName(String capabilityName) { - this.capabilityName = capabilityName; - } - - public String getNode() { - return node; - } - - public void setNode(String node) { - this.node = node; - } } 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 02fda3c51b..8c08a3d040 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 @@ -2082,6 +2082,7 @@ public class ToscaOperationFacade { Component updatedComponent = componentEither.left().value(); component.setCapabilities(updatedComponent.getCapabilities()); component.setRequirements(updatedComponent.getRequirements()); + component.setComponentInstancesRelations(updatedComponent.getComponentInstancesRelations()); component.setComponentInstances(updatedComponent.getComponentInstances()); } diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java index 6dfaebc947..cfc58671e4 100644 --- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java +++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java @@ -32,6 +32,7 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; import org.apache.commons.collections.CollectionUtils; @@ -118,6 +119,7 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.TopologyTemplate; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElement; import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElementTypeEnum; import org.openecomp.sdc.be.model.jsonjanusgraph.enums.JsonConstantKeysEnum; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeTemplateOperation; import org.openecomp.sdc.be.model.operations.StorageException; import org.openecomp.sdc.be.resources.data.ComponentMetadataData; import org.openecomp.sdc.be.resources.data.ProductMetadataData; @@ -481,11 +483,56 @@ public class ModelConverter { requirementCapabilityRelDef.setType(p.getRelation().getRelationship().getType()); requirementCapabilityRelDef.setCapability(p.getRelation().getCapability()); requirementCapabilityRelDef.setOriginUI(relation.isOriginUI()); + createRelationshipInterfaces(p.getOperations()).ifPresent(requirementCapabilityRelDef::setInterfaces); relationsList.add(requirementCapabilityRelDef); }); return relationsList; } + private static Optional> createRelationshipInterfaces(final List operationList) { + if (CollectionUtils.isEmpty(operationList)) { + return Optional.empty(); + } + final ListDataDefinition interfaceList = new ListDataDefinition<>(); + final Map> operationByInterfaceType = operationList.stream() + .collect(Collectors.groupingBy(OperationUi::getInterfaceType)); + for (final Entry> interfaceEntry : operationByInterfaceType.entrySet()) { + interfaceList.add(createInterface(interfaceEntry.getKey(), interfaceEntry.getValue())); + } + return Optional.of(interfaceList); + } + + private static InterfaceDataDefinition createInterface(final String interfaceType, final List operationList) { + final InterfaceDataDefinition interfaceDataDefinition = new InterfaceDataDefinition(); + interfaceDataDefinition.setType(interfaceType); + if (CollectionUtils.isNotEmpty(operationList)) { + final Map operationMap = operationList.stream() + .collect(Collectors.toMap(OperationUi::getOperationType, ModelConverter::createOperation)); + interfaceDataDefinition.setOperations(operationMap); + } + return interfaceDataDefinition; + } + + private static OperationDataDefinition createOperation(final OperationUi operation) { + final OperationDataDefinition operationDataDefinition = new OperationDataDefinition(); + operationDataDefinition.setName(operation.getOperationType()); + operationDataDefinition.setUniqueId(UUID.randomUUID().toString()); + final ArtifactDataDefinition artifactDataDefinition = (ArtifactDataDefinition) operation.getImplementation(); + operationDataDefinition.setImplementation(artifactDataDefinition); + if (CollectionUtils.isNotEmpty(operation.getInputs())) { + final ListDataDefinition inputs = new ListDataDefinition<>(); + operation.getInputs().forEach(input -> { + final OperationInputDefinition operationInputDefinition = new OperationInputDefinition(); + operationInputDefinition.setLabel(input.getName()); + operationInputDefinition.setType(input.getType()); + operationInputDefinition.setValue(input.getValue()); + inputs.add(operationInputDefinition); + }); + operationDataDefinition.setInputs(inputs); + } + return operationDataDefinition; + } + private static void convertCapabilities(Component component, TopologyTemplate topologyTemplate) { convertTopologyTemplateCapabilities(component, topologyTemplate); if (componentInstancesCapabilitiesExist(component) || groupsCapabilitiesExist(component)) { diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadReqInfoTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadReqInfoTest.java deleted file mode 100644 index 8ce7d8db57..0000000000 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadReqInfoTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.openecomp.sdc.be.model; - -import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSetters; -import static org.hamcrest.MatcherAssert.assertThat; - -import org.junit.Test; - -public class UploadReqInfoTest { - - @Test - public void shouldHaveValidGettersAndSetters() { - assertThat(UploadReqInfo.class, hasValidGettersAndSetters()); - } -} diff --git a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverterTest.java b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverterTest.java index 5aa742a540..871a43016f 100644 --- a/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverterTest.java +++ b/catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverterTest.java @@ -29,7 +29,6 @@ */ package org.openecomp.sdc.be.model.jsonjanusgraph.utils; - import java.util.HashMap; import org.junit.jupiter.api.Test; @@ -38,6 +37,7 @@ import org.mockito.InjectMocks; import org.mockito.junit.jupiter.MockitoExtension; import org.openecomp.sdc.be.dao.jsongraph.types.VertexTypeEnum; +import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition; import org.openecomp.sdc.be.datatypes.elements.AttributeDataDefinition; import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition; import org.openecomp.sdc.be.datatypes.elements.ComponentInstanceDataDefinition; @@ -72,6 +72,9 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.datamodel.ToscaElementTypeEnum; import java.util.LinkedList; import java.util.List; import java.util.Map; +import org.openecomp.sdc.be.model.tosca.ToscaType; +import org.openecomp.sdc.be.ui.model.OperationUi; +import org.openecomp.sdc.be.ui.model.PropertyAssignmentUi; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -276,6 +279,49 @@ public class ModelConverterTest { assertEquals("toNode", result.get(0).getToId()); } + @Test + void testConvertRelationTemplateToToscaRelation() + { + RequirementCapabilityRelDef reqCap = new RequirementCapabilityRelDef(); + reqCap.setOriginUI(true); + reqCap.setFromNode("fromNode"); + reqCap.setToNode("toNode"); + List list = new LinkedList<>(); + CapabilityRequirementRelationship relationship = new CapabilityRequirementRelationship(); + RelationshipInfo info = new RelationshipInfo(); + info.setCapabilityOwnerId("capOwnerId"); + info.setId("id"); + info.setCapabilityUid("capUid"); + info.setRequirementOwnerId("reqOwnerId"); + info.setRequirementUid("reqUid"); + info.setRequirement("req"); + info.setCapability("cap"); + RelationshipImpl relationshipImpl = new RelationshipImpl(); + relationshipImpl.setType("type"); + info.setRelationships(relationshipImpl); + relationship.setRelation(info); + OperationUi operationUi = new OperationUi(); + operationUi.setInterfaceType("tosca.interfaces.relationship.Configure"); + operationUi.setOperationType("add_source"); + final ArtifactDataDefinition artifactDataDefinition = new ArtifactDataDefinition(); + artifactDataDefinition.setArtifactName("impl"); + operationUi.setImplementation(artifactDataDefinition); + PropertyAssignmentUi propertyAssignmentUi = new PropertyAssignmentUi(); + propertyAssignmentUi.setName("strInput1"); + propertyAssignmentUi.setType(ToscaType.STRING.getType()); + propertyAssignmentUi.setValue("inputValue"); + operationUi.setInputs(List.of(propertyAssignmentUi)); + relationship.setOperations(List.of(operationUi)); + list.add(relationship); + reqCap.setRelationships(list); + + List result = ModelConverter.convertRelationToToscaRelation(reqCap); + assertEquals(1, result.size()); + assertEquals(false, result.get(0).getInterfaces().isEmpty()); + assertEquals(false, result.get(0).getInterfaces().getListToscaDataDefinition().get(0).getOperations().isEmpty()); + assertEquals(false, result.get(0).getInterfaces().getListToscaDataDefinition().get(0).getOperations().get("add_source").getInputs().isEmpty()); + } + @Test public void testConvertToMapOfMapCapabilityPropertiesonvertRelation() { diff --git a/common-be/src/main/java/org/openecomp/sdc/be/utils/TypeUtils.java b/common-be/src/main/java/org/openecomp/sdc/be/utils/TypeUtils.java index 92a9e3a144..cfbb6db76d 100644 --- a/common-be/src/main/java/org/openecomp/sdc/be/utils/TypeUtils.java +++ b/common-be/src/main/java/org/openecomp/sdc/be/utils/TypeUtils.java @@ -64,8 +64,9 @@ public class TypeUtils { // Heat env Validation PARAMETERS("parameters"), // Import Validations - TOSCA_VERSION("tosca_definitions_version"), TOPOLOGY_TEMPLATE("topology_template"), OCCURRENCES("occurrences"), NODE_TEMPLATES("node_templates"), - GROUPS("groups"), INPUTS("inputs"), OUTPUTS("outputs"), + TOSCA_VERSION("tosca_definitions_version"), TOPOLOGY_TEMPLATE("topology_template"), OCCURRENCES("occurrences"), + NODE_TEMPLATES("node_templates"), GROUPS("groups"), INPUTS("inputs"), + OUTPUTS("outputs"), RELATIONSHIP_TEMPLATES("relationship_templates"), SUBSTITUTION_MAPPINGS("substitution_mappings"), NODE_TYPE("node_type"), DIRECTIVES("directives"), // Attributes ATTRIBUTES("attributes"), LABEL("label"), HIDDEN("hidden"), IMMUTABLE("immutable"), ANNOTATIONS("annotations"),