summaryrefslogtreecommitdiffstats
path: root/catalog-be
diff options
context:
space:
mode:
authorvasraz <vasyl.razinkov@est.tech>2023-09-01 14:31:28 +0100
committerMichael Morris <michael.morris@est.tech>2023-09-07 13:16:33 +0000
commit28e1a54e6074f50dcc06f7ea4eb3943ad873b448 (patch)
treeedc59848dedfda9cf5d68e08b6744516d0e761a4 /catalog-be
parentc469756a1092194adedd590d35f0f1f8feac3a36 (diff)
Create plugin point for csar generation
Issue-ID: SDC-4578 Signed-off-by: franciscovila <javier.paradela.vila@est.tech> Change-Id: I3bb280ce4e442780598464216145abc130765539 Signed-off-by: Vasyl Razinkov <vasyl.razinkov@est.tech>
Diffstat (limited to 'catalog-be')
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/plugins/CsarZipGenerator.java48
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CommonCsarGenerator.java1235
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ComponentCache.java2
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java813
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/DefaultCsarGenerator.java56
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java7
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/MapFromModelCsarGeneratorService.java59
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java110
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java7
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java164
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java12
11 files changed, 1573 insertions, 940 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/plugins/CsarZipGenerator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/plugins/CsarZipGenerator.java
new file mode 100644
index 0000000000..f03c930681
--- /dev/null
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/plugins/CsarZipGenerator.java
@@ -0,0 +1,48 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2023 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.be.plugins;
+
+import fj.data.Either;
+import java.io.IOException;
+import java.util.zip.ZipOutputStream;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.exception.ResponseFormat;
+
+/**
+ * Implementations of this interface shall generate a csar file.
+ */
+public interface CsarZipGenerator {
+
+ /**
+ * Generate the csar file.
+ *
+ * @param component the component the csar is based on
+ * @return Map of name to contents for entries to be included in the csar
+ */
+ Either<ZipOutputStream, ResponseFormat> generateCsarZip(
+ final Component component,
+ boolean getFromCS,
+ ZipOutputStream zip,
+ boolean isInCertificationRequest,
+ boolean isAsdPackage
+ ) throws IOException;
+
+ String getModel();
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CommonCsarGenerator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CommonCsarGenerator.java
new file mode 100644
index 0000000000..633dd6e483
--- /dev/null
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CommonCsarGenerator.java
@@ -0,0 +1,1235 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2023 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.be.tosca;
+
+import static org.openecomp.sdc.be.dao.api.ActionStatus.ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION;
+import static org.openecomp.sdc.be.dao.api.ActionStatus.ERROR_DURING_CSAR_CREATION;
+import static org.openecomp.sdc.be.tosca.ComponentCache.MergeStrategy.overwriteIfSameVersions;
+import static org.openecomp.sdc.be.tosca.FJToVavrHelper.Try0.fromEither;
+import static org.openecomp.sdc.be.tosca.FJToVavrHelper.Try0.javaListToVavrList;
+import static org.openecomp.sdc.common.api.Constants.ADDITIONAL_TYPE_DEFINITIONS;
+
+import com.google.common.primitives.Bytes;
+import fj.F;
+import fj.data.Either;
+import io.vavr.Tuple2;
+import io.vavr.control.Try;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.io.output.ByteArrayOutputStream;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.tuple.ImmutableTriple;
+import org.apache.commons.lang3.tuple.Triple;
+import org.apache.commons.text.WordUtils;
+import org.onap.sdc.tosca.services.YamlUtil;
+import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
+import org.openecomp.sdc.be.config.CategoryBaseTypeConfig;
+import org.openecomp.sdc.be.config.ConfigurationManager;
+import org.openecomp.sdc.be.dao.api.ActionStatus;
+import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
+import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
+import org.openecomp.sdc.be.dao.cassandra.SdcSchemaFilesCassandraDao;
+import org.openecomp.sdc.be.data.model.ToscaImportByModel;
+import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
+import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
+import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
+import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
+import org.openecomp.sdc.be.impl.ComponentsUtils;
+import org.openecomp.sdc.be.model.ArtifactDefinition;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.model.ComponentInstance;
+import org.openecomp.sdc.be.model.InterfaceDefinition;
+import org.openecomp.sdc.be.model.LifecycleStateEnum;
+import org.openecomp.sdc.be.model.Resource;
+import org.openecomp.sdc.be.model.Service;
+import org.openecomp.sdc.be.model.category.CategoryDefinition;
+import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
+import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
+import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
+import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
+import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
+import org.openecomp.sdc.be.plugins.CsarEntryGenerator;
+import org.openecomp.sdc.be.resources.data.DAOArtifactData;
+import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
+import org.openecomp.sdc.be.utils.TypeUtils;
+import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
+import org.openecomp.sdc.common.api.ArtifactTypeEnum;
+import org.openecomp.sdc.common.impl.ExternalConfiguration;
+import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
+import org.openecomp.sdc.common.util.GeneralUtility;
+import org.openecomp.sdc.common.zip.ZipUtils;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * Generates a Network Service CSAR based on a SERVICE component and wraps it in a SDC CSAR entry.
+ */
+@org.springframework.stereotype.Component("commonCsarGenerator")
+public class CommonCsarGenerator {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CommonCsarGenerator.class);
+ public static final String ARTIFACTS_PATH = "Artifacts/";
+ private static final String RESOURCES_PATH = "Resources/";
+ private static final String PATH_DELIMITER = "/";
+ private static final String SERVICE_MANIFEST = "NS.mf";
+ private static final String ARTIFACT_NAME_UNIQUE_ID = "ArtifactName {}, unique ID {}";
+ private static final String TOSCA_META_PATH_FILE_NAME = "TOSCA-Metadata/TOSCA.meta";
+ private static final String TOSCA_META_VERSION = "1.0";
+ private static final String CSAR_VERSION = "1.1";
+ private static final String SDC_VERSION = ExternalConfiguration.getAppVersion();
+ public static final String NODES_YML = "nodes.yml";
+ private static final String CONFORMANCE_LEVEL = ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel();
+ private final ToscaOperationFacade toscaOperationFacade;
+ private final ComponentsUtils componentsUtils;
+ private final ToscaExportHandler toscaExportUtils;
+ private final List<CsarEntryGenerator> generators;
+ private final ArtifactCassandraDao artifactCassandraDao;
+ private final String versionFirstThreeOctets;
+ private final SdcSchemaFilesCassandraDao sdcSchemaFilesCassandraDao;
+ private final ModelOperation modelOperation;
+
+ @Autowired
+ public CommonCsarGenerator(
+ final ToscaOperationFacade toscaOperationFacade,
+ final ComponentsUtils componentsUtils,
+ final ToscaExportHandler toscaExportUtils,
+ final List<CsarEntryGenerator> generators,
+ final ArtifactCassandraDao artifactCassandraDao,
+ final SdcSchemaFilesCassandraDao sdcSchemaFilesCassandraDao,
+ final ModelOperation modelOperation) {
+ this.toscaOperationFacade = toscaOperationFacade;
+ this.componentsUtils = componentsUtils;
+ this.toscaExportUtils = toscaExportUtils;
+ this.generators = generators;
+ this.artifactCassandraDao = artifactCassandraDao;
+ this.versionFirstThreeOctets = readVersionFirstThreeOctets();
+ this.sdcSchemaFilesCassandraDao = sdcSchemaFilesCassandraDao;
+ this.modelOperation = modelOperation;
+ }
+
+ private String readVersionFirstThreeOctets() {
+ if (StringUtils.isEmpty(SDC_VERSION)) {
+ return "";
+ }
+ // change regex to avoid DoS sonar issue
+ Matcher matcher = Pattern.compile("(?!\\.)(\\d{1,9}(\\.\\d{1,9}){1,9})(?![\\d\\.])").matcher(SDC_VERSION);
+ matcher.find();
+ return matcher.group(0);
+ }
+
+ /**
+ * Generates a Network Service CSAR based on a SERVICE component that has category configured in
+ * CategoriesToGenerateNsd enum and wraps it in a SDC CSAR entry.
+ *
+ * @param component the component to create the NS CSAR from
+ * @return an entry to be added in the Component CSAR by SDC
+ */
+
+ public Either<ZipOutputStream, ResponseFormat> generateCsarZip(Component component,
+ boolean getFromCS,
+ ZipOutputStream zip,
+ boolean isInCertificationRequest,
+ boolean isAsdPackage,
+ String definitionsPath,
+ boolean addDependencies,
+ boolean isSkipImports) throws IOException {
+ ArtifactDefinition artifactDef = component.getToscaArtifacts().get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
+ Either<ToscaRepresentation, ResponseFormat> toscaRepresentation = fetchToscaRepresentation(component, getFromCS, artifactDef, isSkipImports);
+
+ // This should not be done but in order to keep the refactoring small enough we stop here.
+ // TODO: Refactor the rest of this function
+ byte[] mainYaml;
+ List<Triple<String, String, Component>> dependencies;
+ if (toscaRepresentation.isLeft()) {
+ mainYaml = toscaRepresentation.left().value().getMainYaml();
+ dependencies = toscaRepresentation.left().value().getDependencies().getOrElse(new ArrayList<>());
+ } else {
+ return Either.right(toscaRepresentation.right().value());
+ }
+ final String fileName = artifactDef.getArtifactName();
+ final byte[] toscaBlock0Byte =
+ createToscaBlock0(TOSCA_META_VERSION, CSAR_VERSION, component.getCreatorFullName(), fileName, isAsdPackage, definitionsPath).getBytes();
+ zip.putNextEntry(new ZipEntry(TOSCA_META_PATH_FILE_NAME));
+ zip.write(toscaBlock0Byte);
+ zip.putNextEntry(new ZipEntry(definitionsPath + fileName));
+ zip.write(mainYaml);
+ LifecycleStateEnum lifecycleState = component.getLifecycleState();
+ addServiceMf(component, zip, lifecycleState, isInCertificationRequest, fileName, mainYaml, definitionsPath);
+ if (addDependencies) {
+ //US798487 - Abstraction of complex types
+ if (hasToWriteComponentSubstitutionType(component)) {
+ LOGGER.debug("Component {} is complex - generating abstract type for it..", component.getName());
+ dependencies.addAll(writeComponentInterface(component, zip, fileName, definitionsPath));
+ }
+ //UID <cassandraId,filename,component>
+ Either<ZipOutputStream, ResponseFormat> zipOutputStreamOrResponseFormat =
+ getZipOutputStreamResponseFormatEither(zip, dependencies, definitionsPath);
+ if (zipOutputStreamOrResponseFormat != null && zipOutputStreamOrResponseFormat.isRight()) {
+ return zipOutputStreamOrResponseFormat;
+ }
+ }
+ if (component.getModel() == null) {
+ //retrieve SDC.zip from Cassandra
+ Either<byte[], ResponseFormat> latestSchemaFiles = getLatestSchemaFilesFromCassandra();
+ if (latestSchemaFiles.isRight()) {
+ LOGGER.error("Error retrieving SDC Schema files from cassandra");
+ return Either.right(latestSchemaFiles.right().value());
+ }
+ final byte[] schemaFileZip = latestSchemaFiles.left().value();
+ final List<String> nodesFromPackage = findNonRootNodesFromPackage(dependencies);
+ //add files from retrieved SDC.zip to Definitions folder in CSAR
+ addSchemaFilesFromCassandra(zip, schemaFileZip, nodesFromPackage, definitionsPath);
+ } else {
+ //retrieve schema files by model from Cassandra
+ addSchemaFilesByModel(zip, component.getModel(), definitionsPath, addDependencies);
+ }
+ Either<CsarDefinition, ResponseFormat> collectedComponentCsarDefinition = collectComponentCsarDefinition(component);
+ if (collectedComponentCsarDefinition.isRight()) {
+ return Either.right(collectedComponentCsarDefinition.right().value());
+ }
+ if (generators != null) {
+ for (CsarEntryGenerator generator : generators) {
+ LOGGER.debug("Invoking CsarEntryGenerator: {}", generator.getClass().getName());
+ for (Map.Entry<String, byte[]> pluginGeneratedFile : generator.generateCsarEntries(component).entrySet()) {
+ zip.putNextEntry(new ZipEntry(pluginGeneratedFile.getKey()));
+ zip.write(pluginGeneratedFile.getValue());
+ }
+ }
+ }
+ return writeAllFilesToCsar(component, collectedComponentCsarDefinition.left().value(), zip, isInCertificationRequest);
+ }
+
+ private Either<ToscaRepresentation, ResponseFormat> fetchToscaRepresentation(Component component, boolean getFromCS,
+ ArtifactDefinition artifactDef, boolean isSkipImports) {
+ LifecycleStateEnum lifecycleState = component.getLifecycleState();
+ boolean shouldBeFetchedFromCassandra =
+ getFromCS || !(lifecycleState == LifecycleStateEnum.NOT_CERTIFIED_CHECKIN || lifecycleState == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
+ Either<ToscaRepresentation, ResponseFormat> toscaRepresentation =
+ shouldBeFetchedFromCassandra ? fetchToscaRepresentation(artifactDef) : generateToscaRepresentation(component, isSkipImports);
+ return toscaRepresentation.left()
+ .bind(iff(myd -> !myd.getDependencies().isDefined(), myd -> fetchToscaTemplateDependencies(myd.getMainYaml(), component)));
+ }
+
+ private Either<ToscaRepresentation, ResponseFormat> fetchToscaTemplateDependencies(byte[] mainYml, Component component) {
+ return toscaExportUtils.getDependencies(component).right().map(toscaError -> {
+ LOGGER.debug("Failed to retrieve dependencies for component {}, error {}", component.getUniqueId(), toscaError);
+ return componentsUtils.getResponseFormat(componentsUtils.convertFromToscaError(toscaError));
+ }).left().map(tt -> ToscaRepresentation.make(mainYml, tt));
+ }
+
+ private Either<ToscaRepresentation, ResponseFormat> fetchToscaRepresentation(ArtifactDefinition artifactDef) {
+ return getFromCassandra(artifactDef.getEsId()).right().map(as -> {
+ LOGGER.debug(ARTIFACT_NAME_UNIQUE_ID, artifactDef.getArtifactName(), artifactDef.getUniqueId());
+ return componentsUtils.getResponseFormat(as);
+ }).left().map(ToscaRepresentation::make);
+ }
+
+ private Either<byte[], ActionStatus> getFromCassandra(String cassandraId) {
+ return artifactCassandraDao.getArtifact(cassandraId).right().map(operationstatus -> {
+ LOGGER.info("Failed to fetch artifact from Cassandra by id {} error {}.", cassandraId, operationstatus);
+ StorageOperationStatus storageStatus = DaoStatusConverter.convertCassandraStatusToStorageStatus(operationstatus);
+ return componentsUtils.convertFromStorageResponse(storageStatus);
+ }).left().map(DAOArtifactData::getDataAsArray);
+ }
+
+ private static <L, R> F<L, Either<L, R>> iff(Predicate<L> p, Function<L, Either<L, R>> ifTrue) {
+ return l -> p.test(l) ? ifTrue.apply(l) : Either.left(l);
+ }
+
+ private static <A, B> F<A, B> iff(Predicate<A> p, Supplier<B> s, Function<A, B> orElse) {
+ return a -> p.test(a) ? s.get() : orElse.apply(a);
+ }
+
+ private void addServiceMf(Component component, ZipOutputStream zip, LifecycleStateEnum lifecycleState, boolean isInCertificationRequest,
+ String fileName, byte[] mainYaml, String definitionsPath) throws IOException {
+ // add mf
+ if ((component.getComponentType() == ComponentTypeEnum.SERVICE) && (lifecycleState != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT)) {
+ String serviceName = component.getName();
+ String createdBy = component.getCreatorUserId();
+ String serviceVersion;
+ if (isInCertificationRequest) {
+ int tmp = Integer.valueOf(component.getVersion().split("\\.")[0]) + 1;
+ serviceVersion = String.valueOf(tmp) + ".0";
+ } else {
+ serviceVersion = component.getVersion();
+ }
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
+ format.setTimeZone(TimeZone.getTimeZone("UTC"));
+ Date date = new Date();
+ String releaseTime = format.format(date);
+ if (component.getCategories() == null || component.getCategories().get(0) == null) {
+ return;
+ }
+ String serviceType = component.getCategories().get(0).getName();
+ String description = component.getDescription();
+ String serviceTemplate = definitionsPath + fileName;
+ String hash = GeneralUtility.calculateMD5Base64EncodedByByteArray(mainYaml);
+ String nsMfBlock0 = createNsMfBlock0(serviceName, createdBy, serviceVersion, releaseTime, serviceType, description, serviceTemplate,
+ hash);
+ byte[] nsMfBlock0Byte = nsMfBlock0.getBytes();
+ zip.putNextEntry(new ZipEntry(SERVICE_MANIFEST));
+ zip.write(nsMfBlock0Byte);
+ }
+ }
+
+ private String createNsMfBlock0(String serviceName, String createdBy, String serviceVersion, String releaseTime, String serviceType,
+ String description, String serviceTemplate, String hash) {
+ final String block0template = "metadata??\n" + "ns_product_name: %s\n" + "ns_provider_id: %s\n" + "ns_package_version: %s\n" +
+ "ns_release_data_time: %s\n" + "ns_type: %s\n" + "ns_package_description: %s\n\n" + "Source: %s\n" + "Algorithm: MD5\n" + "Hash: %s\n\n";
+ return String.format(block0template, serviceName, createdBy, serviceVersion, releaseTime, serviceType, description, serviceTemplate, hash);
+ }
+
+ private boolean hasToWriteComponentSubstitutionType(final Component component) {
+ final Map<String, CategoryBaseTypeConfig> serviceNodeTypesConfig =
+ ConfigurationManager.getConfigurationManager().getConfiguration().getServiceBaseNodeTypes();
+ List<CategoryDefinition> categories = component.getCategories();
+ if (CollectionUtils.isNotEmpty(categories) && MapUtils.isNotEmpty(serviceNodeTypesConfig)
+ && serviceNodeTypesConfig.get(categories.get(0).getName()) != null) {
+ boolean doNotExtendBaseType = serviceNodeTypesConfig.get(categories.get(0).getName()).isDoNotExtendBaseType();
+ if (doNotExtendBaseType) {
+ return false;
+ }
+ }
+ if (component instanceof Service) {
+ return !ModelConverter.isAtomicComponent(component) && ((Service) component).isSubstituteCandidate();
+ }
+ return !ModelConverter.isAtomicComponent(component);
+ }
+
+ private Either<ZipOutputStream, ResponseFormat> writeComponentInterface(Either<ToscaRepresentation, ToscaError> interfaceRepresentation,
+ ZipOutputStream zip, String fileName, String definitionsPath) {
+ // TODO: This should not be done but we need this to keep the refactoring small enough to be easily reviewable
+ return writeComponentInterface(interfaceRepresentation, fileName, ZipWriter.live(zip), definitionsPath)
+ .map(void0 -> Either.<ZipOutputStream, ResponseFormat>left(zip)).recover(th -> {
+ LOGGER.error("#writeComponentInterface - zip writing failed with error: ", th);
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+ }).get();
+ }
+
+ private Try<Void> writeComponentInterface(
+ Either<ToscaRepresentation, ToscaError> interfaceRepresentation, String fileName, ZipWriter zw, String definitionsPath) {
+ Either<byte[], ToscaError> yml = interfaceRepresentation.left()
+ .map(ToscaRepresentation::getMainYaml);
+ return fromEither(yml, ToscaErrorException::new).flatMap(zw.write(definitionsPath + ToscaExportHandler.getInterfaceFilename(fileName)));
+ }
+
+ private List<Triple<String, String, Component>> writeComponentInterface(final Component component, final ZipOutputStream zip,
+ final String fileName, final String definitionsPath) {
+ final Either<ToscaRepresentation, ToscaError> interfaceRepresentation = toscaExportUtils.exportComponentInterface(component, false);
+ writeComponentInterface(interfaceRepresentation, zip, fileName, definitionsPath);
+ return interfaceRepresentation.left().value().getDependencies().getOrElse(new ArrayList<>());
+ }
+
+ private Either<ZipOutputStream, ResponseFormat> getZipOutputStreamResponseFormatEither(ZipOutputStream zip,
+ List<Triple<String, String, Component>> dependencies,
+ String definitionsPath)
+ throws IOException {
+ ComponentCache
+ innerComponentsCache = ComponentCache.overwritable(overwriteIfSameVersions()).onMerge((oldValue, newValue) ->
+ LOGGER.warn("Overwriting component invariantID {} of version {} with a newer version {}", oldValue.getId(),
+ oldValue.getComponentVersion(),
+ newValue.getComponentVersion()));
+ if (dependencies != null && !dependencies.isEmpty()) {
+ for (Triple<String, String, Component> d : dependencies) {
+ String cassandraId = d.getMiddle();
+ Component childComponent = d.getRight();
+ Either<byte[], ResponseFormat> entryData = getEntryData(cassandraId, childComponent).right()
+ .map(componentsUtils::getResponseFormat);
+ if (entryData.isRight()) {
+ return Either.right(entryData.right().value());
+ }
+ //fill innerComponentsCache
+ String fileName = d.getLeft();
+ innerComponentsCache.put(cassandraId, fileName, childComponent);
+ addInnerComponentsToCache(innerComponentsCache, childComponent);
+ }
+ //add inner components to CSAR
+ return addInnerComponentsToCSAR(zip, innerComponentsCache, definitionsPath);
+ }
+ return null;
+ }
+
+ private Either<ZipOutputStream, ResponseFormat> addInnerComponentsToCSAR(ZipOutputStream zip, ComponentCache innerComponentsCache,
+ String definitionsPath)
+ throws IOException {
+ for (ImmutableTriple<String, String, Component> ict : innerComponentsCache.iterable()) {
+ Component innerComponent = ict.getRight();
+ String icFileName = ict.getMiddle();
+ // add component to zip
+ Either<Tuple2<byte[], ZipEntry>, ResponseFormat> zipEntry = toZipEntry(ict, definitionsPath);
+ // TODO: this should not be done, we should instead compose this either further,
+
+ // but in order to keep this refactoring small, we'll stop here.
+ if (zipEntry.isRight()) {
+ return Either.right(zipEntry.right().value());
+ }
+ Tuple2<byte[], ZipEntry> value = zipEntry.left().value();
+ zip.putNextEntry(value._2);
+ zip.write(value._1);
+ // add component interface to zip
+ if (hasToWriteComponentSubstitutionType(innerComponent)) {
+ writeComponentInterface(innerComponent, zip, icFileName, definitionsPath);
+ }
+ }
+ return null;
+ }
+
+ private Either<Tuple2<byte[], ZipEntry>, ResponseFormat> toZipEntry(ImmutableTriple<String, String, Component> cachedEntry,
+ String definitionsPath) {
+ String cassandraId = cachedEntry.getLeft();
+ String fileName = cachedEntry.getMiddle();
+ Component innerComponent = cachedEntry.getRight();
+ return getEntryData(cassandraId, innerComponent).right().map(status -> {
+ LOGGER.debug("Failed adding to zip component {}, error {}", cassandraId, status);
+ return componentsUtils.getResponseFormat(status);
+ }).left().map(content -> new Tuple2<>(content, new ZipEntry(definitionsPath + fileName)));
+ }
+
+ private void addInnerComponentsToCache(ComponentCache componentCache, Component childComponent) {
+ javaListToVavrList(childComponent.getComponentInstances()).filter(ci -> componentCache.notCached(ci.getComponentUid())).forEach(ci -> {
+ // all resource must be only once!
+ Either<Resource, StorageOperationStatus> resource = toscaOperationFacade.getToscaElement(ci.getComponentUid());
+ Component componentRI = checkAndAddComponent(componentCache, ci, resource);
+ //if not atomic - insert inner components as well
+
+ // TODO: This could potentially create a StackOverflowException if the call stack
+
+ // happens to be too large. Tail-recursive optimization should be used here.
+ if (!ModelConverter.isAtomicComponent(componentRI)) {
+ addInnerComponentsToCache(componentCache, componentRI);
+ }
+ });
+ }
+
+ private Component checkAndAddComponent(ComponentCache componentCache, ComponentInstance ci, Either<Resource, StorageOperationStatus> resource) {
+ if (resource.isRight()) {
+ LOGGER.debug("Failed to fetch resource with id {} for instance {}", ci.getComponentUid(), ci.getName());
+ }
+ Component componentRI = resource.left().value();
+ Map<String, ArtifactDefinition> childToscaArtifacts = componentRI.getToscaArtifacts();
+ ArtifactDefinition childArtifactDefinition = childToscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
+ if (childArtifactDefinition != null) {
+ //add to cache
+ componentCache.put(childArtifactDefinition.getEsId(), childArtifactDefinition.getArtifactName(), componentRI);
+ }
+ return componentRI;
+ }
+
+ private Either<byte[], ActionStatus> getEntryData(String cassandraId, Component childComponent) {
+ if (cassandraId == null || cassandraId.isEmpty()) {
+ return toscaExportUtils.exportComponent(childComponent).right().map(toscaErrorToActionStatus(childComponent)).left()
+ .map(ToscaRepresentation::getMainYaml);
+ } else {
+ return getFromCassandra(cassandraId);
+ }
+ }
+
+ private F<ToscaError, ActionStatus> toscaErrorToActionStatus(Component childComponent) {
+ return toscaError -> {
+ LOGGER.debug("Failed to export tosca template for child component {} error {}", childComponent.getUniqueId(), toscaError);
+ return componentsUtils.convertFromToscaError(toscaError);
+ };
+ }
+
+ private Either<byte[], ResponseFormat> getLatestSchemaFilesFromCassandra() {
+ String fto = versionFirstThreeOctets;
+ return sdcSchemaFilesCassandraDao.getSpecificSchemaFiles(fto, CONFORMANCE_LEVEL).right().map(schemaFilesFetchDBError(fto)).left()
+ .bind(iff(List::isEmpty, () -> schemaFileFetchError(fto), s -> Either.left(s.iterator().next().getPayloadAsArray())));
+ }
+
+ private F<CassandraOperationStatus, ResponseFormat> schemaFilesFetchDBError(String firstThreeOctets) {
+ return cos -> {
+ LOGGER.debug("Failed to get the schema files SDC-Version: {} Conformance-Level {}. Please fix DB table accordingly.", firstThreeOctets,
+ CONFORMANCE_LEVEL);
+ StorageOperationStatus sos = DaoStatusConverter.convertCassandraStatusToStorageStatus(cos);
+ return componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(sos));
+ };
+ }
+
+ private Either<byte[], ResponseFormat> schemaFileFetchError(String firstThreeOctets) {
+ LOGGER.debug("Failed to get the schema files SDC-Version: {} Conformance-Level {}", firstThreeOctets, CONFORMANCE_LEVEL);
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_SCHEMA_FILES_NOT_FOUND, firstThreeOctets, CONFORMANCE_LEVEL));
+ }
+
+ /**
+ * Create a list of all derived nodes found on the package
+ *
+ * @param dependencies all node dependencies
+ * @return a list of nodes
+ */
+ private List<String> findNonRootNodesFromPackage(final List<Triple<String, String, Component>> dependencies) {
+ final List<String> nodes = new ArrayList<>();
+ if (CollectionUtils.isNotEmpty(dependencies)) {
+ final String NATIVE_ROOT = "tosca.nodes.Root";
+ dependencies.forEach(dependency -> {
+ if (dependency.getRight() instanceof Resource) {
+ final Resource resource = (Resource) dependency.getRight();
+ if (CollectionUtils.isNotEmpty(resource.getDerivedList())) {
+ resource.getDerivedList().stream().filter(node -> !nodes.contains(node) && !NATIVE_ROOT.equalsIgnoreCase(node))
+ .forEach(node -> nodes.add(node));
+ }
+ }
+ });
+ }
+ return nodes;
+ }
+
+ /**
+ * Writes to a CSAR zip from casandra schema data
+ *
+ * @param zipOutputStream stores the input stream content
+ * @param schemaFileZip zip data from Cassandra
+ * @param nodesFromPackage list of all nodes found on the onboarded package
+ */
+ private void addSchemaFilesFromCassandra(final ZipOutputStream zipOutputStream, final byte[] schemaFileZip, final List<String> nodesFromPackage,
+ final String definitionsPath) {
+ final int initSize = 2048;
+ LOGGER.debug("Starting copy from Schema file zip to CSAR zip");
+ try (final ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(
+ schemaFileZip)); final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
+ byteArrayOutputStream, initSize)) {
+ ZipEntry entry;
+ while ((entry = zipInputStream.getNextEntry()) != null) {
+ ZipUtils.checkForZipSlipInRead(entry);
+ final String entryName = entry.getName();
+ int readSize = initSize;
+ final byte[] entryData = new byte[initSize];
+ if (shouldZipEntryBeHandled(entryName)) {
+ if (NODES_YML.equalsIgnoreCase(entryName)) {
+ handleNode(zipInputStream, byteArrayOutputStream, nodesFromPackage);
+ } else {
+ while ((readSize = zipInputStream.read(entryData, 0, readSize)) != -1) {
+ bufferedOutputStream.write(entryData, 0, readSize);
+ }
+ bufferedOutputStream.flush();
+ }
+ byteArrayOutputStream.flush();
+ zipOutputStream.putNextEntry(new ZipEntry(definitionsPath + entryName));
+ zipOutputStream.write(byteArrayOutputStream.toByteArray());
+ zipOutputStream.flush();
+ byteArrayOutputStream.reset();
+ }
+ }
+ } catch (final Exception e) {
+ LOGGER.error("Error while writing the SDC schema file to the CSAR", e);
+ throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
+ }
+ LOGGER.debug("Finished copy from Schema file zip to CSAR zip");
+ }
+
+ /**
+ * Handles the nodes.yml zip entry, updating the nodes.yml to avoid duplicated nodes on it.
+ *
+ * @param zipInputStream the zip entry to be read
+ * @param byteArrayOutputStream an output stream in which the data is written into a byte array.
+ * @param nodesFromPackage list of all nodes found on the onboarded package
+ */
+ private void handleNode(final ZipInputStream zipInputStream, final ByteArrayOutputStream byteArrayOutputStream,
+ final List<String> nodesFromPackage) throws IOException {
+ final Map<String, Object> nodesFromArtifactFile = readYamlZipEntry(zipInputStream);
+ final Map<String, Object> nodesYaml = updateNodeYml(nodesFromPackage, nodesFromArtifactFile);
+ updateZipEntry(byteArrayOutputStream, nodesYaml);
+ }
+
+ /**
+ * Updates the zip entry from the given parameters
+ *
+ * @param byteArrayOutputStream an output stream in which the data is written into a byte array.
+ * @param nodesYaml a Map of nodes to be written
+ */
+ private void updateZipEntry(final ByteArrayOutputStream byteArrayOutputStream, final Map<String, Object> nodesYaml) throws IOException {
+ if (MapUtils.isNotEmpty(nodesYaml)) {
+ byteArrayOutputStream.write(new YamlUtil().objectToYaml(nodesYaml).getBytes());
+ }
+ }
+
+ /**
+ * Filters and removes all duplicated nodes found
+ *
+ * @param nodesFromPackage a List of all derived nodes found on the given package
+ * @param nodesFromArtifactFile represents the nodes.yml file stored in Cassandra
+ * @return a nodes Map updated
+ */
+ private Map<String, Object> updateNodeYml(final List<String> nodesFromPackage, final Map<String, Object> nodesFromArtifactFile) {
+ if (MapUtils.isNotEmpty(nodesFromArtifactFile)) {
+ final String nodeTypeBlock = TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName();
+ final Map<String, Object> nodeTypes = (Map<String, Object>) nodesFromArtifactFile.get(nodeTypeBlock);
+ nodesFromPackage.stream().filter(nodeTypes::containsKey).forEach(nodeTypes::remove);
+ nodesFromArtifactFile.replace(nodeTypeBlock, nodeTypes);
+ }
+ return nodesFromArtifactFile;
+ }
+
+ /**
+ * Writes a new zip entry
+ *
+ * @param zipInputStream the zip entry to be read
+ * @return a map of the given zip entry
+ */
+ private Map<String, Object> readYamlZipEntry(final ZipInputStream zipInputStream) throws IOException {
+ final int initSize = 2048;
+ final StringBuilder zipEntry = new StringBuilder();
+ final byte[] buffer = new byte[initSize];
+ int read = 0;
+ while ((read = zipInputStream.read(buffer, 0, initSize)) >= 0) {
+ zipEntry.append(new String(buffer, 0, read));
+ }
+ return (Map<String, Object>) new Yaml().load(zipEntry.toString());
+ }
+
+ /**
+ * Checks if the zip entry should or should not be added to the CSAR based on the given global type list
+ *
+ * @param entryName the zip entry name
+ * @return true if the zip entry should be handled
+ */
+ private boolean shouldZipEntryBeHandled(final String entryName) {
+ return ConfigurationManager.getConfigurationManager().getConfiguration().getGlobalCsarImports().stream()
+ .anyMatch(entry -> entry.contains(entryName));
+ }
+
+ private void addSchemaFilesByModel(final ZipOutputStream zipOutputStream, final String modelName,
+ final String definitionsPath, final boolean isSingleImportsFile) {
+ try {
+ final List<ToscaImportByModel> modelDefaultImportList = modelOperation.findAllModelImports(modelName, true);
+ final Set<Path> writtenEntryPathList = new HashSet<>();
+ final var defsPath = Path.of(definitionsPath);
+ Map<Path, byte[]> contentToMerge = new HashMap();
+ for (final ToscaImportByModel toscaImportByModel : modelDefaultImportList) {
+ var importPath = Path.of(toscaImportByModel.getFullPath());
+ if (!isSingleImportsFile) {
+ if (ADDITIONAL_TYPE_DEFINITIONS.equals(Paths.get(String.valueOf(importPath)).normalize().toString())) {
+ final Path entryPath = defsPath.resolve(importPath);
+ contentToMerge.put(entryPath, toscaImportByModel.getContent().getBytes(StandardCharsets.UTF_8));
+ } else {
+ if (writtenEntryPathList.contains(defsPath.resolve(importPath))) {
+ importPath =
+ ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
+ }
+ final Path entryPath = defsPath.resolve(importPath);
+ writtenEntryPathList.add(entryPath);
+ contentToMerge.put(entryPath, toscaImportByModel.getContent().getBytes(StandardCharsets.UTF_8));
+ }
+ } else {
+ if (writtenEntryPathList.contains(defsPath.resolve(importPath))) {
+ importPath =
+ ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
+ }
+ final Path entryPath = defsPath.resolve(importPath);
+ final var zipEntry = new ZipEntry(entryPath.toString());
+ zipOutputStream.putNextEntry(zipEntry);
+ writtenEntryPathList.add(entryPath);
+ final byte[] content = toscaImportByModel.getContent().getBytes(StandardCharsets.UTF_8);
+ zipOutputStream.write(content, 0, content.length);
+ zipOutputStream.closeEntry();
+ }
+ }
+ if (!isSingleImportsFile) {
+ byte[] mergingContent = new byte[0];
+ for (Map.Entry entry : contentToMerge.entrySet()) {
+ if (ADDITIONAL_TYPE_DEFINITIONS.equals(Paths.get(String.valueOf(entry.getKey())).normalize().toString())) {
+ mergingContent = (byte[]) entry.getValue();
+ } else {
+ final var zipEntry = new ZipEntry(entry.getKey().toString());
+ zipOutputStream.putNextEntry(zipEntry);
+ writtenEntryPathList.add((Path) entry.getKey());
+ zipOutputStream.write(Bytes.concat(mergingContent, (byte[]) entry.getValue()), 0,
+ ((byte[]) entry.getValue()).length);
+ zipOutputStream.closeEntry();
+ }
+ }
+ }
+ } catch (final IOException e) {
+ LOGGER.error(String.valueOf(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR), CsarUtils.class.getName(),
+ "Error while writing the schema files by model to the CSAR", e);
+ throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.CSAR_TOSCA_IMPORTS_ERROR));
+ }
+ }
+
+ private Either<CsarDefinition, ResponseFormat> collectComponentCsarDefinition(Component component) {
+ ComponentArtifacts componentArtifacts = new ComponentArtifacts();
+ Component updatedComponent = component;
+
+ //get service to receive the AII artifacts uploaded to the service
+ if (updatedComponent.getComponentType() == ComponentTypeEnum.SERVICE) {
+ Either<Service, StorageOperationStatus> getServiceResponse = toscaOperationFacade.getToscaElement(updatedComponent.getUniqueId());
+
+ if (getServiceResponse.isRight()) {
+ ActionStatus actionStatus = componentsUtils.convertFromStorageResponse(getServiceResponse.right().value());
+ return Either.right(componentsUtils.getResponseFormat(actionStatus));
+ }
+
+ updatedComponent = getServiceResponse.left().value();
+ }
+
+ //find the artifacts of the main component, it would have its composed instances artifacts in a separate folder
+ ComponentTypeArtifacts componentInstanceArtifacts = new ComponentTypeArtifacts();
+ ArtifactsInfo artifactsInfo = collectComponentArtifacts(updatedComponent);
+ componentInstanceArtifacts.setComponentArtifacts(artifactsInfo);
+ componentArtifacts.setMainTypeAndCIArtifacts(componentInstanceArtifacts);
+
+ Map<String, ComponentTypeArtifacts> resourceTypeArtifacts = componentArtifacts
+ .getComponentTypeArtifacts(); //artifacts mapped by the component type(tosca name+version)
+ //get the component instances
+ List<ComponentInstance> componentInstances = updatedComponent.getComponentInstances();
+ if (componentInstances != null) {
+ for (ComponentInstance componentInstance : componentInstances) {
+ //call recursive to find artifacts for all the path
+ Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts = collectComponentInstanceArtifacts(
+ updatedComponent, componentInstance, resourceTypeArtifacts, componentInstanceArtifacts);
+ if (collectComponentInstanceArtifacts.isRight()) {
+ return Either.right(collectComponentInstanceArtifacts.right().value());
+ }
+ }
+ }
+
+ if (LOGGER.isDebugEnabled()) {
+ printResult(componentArtifacts, updatedComponent.getName());
+ }
+
+ return Either.left(new CsarDefinition(componentArtifacts));
+ }
+
+ private void printResult(ComponentArtifacts componentArtifacts, String name) {
+ StringBuilder result = new StringBuilder();
+ result.append("Artifacts of main component " + name + "\n");
+ ComponentTypeArtifacts componentInstanceArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
+ printArtifacts(componentInstanceArtifacts);
+ result.append("Type Artifacts\n");
+ for (Map.Entry<String, ComponentTypeArtifacts> typeArtifacts : componentArtifacts.getComponentTypeArtifacts().entrySet()) {
+ result.append("Folder " + typeArtifacts.getKey() + "\n");
+ result.append(printArtifacts(typeArtifacts.getValue()));
+ }
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(result.toString());
+ }
+ }
+
+ private String printArtifacts(ComponentTypeArtifacts componentInstanceArtifacts) {
+ StringBuilder result = new StringBuilder();
+ ArtifactsInfo artifactsInfo = componentInstanceArtifacts.getComponentArtifacts();
+ Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componentArtifacts = artifactsInfo.getArtifactsInfo();
+ printArtifacts(componentArtifacts);
+ result = result.append("Resources\n");
+ for (Map.Entry<String, ArtifactsInfo> resourceInstance : componentInstanceArtifacts.getComponentInstancesArtifacts().entrySet()) {
+ result.append("Folder" + resourceInstance.getKey() + "\n");
+ result.append(printArtifacts(resourceInstance.getValue().getArtifactsInfo()));
+ }
+
+ return result.toString();
+ }
+
+ private String printArtifacts(Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componetArtifacts) {
+ StringBuilder result = new StringBuilder();
+ for (Map.Entry<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactGroup : componetArtifacts.entrySet()) {
+ result.append(" " + artifactGroup.getKey().getType());
+ for (Map.Entry<String, List<ArtifactDefinition>> groupArtifacts : artifactGroup.getValue().entrySet()) {
+ result.append(" " + groupArtifacts.getKey());
+ for (ArtifactDefinition artifact : groupArtifacts.getValue()) {
+ result.append(" " + artifact.getArtifactDisplayName());
+ }
+ }
+ }
+
+ return result.toString();
+ }
+
+ private Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts(Component parentComponent, ComponentInstance componentInstance,
+ Map<String, ComponentTypeArtifacts> resourcesTypeArtifacts,
+ ComponentTypeArtifacts instanceArtifactsLocation) {
+ //1. get the component instance component
+ String componentUid;
+ if (componentInstance.getOriginType() == OriginTypeEnum.ServiceProxy) {
+ componentUid = componentInstance.getSourceModelUid();
+ } else {
+ componentUid = componentInstance.getComponentUid();
+ }
+ Either<Component, StorageOperationStatus> component = toscaOperationFacade.getToscaElement(componentUid);
+ if (component.isRight()) {
+ LOGGER.error("Failed to fetch resource with id {} for instance {}", componentUid, parentComponent.getUUID());
+ return Either.right(componentsUtils.getResponseFormat(ActionStatus.ASSET_NOT_FOUND_DURING_CSAR_CREATION,
+ parentComponent.getComponentType().getValue(), parentComponent.getUUID(),
+ componentInstance.getOriginType().getComponentType().getValue(), componentUid));
+ }
+ Component fetchedComponent = component.left().value();
+
+ //2. fill the artifacts for the current component parent type
+ String toscaComponentName =
+ componentInstance.getToscaComponentName() + "_v" + componentInstance.getComponentVersion();
+
+ // if there are no artifacts for this component type we need to fetch and build them
+ ComponentTypeArtifacts componentParentArtifacts = Optional
+ .ofNullable(resourcesTypeArtifacts.get(toscaComponentName))
+ .orElseGet(() -> collectComponentTypeArtifacts(fetchedComponent));
+
+ if (componentParentArtifacts.getComponentArtifacts().isNotEmpty()) {
+ resourcesTypeArtifacts.put(toscaComponentName, componentParentArtifacts);
+ }
+
+ //3. find the artifacts specific to the instance
+ Map<String, List<ArtifactDefinition>> componentInstanceSpecificInformationalArtifacts =
+ getComponentInstanceSpecificArtifacts(componentInstance.getArtifacts(),
+ componentParentArtifacts.getComponentArtifacts().getArtifactsInfo(), ArtifactGroupTypeEnum.INFORMATIONAL);
+ Map<String, List<ArtifactDefinition>> componentInstanceSpecificDeploymentArtifacts =
+ getComponentInstanceSpecificArtifacts(componentInstance.getDeploymentArtifacts(),
+ componentParentArtifacts.getComponentArtifacts().getArtifactsInfo(), ArtifactGroupTypeEnum.DEPLOYMENT);
+
+ //4. add the instances artifacts to the component type
+ ArtifactsInfo artifactsInfo = new ArtifactsInfo();
+ if (!componentInstanceSpecificInformationalArtifacts.isEmpty()) {
+ artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.INFORMATIONAL, componentInstanceSpecificInformationalArtifacts);
+ }
+ if (!componentInstanceSpecificDeploymentArtifacts.isEmpty()) {
+ artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.DEPLOYMENT, componentInstanceSpecificDeploymentArtifacts);
+ }
+ if (!artifactsInfo.isEmpty()) {
+ instanceArtifactsLocation.addComponentInstancesArtifacts(componentInstance.getNormalizedName(), artifactsInfo);
+ }
+
+ //5. do the same for all the component instances
+ List<ComponentInstance> componentInstances = fetchedComponent.getComponentInstances();
+ if (componentInstances != null) {
+ for (ComponentInstance childComponentInstance : componentInstances) {
+ Either<Boolean, ResponseFormat> collectComponentInstanceArtifacts = collectComponentInstanceArtifacts(
+ fetchedComponent, childComponentInstance, resourcesTypeArtifacts, componentParentArtifacts);
+ if (collectComponentInstanceArtifacts.isRight()) {
+ return collectComponentInstanceArtifacts;
+ }
+ }
+ }
+
+ return Either.left(true);
+ }
+
+ private Map<String, List<ArtifactDefinition>> getComponentInstanceSpecificArtifacts(Map<String, ArtifactDefinition> componentArtifacts,
+ Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componentTypeArtifacts,
+ ArtifactGroupTypeEnum artifactGroupTypeEnum) {
+ Map<String, List<ArtifactDefinition>> parentArtifacts = componentTypeArtifacts
+ .get(artifactGroupTypeEnum); //the artfiacts of the component itself and not the instance
+
+ Map<String, List<ArtifactDefinition>> artifactsByTypeOfComponentInstance = new HashMap<>();
+ if (componentArtifacts != null) {
+ for (ArtifactDefinition artifact : componentArtifacts.values()) {
+ List<ArtifactDefinition> parentArtifactsByType = null;
+ if (parentArtifacts != null) {
+ parentArtifactsByType = parentArtifacts.get(artifact.getArtifactType());
+ }
+ //the artifact is of instance
+ if (parentArtifactsByType == null || !parentArtifactsByType.contains(artifact)) {
+ List<ArtifactDefinition> typeArtifacts = artifactsByTypeOfComponentInstance.get(artifact.getArtifactType());
+ if (typeArtifacts == null) {
+ typeArtifacts = new ArrayList<>();
+ artifactsByTypeOfComponentInstance.put(artifact.getArtifactType(), typeArtifacts);
+ }
+ typeArtifacts.add(artifact);
+ }
+ }
+ }
+
+ return artifactsByTypeOfComponentInstance;
+ }
+
+ private ComponentTypeArtifacts collectComponentTypeArtifacts(Component fetchedComponent) {
+ ArtifactsInfo componentArtifacts = collectComponentArtifacts(fetchedComponent);
+ ComponentTypeArtifacts componentArtifactsInfo = new ComponentTypeArtifacts();
+ if (componentArtifacts.isNotEmpty()) {
+ componentArtifactsInfo.setComponentArtifacts(componentArtifacts);
+ }
+ return componentArtifactsInfo;
+ }
+
+ private ArtifactsInfo collectComponentArtifacts(Component component) {
+ Map<String, ArtifactDefinition> informationalArtifacts = component.getArtifacts();
+ Map<String, List<ArtifactDefinition>> informationalArtifactsByType = collectGroupArtifacts(informationalArtifacts);
+ Map<String, ArtifactDefinition> deploymentArtifacts = component.getDeploymentArtifacts();
+ Map<String, List<ArtifactDefinition>> deploymentArtifactsByType = collectGroupArtifacts(deploymentArtifacts);
+ ArtifactsInfo artifactsInfo = new ArtifactsInfo();
+ if (!informationalArtifactsByType.isEmpty()) {
+ artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.INFORMATIONAL, informationalArtifactsByType);
+ }
+ if (!deploymentArtifactsByType.isEmpty()) {
+ artifactsInfo.addArtifactsToGroup(ArtifactGroupTypeEnum.DEPLOYMENT, deploymentArtifactsByType);
+ }
+
+ return artifactsInfo;
+ }
+
+ private Map<String, List<ArtifactDefinition>> collectGroupArtifacts(
+ final Map<String, ArtifactDefinition> componentArtifacts) {
+ final Map<String, List<ArtifactDefinition>> artifactsByType = new HashMap<>();
+ for (final ArtifactDefinition artifact : componentArtifacts.values()) {
+ if (artifact.getArtifactUUID() != null) {
+ artifactsByType.putIfAbsent(artifact.getArtifactType(), new ArrayList<>());
+ final List<ArtifactDefinition> typeArtifacts = artifactsByType.get(artifact.getArtifactType());
+ typeArtifacts.add(artifact);
+ }
+ }
+ return artifactsByType;
+ }
+
+ private Either<ZipOutputStream, ResponseFormat> writeAllFilesToCsar(Component mainComponent, CsarDefinition csarDefinition,
+ ZipOutputStream zipstream, boolean isInCertificationRequest)
+ throws IOException {
+ ComponentArtifacts componentArtifacts = csarDefinition.getComponentArtifacts();
+ Either<ZipOutputStream, ResponseFormat> writeComponentArtifactsToSpecifiedPath = writeComponentArtifactsToSpecifiedPath(mainComponent,
+ componentArtifacts, zipstream, ARTIFACTS_PATH, isInCertificationRequest);
+ if (writeComponentArtifactsToSpecifiedPath.isRight()) {
+ return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
+ }
+ ComponentTypeArtifacts mainTypeAndCIArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
+ writeComponentArtifactsToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent, mainTypeAndCIArtifacts.getComponentArtifacts(),
+ zipstream, ARTIFACTS_PATH, isInCertificationRequest);
+ if (writeComponentArtifactsToSpecifiedPath.isRight()) {
+ return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
+ }
+ Map<String, ArtifactsInfo> componentInstancesArtifacts = mainTypeAndCIArtifacts.getComponentInstancesArtifacts();
+ String currentPath = ARTIFACTS_PATH + RESOURCES_PATH;
+ for (String keyAssetName : componentInstancesArtifacts.keySet()) {
+ ArtifactsInfo artifactsInfo = componentInstancesArtifacts.get(keyAssetName);
+ String pathWithAssetName = currentPath + keyAssetName + PATH_DELIMITER;
+ writeComponentArtifactsToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent, artifactsInfo, zipstream, pathWithAssetName,
+ isInCertificationRequest);
+ if (writeComponentArtifactsToSpecifiedPath.isRight()) {
+ return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
+ }
+ }
+ writeComponentArtifactsToSpecifiedPath = writeOperationsArtifactsToCsar(mainComponent, zipstream);
+ if (writeComponentArtifactsToSpecifiedPath.isRight()) {
+ return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
+ }
+ return Either.left(zipstream);
+ }
+
+ private Either<ZipOutputStream, ResponseFormat> writeOperationsArtifactsToCsar(Component component, ZipOutputStream zipstream) {
+ if (checkComponentBeforeOperation(component)) {
+ return Either.left(zipstream);
+ }
+ for (Map.Entry<String, InterfaceDefinition> interfaceEntry : ((Resource) component).getInterfaces().entrySet()) {
+ for (OperationDataDefinition operation : interfaceEntry.getValue().getOperations().values()) {
+ try {
+ if (checkComponentBeforeWrite(component, interfaceEntry, operation)) {
+ continue;
+ }
+ final String artifactUUID = operation.getImplementation().getArtifactUUID();
+ if (artifactUUID == null) {
+ continue;
+ }
+ final Either<byte[], ActionStatus> artifactFromCassandra = getFromCassandra(artifactUUID);
+ final String artifactName = operation.getImplementation().getArtifactName();
+ if (artifactFromCassandra.isRight()) {
+ LOGGER.error(ARTIFACT_NAME_UNIQUE_ID, artifactName, artifactUUID);
+ LOGGER.error("Failed to get {} payload from DB reason: {}", artifactName, artifactFromCassandra.right().value());
+ return Either.right(componentsUtils.getResponseFormat(
+ ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION, "Resource", component.getUniqueId(), artifactName, artifactUUID));
+ }
+ zipstream.putNextEntry(new ZipEntry(OperationArtifactUtil.createOperationArtifactPath(component, null, operation, true)));
+ zipstream.write(artifactFromCassandra.left().value());
+ } catch (IOException e) {
+ LOGGER.error("Component Name {}, Interface Name {}, Operation Name {}", component.getNormalizedName(), interfaceEntry.getKey(),
+ operation.getName());
+ LOGGER.error("Error while writing the operation's artifacts to the CSAR", e);
+ return Either.right(componentsUtils.getResponseFormat(ERROR_DURING_CSAR_CREATION, "Resource", component.getUniqueId()));
+ }
+ }
+ }
+ return Either.left(zipstream);
+ }
+
+ private boolean checkComponentBeforeWrite(Component component, Map.Entry<String, InterfaceDefinition> interfaceEntry,
+ OperationDataDefinition operation) {
+ final ArtifactDataDefinition implementation = operation.getImplementation();
+ if (implementation == null) {
+ LOGGER.debug("Component Name {}, Interface Id {}, Operation Name {} - no Operation Implementation found", component.getNormalizedName(),
+ interfaceEntry.getValue().getUniqueId(), operation.getName());
+ return true;
+ }
+ final String artifactName = implementation.getArtifactName();
+ if (artifactName == null) {
+ LOGGER.debug("Component Name {}, Interface Id {}, Operation Name {} - no artifact found", component.getNormalizedName(),
+ interfaceEntry.getValue().getUniqueId(), operation.getName());
+ return true;
+ }
+ if (OperationArtifactUtil.artifactNameIsALiteralValue(artifactName)) {
+ LOGGER.debug("Component Name {}, Interface Id {}, Operation Name {} - artifact name is a literal value rather than an SDC artifact",
+ component.getNormalizedName(), interfaceEntry.getValue().getUniqueId(), operation.getName());
+ return true;
+ }
+ return false;
+ }
+
+ private boolean checkComponentBeforeOperation(Component component) {
+ if (component instanceof Service) {
+ return true;
+ }
+ if (Objects.isNull(((Resource) component).getInterfaces())) {
+ LOGGER.debug("Component Name {}- no interfaces found", component.getNormalizedName());
+ return true;
+ }
+ return false;
+ }
+
+ private Either<ZipOutputStream, ResponseFormat> writeArtifactsInfoToSpecifiedPath(final Component mainComponent,
+ final ArtifactsInfo currArtifactsInfo,
+ final ZipOutputStream zip, final String path,
+ final boolean isInCertificationRequest) throws IOException {
+ final Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactsInfo = currArtifactsInfo.getArtifactsInfo();
+ for (final ArtifactGroupTypeEnum artifactGroupTypeEnum : artifactsInfo.keySet()) {
+ final String groupTypeFolder = path + WordUtils.capitalizeFully(artifactGroupTypeEnum.getType()) + PATH_DELIMITER;
+ final Map<String, List<ArtifactDefinition>> artifactTypesMap = artifactsInfo.get(artifactGroupTypeEnum);
+ for (final String artifactType : artifactTypesMap.keySet()) {
+ final List<ArtifactDefinition> artifactDefinitionList = artifactTypesMap.get(artifactType);
+ String artifactTypeFolder = groupTypeFolder + artifactType + PATH_DELIMITER;
+ if (ArtifactTypeEnum.WORKFLOW.getType().equals(artifactType) && path.contains(ARTIFACTS_PATH + RESOURCES_PATH)) {
+ // Ignore this packaging as BPMN artifacts needs to be packaged in different manner
+ continue;
+ }
+ if (ArtifactTypeEnum.WORKFLOW.getType().equals(artifactType)) {
+ artifactTypeFolder += OperationArtifactUtil.BPMN_ARTIFACT_PATH + File.separator;
+ } else if (ArtifactTypeEnum.ONBOARDED_PACKAGE.getType().equals(artifactType)) {
+ // renaming legacy folder ONBOARDED_PACKAGE to the new folder ETSI_PACKAGE
+ artifactTypeFolder = artifactTypeFolder
+ .replace(ArtifactTypeEnum.ONBOARDED_PACKAGE.getType(), ArtifactTypeEnum.ETSI_PACKAGE.getType());
+ }
+ // TODO: We should not do this but in order to keep this refactoring small enough,
+
+ // we'll leave this as is for now
+ List<ArtifactDefinition> collect = filterArtifactDefinitionToZip(mainComponent, artifactDefinitionList, isInCertificationRequest)
+ .collect(Collectors.toList());
+ for (ArtifactDefinition ad : collect) {
+ zip.putNextEntry(new ZipEntry(artifactTypeFolder + ad.getArtifactName()));
+ zip.write(ad.getPayloadData());
+ }
+ }
+ }
+ return Either.left(zip);
+ }
+
+ private Stream<ArtifactDefinition> filterArtifactDefinitionToZip(Component mainComponent, List<ArtifactDefinition> artifactDefinitionList,
+ boolean isInCertificationRequest) {
+ return artifactDefinitionList.stream().filter(shouldBeInZip(isInCertificationRequest, mainComponent)).map(this::fetchPayLoadData)
+ .filter(Either::isLeft).map(e -> e.left().value());
+ }
+
+ private Predicate<ArtifactDefinition> shouldBeInZip(boolean isInCertificationRequest, Component component) {
+ return artifactDefinition -> !(!isInCertificationRequest && component.isService() && artifactDefinition.isHeatEnvType() || artifactDefinition
+ .hasNoMandatoryEsId());
+ }
+
+ private Either<ArtifactDefinition, ActionStatus> fetchPayLoadData(ArtifactDefinition ad) {
+ byte[] payloadData = ad.getPayloadData();
+ if (payloadData == null) {
+ return getFromCassandra(ad.getEsId()).left().map(pd -> {
+ ad.setPayload(pd);
+ return ad;
+ }).right().map(as -> {
+ LOGGER.debug(ARTIFACT_NAME_UNIQUE_ID, ad.getArtifactName(), ad.getUniqueId());
+ LOGGER.debug("Failed to get {} payload from DB reason: {}", ad.getArtifactName(), as);
+ return as;
+ });
+ } else {
+ return Either.left(ad);
+ }
+ }
+
+ private Either<ZipOutputStream, ResponseFormat> writeComponentArtifactsToSpecifiedPath(Component mainComponent,
+ ComponentArtifacts componentArtifacts,
+ ZipOutputStream zipstream, String currentPath,
+ boolean isInCertificationRequest) throws IOException {
+ Map<String, ComponentTypeArtifacts> componentTypeArtifacts = componentArtifacts.getComponentTypeArtifacts();
+ //Keys are defined:
+
+ //<Inner Asset TOSCA name (e.g. VFC name)> folder name: <Inner Asset TOSCA name (e.g. VFC name)>_v<version>.
+
+ //E.g. "org.openecomp.resource.vf.vipr_atm_v1.0"
+ Set<String> componentTypeArtifactsKeys = componentTypeArtifacts.keySet();
+ for (String keyAssetName : componentTypeArtifactsKeys) {
+ ComponentTypeArtifacts componentInstanceArtifacts = componentTypeArtifacts.get(keyAssetName);
+ ArtifactsInfo componentArtifacts2 = componentInstanceArtifacts.getComponentArtifacts();
+ String pathWithAssetName = currentPath + keyAssetName + PATH_DELIMITER;
+ Either<ZipOutputStream, ResponseFormat> writeArtifactsInfoToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent,
+ componentArtifacts2, zipstream, pathWithAssetName, isInCertificationRequest);
+ if (writeArtifactsInfoToSpecifiedPath.isRight()) {
+ return writeArtifactsInfoToSpecifiedPath;
+ }
+ }
+ return Either.left(zipstream);
+ }
+
+ private Either<ToscaRepresentation, ResponseFormat> generateToscaRepresentation(Component component, boolean isSkipImports) {
+ return toscaExportUtils.exportComponent(component, isSkipImports).right().map(toscaError -> {
+ LOGGER.debug("exportComponent failed {}", toscaError);
+ return componentsUtils.getResponseFormat(componentsUtils.convertFromToscaError(toscaError));
+ });
+ }
+
+ private String createToscaBlock0(String metaFileVersion, String csarVersion, String createdBy, String entryDef, boolean isAsdPackage,
+ String definitionsPath) {
+ final String block0template = "TOSCA-Meta-File-Version: %s\nCSAR-Version: %s\nCreated-By: %s\nEntry-Definitions: "
+ + definitionsPath + "%s\n%s\nName: csar.meta\nContent-Type: text/plain\n";
+ return String.format(block0template, metaFileVersion, csarVersion, createdBy, entryDef, isAsdPackage ? "entry_definition_type: asd" : "");
+ }
+
+ private class CsarDefinition {
+
+ private ComponentArtifacts componentArtifacts;
+
+ // add list of tosca artifacts and meta describes CSAR zip root
+ public CsarDefinition(ComponentArtifacts componentArtifacts) {
+ this.componentArtifacts = componentArtifacts;
+ }
+
+ public ComponentArtifacts getComponentArtifacts() {
+ return componentArtifacts;
+ }
+ }
+
+ private class ComponentArtifacts {
+
+ //artifacts of the component and CI's artifacts contained in it's composition (represents Informational, Deployment & Resource folders of main component)
+ private ComponentTypeArtifacts mainTypeAndCIArtifacts;
+ //artifacts of all component types mapped by their tosca name
+ private Map<String, ComponentTypeArtifacts> componentTypeArtifacts;
+
+ public ComponentArtifacts() {
+ mainTypeAndCIArtifacts = new ComponentTypeArtifacts();
+ componentTypeArtifacts = new HashMap<>();
+ }
+
+ public ComponentTypeArtifacts getMainTypeAndCIArtifacts() {
+ return mainTypeAndCIArtifacts;
+ }
+
+ public void setMainTypeAndCIArtifacts(ComponentTypeArtifacts componentInstanceArtifacts) {
+ this.mainTypeAndCIArtifacts = componentInstanceArtifacts;
+ }
+
+ public Map<String, ComponentTypeArtifacts> getComponentTypeArtifacts() {
+ return componentTypeArtifacts;
+ }
+ }
+
+ /**
+ * The artifacts of the component and of all its composed instances
+ */
+ private class ComponentTypeArtifacts {
+
+ private ArtifactsInfo componentArtifacts; //component artifacts (describes the Informational Deployment folders)
+
+ private Map<String, ArtifactsInfo> componentInstancesArtifacts; //artifacts of the composed instances mapped by the resourceInstance normalized name (describes the Resources folder)
+
+ public ComponentTypeArtifacts() {
+ componentArtifacts = new ArtifactsInfo();
+ componentInstancesArtifacts = new HashMap<>();
+ }
+
+ public ArtifactsInfo getComponentArtifacts() {
+ return componentArtifacts;
+ }
+
+ public void setComponentArtifacts(ArtifactsInfo artifactsInfo) {
+ this.componentArtifacts = artifactsInfo;
+ }
+
+ public Map<String, ArtifactsInfo> getComponentInstancesArtifacts() {
+ return componentInstancesArtifacts;
+ }
+
+ public void addComponentInstancesArtifacts(String normalizedName, ArtifactsInfo artifactsInfo) {
+ componentInstancesArtifacts.put(normalizedName, artifactsInfo);
+ }
+ }
+
+ /**
+ * The artifacts Definition saved by their structure
+ */
+ private class ArtifactsInfo {
+ //Key is the type of artifacts(Informational/Deployment)
+
+ //Value is a map between an artifact type and a list of all artifacts of this type
+ private Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactsInfoField;
+
+ public ArtifactsInfo() {
+ this.artifactsInfoField = new EnumMap<>(ArtifactGroupTypeEnum.class);
+ }
+
+ public Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> getArtifactsInfo() {
+ return artifactsInfoField;
+ }
+
+ public void addArtifactsToGroup(ArtifactGroupTypeEnum artifactGroup, Map<String, List<ArtifactDefinition>> artifactsDefinition) {
+ if (artifactsInfoField.get(artifactGroup) == null) {
+ artifactsInfoField.put(artifactGroup, artifactsDefinition);
+ } else {
+ Map<String, List<ArtifactDefinition>> artifactTypeEnumListMap = artifactsInfoField.get(artifactGroup);
+ artifactTypeEnumListMap.putAll(artifactsDefinition);
+ artifactsInfoField.put(artifactGroup, artifactTypeEnumListMap);
+ }
+ }
+
+ public boolean isEmpty() {
+ return artifactsInfoField.isEmpty();
+ }
+
+ public boolean isNotEmpty() {
+ return !isEmpty();
+ }
+ }
+
+ public static class ToscaErrorException extends Exception {
+
+ ToscaErrorException(ToscaError error) {
+ super("Error while exporting component's interface (toscaError:" + error + ")");
+ }
+ }
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ComponentCache.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ComponentCache.java
index 57ebcf6822..51719236ca 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ComponentCache.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ComponentCache.java
@@ -27,6 +27,7 @@ import io.vavr.collection.Stream;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import lombok.EqualsAndHashCode;
+import lombok.Getter;
import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.openecomp.sdc.be.model.Component;
@@ -132,6 +133,7 @@ public final class ComponentCache {
* Entry stored by the cache
*/
@EqualsAndHashCode
+ @Getter
public static final class CacheEntry {
final String id;
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
index 6a35307b2a..35854d3570 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
@@ -19,124 +19,65 @@
*/
package org.openecomp.sdc.be.tosca;
-import static org.openecomp.sdc.be.dao.api.ActionStatus.ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION;
-import static org.openecomp.sdc.be.dao.api.ActionStatus.ERROR_DURING_CSAR_CREATION;
-import static org.openecomp.sdc.be.tosca.ComponentCache.MergeStrategy.overwriteIfSameVersions;
-import static org.openecomp.sdc.be.tosca.FJToVavrHelper.Try0.fromEither;
-
import fj.F;
import fj.data.Either;
-import io.vavr.Tuple2;
-import io.vavr.control.Option;
-import io.vavr.control.Try;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.File;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Path;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Objects;
import java.util.Optional;
import java.util.Set;
-import java.util.TimeZone;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
-import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.ImmutableTriple;
-import org.apache.commons.lang3.tuple.Triple;
-import org.apache.commons.text.WordUtils;
-import org.onap.sdc.tosca.services.YamlUtil;
import org.openecomp.sdc.be.components.impl.ImportUtils;
-import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
-import org.openecomp.sdc.be.config.*;
+import org.openecomp.sdc.be.config.ArtifactConfigManager;
+import org.openecomp.sdc.be.config.ArtifactConfiguration;
+import org.openecomp.sdc.be.config.ComponentType;
+import org.openecomp.sdc.be.config.ConfigurationManager;
import org.openecomp.sdc.be.dao.api.ActionStatus;
-import org.openecomp.sdc.be.dao.cassandra.ArtifactCassandraDao;
-import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus;
-import org.openecomp.sdc.be.dao.cassandra.SdcSchemaFilesCassandraDao;
-import org.openecomp.sdc.be.data.model.ToscaImportByModel;
-import org.openecomp.sdc.be.datatypes.elements.ArtifactDataDefinition;
-import org.openecomp.sdc.be.datatypes.elements.OperationDataDefinition;
import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
import org.openecomp.sdc.be.datatypes.enums.OriginTypeEnum;
import org.openecomp.sdc.be.impl.ComponentsUtils;
import org.openecomp.sdc.be.model.ArtifactDefinition;
import org.openecomp.sdc.be.model.Component;
import org.openecomp.sdc.be.model.ComponentInstance;
-import org.openecomp.sdc.be.model.InterfaceDefinition;
-import org.openecomp.sdc.be.model.LifecycleStateEnum;
-import org.openecomp.sdc.be.model.Resource;
import org.openecomp.sdc.be.model.Service;
-import org.openecomp.sdc.be.model.category.CategoryDefinition;
import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
-import org.openecomp.sdc.be.model.jsonjanusgraph.utils.ModelConverter;
import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
-import org.openecomp.sdc.be.model.operations.impl.DaoStatusConverter;
-import org.openecomp.sdc.be.model.operations.impl.ModelOperation;
-import org.openecomp.sdc.be.plugins.CsarEntryGenerator;
-import org.openecomp.sdc.be.resources.data.DAOArtifactData;
-import org.openecomp.sdc.be.tosca.utils.OperationArtifactUtil;
-import org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum;
import org.openecomp.sdc.common.api.ArtifactGroupTypeEnum;
import org.openecomp.sdc.common.api.ArtifactTypeEnum;
-import org.openecomp.sdc.common.impl.ExternalConfiguration;
import org.openecomp.sdc.common.log.elements.LoggerSupportability;
-import org.openecomp.sdc.common.log.enums.EcompLoggerErrorCode;
import org.openecomp.sdc.common.log.enums.LoggerSupportabilityActions;
import org.openecomp.sdc.common.log.enums.StatusCode;
import org.openecomp.sdc.common.log.wrappers.Logger;
import org.openecomp.sdc.common.util.GeneralUtility;
import org.openecomp.sdc.common.util.ValidationUtils;
-import org.openecomp.sdc.common.zip.ZipUtils;
import org.openecomp.sdc.exception.ResponseFormat;
import org.springframework.beans.factory.annotation.Autowired;
-import org.yaml.snakeyaml.Yaml;
@org.springframework.stereotype.Component("csar-utils")
public class CsarUtils {
- public static final String NODES_YML = "nodes.yml";
public static final String ARTIFACTS_PATH = "Artifacts/";
public static final String ARTIFACTS = "Artifacts";
public static final String ARTIFACT_CREATED_FROM_CSAR = "Artifact created from csar";
private static final Logger log = Logger.getLogger(CsarUtils.class);
private static final LoggerSupportability loggerSupportability = LoggerSupportability.getLogger(CsarUtils.class.getName());
private static final String PATH_DELIMITER = "/";
- private static final String CONFORMANCE_LEVEL = ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel();
- private static final String SDC_VERSION = ExternalConfiguration.getAppVersion();
- private static final String RESOURCES_PATH = "Resources/";
- private static final String DEFINITIONS_PATH = "Definitions/";
private static final String CSAR_META_VERSION = "1.0";
private static final String CSAR_META_PATH_FILE_NAME = "csar.meta";
- private static final String TOSCA_META_PATH_FILE_NAME = "TOSCA-Metadata/TOSCA.meta";
- private static final String TOSCA_META_VERSION = "1.0";
- private static final String CSAR_VERSION = "1.1";
- // add manifest
- private static final String SERVICE_MANIFEST = "NS.mf";
private static final String DEFINITION = "Definitions";
private static final String DEL_PATTERN = "([/\\\\]+)";
private static final String WORD_PATTERN = "\\w\\_\\@\\-\\.\\s]+)";
@@ -152,7 +93,6 @@ public class CsarUtils {
// Service Template File Name
VALID_ENGLISH_ARTIFACT_NAME;
private static final String VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS = "([\\d" + WORD_PATTERN;
- private static final String ARTIFACT_NAME_UNIQUE_ID = "ArtifactName {}, unique ID {}";
private static final String VFC_NODE_TYPE_ARTIFACTS_PATH_PATTERN =
ARTIFACTS + DEL_PATTERN + ImportUtils.Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX + VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS + DEL_PATTERN
+ VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS + DEL_PATTERN + VALID_ENGLISH_ARTIFACT_NAME_WITH_DIGITS + DEL_PATTERN
@@ -160,44 +100,16 @@ public class CsarUtils {
private static final String BLOCK_0_TEMPLATE = "SDC-TOSCA-Meta-File-Version: %s\nSDC-TOSCA-Definitions-Version: %s\n";
private final ToscaOperationFacade toscaOperationFacade;
- private final SdcSchemaFilesCassandraDao sdcSchemaFilesCassandraDao;
- private final ArtifactCassandraDao artifactCassandraDao;
private final ComponentsUtils componentsUtils;
- private final ToscaExportHandler toscaExportUtils;
- private final List<CsarEntryGenerator> generators;
- private final ModelOperation modelOperation;
- private final String versionFirstThreeOctets;
+ private final MapFromModelCsarGeneratorService mapFromModelCsarGeneratorService;
@Autowired
- public CsarUtils(final ToscaOperationFacade toscaOperationFacade, final SdcSchemaFilesCassandraDao sdcSchemaFilesCassandraDao,
- final ArtifactCassandraDao artifactCassandraDao, final ComponentsUtils componentsUtils,
- final ToscaExportHandler toscaExportUtils, final List<CsarEntryGenerator> generators, final ModelOperation modelOperation) {
+ public CsarUtils(final ToscaOperationFacade toscaOperationFacade,
+ final ComponentsUtils componentsUtils,
+ final MapFromModelCsarGeneratorService mapFromModelCsarGeneratorService) {
this.toscaOperationFacade = toscaOperationFacade;
- this.sdcSchemaFilesCassandraDao = sdcSchemaFilesCassandraDao;
- this.artifactCassandraDao = artifactCassandraDao;
this.componentsUtils = componentsUtils;
- this.toscaExportUtils = toscaExportUtils;
- this.generators = generators;
- this.modelOperation = modelOperation;
- this.versionFirstThreeOctets = readVersionFirstThreeOctets();
- }
-
- private String readVersionFirstThreeOctets() {
- if (StringUtils.isEmpty(SDC_VERSION)) {
- return "";
- }
- // change regex to avoid DoS sonar issue
- Matcher matcher = Pattern.compile("(?!\\.)(\\d{1,9}(\\.\\d{1,9}){1,9})(?![\\d\\.])").matcher(SDC_VERSION);
- matcher.find();
- return matcher.group(0);
- }
-
- private static <L, R> F<L, Either<L, R>> iff(Predicate<L> p, Function<L, Either<L, R>> ifTrue) {
- return l -> p.test(l) ? ifTrue.apply(l) : Either.left(l);
- }
-
- private static <A, B> F<A, B> iff(Predicate<A> p, Supplier<B> s, Function<A, B> orElse) {
- return a -> p.test(a) ? s.get() : orElse.apply(a);
+ this.mapFromModelCsarGeneratorService = mapFromModelCsarGeneratorService;
}
/**
@@ -367,15 +279,11 @@ public class CsarUtils {
public Either<byte[], ResponseFormat> createCsar(final Component component, final boolean getFromCS, final boolean isInCertificationRequest) {
loggerSupportability
.log(LoggerSupportabilityActions.GENERATE_CSAR, StatusCode.STARTED, "Starting to create Csar for component {} ", component.getName());
- final String createdBy = component.getCreatorFullName();
- final Map<String, ArtifactDefinition> toscaArtifacts = component.getToscaArtifacts();
- final ArtifactDefinition artifactDefinition = toscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
- final String fileName = artifactDefinition.getArtifactName();
final String toscaConformanceLevel = ConfigurationManager.getConfigurationManager().getConfiguration().getToscaConformanceLevel();
final byte[] csarBlock0Byte = createCsarBlock0(CSAR_META_VERSION, toscaConformanceLevel).getBytes();
- final byte[] toscaBlock0Byte = createToscaBlock0(TOSCA_META_VERSION, CSAR_VERSION, createdBy, fileName, isAsdPackage(component)).getBytes();
- return generateCsarZip(csarBlock0Byte, toscaBlock0Byte, component, getFromCS, isInCertificationRequest).left().map(responseFormat -> {
+ return generateCsarZip(csarBlock0Byte,
+ isAsdPackage(component), component, getFromCS, isInCertificationRequest).left().map(responseFormat -> {
loggerSupportability
.log(LoggerSupportabilityActions.GENERATE_CSAR, StatusCode.COMPLETE, "Ended create Csar for component {} ", component.getName());
return responseFormat;
@@ -402,21 +310,22 @@ public class CsarUtils {
return false;
}
- private Either<byte[], ResponseFormat> generateCsarZip(byte[] csarBlock0Byte, byte[] toscaBlock0Byte, Component component, boolean getFromCS,
+ private Either<byte[], ResponseFormat> generateCsarZip(byte[] csarBlock0Byte,
+ boolean isAsdPackage,
+ Component component,
+ boolean getFromCS,
boolean isInCertificationRequest) {
- try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out)) {
+ try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out)) {
zip.putNextEntry(new ZipEntry(CSAR_META_PATH_FILE_NAME));
zip.write(csarBlock0Byte);
- zip.putNextEntry(new ZipEntry(TOSCA_META_PATH_FILE_NAME));
- zip.write(toscaBlock0Byte);
- Either<ZipOutputStream, ResponseFormat> populateZip = populateZip(component, getFromCS, zip, isInCertificationRequest);
+ Either<ZipOutputStream, ResponseFormat> populateZip = mapFromModelCsarGeneratorService.generateCsarZip(
+ component, getFromCS, zip, isInCertificationRequest, isAsdPackage);
if (populateZip.isRight()) {
log.debug("Failed to populate CSAR zip file {}. Please fix DB table accordingly ", populateZip.right().value());
return Either.right(populateZip.right().value());
}
zip.finish();
- byte[] byteArray = out.toByteArray();
- return Either.left(byteArray);
+ return Either.left(out.toByteArray());
} catch (IOException e) {
log.debug("Failed with IOexception to create CSAR zip for component {}. Please fix DB table accordingly ", component.getUniqueId(), e);
ResponseFormat responseFormat = componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR);
@@ -424,679 +333,10 @@ public class CsarUtils {
}
}
- private Either<ZipOutputStream, ResponseFormat> populateZip(Component component, boolean getFromCS, ZipOutputStream zip,
- boolean isInCertificationRequest) throws IOException {
- ArtifactDefinition artifactDef = component.getToscaArtifacts().get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
- Either<ToscaRepresentation, ResponseFormat> toscaRepresentation = fetchToscaRepresentation(component, getFromCS, artifactDef);
-
- // This should not be done but in order to keep the refactoring small enough we stop here.
-
- // TODO: Refactor the rest of this function
- byte[] mainYaml;
- List<Triple<String, String, Component>> dependencies;
- if (toscaRepresentation.isLeft()) {
- mainYaml = toscaRepresentation.left().value().getMainYaml();
- dependencies = toscaRepresentation.left().value().getDependencies().getOrElse(new ArrayList<>());
- } else {
- return Either.right(toscaRepresentation.right().value());
- }
- String fileName = artifactDef.getArtifactName();
- zip.putNextEntry(new ZipEntry(DEFINITIONS_PATH + fileName));
- zip.write(mainYaml);
- LifecycleStateEnum lifecycleState = component.getLifecycleState();
- addServiceMf(component, zip, lifecycleState, isInCertificationRequest, fileName, mainYaml);
- //US798487 - Abstraction of complex types
- if (hasToWriteComponentSubstitutionType(component)) {
- log.debug("Component {} is complex - generating abstract type for it..", component.getName());
- dependencies.addAll(writeComponentInterface(component, zip, fileName));
- }
- //UID <cassandraId,filename,component>
- Either<ZipOutputStream, ResponseFormat> zipOutputStreamOrResponseFormat = getZipOutputStreamResponseFormatEither(zip, dependencies);
- if (zipOutputStreamOrResponseFormat != null && zipOutputStreamOrResponseFormat.isRight()) {
- return zipOutputStreamOrResponseFormat;
- }
- if (component.getModel() == null) {
- //retrieve SDC.zip from Cassandra
- Either<byte[], ResponseFormat> latestSchemaFiles = getLatestSchemaFilesFromCassandra();
- if (latestSchemaFiles.isRight()) {
- log.error("Error retrieving SDC Schema files from cassandra");
- return Either.right(latestSchemaFiles.right().value());
- }
- final byte[] schemaFileZip = latestSchemaFiles.left().value();
- final List<String> nodesFromPackage = findNonRootNodesFromPackage(dependencies);
- //add files from retrieved SDC.zip to Definitions folder in CSAR
- addSchemaFilesFromCassandra(zip, schemaFileZip, nodesFromPackage);
- } else {
- //retrieve schema files by model from Cassandra
- addSchemaFilesByModel(zip, component.getModel());
- }
- Either<CsarDefinition, ResponseFormat> collectedComponentCsarDefinition = collectComponentCsarDefinition(component);
- if (collectedComponentCsarDefinition.isRight()) {
- return Either.right(collectedComponentCsarDefinition.right().value());
- }
- if (generators != null) {
- for (CsarEntryGenerator generator : generators) {
- log.debug("Invoking CsarEntryGenerator: {}", generator.getClass().getName());
- for (Entry<String, byte[]> pluginGeneratedFile : generator.generateCsarEntries(component).entrySet()) {
- zip.putNextEntry(new ZipEntry(pluginGeneratedFile.getKey()));
- zip.write(pluginGeneratedFile.getValue());
- }
- }
- }
- return writeAllFilesToCsar(component, collectedComponentCsarDefinition.left().value(), zip, isInCertificationRequest);
- }
-
- private void addServiceMf(Component component, ZipOutputStream zip, LifecycleStateEnum lifecycleState, boolean isInCertificationRequest,
- String fileName, byte[] mainYaml) throws IOException {
- // add mf
- if ((component.getComponentType() == ComponentTypeEnum.SERVICE) && (lifecycleState != LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT)) {
- String serviceName = component.getName();
- String createdBy = component.getCreatorUserId();
- String serviceVersion;
- if (isInCertificationRequest) {
- int tmp = Integer.valueOf(component.getVersion().split("\\.")[0]) + 1;
- serviceVersion = String.valueOf(tmp) + ".0";
- } else {
- serviceVersion = component.getVersion();
- }
- SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
- format.setTimeZone(TimeZone.getTimeZone("UTC"));
- Date date = new Date();
- String releaseTime = format.format(date);
- if (component.getCategories() == null || component.getCategories().get(0) == null) {
- return;
- }
- String serviceType = component.getCategories().get(0).getName();
- String description = component.getDescription();
- String serviceTemplate = DEFINITIONS_PATH + fileName;
- String hash = GeneralUtility.calculateMD5Base64EncodedByByteArray(mainYaml);
- String nsMfBlock0 = createNsMfBlock0(serviceName, createdBy, serviceVersion, releaseTime, serviceType, description, serviceTemplate,
- hash);
- byte[] nsMfBlock0Byte = nsMfBlock0.getBytes();
- zip.putNextEntry(new ZipEntry(SERVICE_MANIFEST));
- zip.write(nsMfBlock0Byte);
- }
- }
-
- private Either<ToscaRepresentation, ResponseFormat> fetchToscaRepresentation(Component component, boolean getFromCS,
- ArtifactDefinition artifactDef) {
- LifecycleStateEnum lifecycleState = component.getLifecycleState();
- boolean shouldBeFetchedFromCassandra =
- getFromCS || !(lifecycleState == LifecycleStateEnum.NOT_CERTIFIED_CHECKIN || lifecycleState == LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
- Either<ToscaRepresentation, ResponseFormat> toscaRepresentation =
- shouldBeFetchedFromCassandra ? fetchToscaRepresentation(artifactDef) : generateToscaRepresentation(component);
- return toscaRepresentation.left()
- .bind(iff(myd -> !myd.getDependencies().isDefined(), myd -> fetchToscaTemplateDependencies(myd.getMainYaml(), component)));
- }
-
- private Either<ToscaRepresentation, ResponseFormat> fetchToscaTemplateDependencies(byte[] mainYml, Component component) {
- return toscaExportUtils.getDependencies(component).right().map(toscaError -> {
- log.debug("Failed to retrieve dependencies for component {}, error {}", component.getUniqueId(), toscaError);
- return componentsUtils.getResponseFormat(componentsUtils.convertFromToscaError(toscaError));
- }).left().map(tt -> ToscaRepresentation.make(mainYml, tt));
- }
-
- private Either<ToscaRepresentation, ResponseFormat> generateToscaRepresentation(Component component) {
- return toscaExportUtils.exportComponent(component).right().map(toscaError -> {
- log.debug("exportComponent failed {}", toscaError);
- return componentsUtils.getResponseFormat(componentsUtils.convertFromToscaError(toscaError));
- });
- }
-
- private Either<ToscaRepresentation, ResponseFormat> fetchToscaRepresentation(ArtifactDefinition artifactDef) {
- return getFromCassandra(artifactDef.getEsId()).right().map(as -> {
- log.debug(ARTIFACT_NAME_UNIQUE_ID, artifactDef.getArtifactName(), artifactDef.getUniqueId());
- return componentsUtils.getResponseFormat(as);
- }).left().map(ToscaRepresentation::make);
- }
-
- /**
- * Create a list of all derived nodes found on the package
- *
- * @param dependencies all node dependencies
- * @return a list of nodes
- */
- private List<String> findNonRootNodesFromPackage(final List<Triple<String, String, Component>> dependencies) {
- final List<String> nodes = new ArrayList<>();
- if (CollectionUtils.isNotEmpty(dependencies)) {
- final String NATIVE_ROOT = "tosca.nodes.Root";
- dependencies.forEach(dependency -> {
- if (dependency.getRight() instanceof Resource) {
- final Resource resource = (Resource) dependency.getRight();
- if (CollectionUtils.isNotEmpty(resource.getDerivedList())) {
- resource.getDerivedList().stream().filter(node -> !nodes.contains(node) && !NATIVE_ROOT.equalsIgnoreCase(node))
- .forEach(node -> nodes.add(node));
- }
- }
- });
- }
- return nodes;
- }
-
- /**
- * Writes a new zip entry
- *
- * @param zipInputStream the zip entry to be read
- * @return a map of the given zip entry
- */
- private Map<String, Object> readYamlZipEntry(final ZipInputStream zipInputStream) throws IOException {
- final int initSize = 2048;
- final StringBuilder zipEntry = new StringBuilder();
- final byte[] buffer = new byte[initSize];
- int read = 0;
- while ((read = zipInputStream.read(buffer, 0, initSize)) >= 0) {
- zipEntry.append(new String(buffer, 0, read));
- }
- return (Map<String, Object>) new Yaml().load(zipEntry.toString());
- }
-
- /**
- * Filters and removes all duplicated nodes found
- *
- * @param nodesFromPackage a List of all derived nodes found on the given package
- * @param nodesFromArtifactFile represents the nodes.yml file stored in Cassandra
- * @return a nodes Map updated
- */
- private Map<String, Object> updateNodeYml(final List<String> nodesFromPackage, final Map<String, Object> nodesFromArtifactFile) {
- if (MapUtils.isNotEmpty(nodesFromArtifactFile)) {
- final String nodeTypeBlock = ToscaTagNamesEnum.NODE_TYPES.getElementName();
- final Map<String, Object> nodeTypes = (Map<String, Object>) nodesFromArtifactFile.get(nodeTypeBlock);
- nodesFromPackage.stream().filter(nodeTypes::containsKey).forEach(nodeTypes::remove);
- nodesFromArtifactFile.replace(nodeTypeBlock, nodeTypes);
- }
- return nodesFromArtifactFile;
- }
-
- /**
- * Updates the zip entry from the given parameters
- *
- * @param byteArrayOutputStream an output stream in which the data is written into a byte array.
- * @param nodesYaml a Map of nodes to be written
- */
- private void updateZipEntry(final ByteArrayOutputStream byteArrayOutputStream, final Map<String, Object> nodesYaml) throws IOException {
- if (MapUtils.isNotEmpty(nodesYaml)) {
- byteArrayOutputStream.write(new YamlUtil().objectToYaml(nodesYaml).getBytes());
- }
- }
-
- private Either<ZipOutputStream, ResponseFormat> getZipOutputStreamResponseFormatEither(ZipOutputStream zip,
- List<Triple<String, String, Component>> dependencies)
- throws IOException {
- ComponentCache innerComponentsCache = ComponentCache.overwritable(overwriteIfSameVersions()).onMerge((oldValue, newValue) -> {
- log.warn("Overwriting component invariantID {} of version {} with a newer version {}", oldValue.id, oldValue.getComponentVersion(),
- newValue.getComponentVersion());
- });
- if (dependencies != null && !dependencies.isEmpty()) {
- for (Triple<String, String, Component> d : dependencies) {
- String cassandraId = d.getMiddle();
- Component childComponent = d.getRight();
- Either<byte[], ResponseFormat> entryData = getEntryData(cassandraId, childComponent).right()
- .map(componentsUtils::getResponseFormat);
- if (entryData.isRight()) {
- return Either.right(entryData.right().value());
- }
- //fill innerComponentsCache
- String fileName = d.getLeft();
- innerComponentsCache.put(cassandraId, fileName, childComponent);
- addInnerComponentsToCache(innerComponentsCache, childComponent);
- }
- //add inner components to CSAR
- return addInnerComponentsToCSAR(zip, innerComponentsCache);
- }
- return null;
- }
-
- private Either<ZipOutputStream, ResponseFormat> addInnerComponentsToCSAR(ZipOutputStream zip, ComponentCache innerComponentsCache)
- throws IOException {
- for (ImmutableTriple<String, String, Component> ict : innerComponentsCache.iterable()) {
- Component innerComponent = ict.getRight();
- String icFileName = ict.getMiddle();
- // add component to zip
- Either<Tuple2<byte[], ZipEntry>, ResponseFormat> zipEntry = toZipEntry(ict);
- // TODO: this should not be done, we should instead compose this either further,
-
- // but in order to keep this refactoring small, we'll stop here.
- if (zipEntry.isRight()) {
- return Either.right(zipEntry.right().value());
- }
- Tuple2<byte[], ZipEntry> value = zipEntry.left().value();
- zip.putNextEntry(value._2);
- zip.write(value._1);
- // add component interface to zip
- if (hasToWriteComponentSubstitutionType(innerComponent)) {
- writeComponentInterface(innerComponent, zip, icFileName);
- }
- }
- return null;
- }
-
- private boolean hasToWriteComponentSubstitutionType(final Component component) {
- final Map<String, CategoryBaseTypeConfig> serviceNodeTypesConfig =
- ConfigurationManager.getConfigurationManager().getConfiguration().getServiceBaseNodeTypes();
- List<CategoryDefinition> categories = component.getCategories();
- if (CollectionUtils.isNotEmpty(categories) && MapUtils.isNotEmpty(serviceNodeTypesConfig) && serviceNodeTypesConfig.get(categories.get(0).getName()) != null) {
- boolean doNotExtendBaseType = serviceNodeTypesConfig.get(categories.get(0).getName()).isDoNotExtendBaseType();
- if (doNotExtendBaseType) {
- return false;
- }
- }
- if (component instanceof Service) {
- return !ModelConverter.isAtomicComponent(component) && ((Service) component).isSubstituteCandidate();
- }
- return !ModelConverter.isAtomicComponent(component);
- }
-
- private Either<Tuple2<byte[], ZipEntry>, ResponseFormat> toZipEntry(ImmutableTriple<String, String, Component> cachedEntry) {
- String cassandraId = cachedEntry.getLeft();
- String fileName = cachedEntry.getMiddle();
- Component innerComponent = cachedEntry.getRight();
- return getEntryData(cassandraId, innerComponent).right().map(status -> {
- log.debug("Failed adding to zip component {}, error {}", cassandraId, status);
- return componentsUtils.getResponseFormat(status);
- }).left().map(content -> new Tuple2<>(content, new ZipEntry(DEFINITIONS_PATH + fileName)));
- }
-
- /**
- * Writes to a CSAR zip from casandra schema data
- *
- * @param zipOutputStream stores the input stream content
- * @param schemaFileZip zip data from Cassandra
- * @param nodesFromPackage list of all nodes found on the onboarded package
- */
- private void addSchemaFilesFromCassandra(final ZipOutputStream zipOutputStream, final byte[] schemaFileZip, final List<String> nodesFromPackage) {
- final int initSize = 2048;
- log.debug("Starting copy from Schema file zip to CSAR zip");
- try (final ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(
- schemaFileZip)); final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
- byteArrayOutputStream, initSize)) {
- ZipEntry entry;
- while ((entry = zipInputStream.getNextEntry()) != null) {
- ZipUtils.checkForZipSlipInRead(entry);
- final String entryName = entry.getName();
- int readSize = initSize;
- final byte[] entryData = new byte[initSize];
- if (shouldZipEntryBeHandled(entryName)) {
- if (NODES_YML.equalsIgnoreCase(entryName)) {
- handleNode(zipInputStream, byteArrayOutputStream, nodesFromPackage);
- } else {
- while ((readSize = zipInputStream.read(entryData, 0, readSize)) != -1) {
- bufferedOutputStream.write(entryData, 0, readSize);
- }
- bufferedOutputStream.flush();
- }
- byteArrayOutputStream.flush();
- zipOutputStream.putNextEntry(new ZipEntry(DEFINITIONS_PATH + entryName));
- zipOutputStream.write(byteArrayOutputStream.toByteArray());
- zipOutputStream.flush();
- byteArrayOutputStream.reset();
- }
- }
- } catch (final Exception e) {
- log.error("Error while writing the SDC schema file to the CSAR", e);
- throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
- }
- log.debug("Finished copy from Schema file zip to CSAR zip");
- }
-
- /**
- * Checks if the zip entry should or should not be added to the CSAR based on the given global type list
- *
- * @param entryName the zip entry name
- * @return true if the zip entry should be handled
- */
- private boolean shouldZipEntryBeHandled(final String entryName) {
- return ConfigurationManager.getConfigurationManager().getConfiguration().getGlobalCsarImports().stream()
- .anyMatch(entry -> entry.contains(entryName));
- }
-
- /**
- * Handles the nodes.yml zip entry, updating the nodes.yml to avoid duplicated nodes on it.
- *
- * @param zipInputStream the zip entry to be read
- * @param byteArrayOutputStream an output stream in which the data is written into a byte array.
- * @param nodesFromPackage list of all nodes found on the onboarded package
- */
- private void handleNode(final ZipInputStream zipInputStream, final ByteArrayOutputStream byteArrayOutputStream,
- final List<String> nodesFromPackage) throws IOException {
- final Map<String, Object> nodesFromArtifactFile = readYamlZipEntry(zipInputStream);
- final Map<String, Object> nodesYaml = updateNodeYml(nodesFromPackage, nodesFromArtifactFile);
- updateZipEntry(byteArrayOutputStream, nodesYaml);
- }
-
- private void addInnerComponentsToCache(ComponentCache componentCache, Component childComponent) {
- javaListToVavrList(childComponent.getComponentInstances()).filter(ci -> componentCache.notCached(ci.getComponentUid())).forEach(ci -> {
- // all resource must be only once!
- Either<Resource, StorageOperationStatus> resource = toscaOperationFacade.getToscaElement(ci.getComponentUid());
- Component componentRI = checkAndAddComponent(componentCache, ci, resource);
- //if not atomic - insert inner components as well
-
- // TODO: This could potentially create a StackOverflowException if the call stack
-
- // happens to be too large. Tail-recursive optimization should be used here.
- if (!ModelConverter.isAtomicComponent(componentRI)) {
- addInnerComponentsToCache(componentCache, componentRI);
- }
- });
- }
-
- // TODO: Move this function in FJToVavrHelper.java once Change 108540 is merged
- private io.vavr.collection.List<ComponentInstance> javaListToVavrList(List<ComponentInstance> componentInstances) {
- return Option.of(componentInstances).map(io.vavr.collection.List::ofAll).getOrElse(io.vavr.collection.List::empty);
- }
-
- private Component checkAndAddComponent(ComponentCache componentCache, ComponentInstance ci, Either<Resource, StorageOperationStatus> resource) {
- if (resource.isRight()) {
- log.debug("Failed to fetch resource with id {} for instance {}", ci.getComponentUid(), ci.getName());
- }
- Component componentRI = resource.left().value();
- Map<String, ArtifactDefinition> childToscaArtifacts = componentRI.getToscaArtifacts();
- ArtifactDefinition childArtifactDefinition = childToscaArtifacts.get(ToscaExportHandler.ASSET_TOSCA_TEMPLATE);
- if (childArtifactDefinition != null) {
- //add to cache
- componentCache.put(childArtifactDefinition.getEsId(), childArtifactDefinition.getArtifactName(), componentRI);
- }
- return componentRI;
- }
-
- private List<Triple<String, String, Component>> writeComponentInterface(final Component component, final ZipOutputStream zip,
- final String fileName) {
- final Either<ToscaRepresentation, ToscaError> interfaceRepresentation = toscaExportUtils.exportComponentInterface(component, false);
- writeComponentInterface(interfaceRepresentation, zip, fileName);
- return interfaceRepresentation.left().value().getDependencies().getOrElse(new ArrayList<>());
- }
-
-
- private Either<ZipOutputStream, ResponseFormat> writeComponentInterface(Either<ToscaRepresentation, ToscaError> interfaceRepresentation,
- ZipOutputStream zip, String fileName) {
- // TODO: This should not be done but we need this to keep the refactoring small enough to be easily reviewable
- return writeComponentInterface(interfaceRepresentation, fileName, ZipWriter.live(zip))
- .map(void0 -> Either.<ZipOutputStream, ResponseFormat>left(zip)).recover(th -> {
- log.error("#writeComponentInterface - zip writing failed with error: ", th);
- return Either.right(componentsUtils.getResponseFormat(ActionStatus.GENERAL_ERROR));
- }).get();
- }
-
- private Try<Void> writeComponentInterface(
- Either<ToscaRepresentation, ToscaError> interfaceRepresentation, String fileName, ZipWriter zw) {
- Either<byte[], ToscaError> yml = interfaceRepresentation.left()
- .map(ToscaRepresentation::getMainYaml);
- return fromEither(yml, ToscaErrorException::new).flatMap(zw.write(DEFINITIONS_PATH + ToscaExportHandler.getInterfaceFilename(fileName)));
- }
-
- private Either<byte[], ActionStatus> getEntryData(String cassandraId, Component childComponent) {
- if (cassandraId == null || cassandraId.isEmpty()) {
- return toscaExportUtils.exportComponent(childComponent).right().map(toscaErrorToActionStatus(childComponent)).left()
- .map(ToscaRepresentation::getMainYaml);
- } else {
- return getFromCassandra(cassandraId);
- }
- }
-
- private F<ToscaError, ActionStatus> toscaErrorToActionStatus(Component childComponent) {
- return toscaError -> {
- log.debug("Failed to export tosca template for child component {} error {}", childComponent.getUniqueId(), toscaError);
- return componentsUtils.convertFromToscaError(toscaError);
- };
- }
-
- private Either<byte[], ResponseFormat> getLatestSchemaFilesFromCassandra() {
- String fto = versionFirstThreeOctets;
- return sdcSchemaFilesCassandraDao.getSpecificSchemaFiles(fto, CONFORMANCE_LEVEL).right().map(schemaFilesFetchDBError(fto)).left()
- .bind(iff(List::isEmpty, () -> schemaFileFetchError(fto), s -> Either.left(s.iterator().next().getPayloadAsArray())));
- }
-
- private void addSchemaFilesByModel(final ZipOutputStream zipOutputStream, final String modelName) {
- try {
- final List<ToscaImportByModel> modelDefaultImportList = modelOperation.findAllModelImports(modelName, true);
- final Set<Path> writtenEntryPathList = new HashSet<>();
- final var definitionsPath = Path.of(DEFINITIONS_PATH);
- for (final ToscaImportByModel toscaImportByModel : modelDefaultImportList) {
- var importPath = Path.of(toscaImportByModel.getFullPath());
- if (writtenEntryPathList.contains(definitionsPath.resolve(importPath))) {
- importPath =
- ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
- }
- final Path entryPath = definitionsPath.resolve(importPath);
- final var zipEntry = new ZipEntry(entryPath.toString());
- zipOutputStream.putNextEntry(zipEntry);
- writtenEntryPathList.add(entryPath);
- final byte[] content = toscaImportByModel.getContent().getBytes(StandardCharsets.UTF_8);
- zipOutputStream.write(content, 0, content.length);
- zipOutputStream.closeEntry();
- }
- } catch (final IOException e) {
- log.error(EcompLoggerErrorCode.BUSINESS_PROCESS_ERROR, CsarUtils.class.getName(),
- "Error while writing the schema files by model to the CSAR", e);
- throw new ByResponseFormatComponentException(componentsUtils.getResponseFormat(ActionStatus.CSAR_TOSCA_IMPORTS_ERROR));
- }
- }
-
- private F<CassandraOperationStatus, ResponseFormat> schemaFilesFetchDBError(String firstThreeOctets) {
- return cos -> {
- log.debug("Failed to get the schema files SDC-Version: {} Conformance-Level {}. Please fix DB table accordingly.", firstThreeOctets,
- CONFORMANCE_LEVEL);
- StorageOperationStatus sos = DaoStatusConverter.convertCassandraStatusToStorageStatus(cos);
- return componentsUtils.getResponseFormat(componentsUtils.convertFromStorageResponse(sos));
- };
- }
-
- private Either<byte[], ResponseFormat> schemaFileFetchError(String firstThreeOctets) {
- log.debug("Failed to get the schema files SDC-Version: {} Conformance-Level {}", firstThreeOctets, CONFORMANCE_LEVEL);
- return Either.right(componentsUtils.getResponseFormat(ActionStatus.TOSCA_SCHEMA_FILES_NOT_FOUND, firstThreeOctets, CONFORMANCE_LEVEL));
- }
-
- private Either<byte[], ActionStatus> getFromCassandra(String cassandraId) {
- return artifactCassandraDao.getArtifact(cassandraId).right().map(operationstatus -> {
- log.info("Failed to fetch artifact from Cassandra by id {} error {}.", cassandraId, operationstatus);
- StorageOperationStatus storageStatus = DaoStatusConverter.convertCassandraStatusToStorageStatus(operationstatus);
- return componentsUtils.convertFromStorageResponse(storageStatus);
- }).left().map(DAOArtifactData::getDataAsArray);
- }
-
private String createCsarBlock0(String metaFileVersion, String toscaConformanceLevel) {
return String.format(BLOCK_0_TEMPLATE, metaFileVersion, toscaConformanceLevel);
}
- private String createToscaBlock0(String metaFileVersion, String csarVersion, String createdBy, String entryDef, boolean isAsdPackage) {
- final String block0template = "TOSCA-Meta-File-Version: %s\nCSAR-Version: %s\nCreated-By: %s\nEntry-Definitions: Definitions/%s\n%s\nName: csar.meta\nContent-Type: text/plain\n";
- return String.format(block0template, metaFileVersion, csarVersion, createdBy, entryDef, isAsdPackage ? "entry_definition_type: asd" : "");
- }
-
- private String createNsMfBlock0(String serviceName, String createdBy, String serviceVersion, String releaseTime, String serviceType,
- String description, String serviceTemplate, String hash) {
- final String block0template = "metadata??\n" + "ns_product_name: %s\n" + "ns_provider_id: %s\n" + "ns_package_version: %s\n" +
- "ns_release_data_time: %s\n" + "ns_type: %s\n" + "ns_package_description: %s\n\n" + "Source: %s\n" + "Algorithm: MD5\n" + "Hash: %s\n\n";
- return String.format(block0template, serviceName, createdBy, serviceVersion, releaseTime, serviceType, description, serviceTemplate, hash);
- }
-
- private Either<ZipOutputStream, ResponseFormat> writeAllFilesToCsar(Component mainComponent, CsarDefinition csarDefinition,
- ZipOutputStream zipstream, boolean isInCertificationRequest)
- throws IOException {
- ComponentArtifacts componentArtifacts = csarDefinition.getComponentArtifacts();
- Either<ZipOutputStream, ResponseFormat> writeComponentArtifactsToSpecifiedPath = writeComponentArtifactsToSpecifiedPath(mainComponent,
- componentArtifacts, zipstream, ARTIFACTS_PATH, isInCertificationRequest);
- if (writeComponentArtifactsToSpecifiedPath.isRight()) {
- return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
- }
- ComponentTypeArtifacts mainTypeAndCIArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
- writeComponentArtifactsToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent, mainTypeAndCIArtifacts.getComponentArtifacts(),
- zipstream, ARTIFACTS_PATH, isInCertificationRequest);
- if (writeComponentArtifactsToSpecifiedPath.isRight()) {
- return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
- }
- Map<String, ArtifactsInfo> componentInstancesArtifacts = mainTypeAndCIArtifacts.getComponentInstancesArtifacts();
- String currentPath = ARTIFACTS_PATH + RESOURCES_PATH;
- for (String keyAssetName : componentInstancesArtifacts.keySet()) {
- ArtifactsInfo artifactsInfo = componentInstancesArtifacts.get(keyAssetName);
- String pathWithAssetName = currentPath + keyAssetName + PATH_DELIMITER;
- writeComponentArtifactsToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent, artifactsInfo, zipstream, pathWithAssetName,
- isInCertificationRequest);
- if (writeComponentArtifactsToSpecifiedPath.isRight()) {
- return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
- }
- }
- writeComponentArtifactsToSpecifiedPath = writeOperationsArtifactsToCsar(mainComponent, zipstream);
- if (writeComponentArtifactsToSpecifiedPath.isRight()) {
- return Either.right(writeComponentArtifactsToSpecifiedPath.right().value());
- }
- return Either.left(zipstream);
- }
-
- private Either<ZipOutputStream, ResponseFormat> writeOperationsArtifactsToCsar(Component component, ZipOutputStream zipstream) {
- if (checkComponentBeforeOperation(component)) {
- return Either.left(zipstream);
- }
- for (Map.Entry<String, InterfaceDefinition> interfaceEntry : ((Resource) component).getInterfaces().entrySet()) {
- for (OperationDataDefinition operation : interfaceEntry.getValue().getOperations().values()) {
- try {
- if (checkComponentBeforeWrite(component, interfaceEntry, operation)) {
- continue;
- }
- final String artifactUUID = operation.getImplementation().getArtifactUUID();
- if (artifactUUID == null) {
- continue;
- }
- final Either<byte[], ActionStatus> artifactFromCassandra = getFromCassandra(artifactUUID);
- final String artifactName = operation.getImplementation().getArtifactName();
- if (artifactFromCassandra.isRight()) {
- log.error(ARTIFACT_NAME_UNIQUE_ID, artifactName, artifactUUID);
- log.error("Failed to get {} payload from DB reason: {}", artifactName, artifactFromCassandra.right().value());
- return Either.right(componentsUtils.getResponseFormat(
- ARTIFACT_PAYLOAD_NOT_FOUND_DURING_CSAR_CREATION, "Resource", component.getUniqueId(), artifactName, artifactUUID));
- }
- zipstream.putNextEntry(new ZipEntry(OperationArtifactUtil.createOperationArtifactPath(component, null, operation, true)));
- zipstream.write(artifactFromCassandra.left().value());
- } catch (IOException e) {
- log.error("Component Name {}, Interface Name {}, Operation Name {}", component.getNormalizedName(), interfaceEntry.getKey(),
- operation.getName());
- log.error("Error while writing the operation's artifacts to the CSAR", e);
- return Either.right(componentsUtils.getResponseFormat(ERROR_DURING_CSAR_CREATION, "Resource", component.getUniqueId()));
- }
- }
- }
- return Either.left(zipstream);
- }
-
- private boolean checkComponentBeforeWrite(Component component, Entry<String, InterfaceDefinition> interfaceEntry,
- OperationDataDefinition operation) {
- final ArtifactDataDefinition implementation = operation.getImplementation();
- if (Objects.isNull(implementation)) {
- log.debug("Component Name {}, Interface Id {}, Operation Name {} - no Operation Implementation found", component.getNormalizedName(),
- interfaceEntry.getValue().getUniqueId(), operation.getName());
- return true;
- }
- final String artifactName = implementation.getArtifactName();
- if (Objects.isNull(artifactName)) {
- log.debug("Component Name {}, Interface Id {}, Operation Name {} - no artifact found", component.getNormalizedName(),
- interfaceEntry.getValue().getUniqueId(), operation.getName());
- return true;
- }
- if (OperationArtifactUtil.artifactNameIsALiteralValue(artifactName)) {
- log.debug("Component Name {}, Interface Id {}, Operation Name {} - artifact name is a literal value rather than an SDC artifact",
- component.getNormalizedName(), interfaceEntry.getValue().getUniqueId(), operation.getName());
- return true;
- }
- return false;
- }
-
- private boolean checkComponentBeforeOperation(Component component) {
- if (component instanceof Service) {
- return true;
- }
- if (Objects.isNull(((Resource) component).getInterfaces())) {
- log.debug("Component Name {}- no interfaces found", component.getNormalizedName());
- return true;
- }
- return false;
- }
-
- private Either<ZipOutputStream, ResponseFormat> writeComponentArtifactsToSpecifiedPath(Component mainComponent,
- ComponentArtifacts componentArtifacts,
- ZipOutputStream zipstream, String currentPath,
- boolean isInCertificationRequest) throws IOException {
- Map<String, ComponentTypeArtifacts> componentTypeArtifacts = componentArtifacts.getComponentTypeArtifacts();
- //Keys are defined:
-
- //<Inner Asset TOSCA name (e.g. VFC name)> folder name: <Inner Asset TOSCA name (e.g. VFC name)>_v<version>.
-
- //E.g. "org.openecomp.resource.vf.vipr_atm_v1.0"
- Set<String> componentTypeArtifactsKeys = componentTypeArtifacts.keySet();
- for (String keyAssetName : componentTypeArtifactsKeys) {
- ComponentTypeArtifacts componentInstanceArtifacts = componentTypeArtifacts.get(keyAssetName);
- ArtifactsInfo componentArtifacts2 = componentInstanceArtifacts.getComponentArtifacts();
- String pathWithAssetName = currentPath + keyAssetName + PATH_DELIMITER;
- Either<ZipOutputStream, ResponseFormat> writeArtifactsInfoToSpecifiedPath = writeArtifactsInfoToSpecifiedPath(mainComponent,
- componentArtifacts2, zipstream, pathWithAssetName, isInCertificationRequest);
- if (writeArtifactsInfoToSpecifiedPath.isRight()) {
- return writeArtifactsInfoToSpecifiedPath;
- }
- }
- return Either.left(zipstream);
- }
-
- private Either<ZipOutputStream, ResponseFormat> writeArtifactsInfoToSpecifiedPath(final Component mainComponent,
- final ArtifactsInfo currArtifactsInfo,
- final ZipOutputStream zip, final String path,
- final boolean isInCertificationRequest) throws IOException {
- final Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactsInfo = currArtifactsInfo.getArtifactsInfo();
- for (final ArtifactGroupTypeEnum artifactGroupTypeEnum : artifactsInfo.keySet()) {
- final String groupTypeFolder = path + WordUtils.capitalizeFully(artifactGroupTypeEnum.getType()) + PATH_DELIMITER;
- final Map<String, List<ArtifactDefinition>> artifactTypesMap = artifactsInfo.get(artifactGroupTypeEnum);
- for (final String artifactType : artifactTypesMap.keySet()) {
- final List<ArtifactDefinition> artifactDefinitionList = artifactTypesMap.get(artifactType);
- String artifactTypeFolder = groupTypeFolder + artifactType + PATH_DELIMITER;
- if (ArtifactTypeEnum.WORKFLOW.getType().equals(artifactType) && path.contains(ARTIFACTS_PATH + RESOURCES_PATH)) {
- // Ignore this packaging as BPMN artifacts needs to be packaged in different manner
- continue;
- }
- if (ArtifactTypeEnum.WORKFLOW.getType().equals(artifactType)) {
- artifactTypeFolder += OperationArtifactUtil.BPMN_ARTIFACT_PATH + File.separator;
- } else if (ArtifactTypeEnum.ONBOARDED_PACKAGE.getType().equals(artifactType)) {
- // renaming legacy folder ONBOARDED_PACKAGE to the new folder ETSI_PACKAGE
- artifactTypeFolder = artifactTypeFolder
- .replace(ArtifactTypeEnum.ONBOARDED_PACKAGE.getType(), ArtifactTypeEnum.ETSI_PACKAGE.getType());
- }
- // TODO: We should not do this but in order to keep this refactoring small enough,
-
- // we'll leave this as is for now
- List<ArtifactDefinition> collect = filterArtifactDefinitionToZip(mainComponent, artifactDefinitionList, isInCertificationRequest)
- .collect(Collectors.toList());
- for (ArtifactDefinition ad : collect) {
- zip.putNextEntry(new ZipEntry(artifactTypeFolder + ad.getArtifactName()));
- zip.write(ad.getPayloadData());
- }
- }
- }
- return Either.left(zip);
- }
-
- private Stream<ArtifactDefinition> filterArtifactDefinitionToZip(Component mainComponent, List<ArtifactDefinition> artifactDefinitionList,
- boolean isInCertificationRequest) {
- return artifactDefinitionList.stream().filter(shouldBeInZip(isInCertificationRequest, mainComponent)).map(this::fetchPayLoadData)
- .filter(Either::isLeft).map(e -> e.left().value());
- }
-
- private Predicate<ArtifactDefinition> shouldBeInZip(boolean isInCertificationRequest, Component component) {
- return artifactDefinition -> !(!isInCertificationRequest && component.isService() && artifactDefinition.isHeatEnvType() || artifactDefinition
- .hasNoMandatoryEsId());
- }
-
- private Either<ArtifactDefinition, ActionStatus> fetchPayLoadData(ArtifactDefinition ad) {
- byte[] payloadData = ad.getPayloadData();
- if (payloadData == null) {
- return getFromCassandra(ad.getEsId()).left().map(pd -> {
- ad.setPayload(pd);
- return ad;
- }).right().map(as -> {
- log.debug(ARTIFACT_NAME_UNIQUE_ID, ad.getArtifactName(), ad.getUniqueId());
- log.debug("Failed to get {} payload from DB reason: {}", ad.getArtifactName(), as);
- return as;
- });
- } else {
- return Either.left(ad);
- }
- }
-
/************************************ Artifacts Structure END******************************************************************/
private Either<CsarDefinition, ResponseFormat> collectComponentCsarDefinition(Component component) {
@@ -1149,7 +389,7 @@ public class CsarUtils {
ComponentTypeArtifacts componentInstanceArtifacts = componentArtifacts.getMainTypeAndCIArtifacts();
printArtifacts(componentInstanceArtifacts);
result.append("Type Artifacts\n");
- for (Map.Entry<String, ComponentTypeArtifacts> typeArtifacts : componentArtifacts.getComponentTypeArtifacts().entrySet()) {
+ for (Entry<String, ComponentTypeArtifacts> typeArtifacts : componentArtifacts.getComponentTypeArtifacts().entrySet()) {
result.append("Folder " + typeArtifacts.getKey() + "\n");
result.append(printArtifacts(typeArtifacts.getValue()));
}
@@ -1167,7 +407,7 @@ public class CsarUtils {
Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componentArtifacts = artifactsInfo.getArtifactsInfo();
printArtifacts(componentArtifacts);
result = result.append("Resources\n");
- for (Map.Entry<String, ArtifactsInfo> resourceInstance : componentInstanceArtifacts.getComponentInstancesArtifacts().entrySet()) {
+ for (Entry<String, ArtifactsInfo> resourceInstance : componentInstanceArtifacts.getComponentInstancesArtifacts().entrySet()) {
result.append("Folder" + resourceInstance.getKey() + "\n");
result.append(printArtifacts(resourceInstance.getValue().getArtifactsInfo()));
}
@@ -1177,9 +417,9 @@ public class CsarUtils {
private String printArtifacts(Map<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> componetArtifacts) {
StringBuilder result = new StringBuilder();
- for (Map.Entry<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactGroup : componetArtifacts.entrySet()) {
+ for (Entry<ArtifactGroupTypeEnum, Map<String, List<ArtifactDefinition>>> artifactGroup : componetArtifacts.entrySet()) {
result.append(" " + artifactGroup.getKey().getType());
- for (Map.Entry<String, List<ArtifactDefinition>> groupArtifacts : artifactGroup.getValue().entrySet()) {
+ for (Entry<String, List<ArtifactDefinition>> groupArtifacts : artifactGroup.getValue().entrySet()) {
result.append(" " + groupArtifacts.getKey());
for (ArtifactDefinition artifact : groupArtifacts.getValue()) {
result.append(" " + artifact.getArtifactDisplayName());
@@ -1323,12 +563,6 @@ public class CsarUtils {
return artifactsByType;
}
- public static class ToscaErrorException extends Exception {
-
- ToscaErrorException(ToscaError error) {
- super("Error while exporting component's interface (toscaError:" + error + ")");
- }
- }
@Getter
public static final class NonMetaArtifactInfo {
@@ -1348,7 +582,6 @@ public class CsarUtils {
public NonMetaArtifactInfo(final String artifactName, final String path, final String artifactType,
final ArtifactGroupTypeEnum artifactGroupType, final byte[] payloadData, final String artifactUniqueId,
final boolean isFromCsar) {
- super();
this.path = path;
this.isFromCsar = isFromCsar;
this.artifactName = ValidationUtils.normalizeFileName(artifactName);
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/DefaultCsarGenerator.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/DefaultCsarGenerator.java
new file mode 100644
index 0000000000..cad5acebe0
--- /dev/null
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/DefaultCsarGenerator.java
@@ -0,0 +1,56 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2023 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.be.tosca;
+
+import fj.data.Either;
+import java.io.IOException;
+import java.util.zip.ZipOutputStream;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.plugins.CsarZipGenerator;
+import org.openecomp.sdc.exception.ResponseFormat;
+
+/**
+ * Generates a Network Service CSAR based on a SERVICE component and wraps it in a SDC CSAR entry.
+ */
+@org.springframework.stereotype.Component("defaultCsarGenerator")
+public class DefaultCsarGenerator implements CsarZipGenerator {
+
+ private static final String DEFINITIONS_PATH = "Definitions/";
+ private final CommonCsarGenerator commonCsarGenerator;
+
+ public DefaultCsarGenerator(final CommonCsarGenerator commonCsarGenerator) {
+ this.commonCsarGenerator = commonCsarGenerator;
+ }
+
+ @Override
+ public Either<ZipOutputStream, ResponseFormat> generateCsarZip(Component component,
+ boolean getFromCS,
+ ZipOutputStream zip,
+ boolean isInCertificationRequest,
+ boolean isAsdPackage) throws IOException {
+ return commonCsarGenerator.generateCsarZip(component, getFromCS, zip, isInCertificationRequest, isAsdPackage, DEFINITIONS_PATH, true, false);
+ }
+
+ @Override
+ public String getModel() {
+ return null;
+ }
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java
index 94bc279cfe..0b07506ac5 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/FJToVavrHelper.java
@@ -19,8 +19,11 @@
*/
package org.openecomp.sdc.be.tosca;
+import io.vavr.control.Option;
import io.vavr.control.Try;
+import java.util.List;
import java.util.function.Function;
+import org.openecomp.sdc.be.model.ComponentInstance;
/**
* Helper class providing facilities for migrating from FJ to VAVR
@@ -42,5 +45,9 @@ public final class FJToVavrHelper {
static <L, R> Try<L> fromEither(fj.data.Either<L, R> e, Function<R, Throwable> onError) {
return e.either(Try::success, r -> Try.failure(onError.apply(r)));
}
+
+ static io.vavr.collection.List<ComponentInstance> javaListToVavrList(List<ComponentInstance> componentInstances) {
+ return Option.of(componentInstances).map(io.vavr.collection.List::ofAll).getOrElse(io.vavr.collection.List::empty);
+ }
}
}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/MapFromModelCsarGeneratorService.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/MapFromModelCsarGeneratorService.java
new file mode 100644
index 0000000000..8e255c707c
--- /dev/null
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/MapFromModelCsarGeneratorService.java
@@ -0,0 +1,59 @@
+/*
+ * ============LICENSE_START=======================================================
+ * SDC
+ * ================================================================================
+ * Copyright (C) 2023 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.be.tosca;
+
+import fj.data.Either;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.zip.ZipOutputStream;
+import org.openecomp.sdc.be.model.Component;
+import org.openecomp.sdc.be.plugins.CsarZipGenerator;
+import org.openecomp.sdc.exception.ResponseFormat;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class MapFromModelCsarGeneratorService {
+
+ private final Map<String, CsarZipGenerator> servicesByModel;
+
+ @Autowired
+ public MapFromModelCsarGeneratorService(List<CsarZipGenerator> modelServices) {
+ servicesByModel = modelServices.stream()
+ .collect(Collectors.toMap(CsarZipGenerator::getModel, Function.identity()));
+ }
+
+ public Either<ZipOutputStream, ResponseFormat> generateCsarZip(final Component component,
+ boolean getFromCS,
+ ZipOutputStream zip,
+ boolean isInCertificationRequest,
+ boolean isAsdPackage) throws IOException {
+ CsarZipGenerator generatorImpl = servicesByModel.get(component.getModel());
+
+ if (null == generatorImpl) {
+ generatorImpl = servicesByModel.get(null);
+ }
+
+ return generatorImpl.generateCsarZip(component, getFromCS, zip, isInCertificationRequest, isAsdPackage);
+ }
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
index 4d99b4de98..0b57cfe412 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/ToscaExportHandler.java
@@ -22,6 +22,7 @@ package org.openecomp.sdc.be.tosca;
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;
import static org.apache.commons.collections.MapUtils.isNotEmpty;
import static org.openecomp.sdc.be.components.utils.PropertiesUtils.resolvePropertyValueFromInput;
+import static org.openecomp.sdc.common.api.Constants.ADDITIONAL_TYPE_DEFINITIONS;
import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_ATTRIBUTE;
import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_INPUT;
import static org.openecomp.sdc.tosca.datatypes.ToscaFunctions.GET_PROPERTY;
@@ -228,7 +229,11 @@ public class ToscaExportHandler {
}
public Either<ToscaRepresentation, ToscaError> exportComponent(Component component) {
- return convertToToscaTemplate(component).left().map(this::createToscaRepresentation);
+ return convertToToscaTemplate(component, false).left().map(this::createToscaRepresentation);
+ }
+
+ public Either<ToscaRepresentation, ToscaError> exportComponent(Component component, Boolean isSkipImports) {
+ return convertToToscaTemplate(component, isSkipImports).left().map(this::createToscaRepresentation);
}
public Either<ToscaRepresentation, ToscaError> exportDataType(DataTypeDefinition dataTypeDefinition) {
@@ -236,7 +241,7 @@ public class ToscaExportHandler {
}
public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent) {
- final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel()));
+ final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel(), false));
if (CollectionUtils.isEmpty(imports)) {
log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
return Either.right(ToscaError.GENERAL_ERROR);
@@ -248,7 +253,7 @@ public class ToscaExportHandler {
.getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
component.getModel());
if (baseType.isLeft() && baseType.left().value() != null) {
- addDependencies(imports, dependencies, baseType.left().value());
+ addDependencies(imports, dependencies, baseType.left().value(), false);
} else {
log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
}
@@ -272,6 +277,44 @@ public class ToscaExportHandler {
return Either.left(toscaRepresentation);
}
+ public Either<ToscaRepresentation, ToscaError> exportComponentInterface(final Component component, final boolean isAssociatedComponent,
+ final boolean isSkipImports) {
+ final List<Map<String, Map<String, String>>> imports = new ArrayList<>(getDefaultToscaImports(component.getModel(), isSkipImports));
+ if (CollectionUtils.isEmpty(imports)) {
+ log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
+ return Either.right(ToscaError.GENERAL_ERROR);
+ }
+ List<Triple<String, String, Component>> dependencies = new ArrayList<>();
+ if (component.getDerivedFromGenericType() != null && !component.getDerivedFromGenericType()
+ .startsWith("org.openecomp.resource.abstract.nodes.")) {
+ final Either<Component, StorageOperationStatus> baseType = toscaOperationFacade
+ .getByToscaResourceNameAndVersion(component.getDerivedFromGenericType(), component.getDerivedFromGenericVersion(),
+ component.getModel());
+ if (baseType.isLeft() && baseType.left().value() != null) {
+ addDependencies(imports, dependencies, baseType.left().value(), isSkipImports);
+ } else {
+ log.debug("Failed to fetch derived from type {}", component.getDerivedFromGenericType());
+ }
+ }
+
+ String toscaVersion = null;
+ if (component instanceof Resource) {
+ toscaVersion = ((Resource) component).getToscaVersion();
+ }
+ ToscaTemplate toscaTemplate = new ToscaTemplate(toscaVersion != null ? toscaVersion : TOSCA_VERSION);
+ toscaTemplate.setImports(imports);
+ final Map<String, ToscaNodeType> nodeTypes = new HashMap<>();
+ final Either<ToscaTemplate, ToscaError> toscaTemplateRes = convertInterfaceNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes,
+ isAssociatedComponent);
+ if (toscaTemplateRes.isRight()) {
+ return Either.right(toscaTemplateRes.right().value());
+ }
+ toscaTemplate = toscaTemplateRes.left().value();
+ toscaTemplate.setDependencies(dependencies);
+ ToscaRepresentation toscaRepresentation = this.createToscaRepresentation(toscaTemplate);
+ return Either.left(toscaRepresentation);
+ }
+
private ToscaRepresentation createToscaRepresentation(ToscaTemplate toscaTemplate) {
CustomRepresenter representer = new CustomRepresenter();
DumperOptions options = new DumperOptions();
@@ -292,15 +335,24 @@ public class ToscaExportHandler {
public Either<ToscaTemplate, ToscaError> getDependencies(Component component) {
ToscaTemplate toscaTemplate = new ToscaTemplate(null);
- Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate);
+ Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate, false);
+ if (fillImports.isRight()) {
+ return Either.right(fillImports.right().value());
+ }
+ return Either.left(fillImports.left().value().left);
+ }
+
+ public Either<ToscaTemplate, ToscaError> getDependencies(Component component, boolean isSkipImports) {
+ ToscaTemplate toscaTemplate = new ToscaTemplate(null);
+ Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports = fillImports(component, toscaTemplate, isSkipImports);
if (fillImports.isRight()) {
return Either.right(fillImports.right().value());
}
return Either.left(fillImports.left().value().left);
}
- public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component) {
- final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
+ public Either<ToscaTemplate, ToscaError> convertToToscaTemplate(final Component component, final boolean isSkipImports) {
+ final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel(), isSkipImports);
if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
return Either.right(ToscaError.GENERAL_ERROR);
@@ -319,7 +371,7 @@ public class ToscaExportHandler {
return convertNodeType(new HashMap<>(), component, toscaTemplate, nodeTypes);
} else {
log.trace("convert component as topology template");
- return convertToscaTemplate(component, toscaTemplate);
+ return convertToscaTemplate(component, toscaTemplate, isSkipImports);
}
}
@@ -357,7 +409,7 @@ public class ToscaExportHandler {
return Either.left(toscaTemplate);
}
- private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId) {
+ private List<Map<String, Map<String, String>>> getDefaultToscaImports(final String modelId, final boolean isSkipImports) {
if (StringUtils.isEmpty(modelId)) {
return getDefaultToscaImportConfig();
}
@@ -367,18 +419,21 @@ public class ToscaExportHandler {
final Set<Path> addedPathList = new HashSet<>();
for (final ToscaImportByModel toscaImportByModel : allModelImports) {
var importPath = Path.of(toscaImportByModel.getFullPath());
- if (addedPathList.contains(importPath)) {
- importPath = ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
+ if (!(isSkipImports && importPath.toString().equals(ADDITIONAL_TYPE_DEFINITIONS))) {
+ if (addedPathList.contains(importPath)) {
+ importPath =
+ ToscaDefaultImportHelper.addModelAsFilePrefix(importPath, toscaImportByModel.getModelId());
+ }
+ final String fileName = FilenameUtils.getBaseName(importPath.toString());
+ importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
+ addedPathList.add(importPath);
}
- final String fileName = FilenameUtils.getBaseName(importPath.toString());
- importList.add(Map.of(fileName, Map.of("file", importPath.toString())));
- addedPathList.add(importPath);
}
return importList;
}
- private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode) {
- Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode);
+ private Either<ToscaTemplate, ToscaError> convertToscaTemplate(Component component, ToscaTemplate toscaNode, boolean isSkipImports) {
+ Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> importsRes = fillImports(component, toscaNode, isSkipImports);
if (importsRes.isRight()) {
return Either.right(importsRes.right().value());
}
@@ -641,8 +696,8 @@ public class ToscaExportHandler {
return jsonPresentationField.getPresentation();
}
- private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate) {
- final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel());
+ private Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> fillImports(Component component, ToscaTemplate toscaTemplate, boolean isSkipImports) {
+ final List<Map<String, Map<String, String>>> defaultToscaImportConfig = getDefaultToscaImports(component.getModel(), isSkipImports);
if (CollectionUtils.isEmpty(defaultToscaImportConfig)) {
log.debug(FAILED_TO_GET_DEFAULT_IMPORTS_CONFIGURATION);
return Either.right(ToscaError.GENERAL_ERROR);
@@ -659,7 +714,7 @@ public class ToscaExportHandler {
}
List<ComponentInstance> componentInstances = component.getComponentInstances();
if (componentInstances != null && !componentInstances.isEmpty()) {
- componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci));
+ componentInstances.forEach(ci -> createDependency(componentCache, additionalImports, dependencies, ci, isSkipImports));
}
toscaTemplate.setDependencies(dependencies);
toscaTemplate.setImports(additionalImports);
@@ -695,7 +750,8 @@ public class ToscaExportHandler {
}
private void createDependency(final Map<String, Component> componentCache, final List<Map<String, Map<String, String>>> imports,
- final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance) {
+ final List<Triple<String, String, Component>> dependencies, final ComponentInstance componentInstance,
+ final boolean isSkipImports) {
log.debug("createDependency componentCache {}", componentCache);
Component componentRI = componentCache.get(componentInstance.getComponentUid());
if (componentRI == null || componentInstance.getOriginType() == OriginTypeEnum.ServiceSubstitution) {
@@ -708,7 +764,7 @@ public class ToscaExportHandler {
}
final Component fetchedComponent = resource.left().value();
componentRI = setComponentCache(componentCache, componentInstance, fetchedComponent);
- addDependencies(imports, dependencies, componentRI);
+ addDependencies(imports, dependencies, componentRI, isSkipImports);
}
}
@@ -737,9 +793,9 @@ public class ToscaExportHandler {
* Retrieves all derived_from nodes and stores it in a predictable order.
*/
private void addDependencies(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
- final Component fetchedComponent) {
+ final Component fetchedComponent, final boolean isSkipImports) {
final Set<Component> componentsList = new LinkedHashSet<>();
- if (fetchedComponent instanceof Resource) {
+ if (fetchedComponent instanceof Resource && !isSkipImports) {
log.debug("fetchedComponent is a resource {}", fetchedComponent);
final Optional<Map<String, String>> derivedFromMapOfIdToName = getDerivedFromMapOfIdToName(fetchedComponent, componentsList);
if (derivedFromMapOfIdToName.isPresent() && !derivedFromMapOfIdToName.get().isEmpty()) {
@@ -789,7 +845,7 @@ public class ToscaExportHandler {
*/
private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
final Set<Component> componentsList) {
- componentsList.forEach(component -> setImports(imports, dependencies, component));
+ componentsList.forEach(component -> setImports(imports, dependencies, component));
}
private void setImports(final List<Map<String, Map<String, String>>> imports, final List<Triple<String, String, Component>> dependencies,
@@ -1679,8 +1735,7 @@ public class ToscaExportHandler {
nodeFilter.setProperties(propertiesCopy);
}
nodeFilter.setTosca_id(cloneToscaId(inNodeFilter.getTosca_id()));
- nodeFilter = (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
- return nodeFilter;
+ return cloneObjectFromYml(nodeFilter, NodeFilter.class);
}
private NodeFilter convertToSubstitutionFilterComponent(final SubstitutionFilterDataDefinition substitutionFilterDataDefinition) {
@@ -1693,14 +1748,14 @@ public class ToscaExportHandler {
nodeFilter.setProperties(propertiesCopy);
}
nodeFilter.setTosca_id(cloneToscaId(substitutionFilterDataDefinition.getTosca_id()));
- return (NodeFilter) cloneObjectFromYml(nodeFilter, NodeFilter.class);
+ return cloneObjectFromYml(nodeFilter, NodeFilter.class);
}
private Object cloneToscaId(Object toscaId) {
return Objects.isNull(toscaId) ? null : cloneObjectFromYml(toscaId, toscaId.getClass());
}
- private Object cloneObjectFromYml(Object objToClone, Class classOfObj) {
+ private <T> T cloneObjectFromYml(Object objToClone, Class<T> classOfObj) {
String objectAsYml = yamlUtil.objectToYaml(objToClone);
return yamlUtil.yamlToObject(objectAsYml, classOfObj);
}
@@ -1884,7 +1939,6 @@ public class ToscaExportHandler {
private static class CustomRepresenter extends Representer {
CustomRepresenter() {
- super();
this.representers.put(ToscaPropertyAssignment.class, new RepresentToscaPropertyAssignment());
this.representers.put(ToscaAttribute.class, new RepresentToscaAttribute());
// null representer is exceptional and it is stored as an instance
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java b/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java
index 5c018fc0f0..17f7a0434d 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/config/CatalogBESpringConfig.java
@@ -34,6 +34,8 @@ import org.openecomp.sdc.be.ecomp.converters.AssetMetadataConverter;
import org.openecomp.sdc.be.filters.FilterConfiguration;
import org.openecomp.sdc.be.filters.PortalConfiguration;
import org.openecomp.sdc.be.filters.ThreadLocalUtils;
+import org.openecomp.sdc.be.tosca.CommonCsarGenerator;
+import org.openecomp.sdc.be.tosca.DefaultCsarGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
@@ -132,6 +134,11 @@ public class CatalogBESpringConfig {
return new PortalClient(httpClientConnectionManager(), portalConfiguration());
}
+ @Bean(name = "defaultCsarGenerator")
+ public DefaultCsarGenerator defaultCsarGenerator(CommonCsarGenerator commonCsarGenerator) {
+ return new DefaultCsarGenerator(commonCsarGenerator);
+ }
+
@Bean
public org.openecomp.sdc.be.config.Configuration configuration() {
return ConfigurationManager.getConfigurationManager().getConfiguration();
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java
index 373e9b1c89..b749ef68fd 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/CsarUtilsTest.java
@@ -100,7 +100,10 @@ import org.openecomp.sdc.exception.ResponseFormat;
class CsarUtilsTest extends BaseConfDependent {
@InjectMocks
- CsarUtils testSubject;
+ private CsarUtils testSubject;
+
+ @InjectMocks
+ private CommonCsarGenerator commonCsarGenerator;
@Mock
private ArtifactCassandraDao artifactCassandraDao;
@@ -124,7 +127,7 @@ class CsarUtilsTest extends BaseConfDependent {
private final byte[] contentData;
- public CsarUtilsTest() throws IOException {
+ public CsarUtilsTest() throws IOException {
contentData = getFileResource("yamlValidation/resource-serviceTemplate.yml");
}
@@ -158,7 +161,7 @@ class CsarUtilsTest extends BaseConfDependent {
}
@Test
- void testCreateCsar() {
+ void testCreateCsar() throws IOException {
Component component = new Resource();
Map<String, ArtifactDefinition> artifactDefinitionHashMap = new HashMap<>();
ArtifactDefinition artifact = new ArtifactDefinition();
@@ -170,17 +173,22 @@ class CsarUtilsTest extends BaseConfDependent {
component.setArtifacts(artifactDefinitionHashMap);
component.setDeploymentArtifacts(artifactDefinitionHashMap);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ZipOutputStream zip = new ZipOutputStream(out);
+
Mockito.when(artifactCassandraDao.getArtifact(Mockito.any(String.class)))
.thenReturn(Either.right(CassandraOperationStatus.GENERAL_ERROR));
Mockito.when(componentsUtils.convertFromStorageResponse(Mockito.any(StorageOperationStatus.class)))
.thenReturn(ActionStatus.GENERAL_ERROR);
- testSubject.createCsar(component, true, true);
+ assertNotNull(commonCsarGenerator.generateCsarZip(component, false, zip,
+ false, true,
+ "Definitions/", true, false).right());
}
@Test
- void testCreateCsarWithGenerateCsarZipResponseIsLeft() {
+ void testCreateCsarWithGenerateCsarZipResponseIsLeft() throws IOException {
Component component = new Resource();
Map<String, ArtifactDefinition> toscaArtifacts = new HashMap<>();
ArtifactDefinition artifact = new ArtifactDefinition();
@@ -207,6 +215,9 @@ class CsarUtilsTest extends BaseConfDependent {
filedata.setPayloadAsArray(data);
filesData.add(filedata);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ZipOutputStream zip = new ZipOutputStream(out);
+
Mockito.when(artifactCassandraDao.getArtifact(Mockito.any(String.class))).thenReturn(Either.left(artifactData));
Mockito.when(componentsUtils.convertFromStorageResponse(Mockito.any(StorageOperationStatus.class)))
@@ -219,7 +230,9 @@ class CsarUtilsTest extends BaseConfDependent {
sdcSchemaFilesCassandraDao.getSpecificSchemaFiles(Mockito.any(String.class), Mockito.any(String.class)))
.thenReturn(Either.left(filesData));
- testSubject.createCsar(component, false, true);
+ assertNotNull(commonCsarGenerator.generateCsarZip(component, false, zip,
+ false, true,
+ "Definitions/", true, false).right());
}
@Test
@@ -253,11 +266,11 @@ class CsarUtilsTest extends BaseConfDependent {
Mockito.when(toscaExportUtils.getDependencies(Mockito.any(Component.class)))
.thenReturn(Either.right(ToscaError.GENERAL_ERROR));
- try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
- Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, false);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
+ Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, true, "Definitions/", true, false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
@Test
@@ -285,11 +298,11 @@ class CsarUtilsTest extends BaseConfDependent {
Mockito.when(toscaExportUtils.exportComponent(Mockito.any(Component.class)))
.thenReturn(Either.right(ToscaError.GENERAL_ERROR));
- try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
- Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, false);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
+ Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, true, "Definitions/", true, false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
@Test
@@ -357,7 +370,7 @@ class CsarUtilsTest extends BaseConfDependent {
.thenReturn(Either.left(Mockito.any(ArtifactDefinition.class)));
try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
- Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, true);
+ Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, true, "/Definitions", true, false);
} catch (Exception e) {
e.printStackTrace();
}
@@ -405,11 +418,11 @@ class CsarUtilsTest extends BaseConfDependent {
Mockito.when(toscaExportUtils.getDependencies(Mockito.any(Component.class)))
.thenReturn(Either.left(toscaTemplate));
- try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
- Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, true);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
+ Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, true, "Definitions/", true, false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
@Test
@@ -455,11 +468,11 @@ class CsarUtilsTest extends BaseConfDependent {
Mockito.when(toscaExportUtils.getDependencies(Mockito.any(Component.class)))
.thenReturn(Either.left(toscaTemplate));
- try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
- Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, true);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
+ Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, true, "Definitions/", true, false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
@Test
@@ -509,7 +522,7 @@ class CsarUtilsTest extends BaseConfDependent {
.thenReturn(Either.right(CassandraOperationStatus.GENERAL_ERROR));
try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out);) {
- Deencapsulation.invoke(testSubject, "populateZip", component, getFromCS, zip, true);
+ Deencapsulation.invoke(commonCsarGenerator, "generateCsarZip", component, getFromCS, zip, true, "toscaMetaFileName", true, "Definitions/", true, false);
} catch (Exception e) {
e.printStackTrace();
}
@@ -542,7 +555,7 @@ class CsarUtilsTest extends BaseConfDependent {
Mockito.when(toscaOperationFacade.getToscaElement(Mockito.any(String.class)))
.thenReturn(Either.left(componentRI));
- Deencapsulation.invoke(testSubject, "addInnerComponentsToCache", componentCache, childComponent);
+ Deencapsulation.invoke(commonCsarGenerator, "addInnerComponentsToCache", componentCache, childComponent);
io.vavr.collection.List<CacheEntry> expected = io.vavr.collection.List.of(entry("esId","artifactName",componentRI));
assertEquals(expected, componentCache.all().toList());
@@ -591,7 +604,8 @@ class CsarUtilsTest extends BaseConfDependent {
try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(out)) {
- List<Triple<String, String, Component>> output = Deencapsulation.invoke(testSubject, "writeComponentInterface", new Resource(), zip, fileName);
+ List<Triple<String, String, Component>> output = Deencapsulation.invoke(commonCsarGenerator, "writeComponentInterface", new Resource(),
+ zip, fileName, "Definitions/");
assertNotNull(output);
}
}
@@ -604,7 +618,7 @@ class CsarUtilsTest extends BaseConfDependent {
Mockito.when(artifactCassandraDao.getArtifact(Mockito.any(String.class)))
.thenReturn(Either.right(CassandraOperationStatus.GENERAL_ERROR));
- Either<byte[], ActionStatus> output = Deencapsulation.invoke(testSubject, "getEntryData", cassandraId, childComponent);
+ Either<byte[], ActionStatus> output = Deencapsulation.invoke(commonCsarGenerator, "getEntryData", cassandraId, childComponent);
assertNotNull(output);
assertTrue(output.isRight());
@@ -618,7 +632,7 @@ class CsarUtilsTest extends BaseConfDependent {
sdcSchemaFilesCassandraDao.getSpecificSchemaFiles(Mockito.any(String.class), Mockito.any(String.class)))
.thenReturn(Either.left(filesData));
- Either<byte[], ResponseFormat> output = Deencapsulation.invoke(testSubject, "getLatestSchemaFilesFromCassandra");
+ Either<byte[], ResponseFormat> output = Deencapsulation.invoke(commonCsarGenerator, "getLatestSchemaFilesFromCassandra");
assertNotNull(output);
assertTrue(output.isRight());
@@ -704,88 +718,6 @@ class CsarUtilsTest extends BaseConfDependent {
}
@Test
- void testNonMetaArtifactInfoCtor() {
- createNonMetaArtifactInfoTestSubject();
- }
-
- @Test
- void testNonMetaArtifactInfoGetPath() {
- NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
- testSubject.getPath();
- }
-
- @Test
- void testNonMetaArtifactInfoGetArtifactName() {
- NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
- testSubject.getArtifactName();
- }
-
- @Test
- void testNonMetaArtifactInfoGetArtifactType() {
- final NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
- assertThat("The artifact type should be as expected",
- testSubject.getArtifactType(), is(ArtifactTypeEnum.AAI_SERVICE_MODEL.getType()));
- }
-
- @Test
- void testNonMetaArtifactInfoGetDisplayName() {
- NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
- testSubject.getDisplayName();
- }
-
- @Test
- void testNonMetaArtifactInfoGetArtifactGroupType() {
- NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
- testSubject.getArtifactGroupType();
- }
-
- @Test
- void testNonMetaArtifactInfoGetArtifactLabel() {
- NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
- testSubject.getArtifactLabel();
- }
-
- @Test
- void testNonMetaArtifactInfoGetIsFromCsar() {
- NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
- testSubject.isFromCsar();
- }
-
- @Test
- void testNonMetaArtifactInfoGetPayloadData() {
- NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
- testSubject.getPayloadData();
- }
-
- @Test
- void testNonMetaArtifactInfoGetArtifaactChecksum() {
- NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
- testSubject.getArtifactChecksum();
- }
-
- @Test
- void testNonMetaArtifactInfoGetArtifactUniqueId() {
- NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
- testSubject.getArtifactUniqueId();
- }
-
- @Test
- void testNonMetaArtifactInfosetArtifactUniqueId() {
- NonMetaArtifactInfo testSubject = createNonMetaArtifactInfoTestSubject();
-
- testSubject.setArtifactUniqueId("artifactUniqueId");
- }
-
- @Test
void testValidateNonMetaArtifactWithExceptionCaught() {
CsarUtils.validateNonMetaArtifact("", new byte[0], new HashMap<>());
}
@@ -950,7 +882,7 @@ class CsarUtilsTest extends BaseConfDependent {
final Path path = Paths.get(rootPath + "/src/test/resources/sdc.zip");
final byte[] data = Files.readAllBytes(path);
try (final ByteArrayOutputStream out = new ByteArrayOutputStream(); final ZipOutputStream zip = new ZipOutputStream(out)) {
- Deencapsulation.invoke(testSubject, "addSchemaFilesFromCassandra", zip, data, nodesFromPackage);
+ Deencapsulation.invoke(commonCsarGenerator, "addSchemaFilesFromCassandra", zip, data, nodesFromPackage, "Definitions/");
final IOException actualException = assertThrows(IOException.class, () -> zip.putNextEntry(new ZipEntry("Definitions/nodes.yml")));
assertEquals("duplicate entry: Definitions/nodes.yml", actualException.getMessage());
}
@@ -965,7 +897,7 @@ class CsarUtilsTest extends BaseConfDependent {
final Triple<String, String, Component> triple = Triple.of("fileName", "cassandraId", component);
dependencies.add(triple);
final List<String> expectedResult = Arrays.asList("tosca.nodes.Container.Application");
- final List<String> result = Deencapsulation.invoke(testSubject,
+ final List<String> result = Deencapsulation.invoke(commonCsarGenerator,
"findNonRootNodesFromPackage", dependencies);
assertTrue(CollectionUtils.isNotEmpty(result));
assertEquals(expectedResult, result);
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
index 4f267138d7..0b3796261a 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/tosca/ToscaExportHandlerTest.java
@@ -386,7 +386,7 @@ class ToscaExportHandlerTest extends BaseConfDependent {
when(toscaOperationFacade.getToscaFullElement("name")).thenReturn(Either.left(resource));
Either<ImmutablePair<ToscaTemplate, Map<String, Component>>, ToscaError> result;
- result = Deencapsulation.invoke(testSubject, "fillImports", resource, toscaTemplate);
+ result = Deencapsulation.invoke(testSubject, "fillImports", resource, toscaTemplate, false);
verify(toscaOperationFacade, times(1)).getToscaFullElement("name");
assertTrue(result.isLeft());
@@ -421,7 +421,7 @@ class ToscaExportHandlerTest extends BaseConfDependent {
doReturn(map).when(outputConverter).convert(any(), any());
// default test
- result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode);
+ result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode, false);
assertNotNull(result);
}
@@ -471,7 +471,7 @@ class ToscaExportHandlerTest extends BaseConfDependent {
doReturn(map).when(outputConverter).convert(any(), any());
// test component contains group
- final var result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode);
+ final var result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode, false);
assertNotNull(result);
}
@@ -510,7 +510,7 @@ class ToscaExportHandlerTest extends BaseConfDependent {
doReturn(map).when(outputConverter).convert(any(), any());
// test component contains group
- result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode);
+ result = Deencapsulation.invoke(testSubject, "convertToscaTemplate", component, toscaNode, false);
assertNotNull(result);
}
@@ -561,7 +561,7 @@ class ToscaExportHandlerTest extends BaseConfDependent {
when(toscaOperationFacade.getByToscaResourceNameAndVersion("org.typeA", "1.0", null)).thenReturn(Either.left(baseType));
// default test
- result = Deencapsulation.invoke(testSubject, "fillImports", component, toscaTemplate);
+ result = Deencapsulation.invoke(testSubject, "fillImports", component, toscaTemplate, false);
assertNotNull(result);
}
@@ -588,7 +588,7 @@ class ToscaExportHandlerTest extends BaseConfDependent {
when(toscaOperationFacade.getToscaFullElement("modelName")).thenReturn(Either.left(new Service()));
// default test
- Deencapsulation.invoke(testSubject, "createDependency", componentCache, imports, dependecies, ci);
+ Deencapsulation.invoke(testSubject, "createDependency", componentCache, imports, dependecies, ci, false);
assertFalse(componentCache.isEmpty());
}