Importing VSP with node_type in separate file 33/108333/5
authorMichaelMorris <michael.morris@est.tech>
Wed, 27 May 2020 17:09:40 +0000 (18:09 +0100)
committerOfir Sonsino <ofir.sonsino@intl.att.com>
Thu, 18 Jun 2020 05:41:53 +0000 (05:41 +0000)
Import fails when a node_type referenced in the main template is defined in a separate yaml file in the csar even when that separate file is correctly imported in the main template

Change-Id: I6abe074585c2ce592fe9bed7abe76f0856bcfe93
Issue-ID: SDC-2850
Signed-off-by: MichaelMorris <michael.morris@est.tech>
catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarInfo.java
catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java
catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java
catalog-be/src/test/resources/nodeTypeInGlobalSub.csar [new file with mode: 0644]

index 58beecb..feb18c2 100644 (file)
@@ -45,6 +45,7 @@ import org.yaml.snakeyaml.Yaml;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -133,11 +134,13 @@ public class CsarInfo {
     public Map<String,NodeTypeInfo> extractNodeTypesInfo() {
         Map<String, NodeTypeInfo> nodeTypesInfo = new HashMap<>();
         List<Map.Entry<String, byte[]>> globalSubstitutes = new ArrayList<>();
+        final Set<String> nodeTypesUsedInNodeTemplates = new HashSet<>();
         for (Map.Entry<String, byte[]> entry : getCsar().entrySet()) {
-            extractNodeTypeInfo(nodeTypesInfo, globalSubstitutes, entry);
+            extractNodeTypeInfo(nodeTypesInfo, globalSubstitutes, nodeTypesUsedInNodeTemplates, entry);
         }
         if (CollectionUtils.isNotEmpty(globalSubstitutes)) {
             setDerivedFrom(nodeTypesInfo, globalSubstitutes);
+            addGlobalSubstitutionsToNodeTypes(globalSubstitutes, nodeTypesUsedInNodeTemplates, nodeTypesInfo);
         }
         markNestedVfc(getMappedToscaMainTemplate(), nodeTypesInfo);
         return nodeTypesInfo;
@@ -145,7 +148,7 @@ public class CsarInfo {
 
     @SuppressWarnings("unchecked")
     private void extractNodeTypeInfo(Map<String, NodeTypeInfo> nodeTypesInfo,
-                                     List<Map.Entry<String, byte[]>> globalSubstitutes, Map.Entry<String, byte[]> entry) {
+                                     List<Map.Entry<String, byte[]>> globalSubstitutes, final Set<String> nodeTypesUsedInNodeTemplates, Map.Entry<String, byte[]> entry) {
         if (isAServiceTemplate(entry.getKey())) {
             if (isGlobalSubstitute(entry.getKey())) {
                 globalSubstitutes.add(entry);
@@ -154,13 +157,28 @@ public class CsarInfo {
                 findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS, ToscaElementTypeEnum.MAP)
                     .right()
                     .on(sub->handleSubstitutionMappings(nodeTypesInfo, entry, mappedToscaTemplate, (Map<String, Object>)sub));
+                
+                final Either<Object, ResultStatusEnum> nodeTypesEither = findToscaElement(mappedToscaTemplate,
+                    TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES, ToscaElementTypeEnum.MAP);
+                if (nodeTypesEither.isLeft()) {
+                    final Map<String, Map<String, Object>> nodeTemplates = (Map<String, Map<String, Object>>) nodeTypesEither.left().value();
+                    nodeTypesUsedInNodeTemplates.addAll(findNodeTypesUsedInNodeTemplates(nodeTemplates));
+                }
             }
         }
     }
     
     private boolean isAServiceTemplate(final String filePath) {
       return Pattern.compile(CsarUtils.SERVICE_TEMPLATE_PATH_PATTERN).matcher(filePath).matches();
-  }
+    }
+    
+    private Set<String> findNodeTypesUsedInNodeTemplates(final Map<String, Map<String, Object>> nodeTemplates) {
+      final Set<String> nodeTypes = new HashSet<>();
+      for (final Map<String, Object> nodeTemplate : nodeTemplates.values()) {
+          nodeTypes.add((String)nodeTemplate.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName()));
+      }
+      return nodeTypes;
+    }
 
     private ResultStatusEnum handleSubstitutionMappings(Map<String, NodeTypeInfo> nodeTypesInfo, Map.Entry<String, byte[]> entry, Map<String, Object> mappedToscaTemplate, Map<String, Object> substitutionMappings) {
       final Set<String> nodeTypesDefinedInTemplate = findNodeTypesDefinedInTemplate(mappedToscaTemplate);  
@@ -227,12 +245,64 @@ public class CsarInfo {
                 .right()
                 .on(nts-> processNodeTemplates((Map<String, Object>)nts, nodeTypesInfo));
     }
+    
+    @SuppressWarnings("unchecked")
+    private void addGlobalSubstitutionsToNodeTypes(final List<Map.Entry<String, byte[]>> globalSubstitutes, final Set<String> nodeTypesUsedInNodeTemplates, final Map<String, NodeTypeInfo> nodeTypesInfo) {
+        for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
+            final String yamlFileContents = new String(entry.getValue());
+            final Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(yamlFileContents);
+            final Either<Object, ResultStatusEnum> nodeTypesEither = findToscaElement(mappedToscaTemplate,
+                    TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP);
+            if (nodeTypesEither.isLeft()) {
+                final Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
+                for (final Map.Entry<String, Object> nodeType : nodeTypes.entrySet()) {
+                    
+                    if (!nodeTypesInfo.containsKey(nodeType.getKey()) && nodeTypesUsedInNodeTemplates.contains(nodeType.getKey())) {
+                        nodeTypesInfo.put(nodeType.getKey(), buildNodeTypeInfo(nodeType, entry.getKey(), mappedToscaTemplate));
+                    }
+                }
+            }
+        }
+    }
 
     @SuppressWarnings("unchecked")
     private static ResultStatusEnum processNodeTemplates( Map<String, Object> nodeTemplates, Map<String, NodeTypeInfo> nodeTypesInfo) {
         nodeTemplates.values().forEach(nt->processNodeTemplate(nodeTypesInfo, (Map<String, Object>) nt));
         return ResultStatusEnum.OK;
     }
+    
+    @SuppressWarnings("unchecked")
+    private NodeTypeInfo buildNodeTypeInfo(final Map.Entry<String, Object> nodeType, final String templateFileName, final Map<String, Object> mappedToscaTemplate ) {
+        final NodeTypeInfo nodeTypeInfo = new NodeTypeInfo();
+        nodeTypeInfo.setSubstitutionMapping(false);
+        nodeTypeInfo.setNested(true);
+        nodeTypeInfo.setType(nodeType.getKey());
+        nodeTypeInfo.setTemplateFileName(templateFileName);
+        nodeTypeInfo.setMappedToscaTemplate(buildToscaTemplateForNode(nodeType.getKey(), mappedToscaTemplate));
+        
+        final Map<String, Object> nodeTypeMap = (Map<String, Object>) nodeType.getValue();
+        final List<String> derivedFrom = new ArrayList<>();
+        derivedFrom.add((String) nodeTypeMap.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()));
+        nodeTypeInfo.setDerivedFrom(derivedFrom);
+        
+        return nodeTypeInfo;
+    }
+    
+    @SuppressWarnings("unchecked")
+    private Map<String, Object> buildToscaTemplateForNode(final String nodeTypeName, final Map<String, Object> mappedToscaTemplate) {
+        final Map<String, Object> mappedToscaTemplateforNode = new HashMap<>(mappedToscaTemplate);
+        
+        final Either<Object, ResultStatusEnum> nodeTypesEither = findToscaElement(mappedToscaTemplate,
+                TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP);
+        final Map<String, Object> nodeTypes = new HashMap<>();
+        if (nodeTypesEither.isLeft()) {
+            final Map<String, Object> allNodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
+            nodeTypes.put(nodeTypeName, allNodeTypes.get(nodeTypeName));
+        }
+
+        mappedToscaTemplateforNode.put(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName(), nodeTypes);
+        return mappedToscaTemplateforNode;
+    }
 
     private static void processNodeTemplate(Map<String, NodeTypeInfo> nodeTypesInfo, Map<String, Object> nodeTemplate) {
         if (nodeTemplate.containsKey(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())) {
index 7eda330..f479bb5 100644 (file)
@@ -36,6 +36,7 @@ import com.google.common.annotations.VisibleForTesting;
 import fj.data.Either;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -1296,7 +1297,7 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic {
 
                log.debug("************* Going to create node types from yaml {}", yamlName);
                createResourcesFromYamlNodeTypesList(yamlName, resource, nestedVfcJsonMap, false, nodesArtifactsToHandle,
-                               createdArtifacts, nodesInfo, csarInfo);
+                               createdArtifacts, Collections.emptyMap(), csarInfo);
                log.debug("************* Finished to create node types from yaml {}", yamlName);
 
                if (nestedVfcJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.TOPOLOGY_TEMPLATE.getElementName())) {
index a28e2ef..f3f0ab5 100644 (file)
@@ -38,7 +38,7 @@ import org.openecomp.sdc.common.impl.ExternalConfiguration;
 import org.openecomp.sdc.common.impl.FSConfigurationSource;
 import org.openecomp.sdc.common.zip.ZipUtils;
 import org.openecomp.sdc.common.zip.exception.ZipException;
-
+import com.datastax.oss.driver.shaded.guava.common.collect.Lists;
 import java.io.File;
 import java.net.URISyntaxException;
 import java.util.Arrays;
@@ -167,4 +167,16 @@ public class CsarInfoTest {
         
         assertTrue(csarInfo.extractNodeTypesInfo().isEmpty());
     }
+    
+    @Test
+    public void testCreateCsarInfoVnfWithNodeTypeInGlobalSub() throws URISyntaxException, ZipException {
+        final CsarInfo csarInfo = createCsarInfo("nodeTypeInGlobalSub.csar", "Definitions/MainServiceTemplate.yaml");
+
+        assertEquals(1, csarInfo.extractNodeTypesInfo().size());
+        final NodeTypeInfo nodeTypeInfo = csarInfo.extractNodeTypesInfo().get("tosca.nodes.l3vpn");
+        assertNotNull(nodeTypeInfo);
+        assertEquals("Definitions/GlobalSubstitutionTypesServiceTemplate.yaml", nodeTypeInfo.getTemplateFileName());
+        assertEquals("tosca.nodes.l3vpn", nodeTypeInfo.getType());        
+        assertEquals(Lists.newArrayList("tosca.nodes.Root"), nodeTypeInfo.getDerivedFrom());        
+    }
 }
diff --git a/catalog-be/src/test/resources/nodeTypeInGlobalSub.csar b/catalog-be/src/test/resources/nodeTypeInGlobalSub.csar
new file mode 100644 (file)
index 0000000..67ada85
Binary files /dev/null and b/catalog-be/src/test/resources/nodeTypeInGlobalSub.csar differ