Load TOSCA package into Tosca model object 01/82101/3
authorshiria <shiri.amichai@amdocs.com>
Sun, 17 Mar 2019 07:41:10 +0000 (09:41 +0200)
committerAvi Gaffa <avi.gaffa@amdocs.com>
Sun, 17 Mar 2019 09:38:46 +0000 (09:38 +0000)
Change-Id: I24360bcd988df48359eb6092f6a80e989e35f026
Issue-ID: SDC-2192
Signed-off-by: shiria <shiri.amichai@amdocs.com>
15 files changed:
common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/datatypes/model/Status.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/InvalidToscaFile.java [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/InvalidToscaMetaFile.java [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/ToscaEntryDefinitionWasNotFound.java [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/ToscaErrorCodes.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/ToscaAnalyzerService.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java
openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImplTest.java
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/importConvertTest.yml [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/invalidTosca.meta [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/invalidToscaFileTest.yml [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageInvalidEntryDef.csar [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageWithMetadata.csar [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageWithoutMetadata.csar [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/validTosca.meta [new file with mode: 0644]

index c0f6d87..222fdd0 100644 (file)
@@ -25,9 +25,13 @@ package org.onap.sdc.tosca.datatypes.model;
 public enum Status {
 
   SUPPORTED("supported"),
+  supported("supported"),
   UNSUPPORTED("unsupported"),
+  unsupported("unsupported"),
   EXPERIMENTAL("experimental"),
-  DEPRECATED("deprecated"),;
+  experimental("experimental"),
+  DEPRECATED("deprecated"),
+  deprecated("deprecated"),;
   private String displayName;
 
   Status(String displayName) {
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/InvalidToscaFile.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/InvalidToscaFile.java
new file mode 100644 (file)
index 0000000..1bea2bb
--- /dev/null
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019, Nordix Foundation. 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.tosca.errors;
+
+import org.openecomp.sdc.common.errors.ErrorCategory;
+import org.openecomp.sdc.common.errors.ErrorCode;
+
+
+public class InvalidToscaFile {
+
+    private static final String INVALID_TOSCA_FILE =
+            "Tosca file '%s' is not following TOSCA spec, can't be parsed. Related error - '%s'";
+    private final ErrorCode.ErrorCodeBuilder builder = new ErrorCode.ErrorCodeBuilder();
+
+    /**
+     * Instantiates a new invalid TOSCA file error builder.
+     *
+     * @param toscaFileName tosca file name
+     * @param parseError    parse error message
+     */
+    public InvalidToscaFile(String toscaFileName, String parseError) {
+        builder.withId(ToscaErrorCodes.INVALID_TOSCA_FILE);
+        builder.withCategory(ErrorCategory.APPLICATION);
+        builder.withMessage(String.format(INVALID_TOSCA_FILE, toscaFileName, parseError));
+    }
+
+    /**
+     * Build error code.
+     *
+     * @return the error code
+     */
+    public ErrorCode build() {
+        return builder.build();
+    }
+}
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/InvalidToscaMetaFile.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/InvalidToscaMetaFile.java
new file mode 100644 (file)
index 0000000..54e22c9
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019, Nordix Foundation. 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.tosca.errors;
+
+import org.openecomp.sdc.common.errors.ErrorCategory;
+import org.openecomp.sdc.common.errors.ErrorCode;
+
+
+public class InvalidToscaMetaFile {
+
+    private static final String INVALID_TOSCA_META_FILE = "Missing data - TOSCA.meta file must include '%s' data.";
+    private final ErrorCode.ErrorCodeBuilder builder = new ErrorCode.ErrorCodeBuilder();
+
+    /**
+     * Instantiates a new invalid TOSCA meta file error builder.
+     *
+     * @param missingData name of the missing data
+     */
+    public InvalidToscaMetaFile(String missingData) {
+        builder.withId(ToscaErrorCodes.INVALID_TOSCA_META_FILE);
+        builder.withCategory(ErrorCategory.APPLICATION);
+        builder.withMessage(String.format(INVALID_TOSCA_META_FILE, missingData));
+    }
+
+    /**
+     * Build error code.
+     *
+     * @return the error code
+     */
+    public ErrorCode build() {
+        return builder.build();
+    }
+}
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/ToscaEntryDefinitionWasNotFound.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/ToscaEntryDefinitionWasNotFound.java
new file mode 100644 (file)
index 0000000..bb34d3a
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2019, Nordix Foundation. 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.tosca.errors;
+
+import org.openecomp.sdc.common.errors.ErrorCategory;
+import org.openecomp.sdc.common.errors.ErrorCode;
+
+
+public class ToscaEntryDefinitionWasNotFound {
+
+    private static final String ENTRY_DEFINITION_WAS_NOT_FOUND = "TOSCA Entry Definition was not found";
+    private final ErrorCode.ErrorCodeBuilder builder = new ErrorCode.ErrorCodeBuilder();
+
+    /**
+     * Instantiates a new invalid TOSCA entry definition was not found error builder.
+     */
+    public ToscaEntryDefinitionWasNotFound() {
+        builder.withId(ToscaErrorCodes.INVALID_TOSCA_ENTRY_DEF_WAS_NOT_FOUND);
+        builder.withCategory(ErrorCategory.APPLICATION);
+        builder.withMessage(ENTRY_DEFINITION_WAS_NOT_FOUND);
+    }
+
+    /**
+     * Build error code.
+     *
+     * @return the error code
+     */
+    public ErrorCode build() {
+        return builder.build();
+    }
+}
index 2e449e4..aec4091 100644 (file)
@@ -2,14 +2,14 @@
  * ============LICENSE_START=======================================================
  * SDC
  * ================================================================================
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019, Nordix Foundation. 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.
@@ -22,6 +22,10 @@ package org.openecomp.sdc.tosca.errors;
 
 class ToscaErrorCodes {
 
+  private ToscaErrorCodes() {
+    throw new IllegalStateException("Utility class");
+  }
+
   static final String INVALID_SUBSTITUTE_NODE_TEMPLATE = "INVALID_SUBSTITUTE_NODE_TEMPLATE";
   static final String INVALID_SUBSTITUTION_SERVICE_TEMPLATE =
       "INVALID_SUBSTITUTION_SERVICE_TEMPLATE";
@@ -32,6 +36,9 @@ class ToscaErrorCodes {
       "TOSCA_INVALID_SUBSTITUTE_NODE_TEMPLATE";
   static final String TOSCA_INVALID_ADD_ACTION_NULL_ENTITY = "TOSCA_INVALID_ADD_ACTION_NULL_ENTITY";
   static final String INVALID_INTERFACE_VALUE = "INVALID_INTERFACE_VALUE";
+  static final String INVALID_TOSCA_FILE = "INVALID_TOSCA_FILE";
+  static final String INVALID_TOSCA_META_FILE = "INVALID_TOSCA_META_FILE";
+  static final String INVALID_TOSCA_ENTRY_DEF_WAS_NOT_FOUND = "INVALID_TOSCA_ENTRY_DEF_WAS_NOT_FOUND";
 
 
 }
index 7e2c463..b21d847 100644 (file)
@@ -85,4 +85,6 @@ public interface ToscaAnalyzerService {
 
     List<Map<String, RequirementDefinition>> calculateExposedRequirements(List<Map<String, RequirementDefinition>> nodeTypeRequirementsDefinitionList,
                                                                                  Map<String, RequirementAssignment> nodeTemplateRequirementsAssignment);
+
+    ToscaServiceModel loadToscaCsarPackage(byte[] toscaCsarPackage);
 }
index b254671..1f0b728 100644 (file)
 
 package org.openecomp.sdc.tosca.services.impl;
 
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -27,6 +31,8 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -46,13 +52,19 @@ import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
 import org.onap.sdc.tosca.datatypes.model.RequirementDefinition;
 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
 import org.onap.sdc.tosca.services.ToscaExtensionYamlUtil;
+import org.onap.sdc.tosca.services.YamlUtil;
 import org.openecomp.core.utilities.CommonMethods;
+import org.openecomp.core.utilities.file.FileContentHandler;
+import org.openecomp.core.utilities.file.FileUtils;
 import org.openecomp.sdc.common.errors.CoreException;
 import org.openecomp.sdc.common.errors.SdcRuntimeException;
 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
 import org.openecomp.sdc.tosca.datatypes.ToscaFlatData;
 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
+import org.openecomp.sdc.tosca.errors.InvalidToscaFile;
+import org.openecomp.sdc.tosca.errors.InvalidToscaMetaFile;
 import org.openecomp.sdc.tosca.errors.ToscaElementTypeNotFoundErrorBuilder;
+import org.openecomp.sdc.tosca.errors.ToscaEntryDefinitionWasNotFound;
 import org.openecomp.sdc.tosca.errors.ToscaFileNotFoundErrorBuilder;
 import org.openecomp.sdc.tosca.errors.ToscaInvalidEntryNotFoundErrorBuilder;
 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder;
@@ -72,6 +84,9 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
     private static final String GET_CAPABILITY_TYPE_METHOD_NAME = "getCapability_types";
     private static final String TOSCA_DOT = "tosca.";
     private static final String DOT_ROOT = ".Root";
+    private static final String IMPORTS = "imports";
+    private static final String TOSCA_META_FILE = "TOSCA-Metadata/TOSCA.meta";
+    private static final String ENTRY_DEFINITIONS = "Entry-Definitions";
 
     @Override
     public List<Map<String, RequirementDefinition>> calculateExposedRequirements(
@@ -99,6 +114,151 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
         return nodeTypeRequirementsDefinitionList;
     }
 
+    @Override
+    public ToscaServiceModel loadToscaCsarPackage(byte[] toscaCsarPackage) {
+        ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
+        ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
+        FileContentHandler artifactFiles = new FileContentHandler();
+
+        try (ZipInputStream inputZipStream = new ZipInputStream(new ByteArrayInputStream(toscaCsarPackage))) {
+            ZipEntry zipEntry;
+            while ((zipEntry = inputZipStream.getNextEntry()) != null) {
+                byte[] fileContent = FileUtils.toByteArray(inputZipStream);
+                String currentEntryName = zipEntry.getName();
+                if (!isFile(currentEntryName)) {
+                    continue;
+                }
+                if (isYamlFile(currentEntryName) && isToscaYamlFile(fileContent)) {
+                    loadToscaYamlFile(toscaServiceModel, toscaExtensionYamlUtil, fileContent, currentEntryName);
+                } else if (currentEntryName.equals(TOSCA_META_FILE)) {
+                    loadToscaMetaFile(toscaServiceModel, fileContent);
+                } else {
+                    artifactFiles.addFile(currentEntryName, fileContent);
+                }
+            }
+            toscaServiceModel.setArtifactFiles(artifactFiles);
+            if (StringUtils.isEmpty(toscaServiceModel.getEntryDefinitionServiceTemplate())) {
+                handleToscaCsarWithoutToscaMetadata(toscaServiceModel);
+            }
+
+        } catch (IOException exc) {
+            throw new SdcRuntimeException(exc.getMessage(), exc);
+        }
+        return toscaServiceModel;
+    }
+
+    private void handleToscaCsarWithoutToscaMetadata(ToscaServiceModel toscaServiceModel) {
+        for (String fileName : toscaServiceModel.getServiceTemplates().keySet()) {
+            if (!fileName.contains("/")) {
+                if (StringUtils.isNotEmpty(toscaServiceModel.getEntryDefinitionServiceTemplate())) {
+                    throw new CoreException(new ToscaEntryDefinitionWasNotFound().build());
+                }
+                toscaServiceModel.setEntryDefinitionServiceTemplate(fileName);
+            }
+        }
+    }
+
+    void loadToscaMetaFile(ToscaServiceModel toscaServiceModel, byte[] toscaMetaFileContent) {
+        String toscaMeta = new String(toscaMetaFileContent);
+        Map toscaMetaMap = new YamlUtil().yamlToObject(toscaMeta, Map.class);
+        if (Objects.isNull(toscaMetaMap.get(ENTRY_DEFINITIONS))) {
+            throw new CoreException(new InvalidToscaMetaFile(ENTRY_DEFINITIONS).build());
+        }
+        String entryDefinition = (String) toscaMetaMap.get(ENTRY_DEFINITIONS);
+        toscaServiceModel.setEntryDefinitionServiceTemplate(entryDefinition);
+    }
+
+    void loadToscaYamlFile(ToscaServiceModel toscaServiceModel, ToscaExtensionYamlUtil toscaExtensionYamlUtil,
+            byte[] fileContent, String fileFullName) {
+        try {
+            String serviceTemplateYamlString = convertServiceTemplateImport(toscaExtensionYamlUtil, fileContent);
+            ServiceTemplate serviceTemplate =
+                    toscaExtensionYamlUtil.yamlToObject(serviceTemplateYamlString, ServiceTemplate.class);
+            toscaServiceModel.addServiceTemplate(fileFullName, serviceTemplate);
+
+        } catch (Exception exc) {
+            throw new CoreException(new InvalidToscaFile(fileFullName, exc.getMessage()).build());
+        }
+    }
+
+    String convertServiceTemplateImport(ToscaExtensionYamlUtil toscaExtensionYamlUtil, byte[] fileContent) {
+
+        Map serviceTemplateMap = toscaExtensionYamlUtil.yamlToObject(new String(fileContent), Map.class);
+        convertToscaImports(serviceTemplateMap, toscaExtensionYamlUtil);
+        return toscaExtensionYamlUtil.objectToYaml(serviceTemplateMap);
+    }
+
+    private void convertToscaImports(Map serviceTemplateMap, ToscaExtensionYamlUtil toscaExtensionYamlUtil) {
+        List<Map<String, Import>> convertedImport = new ArrayList<>();
+        Object importObj = serviceTemplateMap.get(IMPORTS);
+        if (!(importObj instanceof List)) {
+            throw new SdcRuntimeException("Illegal Statement");
+        }
+        List<Object> imports = (List) importObj;
+        if (CollectionUtils.isEmpty(imports)) {
+            return;
+        }
+        for (Object importEntry : imports) {
+            convertToscaImportEntry(convertedImport, importEntry, toscaExtensionYamlUtil);
+        }
+        serviceTemplateMap.remove(IMPORTS);
+        serviceTemplateMap.put(IMPORTS, convertedImport);
+    }
+
+    private void convertToscaImportEntry(List<Map<String, Import>> convertedImport, Object importEntry,
+            ToscaExtensionYamlUtil toscaExtensionYamlUtil) {
+        if (importEntry instanceof String) {
+            convertImportShortNotation(convertedImport, importEntry.toString());
+        } else if (importEntry instanceof Map) {
+            if (((Map) importEntry).containsKey("file")) {
+                Import importObject = toscaExtensionYamlUtil
+                                              .yamlToObject(toscaExtensionYamlUtil.objectToYaml(importEntry),
+                                                      Import.class);
+                convertImportExtendNotation(convertedImport, importObject);
+            } else {
+                convertedImport.add((Map<String, Import>) importEntry);
+            }
+        }
+    }
+
+    private void convertImportExtendNotation(List<Map<String, Import>> convertedImport, Import importEntry) {
+        Map<String, Import> importMap = new HashMap();
+        importMap.put(FileUtils.getFileWithoutExtention(getFileName(importEntry.getFile()).replaceAll("/", "_")),
+                importEntry);
+        convertedImport.add(importMap);
+    }
+
+    private void convertImportShortNotation(List<Map<String, Import>> convertImport, String fileFullName) {
+        Import importObject = new Import();
+        importObject.setFile(fileFullName);
+        Map<String, Import> importMap = new HashMap();
+        importMap
+                .put((FileUtils.getFileWithoutExtention(getFileName(fileFullName)).replaceAll("/", "_")), importObject);
+        convertImport.add(importMap);
+    }
+
+    private static String getFileName(String relativeFileName) {
+        if (relativeFileName.contains("../")) {
+            return relativeFileName.replace("../", "");
+        } else {
+            return relativeFileName;
+        }
+
+    }
+
+    private static boolean isFile(String currentEntryName) {
+        return !(currentEntryName.endsWith("\\") || currentEntryName.endsWith("/"));
+    }
+
+    private boolean isYamlFile(String fileName) {
+        return fileName.endsWith("yaml") || fileName.endsWith("yml");
+    }
+
+    private boolean isToscaYamlFile(byte[] fileContent) {
+        Map fileMap = new YamlUtil().yamlToObject(new String(fileContent), Map.class);
+        return fileMap.containsKey("tosca_definitions_version");
+    }
+
     private void updateMinMaxOccurencesForNodeTypeRequirement(Map.Entry<String, RequirementAssignment> entry,
             Map<String, RequirementDefinition> nodeTypeRequirementsMap) {
         Object max = nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences() != null
@@ -209,7 +369,7 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
         if (Objects.nonNull(serviceTemplate.getTopology_template()) && MapUtils.isNotEmpty(
                 serviceTemplate.getTopology_template().getNode_templates())) {
             for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : serviceTemplate.getTopology_template()
-                                                                             .getNode_templates().entrySet()) {
+                                                                                    .getNode_templates().entrySet()) {
                 if (isTypeOf(nodeTemplateEntry.getValue(), nodeType, serviceTemplate, toscaServiceModel)) {
                     nodeTemplates.put(nodeTemplateEntry.getKey(), nodeTemplateEntry.getValue());
                 }
@@ -222,8 +382,11 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
     @Override
     public Optional<NodeType> fetchNodeType(String nodeTypeKey, Collection<ServiceTemplate> serviceTemplates) {
         Optional<Map<String, NodeType>> nodeTypeMap = serviceTemplates.stream().map(ServiceTemplate::getNode_types)
-                                                              .filter(nodeTypes -> Objects.nonNull(nodeTypes)
-                                                              && nodeTypes.containsKey(nodeTypeKey)).findFirst();
+                                                                      .filter(nodeTypes -> Objects.nonNull(nodeTypes)
+                                                                                                   && nodeTypes
+                                                                                                              .containsKey(
+                                                                                                                      nodeTypeKey))
+                                                                      .findFirst();
         return nodeTypeMap.map(stringNodeTypeMap -> stringNodeTypeMap.get(nodeTypeKey));
     }
 
@@ -285,9 +448,9 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
             return Optional.empty();
         }
 
-        if (substitutableNodeTemplate.getProperties() != null
-              && substitutableNodeTemplate.getProperties().get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME)
-                 != null) {
+        if (substitutableNodeTemplate.getProperties() != null &&
+                    substitutableNodeTemplate.getProperties().get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME)
+                            != null) {
             Object serviceTemplateFilter =
                     substitutableNodeTemplate.getProperties().get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
             if (serviceTemplateFilter instanceof Map) {
@@ -389,14 +552,14 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
     }
 
     private boolean isSameRelationship(RequirementAssignment requirementAssignment, String relationship) {
-        return relationship != null
-                       && (requirementAssignment.getRelationship() == null
-                                   || !requirementAssignment.getRelationship().equals(relationship));
+        return relationship != null && (requirementAssignment.getRelationship() == null || !requirementAssignment
+                                                                                                    .getRelationship()
+                                                                                                    .equals(relationship));
     }
 
     private boolean isSameRequirement(RequirementAssignment requirementAssignment, String node) {
         return node != null && (requirementAssignment.getNode() == null || !requirementAssignment.getNode()
-                                                                                    .equals(node));
+                                                                                                 .equals(node));
     }
 
     private boolean isSameCapability(RequirementAssignment requirementAssignment, String capability) {
@@ -486,8 +649,11 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
                                               Import.class);
             handleImportWithNoFileEntry(anImport);
             String importFile = anImport.getFile();
-            ServiceTemplate template = toscaServiceModel.getServiceTemplates().get(fetchFileNameForImport(importFile,
-                    serviceTemplate.getMetadata() == null ? null : serviceTemplate.getMetadata().get("filename")));
+            ServiceTemplate template = toscaServiceModel.getServiceTemplates()
+                                                        .get(fetchFullFileNameForImport(importFile,
+                                                                serviceTemplate.getMetadata() == null ? null :
+                                                                        serviceTemplate.getMetadata().get("filename"),
+                                                                serviceTemplate, toscaServiceModel));
             if (Objects.isNull(template) || createdFilesScanned
                                                     .contains(ToscaUtil.getServiceTemplateFileName(template))) {
                 continue;
@@ -573,8 +739,9 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
             Import importServiceTemplate = toscaExtensionYamlUtil
                                                    .yamlToObject(toscaExtensionYamlUtil.objectToYaml(importObject),
                                                            Import.class);
-            String fileName = fetchFileNameForImport(importServiceTemplate.getFile(),
-                    serviceTemplate.getMetadata() == null ? null : serviceTemplate.getMetadata().get("filename"));
+            String fileName = fetchFullFileNameForImport(importServiceTemplate.getFile(),
+                    serviceTemplate.getMetadata() == null ? null : serviceTemplate.getMetadata().get("filename"),
+                    serviceTemplate, toscaModel);
             if (filesScanned.contains(fileName)) {
                 return false;
             } else {
@@ -590,16 +757,27 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
         return found;
     }
 
-    private String fetchFileNameForImport(String importServiceTemplateFile, String currentMetadatafileName) {
-        if (importServiceTemplateFile.contains("../")) {
-            return importServiceTemplateFile.replace("../", "");
-        } else if (currentMetadatafileName != null && currentMetadatafileName.indexOf('/') != -1) {
-            return currentMetadatafileName.substring(0, currentMetadatafileName.indexOf('/')) + "/"
-                           + importServiceTemplateFile;
-        } else {
-            return importServiceTemplateFile;
+    String fetchFullFileNameForImport(String importServiceTemplateFile, String currentMetadatafileName,
+            ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
+        Optional<Map.Entry<String, ServiceTemplate>> serviceTemplateEntry =
+                toscaServiceModel.getServiceTemplates().entrySet().stream()
+                                 .filter(entry -> entry.getValue().equals(serviceTemplate)).findFirst();
+        if (!serviceTemplateEntry.isPresent()) {
+            if (importServiceTemplateFile.contains("../")) {
+                return importServiceTemplateFile.replace("../", "");
+            } else if (currentMetadatafileName != null && currentMetadatafileName.indexOf('/') != -1) {
+                return currentMetadatafileName.substring(0, currentMetadatafileName.indexOf('/')) + "/"
+                               + importServiceTemplateFile;
+            } else {
+                return importServiceTemplateFile;
+            }
         }
 
+        Path currentPath = Paths.get(serviceTemplateEntry.get().getKey()).getParent();
+        if (currentPath == null) {
+            currentPath = Paths.get("");
+        }
+        return currentPath.resolve(importServiceTemplateFile).normalize().toString().replaceAll("\\\\", "/");
     }
 
     private boolean enrichEntityFromCurrentServiceTemplate(ToscaElementTypes elementType, String typeId,
@@ -696,7 +874,7 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
             int rootScanStartInx) {
         String derivedFrom;
         if (serviceTemplate.getCapability_types() != null && serviceTemplate.getCapability_types()
-                                                                     .containsKey(typeId)) {
+                                                                            .containsKey(typeId)) {
 
             filesScanned.clear();
             flatData.addInheritanceHierarchyType(typeId);
@@ -750,10 +928,9 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
         for (Map.Entry<String, Object> sourceInterfaceDefEntry : sourceNodeType.getInterfaces().entrySet()) {
             String interfaceName = sourceInterfaceDefEntry.getKey();
             if (!MapUtils.isEmpty(targetNodeType.getInterfaces()) && targetNodeType.getInterfaces()
-                                                                             .containsKey(interfaceName)) {
-                combineInterfaces.put(interfaceName,
-                        combineInterfaceDefinition(sourceInterfaceDefEntry.getValue(),
-                                targetNodeType.getInterfaces().get(interfaceName)));
+                                                                                   .containsKey(interfaceName)) {
+                combineInterfaces.put(interfaceName, combineInterfaceDefinition(sourceInterfaceDefEntry.getValue(),
+                        targetNodeType.getInterfaces().get(interfaceName)));
             } else {
                 combineInterfaces.put(sourceInterfaceDefEntry.getKey(), sourceInterfaceDefEntry.getValue());
             }
@@ -836,13 +1013,13 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
 
 
     /*
-   * Create node type according to the input substitution service template, while the substitution
-   * service template can be mappted to this node type, for substitution mapping.
-   *
-   * @param substitutionServiceTemplate  substitution serivce template
-   * @param nodeTypeDerivedFromValue derived from value for the created node type
-   * @return the node type
-   */
+     * Create node type according to the input substitution service template, while the substitution
+     * service template can be mappted to this node type, for substitution mapping.
+     *
+     * @param substitutionServiceTemplate  substitution serivce template
+     * @param nodeTypeDerivedFromValue derived from value for the created node type
+     * @return the node type
+     */
     @Override
     public NodeType createInitSubstitutionNodeType(ServiceTemplate substitutionServiceTemplate,
             String nodeTypeDerivedFromValue) {
@@ -893,7 +1070,7 @@ public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
 
 
     private Map<String, AttributeDefinition> manageSubstitutionNodeTypeAttributes(
-                                                                         ServiceTemplate substitutionServiceTemplate) {
+            ServiceTemplate substitutionServiceTemplate) {
         Map<String, AttributeDefinition> substitutionNodeTypeAttributes = new HashMap<>();
         Map<String, ParameterDefinition> attributes = substitutionServiceTemplate.getTopology_template().getOutputs();
         if (attributes == null) {
index 2814f01..4962f24 100644 (file)
@@ -30,7 +30,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-
+import org.apache.commons.io.IOUtils;
+import org.hamcrest.core.StringContains;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -61,6 +62,7 @@ import org.onap.sdc.tosca.datatypes.model.Status;
 import org.onap.sdc.tosca.datatypes.model.SubstitutionMapping;
 import org.onap.sdc.tosca.datatypes.model.TopologyTemplate;
 import org.onap.sdc.tosca.services.ToscaExtensionYamlUtil;
+import org.onap.sdc.tosca.services.YamlUtil;
 import org.openecomp.sdc.common.errors.CoreException;
 import org.openecomp.sdc.common.errors.SdcRuntimeException;
 import org.openecomp.sdc.tosca.TestUtil;
@@ -1104,5 +1106,166 @@ public class ToscaAnalyzerServiceImplTest {
     public void testGetFlatEntityThrowsExceptionIncorrectSwitchProvided() {
         toscaAnalyzerService.getFlatEntity(ToscaElementTypes.RELATIONSHIP_TYPE, null, null, null);
     }
+
+    @Test
+    public void getFullPathFromRelativePathBackwards(){
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        String importFile = "../ImportedServiceTemplate";
+        ServiceTemplate mainServiceTemplate = new ServiceTemplate();
+        ServiceTemplate importedServiceTemplate = new ServiceTemplate();
+        ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
+        toscaServiceModel.addServiceTemplate("Definitions/service/MainServiceTemplate", mainServiceTemplate);
+        toscaServiceModel.addServiceTemplate("Definitions/ImportedServiceTemplate", importedServiceTemplate);
+
+        String fileNameForImport = toscaAnalyzerServiceImpl
+                           .fetchFullFileNameForImport(importFile, null, mainServiceTemplate, toscaServiceModel);
+        assertEquals("Definitions/ImportedServiceTemplate", fileNameForImport);
+    }
+
+    @Test
+    public void getFullPathFromRelativePathForwards(){
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        String importFile = "services/ImportedServiceTemplate";
+        ServiceTemplate mainServiceTemplate = new ServiceTemplate();
+        ServiceTemplate importedServiceTemplate = new ServiceTemplate();
+        ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
+        toscaServiceModel.addServiceTemplate("Definitions/MainServiceTemplate", mainServiceTemplate);
+        toscaServiceModel.addServiceTemplate("Definitions/services/ImportedServiceTemplate", importedServiceTemplate);
+
+        String fileNameForImport = toscaAnalyzerServiceImpl
+                                           .fetchFullFileNameForImport(importFile, null, mainServiceTemplate, toscaServiceModel);
+        assertEquals("Definitions/services/ImportedServiceTemplate", fileNameForImport);
+    }
+
+    @Test
+    public void getFullPathFromRelativePathMix(){
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        String importFile = "../types/global/ImportedServiceTemplate";
+        ServiceTemplate mainServiceTemplate = new ServiceTemplate();
+        ServiceTemplate importedServiceTemplate = new ServiceTemplate();
+        ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
+        toscaServiceModel.addServiceTemplate("Definitions/services/MainServiceTemplate", mainServiceTemplate);
+        toscaServiceModel.addServiceTemplate("Definitions/types/global/ImportedServiceTemplate", importedServiceTemplate);
+
+        String fileNameForImport = toscaAnalyzerServiceImpl
+                                           .fetchFullFileNameForImport(importFile, null, mainServiceTemplate, toscaServiceModel);
+        assertEquals("Definitions/types/global/ImportedServiceTemplate", fileNameForImport);
+    }
+
+    @Test
+    public void testConvertToscaImport() throws Exception {
+        String inputResourceName = "/mock/analyzerService/importConvertTest.yml";
+        byte[] uploadedFileData = IOUtils.toByteArray(this.getClass().getResource(inputResourceName));
+
+        ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        String convertServiceTemplateImport =
+                toscaAnalyzerServiceImpl.convertServiceTemplateImport(toscaExtensionYamlUtil, uploadedFileData);
+
+        Assert.assertNotNull(convertServiceTemplateImport);
+        ServiceTemplate serviceTemplate =
+                new YamlUtil().yamlToObject(convertServiceTemplateImport, ServiceTemplate.class);
+        Assert.assertNotNull(serviceTemplate.getImports().get(0).get("data"));
+        Assert.assertNotNull(serviceTemplate.getImports().get(1).get("artifacts"));
+        Assert.assertNotNull(serviceTemplate.getImports().get(2).get("capabilities"));
+        Assert.assertNotNull(serviceTemplate.getImports().get(3).get("api_interfaces"));
+        Assert.assertNotNull(serviceTemplate.getImports().get(4).get("api_util_relationships"));
+        Assert.assertNotNull(serviceTemplate.getImports().get(5).get("common"));
+        Assert.assertNotNull(serviceTemplate.getImports().get(6).get("api_util"));
+        Assert.assertNotNull(serviceTemplate.getImports().get(7).get("relationshipsExt"));
+    }
+
+    @Test
+    public void loadValidToscaYamlFileTest() throws Exception {
+        String inputResourceName = "/mock/analyzerService/ServiceTemplateInterfaceInheritanceTest.yaml";
+        byte[] uploadedFileData = IOUtils.toByteArray(this.getClass().getResource(inputResourceName));
+
+        ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
+        String fileFullName = "Definition/service.yaml";
+        toscaAnalyzerServiceImpl
+                .loadToscaYamlFile(toscaServiceModel, toscaExtensionYamlUtil, uploadedFileData, fileFullName);
+        Assert.assertNotNull(toscaServiceModel.getServiceTemplate(fileFullName));
+    }
+
+    @Test
+    public void loadInvalidToscaYamlFileTest() throws Exception {
+        thrown.expect(CoreException.class);
+        thrown.expectMessage(StringContains.containsString(
+                "Tosca file 'Definition/service.yaml' is not following TOSCA spec, can't be parsed. Related error - "));
+        String inputResourceName = "/mock/analyzerService/invalidToscaFileTest.yml";
+        byte[] uploadedFileData = IOUtils.toByteArray(this.getClass().getResource(inputResourceName));
+
+        ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
+        String fileFullName = "Definition/service.yaml";
+        toscaAnalyzerServiceImpl
+                .loadToscaYamlFile(toscaServiceModel, toscaExtensionYamlUtil, uploadedFileData, fileFullName);
+    }
+
+    @Test
+    public void loadValidToscaMetadataFileTest() throws Exception {
+        String inputResourceName = "/mock/analyzerService/validTosca.meta";
+        byte[] uploadedFileData = IOUtils.toByteArray(this.getClass().getResource(inputResourceName));
+
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
+        toscaAnalyzerServiceImpl
+                .loadToscaMetaFile(toscaServiceModel, uploadedFileData);
+        Assert.assertEquals("Definitions/service-Service2-template.yml",
+                toscaServiceModel.getEntryDefinitionServiceTemplate());
+    }
+
+    @Test
+    public void loadInvalidToscaMetadataFileTest() throws Exception {
+        thrown.expect(CoreException.class);
+        thrown.expectMessage("Missing data - TOSCA.meta file must include 'Entry-Definitions' data.");
+        String inputResourceName = "/mock/analyzerService/invalidTosca.meta";
+        byte[] uploadedFileData = IOUtils.toByteArray(this.getClass().getResource(inputResourceName));
+
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
+        toscaAnalyzerServiceImpl
+                .loadToscaMetaFile(toscaServiceModel, uploadedFileData);
+    }
+
+    @Test
+    public void loadToscaCsarPackageWithMetadataTest() throws Exception {
+        String inputResourceName = "/mock/analyzerService/toscaPackageWithMetadata.csar";
+        byte[] uploadedFileData = IOUtils.toByteArray(this.getClass().getResource(inputResourceName));
+        //InputStream toscaPackage = new ByteArrayInputStream(uploadedFileData);
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        ToscaServiceModel toscaServiceModel = toscaAnalyzerServiceImpl.loadToscaCsarPackage(uploadedFileData);
+        assertNotNull(toscaServiceModel);
+        assertEquals("Definitions/service.yaml", toscaServiceModel.getEntryDefinitionServiceTemplate());
+        assertEquals(10, toscaServiceModel.getServiceTemplates().size());
+        assertEquals(1, toscaServiceModel.getArtifactFiles().getFiles().size());
+    }
+
+    @Test
+    public void loadToscaCsarPackageWithoutMetadataTest() throws Exception {
+        String inputResourceName = "/mock/analyzerService/toscaPackageWithoutMetadata.csar";
+        byte[] uploadedFileData = IOUtils.toByteArray(this.getClass().getResource(inputResourceName));
+        //InputStream toscaPackage = new ByteArrayInputStream(uploadedFileData);
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        ToscaServiceModel toscaServiceModel = toscaAnalyzerServiceImpl.loadToscaCsarPackage(uploadedFileData);
+        assertNotNull(toscaServiceModel);
+        assertEquals("service.yaml", toscaServiceModel.getEntryDefinitionServiceTemplate());
+        assertEquals(10, toscaServiceModel.getServiceTemplates().size());
+        assertEquals(1, toscaServiceModel.getArtifactFiles().getFiles().size());
+    }
+
+    @Test
+    public void loadInvalidToscaCsarPackageWithoutEntryDefTest() throws Exception {
+        thrown.expect(CoreException.class);
+        thrown.expectMessage("TOSCA Entry Definition was not found");
+        String inputResourceName = "/mock/analyzerService/toscaPackageInvalidEntryDef.csar";
+        byte[] uploadedFileData = IOUtils.toByteArray(this.getClass().getResource(inputResourceName));
+        //InputStream toscaPackage = new ByteArrayInputStream(uploadedFileData);
+        ToscaAnalyzerServiceImpl toscaAnalyzerServiceImpl = new ToscaAnalyzerServiceImpl();
+        toscaAnalyzerServiceImpl.loadToscaCsarPackage(uploadedFileData);
+    }
 }
 
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/importConvertTest.yml b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/importConvertTest.yml
new file mode 100644 (file)
index 0000000..08ddc3c
--- /dev/null
@@ -0,0 +1,14 @@
+tosca_definitions_version: tosca_simple_yaml_1_1
+imports:
+- data.yml
+- artifacts.yml
+- capabilities.yml
+- ../../api/interfaces.yml
+- api/util/relationships.yml
+- common:
+    file: api/common.yaml
+- file: api/util.yaml
+- relationshipsExt.yml
+node_types:
+  tosca.nodes.Root:
+    description: The TOSCA Node Type all other TOSCA base Node Types derive from
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/invalidTosca.meta b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/invalidTosca.meta
new file mode 100644 (file)
index 0000000..c9be3f4
--- /dev/null
@@ -0,0 +1,6 @@
+TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: Carlos Santana
+
+Name: csar.meta
+Content-Type: text/plain
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/invalidToscaFileTest.yml b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/invalidToscaFileTest.yml
new file mode 100644 (file)
index 0000000..f572a3a
--- /dev/null
@@ -0,0 +1,8 @@
+tosca_definitions_version: tosca_simple_yaml_1_1
+imports:
+- data.yml
+- artifacts.yml
+node_types:
+  tosca.nodes.Root:
+    description: The TOSCA Node Type all other TOSCA base Node Types derive from
+    invalidFiled: invalid filed
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageInvalidEntryDef.csar b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageInvalidEntryDef.csar
new file mode 100644 (file)
index 0000000..02c2caf
Binary files /dev/null and b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageInvalidEntryDef.csar differ
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageWithMetadata.csar b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageWithMetadata.csar
new file mode 100644 (file)
index 0000000..e844509
Binary files /dev/null and b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageWithMetadata.csar differ
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageWithoutMetadata.csar b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageWithoutMetadata.csar
new file mode 100644 (file)
index 0000000..0256cc9
Binary files /dev/null and b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageWithoutMetadata.csar differ
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/validTosca.meta b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/validTosca.meta
new file mode 100644 (file)
index 0000000..8eba903
--- /dev/null
@@ -0,0 +1,7 @@
+TOSCA-Meta-File-Version: 1.0
+CSAR-Version: 1.1
+Created-By: Carlos Santana
+Entry-Definitions: Definitions/service-Service2-template.yml
+
+Name: csar.meta
+Content-Type: text/plain
\ No newline at end of file