From 532b6da80ebd6977aa27300ab3cbe7b21d88609a Mon Sep 17 00:00:00 2001 From: shiria Date: Sun, 17 Mar 2019 09:41:10 +0200 Subject: Load TOSCA package into Tosca model object Change-Id: I24360bcd988df48359eb6092f6a80e989e35f026 Issue-ID: SDC-2192 Signed-off-by: shiria --- .../sdc/tosca/errors/InvalidToscaFile.java | 53 +++++ .../sdc/tosca/errors/InvalidToscaMetaFile.java | 51 +++++ .../errors/ToscaEntryDefinitionWasNotFound.java | 49 ++++ .../sdc/tosca/errors/ToscaErrorCodes.java | 13 +- .../sdc/tosca/services/ToscaAnalyzerService.java | 2 + .../services/impl/ToscaAnalyzerServiceImpl.java | 247 ++++++++++++++++++--- .../impl/ToscaAnalyzerServiceImplTest.java | 165 +++++++++++++- .../mock/analyzerService/importConvertTest.yml | 14 ++ .../mock/analyzerService/invalidTosca.meta | 6 + .../mock/analyzerService/invalidToscaFileTest.yml | 8 + .../toscaPackageInvalidEntryDef.csar | Bin 0 -> 13114 bytes .../analyzerService/toscaPackageWithMetadata.csar | Bin 0 -> 13070 bytes .../toscaPackageWithoutMetadata.csar | Bin 0 -> 12828 bytes .../resources/mock/analyzerService/validTosca.meta | 7 + 14 files changed, 576 insertions(+), 39 deletions(-) create mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/InvalidToscaFile.java create mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/InvalidToscaMetaFile.java create mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/ToscaEntryDefinitionWasNotFound.java create mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/importConvertTest.yml create mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/invalidTosca.meta create mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/invalidToscaFileTest.yml create mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageInvalidEntryDef.csar create mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageWithMetadata.csar create mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/toscaPackageWithoutMetadata.csar create mode 100644 openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/validTosca.meta (limited to 'openecomp-be/lib') 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 index 0000000000..1bea2bbce6 --- /dev/null +++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/InvalidToscaFile.java @@ -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 index 0000000000..54e22c97ae --- /dev/null +++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/InvalidToscaMetaFile.java @@ -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 index 0000000000..bb34d3a485 --- /dev/null +++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/ToscaEntryDefinitionWasNotFound.java @@ -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(); + } +} diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/ToscaErrorCodes.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/ToscaErrorCodes.java index 2e449e4acc..aec4091e68 100644 --- a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/ToscaErrorCodes.java +++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/errors/ToscaErrorCodes.java @@ -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"; } diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/ToscaAnalyzerService.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/ToscaAnalyzerService.java index 7e2c463e29..b21d847a07 100644 --- a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/ToscaAnalyzerService.java +++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/ToscaAnalyzerService.java @@ -85,4 +85,6 @@ public interface ToscaAnalyzerService { List> calculateExposedRequirements(List> nodeTypeRequirementsDefinitionList, Map nodeTemplateRequirementsAssignment); + + ToscaServiceModel loadToscaCsarPackage(byte[] toscaCsarPackage); } diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java index b254671dc7..1f0b728c53 100644 --- a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java +++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java @@ -16,7 +16,11 @@ 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> 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> convertedImport = new ArrayList<>(); + Object importObj = serviceTemplateMap.get(IMPORTS); + if (!(importObj instanceof List)) { + throw new SdcRuntimeException("Illegal Statement"); + } + List 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> 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) importEntry); + } + } + } + + private void convertImportExtendNotation(List> convertedImport, Import importEntry) { + Map importMap = new HashMap(); + importMap.put(FileUtils.getFileWithoutExtention(getFileName(importEntry.getFile()).replaceAll("/", "_")), + importEntry); + convertedImport.add(importMap); + } + + private void convertImportShortNotation(List> convertImport, String fileFullName) { + Import importObject = new Import(); + importObject.setFile(fileFullName); + Map 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 entry, Map 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 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 fetchNodeType(String nodeTypeKey, Collection serviceTemplates) { Optional> 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> 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 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 manageSubstitutionNodeTypeAttributes( - ServiceTemplate substitutionServiceTemplate) { + ServiceTemplate substitutionServiceTemplate) { Map substitutionNodeTypeAttributes = new HashMap<>(); Map attributes = substitutionServiceTemplate.getTopology_template().getOutputs(); if (attributes == null) { diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImplTest.java b/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImplTest.java index 2814f0143b..4962f243ca 100644 --- a/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImplTest.java +++ b/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImplTest.java @@ -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 index 0000000000..08ddc3c206 --- /dev/null +++ b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/importConvertTest.yml @@ -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 index 0000000000..c9be3f4d2e --- /dev/null +++ b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/invalidTosca.meta @@ -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 index 0000000000..f572a3a196 --- /dev/null +++ b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/invalidToscaFileTest.yml @@ -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 index 0000000000..02c2caf555 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 index 0000000000..e844509c20 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 index 0000000000..0256cc9797 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 index 0000000000..8eba903cd8 --- /dev/null +++ b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/mock/analyzerService/validTosca.meta @@ -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 -- cgit 1.2.3-korg