From 0f6ae59460165381a8b5da2eea58c2c2efa75f2f Mon Sep 17 00:00:00 2001 From: MichaelMorris Date: Mon, 25 Jul 2022 23:01:50 +0100 Subject: [PATCH] Support unknown data types in service import Signed-off-by: MichaelMorris Issue-ID: SDC-4119 Change-Id: I426ebb96e7b354dfd5dfb06a10845c3162055968 --- .../sdc/be/components/csar/CsarBusinessLogic.java | 8 +- .../openecomp/sdc/be/components/csar/CsarInfo.java | 171 +++-------------- .../sdc/be/components/csar/OnboardedCsarInfo.java | 205 +++++++++++++++++++++ .../sdc/be/components/csar/ServiceCsarInfo.java | 145 +++++++++++++++ .../be/components/impl/DataTypeImportManager.java | 64 ++++++- .../be/components/impl/ResourceBusinessLogic.java | 5 +- .../impl/ServiceImportBusinessLogic.java | 41 ++++- ...sarInfoTest.java => OnboardedCsarInfoTest.java} | 12 +- .../be/components/csar/ServiceCsarInfoTest.java | 81 ++++++++ .../csar/YamlTemplateParsingHandlerTest.java | 6 +- .../impl/DataTypesImportManagerTest.java | 121 ++++++++++++ .../components/impl/ResourceBusinessLogicTest.java | 7 +- .../impl/ServiceImportBusinessLogicTest.java | 63 +++++-- .../ServiceImportBussinessLogicBaseTestSetup.java | 3 +- .../impl/ServiceImportParseLogicTest.java | 36 ++-- .../resources/csars/service-Ser09080002-csar.csar | Bin 0 -> 65020 bytes .../csars/serviceWithUnknownDataTypes.csar | Bin 0 -> 56980 bytes catalog-be/src/test/resources/valid_vf.csar | Bin 1316 -> 1681 bytes 18 files changed, 770 insertions(+), 198 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfo.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java rename catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/{CsarInfoTest.java => OnboardedCsarInfoTest.java} (94%) create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfoTest.java create mode 100644 catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypesImportManagerTest.java create mode 100644 catalog-be/src/test/resources/csars/service-Ser09080002-csar.csar create mode 100644 catalog-be/src/test/resources/csars/serviceWithUnknownDataTypes.csar diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java index 1d37efef28..aa5706c77f 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogic.java @@ -106,7 +106,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { } } - public CsarInfo getCsarInfo(Resource resource, Resource oldResource, User user, Map payload, String csarUUID) { + public OnboardedCsarInfo getCsarInfo(Resource resource, Resource oldResource, User user, Map payload, String csarUUID) { Map csar = payload; if (csar == null) { final var vendorSoftwareProduct = getCsar(resource, user); @@ -125,7 +125,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { csarUUID, oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().getImportedToscaChecksum(), checksum); oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().setImportedToscaChecksum(checksum); } - return new CsarInfo(user, csarUUID, resource.getCsarVersionId(), csar, resource.getName(), toscaYamlCsarStatus.getKey(), + return new OnboardedCsarInfo(user, csarUUID, resource.getCsarVersionId(), csar, resource.getName(), toscaYamlCsarStatus.getKey(), toscaYamlCsarStatus.getValue(), true); } @@ -144,7 +144,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { } } - public CsarInfo getCsarInfo(Service service, Service oldResource, User user, Map payload, String csarUUID) { + public ServiceCsarInfo getCsarInfo(Service service, Service oldResource, User user, Map payload, String csarUUID) { Map csar = getCsar(service, user, payload, csarUUID); ImmutablePair toscaYamlCsarStatus = validateAndParseCsar(service, user, csar, csarUUID).left() .on(this::throwComponentException); @@ -157,7 +157,7 @@ public class CsarBusinessLogic extends BaseBusinessLogic { csarUUID, oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().getImportedToscaChecksum(), checksum); oldResource.getComponentMetadataDefinition().getMetadataDataDefinition().setImportedToscaChecksum(checksum); } - return new CsarInfo(user, csarUUID, csar, service.getName(), toscaYamlCsarStatus.getKey(), toscaYamlCsarStatus.getValue(), true); + return new ServiceCsarInfo(user, csarUUID, csar, service.getName(), toscaYamlCsarStatus.getKey(), toscaYamlCsarStatus.getValue(), true); } public ParsedToscaYamlInfo getParsedToscaYamlInfo(String topologyTemplateYaml, String yamlName, Map nodeTypesInfo, diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarInfo.java index dc6f7c4416..49b7bb2f86 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarInfo.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/CsarInfo.java @@ -21,8 +21,6 @@ */ package org.openecomp.sdc.be.components.csar; -import static org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; -import static org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum; import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement; import com.google.common.annotations.VisibleForTesting; @@ -37,11 +35,11 @@ import java.util.Optional; import java.util.PriorityQueue; import java.util.Queue; import java.util.Set; -import java.util.regex.Pattern; import lombok.Getter; import lombok.Setter; -import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; +import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; +import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.config.NonManoArtifactType; import org.openecomp.sdc.be.config.NonManoConfiguration; @@ -51,13 +49,15 @@ import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.model.NodeTypeInfo; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.User; -import org.openecomp.sdc.be.tosca.CsarUtils; import org.openecomp.sdc.be.utils.TypeUtils; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.log.wrappers.Logger; import org.yaml.snakeyaml.Yaml; -public class CsarInfo { +/** + * Provides access to the contents of a CSAR + */ +public abstract class CsarInfo { private static final Logger log = Logger.getLogger(CsarInfo.class); private final NonManoConfiguration nonManoConfiguration; @@ -74,22 +74,21 @@ public class CsarInfo { private String csarVersionId; @Getter @Setter - private Map csar; + protected Map csar; @Getter private String mainTemplateName; @Getter private String mainTemplateContent; @Getter - private Map mappedToscaMainTemplate; + protected Map mappedToscaMainTemplate; @Getter private Map createdNodesToscaResourceNames; private Queue cvfcToCreateQueue; private boolean isUpdate; @Getter private Map createdNodes; - private Map datatypeDefinitions; + protected Map datatypeDefinitions; private Map policytypeDefinitions; - private List> globalSubstitutes; public CsarInfo(User modifier, String csarUUID, Map csar, String vfResourceName, String mainTemplateName, @@ -106,18 +105,11 @@ public class CsarInfo { this.isUpdate = isUpdate; this.createdNodes = new HashMap<>(); this.nonManoConfiguration = NonManoConfigurationManager.getInstance().getNonManoConfiguration(); - this.globalSubstitutes = getGlobalSubstitutes(csar); } - private List> getGlobalSubstitutes(final Map csar){ - final List> globalSubstitutesInCsar = new ArrayList<>(); - for (Map.Entry entry : csar.entrySet()) { - if (isAServiceTemplate(entry.getKey()) && isGlobalSubstitute(entry.getKey())) { - globalSubstitutesInCsar.add(entry); - } - } - return globalSubstitutesInCsar; - } + public String getVfResourceName() { + return vfResourceName; + } public CsarInfo(final User modifier, final String csarUUID, final String csarVersionId, final Map csarContent, final String vfResourceName, final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) { @@ -174,34 +166,15 @@ public class CsarInfo { public void setUpdate(boolean isUpdate) { this.isUpdate = isUpdate; } - - public Map extractTypesInfo() { - Map nodeTypesInfo = new HashMap<>(); - final Set nodeTypesUsedInNodeTemplates = new HashSet<>(); - for (Map.Entry entry : getCsar().entrySet()) { - extractNodeTypeInfo(nodeTypesInfo, nodeTypesUsedInNodeTemplates, entry); - } - if (CollectionUtils.isNotEmpty(globalSubstitutes)) { - setDerivedFrom(nodeTypesInfo); - addGlobalSubstitutionsToNodeTypes(nodeTypesUsedInNodeTemplates, nodeTypesInfo); - } - - markNestedVfc(getMappedToscaMainTemplate(), nodeTypesInfo); - return nodeTypesInfo; - } - public Map getDataTypes() { - if (datatypeDefinitions == null) { - datatypeDefinitions = new HashMap<>(); - for (Map.Entry entry : globalSubstitutes) { - final String yamlFileContents = new String(entry.getValue()); - final Map mappedToscaTemplate = new Yaml().load(yamlFileContents); - datatypeDefinitions.putAll(getTypesFromTemplate(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.DATA_TYPES)); - } - datatypeDefinitions.putAll(getTypesFromTemplate(mappedToscaMainTemplate, TypeUtils.ToscaTagNamesEnum.DATA_TYPES)); - } - return datatypeDefinitions; - } + public abstract Map extractTypesInfo(); + + /** + * Get the data types defined in the CSAR + * + * @return map with the data type name as key and representaion of the data type defintion as value + */ + public abstract Map getDataTypes(); public Map getPolicyTypes() { if (policytypeDefinitions == null) { @@ -211,8 +184,8 @@ public class CsarInfo { return policytypeDefinitions; } - @SuppressWarnings("unchecked") - private Map getTypesFromTemplate(final Map mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum type) { + @SuppressWarnings("unchecked") + protected Map getTypesFromTemplate(final Map mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum type) { final Either dataTypesEither = findToscaElement(mappedToscaTemplate, type, ToscaElementTypeEnum.MAP); if (dataTypesEither != null && dataTypesEither.isLeft()) { @@ -221,27 +194,7 @@ public class CsarInfo { return Collections.emptyMap(); } - @SuppressWarnings("unchecked") - private void extractNodeTypeInfo(Map nodeTypesInfo, - final Set nodeTypesUsedInNodeTemplates, Map.Entry entry) { - if (isAServiceTemplate(entry.getKey()) && !isGlobalSubstitute(entry.getKey())) { - Map mappedToscaTemplate = (Map) new Yaml().load(new String(entry.getValue())); - findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS, ToscaElementTypeEnum.MAP).right() - .on(sub -> handleSubstitutionMappings(nodeTypesInfo, entry, mappedToscaTemplate, (Map) sub)); - final Either nodeTypesEither = findToscaElement(mappedToscaTemplate, - TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES, ToscaElementTypeEnum.MAP); - if (nodeTypesEither.isLeft()) { - final Map> nodeTemplates = (Map>) nodeTypesEither.left().value(); - nodeTypesUsedInNodeTemplates.addAll(findNodeTypesUsedInNodeTemplates(nodeTemplates)); - } - } - } - - private boolean isAServiceTemplate(final String filePath) { - return Pattern.compile(CsarUtils.SERVICE_TEMPLATE_PATH_PATTERN).matcher(filePath).matches(); - } - - private Set findNodeTypesUsedInNodeTemplates(final Map> nodeTemplates) { + protected Set findNodeTypesUsedInNodeTemplates(final Map> nodeTemplates) { final Set nodeTypes = new HashSet<>(); for (final Map nodeTemplate : nodeTemplates.values()) { nodeTypes.add((String) nodeTemplate.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())); @@ -249,84 +202,8 @@ public class CsarInfo { return nodeTypes; } - private ResultStatusEnum handleSubstitutionMappings(Map nodeTypesInfo, Map.Entry entry, - Map mappedToscaTemplate, Map substitutionMappings) { - final Set nodeTypesDefinedInTemplate = findNodeTypesDefinedInTemplate(mappedToscaTemplate); - if (substitutionMappings.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()) && !nodeTypesDefinedInTemplate - .contains(substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()))) { - NodeTypeInfo nodeTypeInfo = new NodeTypeInfo(); - nodeTypeInfo.setSubstitutionMapping(true); - nodeTypeInfo.setType((String) substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName())); - nodeTypeInfo.setTemplateFileName(entry.getKey()); - nodeTypeInfo.setMappedToscaTemplate(mappedToscaTemplate); - nodeTypesInfo.put(nodeTypeInfo.getType(), nodeTypeInfo); - } - return ResultStatusEnum.OK; - } - - @SuppressWarnings("unchecked") - private Set findNodeTypesDefinedInTemplate(final Map mappedToscaTemplate) { - final Either nodeTypesEither = findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, - ToscaElementTypeEnum.MAP); - if (nodeTypesEither.isLeft()) { - final Map nodeTypes = (Map) nodeTypesEither.left().value(); - return nodeTypes.keySet(); - } - return Collections.emptySet(); - } - - private boolean isGlobalSubstitute(String fileName) { - return fileName.equalsIgnoreCase(Constants.GLOBAL_SUBSTITUTION_TYPES_SERVICE_TEMPLATE) || fileName - .equalsIgnoreCase(Constants.ABSTRACT_SUBSTITUTE_GLOBAL_TYPES_SERVICE_TEMPLATE); - } - - @SuppressWarnings("unchecked") - private void setDerivedFrom(Map nodeTypesInfo) { - for (Map.Entry entry : globalSubstitutes) { - String yamlFileContents = new String(entry.getValue()); - Map mappedToscaTemplate = (Map) new Yaml().load(yamlFileContents); - Either nodeTypesEither = findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, - ToscaElementTypeEnum.MAP); - if (nodeTypesEither.isLeft()) { - Map nodeTypes = (Map) nodeTypesEither.left().value(); - for (Map.Entry nodeType : nodeTypes.entrySet()) { - processNodeType(nodeTypesInfo, nodeType); - } - } - } - } - - @SuppressWarnings("unchecked") - private void processNodeType(Map nodeTypesInfo, Map.Entry nodeType) { - Map nodeTypeMap = (Map) nodeType.getValue(); - if (nodeTypeMap.containsKey(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()) && nodeTypesInfo.containsKey(nodeType.getKey())) { - NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(nodeType.getKey()); - List derivedFrom = new ArrayList<>(); - derivedFrom.add((String) nodeTypeMap.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName())); - nodeTypeInfo.setDerivedFrom(derivedFrom); - } - } - - @SuppressWarnings("unchecked") - private void addGlobalSubstitutionsToNodeTypes(final Set nodeTypesUsedInNodeTemplates, final Map nodeTypesInfo) { - for (Map.Entry entry : globalSubstitutes) { - final String yamlFileContents = new String(entry.getValue()); - final Map mappedToscaTemplate = (Map) new Yaml().load(yamlFileContents); - final Either nodeTypesEither = findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, - ToscaElementTypeEnum.MAP); - if (nodeTypesEither.isLeft()) { - final Map nodeTypes = (Map) nodeTypesEither.left().value(); - for (final Map.Entry nodeType : nodeTypes.entrySet()) { - if (!nodeTypesInfo.containsKey(nodeType.getKey()) && nodeTypesUsedInNodeTemplates.contains(nodeType.getKey())) { - nodeTypesInfo.put(nodeType.getKey(), buildNodeTypeInfo(nodeType, entry.getKey(), mappedToscaTemplate)); - } - } - } - } - } - @SuppressWarnings("unchecked") - private NodeTypeInfo buildNodeTypeInfo(final Map.Entry nodeType, final String templateFileName, + protected NodeTypeInfo buildNodeTypeInfo(final Map.Entry nodeType, final String templateFileName, final Map mappedToscaTemplate) { final NodeTypeInfo nodeTypeInfo = new NodeTypeInfo(); nodeTypeInfo.setSubstitutionMapping(false); diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfo.java new file mode 100644 index 0000000000..85f64699d4 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfo.java @@ -0,0 +1,205 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.csar; + +import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; +import org.apache.commons.collections.CollectionUtils; +import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; +import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum; +import org.openecomp.sdc.be.config.NonManoConfiguration; +import org.openecomp.sdc.be.model.NodeTypeInfo; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.tosca.CsarUtils; +import org.openecomp.sdc.be.utils.TypeUtils; +import org.openecomp.sdc.common.api.Constants; +import org.yaml.snakeyaml.Yaml; +import fj.data.Either; + +/** + * Provides access to the contents of a CSAR which has been created through the SDC onboarding + * process + */ +public class OnboardedCsarInfo extends CsarInfo { + + private List> globalSubstitutes; + + OnboardedCsarInfo(NonManoConfiguration nonManoConfiguration) { + super(nonManoConfiguration); + } + + public OnboardedCsarInfo(final User modifier, final String csarUUID, final Map csar, final String vfResourceName, + final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) { + super(modifier, csarUUID, csar, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate); + this.globalSubstitutes = getGlobalSubstitutes(csar); + } + + public OnboardedCsarInfo(final User modifier, final String csarUUID, final String csarVersionId, final Map csarContent, + final String vfResourceName, final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) { + super(modifier, csarUUID, csarVersionId, csarContent, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate); + this.globalSubstitutes = getGlobalSubstitutes(csar); + } + + private List> getGlobalSubstitutes(final Map csar) { + final List> globalSubstitutesInCsar = new ArrayList<>(); + for (Map.Entry entry : csar.entrySet()) { + if (isAServiceTemplate(entry.getKey()) && isGlobalSubstitute(entry.getKey())) { + globalSubstitutesInCsar.add(entry); + } + } + return globalSubstitutesInCsar; + } + + public Map extractTypesInfo() { + final Map nodeTypesInfo = new HashMap<>(); + final Set nodeTypesUsedInNodeTemplates = new HashSet<>(); + for (Map.Entry entry : getCsar().entrySet()) { + extractNodeTypeInfo(nodeTypesInfo, nodeTypesUsedInNodeTemplates, entry); + } + if (CollectionUtils.isNotEmpty(globalSubstitutes)) { + setDerivedFrom(nodeTypesInfo); + addGlobalSubstitutionsToNodeTypes(nodeTypesUsedInNodeTemplates, nodeTypesInfo); + } + + markNestedVfc(getMappedToscaMainTemplate(), nodeTypesInfo); + return nodeTypesInfo; + } + + @SuppressWarnings("unchecked") + private void extractNodeTypeInfo(final Map nodeTypesInfo, final Set nodeTypesUsedInNodeTemplates, + final Map.Entry entry) { + if (isAServiceTemplate(entry.getKey()) && !isGlobalSubstitute(entry.getKey())) { + final Map mappedToscaTemplate = (Map) new Yaml().load(new String(entry.getValue())); + findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS, ToscaElementTypeEnum.MAP).right() + .on(sub -> handleSubstitutionMappings(nodeTypesInfo, entry, mappedToscaTemplate, (Map) sub)); + final Either nodeTypesEither = + findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES, ToscaElementTypeEnum.MAP); + if (nodeTypesEither.isLeft()) { + final Map> nodeTemplates = (Map>) nodeTypesEither.left().value(); + nodeTypesUsedInNodeTemplates.addAll(findNodeTypesUsedInNodeTemplates(nodeTemplates)); + } + } + } + + private boolean isAServiceTemplate(final String filePath) { + return Pattern.compile(CsarUtils.SERVICE_TEMPLATE_PATH_PATTERN).matcher(filePath).matches(); + } + + private boolean isGlobalSubstitute(final String fileName) { + return fileName.equalsIgnoreCase(Constants.GLOBAL_SUBSTITUTION_TYPES_SERVICE_TEMPLATE) + || fileName.equalsIgnoreCase(Constants.ABSTRACT_SUBSTITUTE_GLOBAL_TYPES_SERVICE_TEMPLATE); + } + + + private ResultStatusEnum handleSubstitutionMappings(final Map nodeTypesInfo, final Map.Entry entry, + final Map mappedToscaTemplate, final Map substitutionMappings) { + final Set nodeTypesDefinedInTemplate = findNodeTypesDefinedInTemplate(mappedToscaTemplate); + if (substitutionMappings.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()) + && !nodeTypesDefinedInTemplate.contains(substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()))) { + NodeTypeInfo nodeTypeInfo = new NodeTypeInfo(); + nodeTypeInfo.setSubstitutionMapping(true); + nodeTypeInfo.setType((String) substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName())); + nodeTypeInfo.setTemplateFileName(entry.getKey()); + nodeTypeInfo.setMappedToscaTemplate(mappedToscaTemplate); + nodeTypesInfo.put(nodeTypeInfo.getType(), nodeTypeInfo); + } + return ResultStatusEnum.OK; + } + + @SuppressWarnings("unchecked") + private Set findNodeTypesDefinedInTemplate(final Map mappedToscaTemplate) { + final Either nodeTypesEither = + findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP); + if (nodeTypesEither.isLeft()) { + final Map nodeTypes = (Map) nodeTypesEither.left().value(); + return nodeTypes.keySet(); + } + return Collections.emptySet(); + } + + @SuppressWarnings("unchecked") + private void setDerivedFrom(final Map nodeTypesInfo) { + for (Map.Entry entry : globalSubstitutes) { + final String yamlFileContents = new String(entry.getValue()); + final Map mappedToscaTemplate = (Map) new Yaml().load(yamlFileContents); + Either nodeTypesEither = + findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP); + if (nodeTypesEither.isLeft()) { + Map nodeTypes = (Map) nodeTypesEither.left().value(); + for (Map.Entry nodeType : nodeTypes.entrySet()) { + processNodeType(nodeTypesInfo, nodeType); + } + } + } + } + + @SuppressWarnings("unchecked") + private void processNodeType(final Map nodeTypesInfo, final Map.Entry nodeType) { + final Map nodeTypeMap = (Map) nodeType.getValue(); + if (nodeTypeMap.containsKey(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()) && nodeTypesInfo.containsKey(nodeType.getKey())) { + final NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(nodeType.getKey()); + final List derivedFrom = new ArrayList<>(); + derivedFrom.add((String) nodeTypeMap.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName())); + nodeTypeInfo.setDerivedFrom(derivedFrom); + } + } + + @SuppressWarnings("unchecked") + private void addGlobalSubstitutionsToNodeTypes(final Set nodeTypesUsedInNodeTemplates, final Map nodeTypesInfo) { + for (Map.Entry entry : globalSubstitutes) { + final String yamlFileContents = new String(entry.getValue()); + final Map mappedToscaTemplate = (Map) new Yaml().load(yamlFileContents); + final Either nodeTypesEither = + findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP); + if (nodeTypesEither.isLeft()) { + final Map nodeTypes = (Map) nodeTypesEither.left().value(); + for (final Map.Entry nodeType : nodeTypes.entrySet()) { + if (!nodeTypesInfo.containsKey(nodeType.getKey()) && nodeTypesUsedInNodeTemplates.contains(nodeType.getKey())) { + nodeTypesInfo.put(nodeType.getKey(), buildNodeTypeInfo(nodeType, entry.getKey(), mappedToscaTemplate)); + } + } + } + } + } + + @Override + public Map getDataTypes() { + if (datatypeDefinitions == null) { + datatypeDefinitions = new HashMap<>(); + for (Map.Entry entry : globalSubstitutes) { + final String yamlFileContents = new String(entry.getValue()); + final Map mappedToscaTemplate = new Yaml().load(yamlFileContents); + datatypeDefinitions.putAll(getTypesFromTemplate(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.DATA_TYPES)); + } + datatypeDefinitions.putAll(getTypesFromTemplate(mappedToscaMainTemplate, TypeUtils.ToscaTagNamesEnum.DATA_TYPES)); + } + return datatypeDefinitions; + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java new file mode 100644 index 0000000000..ca3c92bcbd --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfo.java @@ -0,0 +1,145 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.csar; + +import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; +import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum; +import org.openecomp.sdc.be.model.NodeTypeInfo; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.utils.TypeUtils; +import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum; +import org.openecomp.sdc.common.log.wrappers.Logger; +import org.yaml.snakeyaml.Yaml; +import fj.data.Either; + +/** + * Provides access to the contents of a Service CSAR + */ +public class ServiceCsarInfo extends CsarInfo { + + private Map> mainTemplateImports; + private static final Logger log = Logger.getLogger(ServiceCsarInfo.class); + + public ServiceCsarInfo(final User modifier, final String csarUUID, final Map csar, final String vfResourceName, + final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) { + super(modifier, csarUUID, csar, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate); + + final Path mainTemplateDir = Paths.get(getMainTemplateName().substring(0, getMainTemplateName().lastIndexOf('/') + 1)); + final Collection filesHandled = new HashSet<>(); + filesHandled.add(Paths.get(mainTemplateName)); + this.mainTemplateImports = getTemplateImports(csar, new Yaml().load(mainTemplateContent), mainTemplateDir, filesHandled); + } + + private Map> getTemplateImports(final Map csar, Map mappedToscaMainTemplate, + final Path fileParentDir, final Collection filesHandled) { + final Map> templateImports = new HashMap<>(); + + final List importFilePaths = getTempateImportFilePaths(mappedToscaMainTemplate, fileParentDir); + + importFilePaths.stream().filter(path -> !filesHandled.contains(path)).forEach( + importFilePath -> { + byte[] importFile = csar.get(importFilePath.toString()); + if (importFile != null) { + filesHandled.add(importFilePath); + Map mappedImportFile = new Yaml().load(new String(csar.get(importFilePath.toString()))); + templateImports.put(importFilePath.toString(), mappedImportFile); + + templateImports.putAll(getTemplateImports(csar, mappedImportFile, importFilePath.getParent(), filesHandled)); + + } else { + log.info("Import {} cannot be found in CSAR", importFilePath.toString()); + } + }); + + return templateImports; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private List getTempateImportFilePaths(final Map mappedToscaTemplate, final Path fileParentDir) { + final Either importsEither = + findToscaElement(mappedToscaTemplate, ToscaTagNamesEnum.IMPORTS, ToscaElementTypeEnum.ALL); + + if (importsEither.isLeft()) { + final List importsList = (List) importsEither.left().value(); + if (CollectionUtils.isNotEmpty(importsList)) { + if (importsList.get(0) instanceof String) { + List importPaths = new ArrayList<>(); + importsList.stream().forEach(importPath -> importPaths.add(Paths.get((String)importPath))); + return importPaths; + } else if (importsList.get(0) instanceof Map) { + return getTemplateImportFilePathsMultiLineGrammar(importsList, fileParentDir); + } + } + + } + return Collections.emptyList(); + } + + @SuppressWarnings("unchecked") + private List getTemplateImportFilePathsMultiLineGrammar(final List> importsList, final Path fileParentDir) { + final List importFiles = new ArrayList<>(); + + for (Map importFileMultiLineGrammar : (List>) importsList) { + if (MapUtils.isNotEmpty(importFileMultiLineGrammar)) { + if (importFileMultiLineGrammar.values().iterator().next() instanceof String) { + Path relativePath = Paths.get((String) importFileMultiLineGrammar.get("file")); + Path absolutePath = fileParentDir.resolve(relativePath).normalize(); + importFiles.add(absolutePath); + } else if (importFileMultiLineGrammar.values().iterator().next() instanceof Map) { + importFileMultiLineGrammar.values().forEach(value -> { + Path relativePath = Paths.get((String) ((Map) value).get("file")); + Path absolutePath = fileParentDir == null ? relativePath : fileParentDir.resolve(relativePath).normalize(); + importFiles.add(absolutePath); + }); + } + } + } + return importFiles; + } + + @Override + public Map extractTypesInfo() { + return Collections.emptyMap(); + } + + @Override + public Map getDataTypes() { + final Map definitions = new HashMap<>(); + mainTemplateImports.entrySet().stream() + .forEach(entry -> definitions.putAll(getTypesFromTemplate(entry.getValue(), TypeUtils.ToscaTagNamesEnum.DATA_TYPES))); + definitions.putAll(getTypesFromTemplate(getMappedToscaMainTemplate(), TypeUtils.ToscaTagNamesEnum.DATA_TYPES)); + return definitions; + } + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeImportManager.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeImportManager.java index cad0f28477..60fdc0b3d5 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeImportManager.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/DataTypeImportManager.java @@ -17,10 +17,13 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.openecomp.sdc.be.components.impl; import fj.data.Either; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -72,17 +75,66 @@ public class DataTypeImportManager { } private Either, ActionStatus> createDataTypesFromYml(final String dataTypesYml, final String modelName) { - final Either, ActionStatus> dataTypes = commonImportManager.createElementTypesFromYml(dataTypesYml, + final Either, ActionStatus> dataTypesEither = commonImportManager.createElementTypesFromYml(dataTypesYml, this::createDataType); - if (dataTypes.isLeft() && StringUtils.isNotEmpty(modelName)) { + if (dataTypesEither.isRight()) { + return dataTypesEither; + } + final List dataTypes = dataTypesEither.left().value(); + if (StringUtils.isNotEmpty(modelName)) { final Optional modelOptional = modelOperation.findModelByName(modelName); if (modelOptional.isPresent()) { - dataTypes.left().value().forEach(dataType -> dataType.setModel(modelName)); - return dataTypes; + dataTypes.forEach(dataType -> dataType.setModel(modelName)); + } else { + return Either.right(ActionStatus.INVALID_MODEL); + } + } + if (log.isTraceEnabled()) { + log.trace("Unsorted datatypes order:"); + dataTypes.stream().forEach(dt -> log.trace(dt.getName())); + } + + long startTime = System.currentTimeMillis(); + List sortedDataTypeDefinitions = sortDataTypesByDependencyOrder(dataTypes); + + if (log.isTraceEnabled()) { + long sortTime = System.currentTimeMillis() - startTime; + log.trace("Sorting " + sortedDataTypeDefinitions.size() + " data types from model: " + modelName + " took: " + sortTime); + log.trace("Sorted datatypes order:"); + sortedDataTypeDefinitions.stream().forEach(dt -> log.trace(dt.getName())); + } + return Either.left(sortedDataTypeDefinitions); + } + + private List sortDataTypesByDependencyOrder(final List dataTypes) { + final List sortedDataTypeDefinitions = new ArrayList<>(); + final Map dataTypeDefinitionsMap = new HashMap<>(); + + dataTypes.forEach(dataType -> { + + int highestDependencyIndex = -1; + for (final String dependencyName : getDependencyTypes(dataType)) { + final DataTypeDefinition dependency = dataTypeDefinitionsMap.get(dependencyName); + final int indexOfDependency = sortedDataTypeDefinitions.lastIndexOf(dependency); + highestDependencyIndex = indexOfDependency > highestDependencyIndex ? indexOfDependency : highestDependencyIndex; } - return Either.right(ActionStatus.INVALID_MODEL); + sortedDataTypeDefinitions.add(highestDependencyIndex + 1, dataType); + dataTypeDefinitionsMap.put(dataType.getName(), dataType); + + } ); + + return sortedDataTypeDefinitions; + } + + private Collection getDependencyTypes(final DataTypeDefinition dataType) { + final Set dependencies = new HashSet<>(); + if (dataType.getDerivedFromName() != null) { + dependencies.add(dataType.getDerivedFromName()); + } + if (dataType.getProperties() != null) { + dataType.getProperties().stream().forEach(property -> dependencies.add(property.getType())); } - return dataTypes; + return dependencies; } private Either>, ResponseFormat> createDataTypesByDao( diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java index 1f107e4ec1..b923cbc3a1 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogic.java @@ -58,6 +58,7 @@ import org.openecomp.sdc.be.catalog.enums.ChangeTypeEnum; import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarInfo; +import org.openecomp.sdc.be.components.csar.OnboardedCsarInfo; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum; import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo; @@ -1041,7 +1042,8 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { loggerSupportability .log(LoggerSupportabilityActions.CREATE_RESOURCE_FROM_YAML, StatusCode.STARTED, "Starting to create Resource From Csar by user {}", user.getUserId()); - CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(resource, null, user, csarUIPayload, csarUUID); + OnboardedCsarInfo csarInfo = csarBusinessLogic.getCsarInfo(resource, null, user, csarUIPayload, csarUUID); + Map nodeTypesInfo = csarInfo.extractTypesInfo(); final String model = resource.getModel(); if (StringUtils.isNotEmpty(model)) { @@ -1057,7 +1059,6 @@ public class ResourceBusinessLogic extends ComponentBusinessLogic { policyTypeBusinessLogic.createPolicyTypeFromYaml(new Yaml().dump(policyTypesToCreate), model, true); } } - Either>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = findNodeTypesArtifactsToHandle( nodeTypesInfo, csarInfo, resource); if (findNodeTypesArtifactsToHandleRes.isRight()) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java index 7e15a52b90..e4129a24eb 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogic.java @@ -48,6 +48,7 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarInfo; +import org.openecomp.sdc.be.components.csar.ServiceCsarInfo; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum; import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo; import org.openecomp.sdc.be.components.impl.exceptions.BusinessLogicException; @@ -62,6 +63,7 @@ import org.openecomp.sdc.be.config.BeEcompErrorManager; import org.openecomp.sdc.be.config.ConfigurationManager; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.dao.janusgraph.JanusGraphDao; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus; import org.openecomp.sdc.be.datamodel.utils.ArtifactUtils; import org.openecomp.sdc.be.datamodel.utils.UiComponentDataConverter; import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition; @@ -118,6 +120,8 @@ import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter; import org.openecomp.sdc.be.model.operations.StorageException; import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; +import org.openecomp.sdc.be.model.operations.impl.UniqueIdBuilder; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.tosca.CsarUtils; import org.openecomp.sdc.be.ui.model.OperationUi; @@ -130,6 +134,7 @@ import org.openecomp.sdc.common.kpi.api.ASDCKpiApi; import org.openecomp.sdc.common.log.wrappers.Logger; import org.openecomp.sdc.common.util.ValidationUtils; import org.openecomp.sdc.exception.ResponseFormat; +import org.springframework.beans.factory.annotation.Autowired; import org.yaml.snakeyaml.Yaml; @Getter @@ -167,6 +172,9 @@ public class ServiceImportBusinessLogic { private final ArtifactsBusinessLogic artifactsBusinessLogic; private final IGraphLockOperation graphLockOperation; private final ToscaFunctionService toscaFunctionService; + private final PropertyOperation propertyOperation; + private final DataTypeBusinessLogic dataTypeBusinessLogic; + private ApplicationDataTypeCache applicationDataTypeCache; public ServiceImportBusinessLogic(final GroupBusinessLogic groupBusinessLogic, final ArtifactsBusinessLogic artifactsBusinessLogic, @@ -180,7 +188,8 @@ public class ServiceImportBusinessLogic { final ServiceImportParseLogic serviceImportParseLogic, final ComponentNodeFilterBusinessLogic componentNodeFilterBusinessLogic, final PolicyBusinessLogic policyBusinessLogic, final JanusGraphDao janusGraphDao, - final IGraphLockOperation graphLockOperation, final ToscaFunctionService toscaFunctionService) { + final IGraphLockOperation graphLockOperation, final ToscaFunctionService toscaFunctionService, + final PropertyOperation propertyOperation, final DataTypeBusinessLogic dataTypeBusinessLogic) { this.componentInstanceBusinessLogic = componentInstanceBusinessLogic; this.uiComponentDataConverter = uiComponentDataConverter; this.componentsUtils = componentsUtils; @@ -199,6 +208,13 @@ public class ServiceImportBusinessLogic { this.artifactsBusinessLogic = artifactsBusinessLogic; this.graphLockOperation = graphLockOperation; this.toscaFunctionService = toscaFunctionService; + this.propertyOperation = propertyOperation; + this.dataTypeBusinessLogic = dataTypeBusinessLogic; + } + + @Autowired + public void setApplicationDataTypeCache(ApplicationDataTypeCache applicationDataTypeCache) { + this.applicationDataTypeCache = applicationDataTypeCache; } public Service createService(Service service, AuditingActionEnum auditingAction, User user, Map csarUIPayload, @@ -232,7 +248,13 @@ public class ServiceImportBusinessLogic { protected Service createServiceFromCsar(Service service, User user, Map csarUIPayload, String csarUUID) { log.trace("************* created successfully from YAML, resource TOSCA "); try { - CsarInfo csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID); + ServiceCsarInfo csarInfo = csarBusinessLogic.getCsarInfo(service, null, user, csarUIPayload, csarUUID); + + final Map dataTypesToCreate = getDatatypesToCreate(service.getModel(), csarInfo); + if (MapUtils.isNotEmpty(dataTypesToCreate)) { + dataTypeBusinessLogic.createDataTypeFromYaml(new Yaml().dump(dataTypesToCreate), service.getModel(), true); + } + Map nodeTypesInfo = csarInfo.extractTypesInfo(); Either>>, ResponseFormat> findNodeTypesArtifactsToHandleRes = serviceImportParseLogic .findNodeTypesArtifactsToHandle(nodeTypesInfo, csarInfo, service); @@ -250,6 +272,19 @@ public class ServiceImportBusinessLogic { throw new ComponentException(ActionStatus.GENERAL_ERROR); } } + + private Map getDatatypesToCreate(final String model, final CsarInfo csarInfo) { + final Map dataTypesToCreate = new HashMap<>(); + + for (final Entry dataTypeEntry : csarInfo.getDataTypes().entrySet()){ + final Either result = applicationDataTypeCache.get(model, UniqueIdBuilder.buildDataTypeUid(model, dataTypeEntry.getKey())); + if (result.isRight() && result.right().value().equals(JanusGraphOperationStatus.NOT_FOUND)) { + dataTypesToCreate.put(dataTypeEntry.getKey(), dataTypeEntry.getValue()); + log.info("Deploying unknown type " + dataTypeEntry.getKey() + " to model " + model + " from package " + csarInfo.getCsarUUID()); + } + } + return dataTypesToCreate; + } protected Service createServiceFromYaml(Service service, String topologyTemplateYaml, String yamlName, Map nodeTypesInfo, CsarInfo csarInfo, @@ -2545,7 +2580,7 @@ public class ServiceImportBusinessLogic { mapToConvert.put(TypeUtils.ToscaTagNamesEnum.TOSCA_VERSION.getElementName(), toscaVersion.left().value()); Map nodeTypes = serviceImportParseLogic.getNodeTypesFromTemplate(mappedToscaTemplate); createNodeTypes(yamlName, service, needLock, nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, csarInfo, - mapToConvert, nodeTypes); + mapToConvert, nodeTypes); return csarInfo.getCreatedNodes(); } catch (Exception e) { log.debug("Exception occured when createResourcesFromYamlNodeTypesList,error is:{}", e.getMessage(), e); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfoTest.java similarity index 94% rename from catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java rename to catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfoTest.java index 07a8ded378..abdf153155 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/OnboardedCsarInfoTest.java @@ -58,9 +58,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) -public class CsarInfoTest { +public class OnboardedCsarInfoTest { - private CsarInfo csarInfo; + private OnboardedCsarInfo csarInfo; @Mock private User user; @@ -81,12 +81,12 @@ public class CsarInfoTest { new ConfigurationManager(new FSConfigurationSource(ExternalConfiguration.getChangeListener(), "src/test/resources/config/catalog-be")); } - private CsarInfo createCsarInfo(final String csarFileName, final String mainTemplateName) throws URISyntaxException, ZipException { - final File csarFile = new File(CsarInfoTest.class.getClassLoader().getResource(csarFileName).toURI()); + private OnboardedCsarInfo createCsarInfo(final String csarFileName, final String mainTemplateName) throws URISyntaxException, ZipException { + final File csarFile = new File(OnboardedCsarInfoTest.class.getClassLoader().getResource(csarFileName).toURI()); final Map payload = ZipUtils.readZip(csarFile, false); String mainTemplateContent = new String(payload.get(mainTemplateName)); - return new CsarInfo(user, CSAR_UUID, payload, RESOURCE_NAME, + return new OnboardedCsarInfo(user, CSAR_UUID, payload, RESOURCE_NAME, mainTemplateName, mainTemplateContent, true); } @@ -149,7 +149,7 @@ public class CsarInfoTest { @Test public void getSoftwareInformationPathTest() { final NonManoConfiguration nonManoConfigurationMock = Mockito.mock(NonManoConfiguration.class); - final CsarInfo csarInfo = new CsarInfo(nonManoConfigurationMock); + final CsarInfo csarInfo = new OnboardedCsarInfo(nonManoConfigurationMock); final NonManoFolderType testNonManoFolderType = new NonManoFolderType(); testNonManoFolderType.setLocation("sw-location-test"); testNonManoFolderType.setType("informational-test"); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfoTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfoTest.java new file mode 100644 index 0000000000..80ecc212f1 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/ServiceCsarInfoTest.java @@ -0,0 +1,81 @@ +/* + * - + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.csar; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import java.io.File; +import java.net.URISyntaxException; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.openecomp.sdc.be.config.ConfigurationManager; +import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.common.impl.ExternalConfiguration; +import org.openecomp.sdc.common.impl.FSConfigurationSource; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; + +@ExtendWith(MockitoExtension.class) +class ServiceCsarInfoTest { + + private ServiceCsarInfo csarInfo; + + @Mock + private User user; + + private static final String CSAR_UUID = "csarUUID"; + private static final String PAYLOAD_NAME = "csars/serviceWithUnknownDataTypes.csar"; + private static final String SERVICE_NAME = "serviceWithDataType"; + private static final String MAIN_TEMPLATE_NAME = "Definitions/service-Servicewithdatatype-template.yml"; + + @BeforeEach + void setup() throws ZipException, URISyntaxException { + csarInfo = createCsarInfo(PAYLOAD_NAME, MAIN_TEMPLATE_NAME); + + new ConfigurationManager(new FSConfigurationSource(ExternalConfiguration.getChangeListener(), "src/test/resources/config/catalog-be")); + } + + private ServiceCsarInfo createCsarInfo(final String csarFileName, final String mainTemplateName) throws URISyntaxException, ZipException { + final File csarFile = new File(ServiceCsarInfoTest.class.getClassLoader().getResource(csarFileName).toURI()); + final Map payload = ZipUtils.readZip(csarFile, false); + String mainTemplateContent = new String(payload.get(mainTemplateName)); + +return new ServiceCsarInfo(user, CSAR_UUID, payload, SERVICE_NAME, mainTemplateName, mainTemplateContent, true); + } + + @SuppressWarnings("unchecked") + @Test + void testGetDataTypes() { + final Map dataTypes = csarInfo.getDataTypes(); + assertEquals(184, dataTypes.size()); + final Map dataTypeDefinition = (Map) dataTypes.get("tosca.datatypes.test_g"); + assertNotNull(dataTypeDefinition); + assertEquals("tosca.datatypes.Root", dataTypeDefinition.get("derived_from")); + assertEquals("tosca.datatypes.test_h", + ((Map) ((Map) dataTypeDefinition.get("properties")).get("prop2")).get("type")); + } + +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandlerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandlerTest.java index d9525b1590..967beb2235 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandlerTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/YamlTemplateParsingHandlerTest.java @@ -148,7 +148,7 @@ public class YamlTemplateParsingHandlerTest { when(groupTypeBusinessLogic.getLatestGroupTypeByType(eq(HEAT_GROUP_TYPE), any())).thenReturn(heatGroupType); String main_template_content = new String(csar.get(MAIN_TEMPLATE_NAME)); - CsarInfo csarInfo = new CsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME, + CsarInfo csarInfo = new OnboardedCsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME, MAIN_TEMPLATE_NAME, main_template_content, true); Resource resource = new Resource(); @@ -163,7 +163,7 @@ public class YamlTemplateParsingHandlerTest { void parseServicePropertiesInfoFromYamlTest() { when(groupTypeBusinessLogic.getLatestGroupTypeByType(eq(HEAT_GROUP_TYPE), any())).thenReturn(heatGroupType); String main_template_content = new String(csar.get(MAIN_TEMPLATE_NAME)); - CsarInfo csarInfo = new CsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME, + CsarInfo csarInfo = new OnboardedCsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME, MAIN_TEMPLATE_NAME, main_template_content, true); Service service = new Service(); @@ -183,7 +183,7 @@ public class YamlTemplateParsingHandlerTest { void parseRelationshipTemplateInfoFromYamlTest() { when(groupTypeBusinessLogic.getLatestGroupTypeByType(eq(HEAT_GROUP_TYPE), any())).thenReturn(heatGroupType); String main_template_content = new String(csar.get(MAIN_TEMPLATE_NAME)); - CsarInfo csarInfo = new CsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME, + CsarInfo csarInfo = new OnboardedCsarInfo(user, CSAR_UUID, csar, RESOURCE_NAME, MAIN_TEMPLATE_NAME, main_template_content, true); Service service = new Service(); diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypesImportManagerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypesImportManagerTest.java new file mode 100644 index 0000000000..e4e63fc3b7 --- /dev/null +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/DataTypesImportManagerTest.java @@ -0,0 +1,121 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.components.impl; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; +import fj.data.Either; +import java.util.Collections; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.model.DataTypeDefinition; +import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; +import org.openecomp.sdc.be.model.operations.impl.ModelOperation; +import org.openecomp.sdc.be.model.operations.impl.PropertyOperation; + +public class DataTypesImportManagerTest { + + private static final ComponentsUtils componentsUtils = mock(ComponentsUtils.class); + private static final JanusGraphGenericDao janusGraphGenericDao = mock(JanusGraphGenericDao.class); + private static final PropertyOperation propertyOperation = mock(PropertyOperation.class); + private static final ModelOperation modelOperation = mock(ModelOperation.class); + @Spy + private CommonImportManager commonImportManager = new CommonImportManager(componentsUtils, propertyOperation, modelOperation); + + @InjectMocks + private DataTypeImportManager dataTypeImportManager = new DataTypeImportManager(); + + private AutoCloseable closeable; + + @BeforeEach + public void openMocks() { + closeable = MockitoAnnotations.openMocks(this); + } + + @AfterEach + public void releaseMocks() throws Exception { + closeable.close(); + } + + @Test + public void testCreateDataTypes() { + + DataTypeDefinition rootDataTypeDef = new DataTypeDefinition(); + rootDataTypeDef.setName("tosca.datatypes.Root"); + rootDataTypeDef.setProperties(Collections.emptyList()); + DataTypeDefinition testADataTypeDef = new DataTypeDefinition(); + testADataTypeDef.setName("tosca.datatypes.test_a"); + testADataTypeDef.setProperties(Collections.emptyList()); + DataTypeDefinition testCDataTypeDef = new DataTypeDefinition(); + testCDataTypeDef.setName("tosca.datatypes.test_c"); + testCDataTypeDef.setProperties(Collections.emptyList()); + when(propertyOperation.getDataTypeByName("tosca.datatypes.Root", null)).thenReturn(Either.left(rootDataTypeDef)); + when(propertyOperation.getDataTypeByName("tosca.datatypes.test_c", null)).thenReturn(Either.left(testCDataTypeDef)); + + when(propertyOperation.getJanusGraphGenericDao()).thenReturn(janusGraphGenericDao); + when(propertyOperation.getDataTypeByUidWithoutDerived("tosca.datatypes.Root.datatype", true)).thenReturn(Either.left(rootDataTypeDef)); + when(propertyOperation.getDataTypeByUidWithoutDerived("tosca.datatypes.test_a.datatype", true)) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(propertyOperation.getDataTypeByUidWithoutDerived("tosca.datatypes.test_b.datatype", true)) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(propertyOperation.getDataTypeByUidWithoutDerived("tosca.datatypes.test_c.datatype", true)) + .thenReturn(Either.right(StorageOperationStatus.NOT_FOUND)); + when(propertyOperation.addDataType(any())).thenReturn(Either.left(testADataTypeDef)); + + String dataTypeYml = + "tosca.datatypes.test_a:\n" + + " derived_from: tosca.datatypes.Root\n" + + " properties:\n" + + " prop2:\n" + + " type: tosca.datatypes.test_b\n" + + "tosca.datatypes.test_b:\n" + + " derived_from: tosca.datatypes.test_c\n" + + " properties:\n" + + " prop2:\n" + + " type: string\n" + + "tosca.datatypes.test_c:\n" + + " derived_from: tosca.datatypes.Root\n" + + " properties:\n" + + " prop1:\n" + + " type: string"; + dataTypeImportManager.createDataTypes(dataTypeYml, "", false); + + ArgumentCaptor dataTypeDefinitionCaptor = ArgumentCaptor.forClass(DataTypeDefinition.class); + Mockito.verify(propertyOperation, times(3)).addDataType(dataTypeDefinitionCaptor.capture()); + + assertEquals("tosca.datatypes.test_c", dataTypeDefinitionCaptor.getAllValues().get(0).getName()); + assertEquals("tosca.datatypes.test_b", dataTypeDefinitionCaptor.getAllValues().get(1).getName()); + assertEquals("tosca.datatypes.test_a", dataTypeDefinitionCaptor.getAllValues().get(2).getName()); + } + + +} diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java index ff47d75509..cee47ec984 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ResourceBusinessLogicTest.java @@ -64,6 +64,7 @@ import org.openecomp.sdc.be.components.ArtifactsResolver; import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarInfo; +import org.openecomp.sdc.be.components.csar.OnboardedCsarInfo; import org.openecomp.sdc.be.components.csar.YamlTemplateParsingHandler; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; @@ -387,7 +388,7 @@ class ResourceBusinessLogicTest { nodeTypesArtifactsToHandle, nodeTypesNewCreatedArtifacts, nodeTypesInfo, - new CsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", + new OnboardedCsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", ImportUtilsTest.loadFileNameToJsonString("normative-types-new-webServer.yml"), true), ""); }); } @@ -1876,7 +1877,7 @@ class ResourceBusinessLogicTest { Resource resourceToUpdate = createResourceObject(false); String nodeName = Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + "." + "abc"; String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-webServer.yml"); - CsarInfo csarInfo = new CsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", jsonContent, + CsarInfo csarInfo = new OnboardedCsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", jsonContent, true); String nestedResourceName = bl.buildNestedToscaResourceName(resourceToUpdate.getResourceType() .name(), csarInfo.getVfResourceName(), nodeName) @@ -1914,7 +1915,7 @@ class ResourceBusinessLogicTest { setCanWorkOnResource(resourceResponse); String nodeName = Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + "." + "abc"; String jsonContent = ImportUtilsTest.loadFileNameToJsonString("normative-types-new-webServer.yml"); - CsarInfo csarInfo = new CsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", jsonContent, + CsarInfo csarInfo = new OnboardedCsarInfo(user, "abcd1234", new HashMap<>(), RESOURCE_NAME, "template name", jsonContent, true); String nestedResourceName = bl.buildNestedToscaResourceName(resourceToUpdate.getResourceType() .name(), csarInfo.getVfResourceName(), nodeName) diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java index 1f45f77f3f..d40bac1585 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBusinessLogicTest.java @@ -19,21 +19,28 @@ package org.openecomp.sdc.be.components.impl; import static org.assertj.core.api.Java6Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyList; import static org.mockito.Mockito.anyMap; -import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.contains; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.matches; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.isNull; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.openecomp.sdc.be.components.impl.ServiceImportBusinessLogic.CREATE_RESOURCE; import fj.data.Either; +import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.net.URISyntaxException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; @@ -43,6 +50,7 @@ import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.map.HashedMap; @@ -50,9 +58,11 @@ import org.apache.commons.lang3.tuple.ImmutablePair; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.MockitoAnnotations; import org.openecomp.sdc.be.components.csar.CsarInfo; +import org.openecomp.sdc.be.components.csar.ServiceCsarInfo; import org.openecomp.sdc.be.components.impl.artifact.ArtifactOperationInfo; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.impl.utils.CreateServiceFromYamlParameter; @@ -96,6 +106,7 @@ import org.openecomp.sdc.be.model.UploadPropInfo; import org.openecomp.sdc.be.model.UploadReqInfo; import org.openecomp.sdc.be.model.UploadResourceInfo; import org.openecomp.sdc.be.model.User; +import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache; import org.openecomp.sdc.be.model.operations.api.ICapabilityTypeOperation; import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; @@ -104,7 +115,10 @@ import org.openecomp.sdc.be.tosca.CsarUtils; import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum; import org.openecomp.sdc.common.api.ArtifactTypeEnum; import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.exception.ResponseFormat; +import org.yaml.snakeyaml.Yaml; class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTestSetup { @@ -115,6 +129,9 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest private final ServletUtils servletUtils = mock(ServletUtils.class); private final AbstractValidationsServlet servlet = new ArtifactExternalServlet(userBusinessLogic, componentInstanceBusinessLogic, componentsUtils, servletUtils, resourceImportManager, artifactsBusinessLogic); + private final ApplicationDataTypeCache applicationDataTypeCache = mock(ApplicationDataTypeCache.class); + private final DataTypeBusinessLogic dataTypeBusinessLogic = mock(DataTypeBusinessLogic.class); + @InjectMocks private ServiceImportBusinessLogic sIBL; @@ -148,7 +165,7 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest when(serviceBusinessLogic.validateServiceBeforeCreate(eq(newService), any(User.class), any(AuditingActionEnum.class))) .thenReturn(Either.left(newService)); when(toscaOperationFacade.validateCsarUuidUniqueness(anyString())).thenReturn(StorageOperationStatus.OK); - CsarInfo csarInfo = getCsarInfo(); + ServiceCsarInfo csarInfo = getCsarInfo(); when(csarBusinessLogic.getCsarInfo(any(Service.class), any(), any(User.class), any(Map.class), anyString())).thenReturn(csarInfo); when(serviceImportParseLogic.findNodeTypesArtifactsToHandle(any(Map.class), any(CsarInfo.class), any(Service.class))) .thenReturn(Either.left(new HashMap>>())); @@ -183,7 +200,10 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest when(mockJanusGraphDao.commit()).thenReturn(JanusGraphOperationStatus.OK); when(graphLockOperation.unlockComponentByName(anyString(), anyString(), any(NodeTypeEnum.class))).thenReturn(StorageOperationStatus.OK); when(serviceImportParseLogic.createOutputsOnService(any(Service.class), any(), anyString())).thenReturn(newService); - + + when(applicationDataTypeCache.get(any(), contains("tosca.datatypes.test_"))).thenReturn(Either.right(JanusGraphOperationStatus.NOT_FOUND)); + when(applicationDataTypeCache.get(any(), matches("^((?!tosca.datatypes.test_).)*$"))).thenReturn(Either.left(new DataTypeDefinition())); + Service result = sIBL.createService(oldService, AuditingActionEnum.CREATE_RESOURCE, user, payload, payloadName); assertNotNull(result); assertNotNull(result.getComponentInstances()); @@ -195,6 +215,13 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest assertEquals(1, result.getComponentInstances().get(0).getRequirements().size()); assertNotNull(result.getCategories()); assertEquals(1, result.getCategories().size()); + + ArgumentCaptor yaml = ArgumentCaptor.forClass(String.class); + verify(dataTypeBusinessLogic).createDataTypeFromYaml(yaml.capture(), isNull(), anyBoolean()); + Map yamlMap = new Yaml().load(yaml.getValue()); + assertEquals(2, yamlMap.size()); + assertNotNull(yamlMap.get("tosca.datatypes.test_a")); + assertNotNull(yamlMap.get("tosca.datatypes.test_b")); } @Test @@ -222,7 +249,7 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest Service oldService = createServiceObject(true); String csarUUID = "valid_vf"; Map payload = crateCsarFromPayload(); - CsarInfo csarInfo = getCsarInfo(); + ServiceCsarInfo csarInfo = getCsarInfo(); Map>> map = new HashedMap(); @@ -240,7 +267,7 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest Resource resource = createOldResource(); String topologyTemplateYaml = getMainTemplateContent("service_import_template.yml"); String yamlName = "group.yml"; - CsarInfo csarInfo = getCsarInfo(); + ServiceCsarInfo csarInfo = getCsarInfo(); Map>> nodeTypesArtifactsToCreate = new HashMap<>(); String nodeName = "org.openecomp.resource.derivedFrom.zxjTestImportServiceAb.test"; @@ -2342,14 +2369,28 @@ class ServiceImportBusinessLogicTest extends ServiceImportBussinessLogicBaseTest return mainTemplateContent; } - protected CsarInfo getCsarInfo() { + protected ServiceCsarInfo getCsarInfo() { String csarUuid = "0010"; User user = new User("jh0003"); - Map csar = crateCsarFromPayload(); - String vfReousrceName = "resouceName"; - String mainTemplateName = "mainTemplateName"; - String mainTemplateContent = getMainTemplateContent("service_import_template.yml"); - return new CsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false); + + try { + File csarFile = new File( + ServiceImportBusinessLogicTest.class.getClassLoader().getResource("csars/service-Ser09080002-csar.csar").toURI()); + Map csar = ZipUtils.readZip(csarFile, false); + + String vfReousrceName = "resouceName"; + String mainTemplateName = "Definitions/service_import_template.yml"; + + Optional keyOp = csar.keySet().stream().filter(k -> k.endsWith("service-Ser09080002-template.yml")).findAny(); + byte[] mainTemplateService = keyOp.map(csar::get).orElse(null); + assertNotNull(mainTemplateService); + final String mainTemplateContent = new String(mainTemplateService); + + return new ServiceCsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false); + } catch (URISyntaxException | ZipException e) { + fail(e); + } + return null; } protected CsarUtils.NonMetaArtifactInfo getNonMetaArtifactInfo() { diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBussinessLogicBaseTestSetup.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBussinessLogicBaseTestSetup.java index c8fd87ca3b..06594dc180 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBussinessLogicBaseTestSetup.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportBussinessLogicBaseTestSetup.java @@ -44,6 +44,7 @@ import org.openecomp.sdc.ElementOperationMock; import org.openecomp.sdc.be.components.csar.CsarArtifactsAndGroupsBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarBusinessLogic; import org.openecomp.sdc.be.components.csar.CsarInfo; +import org.openecomp.sdc.be.components.csar.OnboardedCsarInfo; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.impl.utils.CreateServiceFromYamlParameter; import org.openecomp.sdc.be.components.validation.UserValidations; @@ -673,7 +674,7 @@ public class ServiceImportBussinessLogicBaseTestSetup extends BaseBusinessLogicM String mainTemplateName = "mainTemplateName"; String mainTemplateContent = getMainTemplateContent(); final Service service = createServiceObject(false); - CsarInfo csarInfo = new CsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false); + CsarInfo csarInfo = new OnboardedCsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false); return csarInfo; } diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogicTest.java index c564f59398..b3154efe62 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogicTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/ServiceImportParseLogicTest.java @@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyMap; @@ -33,7 +34,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import fj.data.Either; +import java.io.File; import java.io.IOException; +import java.net.URISyntaxException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.util.ArrayList; @@ -44,6 +47,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.NoSuchElementException; +import java.util.Optional; import org.apache.commons.collections.map.HashedMap; import org.apache.commons.lang3.tuple.ImmutablePair; import org.glassfish.grizzly.http.util.HttpStatus; @@ -54,6 +58,7 @@ import org.mockito.MockitoAnnotations; import org.openecomp.sdc.ElementOperationMock; import org.openecomp.sdc.be.auditing.impl.AuditingManager; import org.openecomp.sdc.be.components.csar.CsarInfo; +import org.openecomp.sdc.be.components.csar.ServiceCsarInfo; import org.openecomp.sdc.be.components.impl.ArtifactsBusinessLogic.ArtifactOperationEnum; import org.openecomp.sdc.be.components.impl.exceptions.ComponentException; import org.openecomp.sdc.be.components.lifecycle.LifecycleBusinessLogic; @@ -103,16 +108,14 @@ import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus; import org.openecomp.sdc.be.resources.data.auditing.AuditingActionEnum; import org.openecomp.sdc.be.user.Role; import org.openecomp.sdc.common.api.Constants; +import org.openecomp.sdc.common.zip.ZipUtils; +import org.openecomp.sdc.common.zip.exception.ZipException; import org.openecomp.sdc.exception.ResponseFormat; class ServiceImportParseLogicTest extends ServiceImportBussinessLogicBaseTestSetup { private static final String RESOURCE_NAME = "My-Resource_Name with space"; private static final String RESOURCE_TOSCA_NAME = "My-Resource_Tosca_Name"; - private static final String GENERIC_ROOT_NAME = "tosca.nodes.Root"; - private static final String GENERIC_VF_NAME = "org.openecomp.resource.abstract.nodes.VF"; - private static final String GENERIC_CR_NAME = "org.openecomp.resource.abstract.nodes.CR"; - private static final String GENERIC_PNF_NAME = "org.openecomp.resource.abstract.nodes.PNF"; private static final String RESOURCE_CATEGORY1 = "Network Layer 2-3"; private static final String RESOURCE_SUBCATEGORY = "Router"; @@ -2074,16 +2077,25 @@ class ServiceImportParseLogicTest extends ServiceImportBussinessLogicBaseTestSet protected CsarInfo getCsarInfo() { String csarUuid = "0010"; User user = new User(); - Map csar = new HashMap<>(); - String vfReousrceName = "resouceName"; - String mainTemplateName = "mainTemplateName"; - String mainTemplateContent = null; + File csarFile; try { - mainTemplateContent = loadFileNameToJsonString("service_import_template.yml"); - } catch (IOException e) { - e.printStackTrace(); + csarFile = new File( + ServiceImportBusinessLogicTest.class.getClassLoader().getResource("csars/service-Ser09080002-csar.csar").toURI()); + Map csar = ZipUtils.readZip(csarFile, false); + + String vfReousrceName = "resouceName"; + String mainTemplateName = "Definitions/service_import_template.yml"; + + Optional keyOp = csar.keySet().stream().filter(k -> k.endsWith("service-Ser09080002-template.yml")).findAny(); + byte[] mainTemplateService = keyOp.map(csar::get).orElse(null); + assertNotNull(mainTemplateService); + final String mainTemplateContent = new String(mainTemplateService); + + return new ServiceCsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false); + } catch (URISyntaxException | ZipException e) { + fail(e); } - return new CsarInfo(user, csarUuid, csar, vfReousrceName, mainTemplateName, mainTemplateContent, false); + return null; } private String loadFileNameToJsonString(String fileName) throws IOException { diff --git a/catalog-be/src/test/resources/csars/service-Ser09080002-csar.csar b/catalog-be/src/test/resources/csars/service-Ser09080002-csar.csar new file mode 100644 index 0000000000000000000000000000000000000000..a65850469d2e2c5e067c2a9c12e9b6b744a1a556 GIT binary patch literal 65020 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 literal 0 HcmV?d00001 diff --git a/catalog-be/src/test/resources/csars/serviceWithUnknownDataTypes.csar b/catalog-be/src/test/resources/csars/serviceWithUnknownDataTypes.csar new file mode 100644 index 0000000000000000000000000000000000000000..ffd209978fe4f5265fb9e8090be2186421dea745 GIT binary patch literal 56980 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 literal 0 HcmV?d00001 diff --git a/catalog-be/src/test/resources/valid_vf.csar b/catalog-be/src/test/resources/valid_vf.csar index 01bf1590712f0a8c718098e4f427c9a2644e8a74..cb9be9bc7e22e1ffde80fa698b5da946f33f0880 100644 GIT binary patch delta 922 zcmZ3&HIa9Memye-0|!IvoIfE2Q#Uv^FfcG!GBPko0cn@iw9LHBlFadZMT|1)Kq?CL|JM>AypSoZJZDYdIGUHHjzbxmww<)1mPr~GCL@MdNa0XsYe=dBShsM%2AFa4s)o-I0;q2Bkd!-s?h zgIOsOsS{ixU&zUrOTM&FdEVb}FGM%WqQyk`Y(zzdLE>s{J3G2*`eZ(X%= zr`7zP67q`gogVO<_U)W;!?(rz>DPKA#uGn;I*PNFS{%91_IQD$>fA(;2NH#vXKaFV zB-g8SckXdITE3<%c>l5VW2%3y?rxE-T6Xo2s7YhRT>U?(?^Z4QpRw%om2Fi~f0`46 zB@cOr{J&Vb#cR#hbeDVe_hR)vSR9-6HnaEkg`@L6p1ImuePz*-C%m@aZ{NHqnSZPG z$s7OYzskO6?)iG>!Oyez9S+N!e*Jp8{Qi4W^0(c7yXSAptvH`QZOWU>&YTRj^?rDK zR-l>t&h>49(%Hg72mOC+Ubg9~YMt1doD~(G^@sL9arn!+`6c5d#(HK*jAJHM6<}fo z0fmMwjaon&cf#djPyi`pU}TVBXxP;Ce8Zv}j4+yEgL>RXAV0vHk;xuv7jo(n1}85D zWXm1_6PvDFgZ;EaV1v+Tut5xy-!e+@!8HNxe#JCdh$V{2hk0@yOFUC0^W^g^?tE+v QYz#?E3=ERMB+S4703vgPRR910 delta 555 zcmbQpyM$|kz8C`o0|!HJ>kN;_H5SvG85tNJFf%a7P3B`&te+Zm+wZUePwo5gAI!%j z9<6oqh>4rvpuqNsaiK=+9@7=RPH*^pJL->TT5oGS=5}S(%G#Q9g-PE`E}nXD#p?7m z>!9KumDw`8L~dGztPtC^?#e`|)R~U6T%>m#os-7Ezf`qihiv>DNA@;>zgJFOPgwD% z=|E-kdXt7*yJwmoWeD)E_xiwRBETkVx;ST%2KU|FPlF~T9e017*5D^DDmCNR4dJg5 z75aurk1lwY&b*=+QnqNay+HEDLcff*38`N>~fww8U}(UITV8?pFt$nEva8nz!_)t{WNzPPLILW%nlpN;jge}Xpa znLM;xb-%=PtxDKNdzW+h$NmfaxO!~W_P0{v`}lYt?^<1(y{ks8f6uE>+S#m -- 2.16.6