Service Import - Node Template Relationship Template 94/129794/13
authorKrupaNagabhushan <krupa.nagabhushan@est.tech>
Tue, 5 Jul 2022 17:43:07 +0000 (18:43 +0100)
committerKrupa Nagabhushan <krupa.nagabhushan@est.tech>
Tue, 2 Aug 2022 21:10:26 +0000 (21:10 +0000)
Issue-ID: SDC-4083
Signed-off-by: KrupaNagabhushan <krupa.nagabhushan@est.tech>
Signed-off-by: andre.schmid <andre.schmid@est.tech>
Change-Id: Ia0f3635df969c44de5aba2d672fad34f0855e4e2

15 files changed:
catalog-be/src/main/docker/backend/chef-repo/cookbooks/sdc-catalog-be/files/default/error-configuration.yaml
catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandler.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandlerTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBussinessLogicBaseTestSetup.java
catalog-be/src/test/resources/csars/with_groups.csar
catalog-dao/src/main/java/org/openecomp/sdc/be/dao/api/ActionStatus.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadComponentInstanceInfo.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/UploadReqInfo.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/operations/ToscaOperationFacade.java
catalog-model/src/main/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverter.java
catalog-model/src/test/java/org/openecomp/sdc/be/model/UploadReqInfoTest.java [deleted file]
catalog-model/src/test/java/org/openecomp/sdc/be/model/jsonjanusgraph/utils/ModelConverterTest.java
common-be/src/main/java/org/openecomp/sdc/be/utils/TypeUtils.java

index 58f3dc3..50a7014 100644 (file)
@@ -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"
+    }
index 940363b..a68bbf3 100644 (file)
@@ -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<String, NodeTypeInfo> nodeTypesInfo, String nodeName,
                                                          Component component, String interfaceTemplateYaml) {
         log.debug("#parseResourceInfoFromYAML - Going to parse yaml {} ", fileName);
-        final Map<String, Object> mappedToscaTemplate = getMappedToscaTemplate(fileName, resourceYml, nodeTypesInfo, nodeName);
-        final ParsedToscaYamlInfo parsedToscaYamlInfo = new ParsedToscaYamlInfo();
-        final Map<String, Object> mappedTopologyTemplate = (Map<String, Object>) findToscaElement(mappedToscaTemplate, TOPOLOGY_TEMPLATE,
+        Map<String, Object> mappedToscaTemplate = getMappedToscaTemplate(fileName, resourceYml, nodeTypesInfo, nodeName);
+        ParsedToscaYamlInfo parsedToscaYamlInfo = new ParsedToscaYamlInfo();
+        Map<String, Object> mappedTopologyTemplate = (Map<String, Object>) findToscaElement(mappedToscaTemplate, TOPOLOGY_TEMPLATE,
             ToscaElementTypeEnum.ALL).left().on(err -> failIfNotTopologyTemplate(fileName));
         final Map<String, Object> 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<String, Object> substitutionMappings = getSubstitutionMappings(mappedToscaTemplate);
@@ -354,6 +367,102 @@ public class YamlTemplateParsingHandler {
         return null;
     }
 
+    private void associateRelationshipTemplatesToInstances(final Map<String, UploadComponentInstanceInfo> instances,
+                                                           final Map<String, Object> toscaJson) {
+        if (MapUtils.isEmpty(instances)) {
+            return;
+        }
+        for (UploadComponentInstanceInfo instance : instances.values()) {
+            final Map<String, List<OperationUi>> operations = new HashMap<>();
+            final Map<String, List<UploadReqInfo>> 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<String, Object> getRelationshipTemplates(final Map<String, Object> toscaJson, final String relationshipTemplate) {
+        final Either<Map<String, Object>, ResultStatusEnum> eitherRelationshipTemplates = findFirstToscaMapElement(toscaJson, RELATIONSHIP_TEMPLATES);
+        if (eitherRelationshipTemplates.isRight()) {
+            throw new ByActionStatusComponentException(ActionStatus.RELATIONSHIP_TEMPLATE_NOT_FOUND);
+        }
+        final Map<String, Object> relationshipTemplateMap = eitherRelationshipTemplates.left().value();
+        final Map<String, Map<String, Object>> relationship = (Map<String, Map<String, Object>>) relationshipTemplateMap.get(relationshipTemplate);
+        if (relationship == null) {
+            throw new ByActionStatusComponentException(ActionStatus.RELATIONSHIP_TEMPLATE_DEFINITION_NOT_FOUND);
+        }
+        return relationship.get(INTERFACES.getElementName());
+    }
+
+    private List<ToscaInterfaceDefinition> buildToscaInterfacesFromRelationship(final Map<String, Object> interfaces) {
+        return interfaces.entrySet().stream()
+            .map(entry -> {
+                final var toscaInterfaceDefinition = new ToscaInterfaceDefinition();
+                toscaInterfaceDefinition.setType(entry.getKey());
+                final Map<String, Object> toscaInterfaceMap = (Map<String, Object>) entry.getValue();
+                toscaInterfaceDefinition.setOperations((Map<String, Object>) toscaInterfaceMap.get(OPERATIONS.getElementName()));
+                return toscaInterfaceDefinition;
+            })
+            .collect(toList());
+    }
+
+    private Optional<Object> getImplementation(final Map<String, Object> operationToscaMap) {
+        if (MapUtils.isEmpty(operationToscaMap) || !operationToscaMap.containsKey(IMPLEMENTATION.getElementName())) {
+            return Optional.empty();
+        }
+        final Map<String, Object> implementationToscaMap = (Map<String, Object>) operationToscaMap.get(IMPLEMENTATION.getElementName());
+        return Optional.ofNullable(
+            implementationToscaMap.computeIfPresent("toscaPresentation", (key, value) -> ((Map<String, Object>) value).get(NAME.getName()))
+        );
+    }
+
+    private List<PropertyAssignmentUi> getOperationsInputs(final Map<String, Object> operationToscaMap) {
+        if (MapUtils.isEmpty(operationToscaMap) || !operationToscaMap.containsKey(INPUTS.getElementName())) {
+            return Collections.emptyList();
+        }
+        final Map<String, Object> inputsMap = (Map<String, Object>) operationToscaMap.get(INPUTS.getElementName());
+        return inputsMap.entrySet().stream().map(this::buildInputAssignment).collect(toList());
+    }
+
+    private PropertyAssignmentUi buildInputAssignment(final Entry<String, Object> inputAssignmentMap) {
+        var propertyAssignmentUi = new PropertyAssignmentUi();
+        propertyAssignmentUi.setName(inputAssignmentMap.getKey());
+        propertyAssignmentUi.setValue(inputAssignmentMap.getValue().toString());
+        propertyAssignmentUi.setType(STRING.getType());
+        return propertyAssignmentUi;
+    }
+
+    private List<OperationUi> getOperationsFromRelationshipTemplate(final Map<String, Object> toscaJson, final String relationshipTemplate) {
+        final List<OperationUi> operationUiList = new ArrayList<>();
+        final List<ToscaInterfaceDefinition> 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<String, Object>) operationValue))
+            ));
+        return operationUiList;
+    }
+
+    private OperationUi buildOperation(final String interfaceType, final String operationType, final Map<String, Object> operationToscaMap) {
+        var operationUi = new OperationUi();
+        operationUi.setInterfaceType(interfaceType);
+        operationUi.setOperationType(operationType);
+        getImplementation(operationToscaMap).ifPresent(operationUi::setImplementation);
+        final List<PropertyAssignmentUi> operationsInputs = getOperationsInputs(operationToscaMap);
+        if (CollectionUtils.isNotEmpty(operationsInputs)) {
+            operationUi.setInputs(operationsInputs);
+        }
+        return operationUi;
+    }
+
     @SuppressWarnings("unchecked")
     private Map<String, GroupDefinition> getGroups(Map<String, Object> toscaJson, String model) {
         Map<String, Object> mappedTopologyTemplate = (Map<String, Object>) findToscaElement(toscaJson, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL)
@@ -715,7 +824,7 @@ public class YamlTemplateParsingHandler {
 
     private void setRequirements(UploadComponentInstanceInfo nodeTemplateInfo, Map<String, Object> nodeTemplateJsonMap) {
         if (nodeTemplateJsonMap.containsKey(REQUIREMENTS.getElementName())) {
-            Map<String, List<UploadReqInfo>> regResponse = createReqModuleFromYaml(nodeTemplateJsonMap);
+            Map<String, List<UploadReqInfo>> regResponse = createReqModuleFromYaml(nodeTemplateJsonMap, nodeTemplateInfo.getName());
             if (!regResponse.isEmpty()) {
                 nodeTemplateInfo.setRequirements(regResponse);
             }
@@ -746,14 +855,14 @@ public class YamlTemplateParsingHandler {
     }
 
     @SuppressWarnings("unchecked")
-    private Map<String, List<UploadReqInfo>> createReqModuleFromYaml(Map<String, Object> nodeTemplateJsonMap) {
+    private Map<String, List<UploadReqInfo>> createReqModuleFromYaml(Map<String, Object> nodeTemplateJsonMap, String nodeName) {
         Map<String, List<UploadReqInfo>> moduleRequirements = new HashMap<>();
         Either<List<Object>, ResultStatusEnum> requirementsListRes = findFirstToscaListElement(nodeTemplateJsonMap, REQUIREMENTS);
         if (requirementsListRes.isLeft()) {
             for (Object jsonReqObj : requirementsListRes.left().value()) {
                 String reqName = ((Map<String, Object>) jsonReqObj).keySet().iterator().next();
                 Object reqJson = ((Map<String, Object>) jsonReqObj).get(reqName);
-                addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName);
+                addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName, nodeName);
             }
         } else {
             Either<Map<String, Object>, ResultStatusEnum> requirementsMapRes = findFirstToscaMapElement(nodeTemplateJsonMap, REQUIREMENTS);
@@ -761,15 +870,15 @@ public class YamlTemplateParsingHandler {
                 for (Map.Entry<String, Object> 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<String, List<UploadReqInfo>> moduleRequirements, Object requirementJson, String requirementName) {
-        UploadReqInfo requirement = buildModuleNodeTemplateReg(requirementJson);
+    private void addModuleNodeTemplateReq(Map<String, List<UploadReqInfo>> 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;
     }
index 225a6c4..0850535 100644 (file)
@@ -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<OperationUi> getOperations(final Map<String, List<OperationUi>> operations, final String relationshipTemplate) {
+        final List<OperationUi> 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<Service, StorageOperationStatus> eitherGetResource = toscaOperationFacade.getToscaElement(service.getUniqueId(), parametersView);
index edf17b7..6d779a1 100644 (file)
@@ -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<String, List<OperationUi>> operations = new HashMap<>();
+        for (UploadComponentInstanceInfo instance : parsedYaml.getInstances().values()) {
+            final Map<String, List<UploadReqInfo>> 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();
index dcc0289..1f45f77 100644 (file)
@@ -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<RequirementCapabilityRelDef> relations = new ArrayList<>();
         when(componentsUtils.getResponseFormat(any(ActionStatus.class), anyString())).thenReturn(responseFormat);
         Assertions.assertNotNull(sIBL.addRelationToRI(yamlName, service, nodesInfoValue, relations));
-
     }
 
     @Test
index beaa695..c8fd87c 100644 (file)
@@ -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<String, List<OperationUi>> 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<String, List<UploadCapInfo>> getCapabilities() {
         List<UploadCapInfo> uploadCapInfoList = new ArrayList<>();
         UploadCapInfo uploadCapInfo = new UploadCapInfo();
index dd7f5df..cd701a2 100644 (file)
Binary files a/catalog-be/src/test/resources/csars/with_groups.csar and b/catalog-be/src/test/resources/csars/with_groups.csar differ
index 9c6ac18..603f9cc 100644 (file)
@@ -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
+
 }
index 57652ee..ef9f1f1 100644 (file)
@@ -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<String, String> requirementsNamesToUpdate;
     private Collection<String> directives;
     private UploadNodeFilterInfo uploadNodeFilterInfo;
+    private Map<String, List<OperationUi>> operations;
 }
index a3f9279..b18a8e4 100644 (file)
  */
 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;
-    }
 }
index 02fda3c..8c08a3d 100644 (file)
@@ -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());
     }
 
index 6dfaebc..cfc5867 100644 (file)
@@ -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<ListDataDefinition<InterfaceDataDefinition>> createRelationshipInterfaces(final List<OperationUi> operationList) {
+        if (CollectionUtils.isEmpty(operationList)) {
+            return Optional.empty();
+        }
+        final ListDataDefinition<InterfaceDataDefinition> interfaceList = new ListDataDefinition<>();
+        final Map<String, List<OperationUi>> operationByInterfaceType = operationList.stream()
+            .collect(Collectors.groupingBy(OperationUi::getInterfaceType));
+        for (final Entry<String, List<OperationUi>> interfaceEntry : operationByInterfaceType.entrySet()) {
+            interfaceList.add(createInterface(interfaceEntry.getKey(), interfaceEntry.getValue()));
+        }
+        return Optional.of(interfaceList);
+    }
+
+    private static InterfaceDataDefinition createInterface(final String interfaceType, final List<OperationUi> operationList) {
+        final InterfaceDataDefinition interfaceDataDefinition = new InterfaceDataDefinition();
+        interfaceDataDefinition.setType(interfaceType);
+        if (CollectionUtils.isNotEmpty(operationList)) {
+            final Map<String, OperationDataDefinition> 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<OperationInputDefinition> 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 (file)
index 8ce7d8d..0000000
+++ /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());
-       }
-}
index 5aa742a..871a430 100644 (file)
@@ -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<CapabilityRequirementRelationship> 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<RelationshipInstDataDefinition> 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()
     {
index 92a9e3a..cfbb6db 100644 (file)
@@ -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"),