From 707fb6d83819058d5736b2dc38bea3c2d9e07a2d Mon Sep 17 00:00:00 2001 From: vasraz Date: Fri, 8 Oct 2021 14:48:08 +0100 Subject: Large csar handling - object store Change-Id: I4e88bd7bfcc1fdbc93d67da2682f2e873ba243c6 Signed-off-by: Vasyl Razinkov Issue-ID: SDC-3754 --- .../sdc/be/csar/storage/CsarSizeReducer.java | 233 ------------------- .../sdc/be/csar/storage/MinIoArtifactInfo.java | 38 ++++ .../storage/MinIoStorageArtifactStorageConfig.java | 52 +++++ .../MinIoStorageArtifactStorageManager.java | 247 +++++++++++++++++++++ .../csar/storage/MinIoStorageCsarSizeReducer.java | 233 +++++++++++++++++++ .../sdc/be/csar/storage/NoneStorageManager.java | 54 +++++ .../storage/PersistentStorageArtifactInfo.java | 33 --- .../PersistentVolumeArtifactStorageConfig.java | 32 --- .../PersistentVolumeArtifactStorageManager.java | 161 -------------- .../sdc/be/csar/storage/StorageFactory.java | 91 ++++++++ .../exception/ArtifactStorageException.java | 34 +++ .../PersistentVolumeArtifactStorageException.java | 34 --- 12 files changed, 749 insertions(+), 493 deletions(-) delete mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/CsarSizeReducer.java create mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoArtifactInfo.java create mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageConfig.java create mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManager.java create mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageCsarSizeReducer.java create mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/NoneStorageManager.java delete mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentStorageArtifactInfo.java delete mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageConfig.java delete mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageManager.java create mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/StorageFactory.java create mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/exception/ArtifactStorageException.java delete mode 100644 common-be/src/main/java/org/openecomp/sdc/be/csar/storage/exception/PersistentVolumeArtifactStorageException.java (limited to 'common-be/src/main/java') diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/CsarSizeReducer.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/CsarSizeReducer.java deleted file mode 100644 index 822acc0766..0000000000 --- a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/CsarSizeReducer.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.openecomp.sdc.be.csar.storage; - -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; - -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; -import lombok.Getter; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.io.FilenameUtils; -import org.openecomp.sdc.be.csar.storage.exception.CsarSizeReducerException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CsarSizeReducer implements PackageSizeReducer { - - private static final Logger LOGGER = LoggerFactory.getLogger(CsarSizeReducer.class); - private static final Set ALLOWED_SIGNATURE_EXTENSIONS = Set.of("cms"); - private static final Set ALLOWED_CERTIFICATE_EXTENSIONS = Set.of("cert", "crt"); - private static final String CSAR_EXTENSION = "csar"; - private static final String UNEXPECTED_PROBLEM_HAPPENED_WHILE_READING_THE_CSAR = "An unexpected problem happened while reading the CSAR '%s'"; - @Getter - private final AtomicBoolean reduced = new AtomicBoolean(false); - - private final CsarPackageReducerConfiguration configuration; - - public CsarSizeReducer(final CsarPackageReducerConfiguration configuration) { - this.configuration = configuration; - } - - @Override - public byte[] reduce(final Path csarPackagePath) { - if (hasSignedPackageStructure(csarPackagePath)) { - return reduce(csarPackagePath, this::signedZipProcessingConsumer); - } else { - return reduce(csarPackagePath, this::unsignedZipProcessingConsumer); - } - } - - private byte[] reduce(final Path csarPackagePath, final ZipProcessFunction zipProcessingFunction) { - final var reducedCsarPath = Path.of(csarPackagePath + "." + UUID.randomUUID()); - - try (final var zf = new ZipFile(csarPackagePath.toString()); - final var zos = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(reducedCsarPath)))) { - zf.entries().asIterator().forEachRemaining(zipProcessingFunction.getProcessZipConsumer(csarPackagePath, zf, zos)); - } catch (final IOException ex1) { - rollback(reducedCsarPath); - final var errorMsg = String.format(UNEXPECTED_PROBLEM_HAPPENED_WHILE_READING_THE_CSAR, csarPackagePath); - throw new CsarSizeReducerException(errorMsg, ex1); - } - final byte[] reducedCsarBytes; - try { - if (reduced.get()) { - reducedCsarBytes = Files.readAllBytes(reducedCsarPath); - } else { - reducedCsarBytes = Files.readAllBytes(csarPackagePath); - } - } catch (final IOException e) { - final var errorMsg = String.format("Could not read bytes of file '%s'", csarPackagePath); - throw new CsarSizeReducerException(errorMsg, e); - } - try { - Files.delete(reducedCsarPath); - } catch (final IOException e) { - final var errorMsg = String.format("Could not delete temporary file '%s'", reducedCsarPath); - throw new CsarSizeReducerException(errorMsg, e); - } - - return reducedCsarBytes; - } - - private Consumer signedZipProcessingConsumer(final Path csarPackagePath, final ZipFile zf, final ZipOutputStream zos) { - final var thresholdEntries = configuration.getThresholdEntries(); - final var totalEntryArchive = new AtomicInteger(0); - return zipEntry -> { - final var entryName = zipEntry.getName(); - try { - if (totalEntryArchive.getAndIncrement() > thresholdEntries) { - // too much entries in this archive, can lead to inodes exhaustion of the system - final var errorMsg = String.format("Failed to extract '%s' from zip '%s'", entryName, csarPackagePath); - throw new CsarSizeReducerException(errorMsg); - } - zos.putNextEntry(new ZipEntry(entryName)); - if (!zipEntry.isDirectory()) { - if (entryName.toLowerCase().endsWith(CSAR_EXTENSION)) { - final var internalCsarExtractPath = Path.of(csarPackagePath + "." + UUID.randomUUID()); - Files.copy(zf.getInputStream(zipEntry), internalCsarExtractPath, REPLACE_EXISTING); - zos.write(reduce(internalCsarExtractPath, this::unsignedZipProcessingConsumer)); - Files.delete(internalCsarExtractPath); - } else { - zos.write(zf.getInputStream(zipEntry).readAllBytes()); - } - } - zos.closeEntry(); - } catch (final IOException ei) { - final var errorMsg = String.format("Failed to extract '%s' from zip '%s'", entryName, csarPackagePath); - throw new CsarSizeReducerException(errorMsg, ei); - } - }; - } - - private Consumer unsignedZipProcessingConsumer(final Path csarPackagePath, final ZipFile zf, final ZipOutputStream zos) { - final var thresholdEntries = configuration.getThresholdEntries(); - final var totalEntryArchive = new AtomicInteger(0); - return zipEntry -> { - final var entryName = zipEntry.getName(); - if (totalEntryArchive.getAndIncrement() > thresholdEntries) { - // too much entries in this archive, can lead to inodes exhaustion of the system - final var errorMsg = String.format("Failed to extract '%s' from zip '%s'", entryName, csarPackagePath); - throw new CsarSizeReducerException(errorMsg); - } - try { - zos.putNextEntry(new ZipEntry(entryName)); - if (!zipEntry.isDirectory()) { - if (isCandidateToRemove(zipEntry)) { - // replace with EMPTY string to avoid package description inconsistency/validation errors - zos.write("".getBytes()); - reduced.set(true); - } else { - zos.write(zf.getInputStream(zipEntry).readAllBytes()); - } - } - zos.closeEntry(); - } catch (final IOException ei) { - final var errorMsg = String.format("Failed to extract '%s' from zip '%s'", entryName, csarPackagePath); - throw new CsarSizeReducerException(errorMsg, ei); - } - }; - } - - private void rollback(final Path reducedCsarPath) { - if (Files.exists(reducedCsarPath)) { - try { - Files.delete(reducedCsarPath); - } catch (final Exception ex2) { - LOGGER.warn("Could not delete temporary file '{}'", reducedCsarPath, ex2); - } - } - } - - private boolean isCandidateToRemove(final ZipEntry zipEntry) { - final String zipEntryName = zipEntry.getName(); - return configuration.getFoldersToStrip().stream().anyMatch(Path.of(zipEntryName)::startsWith) - || zipEntry.getSize() > configuration.getSizeLimit(); - } - - private boolean hasSignedPackageStructure(final Path csarPackagePath) { - final List packagePathList; - try (final var zf = new ZipFile(csarPackagePath.toString())) { - packagePathList = zf.stream() - .filter(zipEntry -> !zipEntry.isDirectory()) - .map(ZipEntry::getName).map(Path::of) - .collect(Collectors.toList()); - } catch (final IOException e) { - final var errorMsg = String.format(UNEXPECTED_PROBLEM_HAPPENED_WHILE_READING_THE_CSAR, csarPackagePath); - throw new CsarSizeReducerException(errorMsg, e); - } - - if (CollectionUtils.isEmpty(packagePathList)) { - return false; - } - final int numberOfFiles = packagePathList.size(); - if (numberOfFiles == 2) { - return hasOneInternalPackageFile(packagePathList) && hasOneSignatureFile(packagePathList); - } - if (numberOfFiles == 3) { - return hasOneInternalPackageFile(packagePathList) && hasOneSignatureFile(packagePathList) && hasOneCertificateFile(packagePathList); - } - return false; - } - - private boolean hasOneInternalPackageFile(final List packagePathList) { - return packagePathList.parallelStream() - .map(Path::toString) - .map(FilenameUtils::getExtension) - .map(String::toLowerCase) - .filter(extension -> extension.endsWith(CSAR_EXTENSION)).count() == 1; - } - - private boolean hasOneSignatureFile(final List packagePathList) { - return packagePathList.parallelStream() - .map(Path::toString) - .map(FilenameUtils::getExtension) - .map(String::toLowerCase) - .filter(ALLOWED_SIGNATURE_EXTENSIONS::contains).count() == 1; - } - - private boolean hasOneCertificateFile(final List packagePathList) { - return packagePathList.parallelStream() - .map(Path::toString) - .map(FilenameUtils::getExtension) - .map(String::toLowerCase) - .filter(ALLOWED_CERTIFICATE_EXTENSIONS::contains).count() == 1; - } - - @FunctionalInterface - private interface ZipProcessFunction { - - Consumer getProcessZipConsumer(Path csarPackagePath, ZipFile zf, ZipOutputStream zos); - } - -} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoArtifactInfo.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoArtifactInfo.java new file mode 100644 index 0000000000..a193cdd6db --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoArtifactInfo.java @@ -0,0 +1,38 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.csar.storage; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class MinIoArtifactInfo implements ArtifactInfo { + + private final String bucket; + private final String objectName; + + @Override + public String getInfo() { + return String.format("bucket: %s\n" + + "object: %s", bucket, objectName); + } +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageConfig.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageConfig.java new file mode 100644 index 0000000000..6f6778f2b0 --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageConfig.java @@ -0,0 +1,52 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.csar.storage; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public class MinIoStorageArtifactStorageConfig implements ArtifactStorageConfig { + + private final boolean isEnabled; + private final EndPoint endPoint; + private final Credentials credentials; + private final String tempPath; + + @AllArgsConstructor + @Getter + public static class EndPoint { + + private final String host; + private final int port; + private final boolean secure; + } + + @AllArgsConstructor + @Getter + public static class Credentials { + + private final String accessKey; + private final String secretKey; + } + +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManager.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManager.java new file mode 100644 index 0000000000..0a48c2233c --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageArtifactStorageManager.java @@ -0,0 +1,247 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.csar.storage; + +import static org.openecomp.sdc.common.errors.Messages.EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING; + +import io.minio.BucketExistsArgs; +import io.minio.CopyObjectArgs; +import io.minio.CopySource; +import io.minio.GetObjectArgs; +import io.minio.MakeBucketArgs; +import io.minio.MinioClient; +import io.minio.MinioClient.Builder; +import io.minio.PutObjectArgs; +import io.minio.RemoveObjectArgs; +import java.io.InputStream; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import lombok.Getter; +import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.Credentials; +import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.EndPoint; +import org.openecomp.sdc.be.csar.storage.exception.ArtifactStorageException; +import org.openecomp.sdc.common.CommonConfigurationManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MinIoStorageArtifactStorageManager implements ArtifactStorageManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(MinIoStorageArtifactStorageManager.class); + private static final String EXTERNAL_CSAR_STORE = "externalCsarStore"; + + @Getter + private final MinIoStorageArtifactStorageConfig storageConfiguration; + private final MinioClient minioClient; + + public MinIoStorageArtifactStorageManager() { + this.storageConfiguration = readMinIoStorageArtifactStorageConfig(); + minioClient = initMinioClient(); + } + + //for testing only + MinIoStorageArtifactStorageManager(final ArtifactStorageConfig storageConfiguration) { + this.storageConfiguration = (MinIoStorageArtifactStorageConfig) storageConfiguration; + minioClient = initMinioClient(); + } + + @Override + public ArtifactInfo persist(final String vspId, final String versionId, final ArtifactInfo uploadedArtifactInfo) { + final MinIoArtifactInfo minioObjectTemp = (MinIoArtifactInfo) uploadedArtifactInfo; + try { + minioClient.getObject( + GetObjectArgs.builder() + .bucket(minioObjectTemp.getBucket()) + .object(minioObjectTemp.getObjectName()) + .build() + ); + } catch (final Exception e) { + throw new ArtifactStorageException( + String.format("Failed to retrieve uploaded artifact with bucket '%s' and name '%s' while persisting", + minioObjectTemp.getBucket(), minioObjectTemp.getObjectName()), e); + } + + final var backupPath = backupPreviousVersion(vspId, versionId).orElse(null); + try { + moveFile(minioObjectTemp, vspId, versionId); + } catch (final Exception e) { + rollback(minioObjectTemp, vspId, versionId); + final var errorMsg = String.format("Could not persist artifact for VSP '%s', version '%s'", vspId, versionId); + throw new ArtifactStorageException(errorMsg, e); + } + + removePreviousVersion(backupPath); + + return new MinIoArtifactInfo(vspId, versionId); + } + + @Override + public ArtifactInfo upload(final String vspId, final String versionId, final InputStream fileToUpload) { + + final String name = versionId + "--" + UUID.randomUUID(); + try { + // Make bucket if not exist. + final boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(vspId).build()); + + if (!found) { + // Make a new bucket ${vspId} . + minioClient.makeBucket(MakeBucketArgs.builder().bucket(vspId).build()); + } else { + LOGGER.info("Bucket '{}' already exists.", vspId); + } + + minioClient.putObject( + PutObjectArgs.builder() + .bucket(vspId) + .object(name) + .stream(fileToUpload, fileToUpload.available(), -1) + .build() + ); + + } catch (final Exception e) { + throw new ArtifactStorageException("Failed to upload artifact", e); + } + + return new MinIoArtifactInfo(vspId, name); + } + + @Override + public boolean isEnabled() { + return storageConfiguration != null && storageConfiguration.isEnabled(); + } + + @Override + public InputStream get(final ArtifactInfo artifactInfo) { + final MinIoArtifactInfo minioObject = (MinIoArtifactInfo) artifactInfo; + try { + return minioClient.getObject(GetObjectArgs.builder() + .bucket(minioObject.getBucket()) + .object(minioObject.getObjectName()) + .build()); + } catch (final Exception e) { + throw new ArtifactStorageException("Failed to get Object", e); + } + } + + @Override + public void delete(final ArtifactInfo artifactInfo) { + final MinIoArtifactInfo minioObject = (MinIoArtifactInfo) artifactInfo; + try { + minioClient.removeObject(RemoveObjectArgs.builder() + .bucket(minioObject.getBucket()) + .object(minioObject.getObjectName()) + .bypassGovernanceMode(true) + .build()); + } catch (final Exception e) { + throw new ArtifactStorageException(String.format("Failed to delete '%s'", minioObject.getObjectName()), e); + } + + } + + private Optional backupPreviousVersion(final String vspId, final String versionId) { + + final String tempName = versionId + "--" + UUID.randomUUID().toString(); + try { + copy(vspId, tempName, versionId); + } catch (final Exception e) { + return Optional.empty(); + } + + return Optional.of(new MinIoArtifactInfo(vspId, tempName)); + } + + private void rollback(final MinIoArtifactInfo minioObject, final String vspId, final String versionId) { + try { + moveFile(minioObject, vspId, versionId); + } catch (final Exception ex) { + LOGGER.warn("Could not rollback the backup '{}' to the original '{}'", versionId, minioObject.getObjectName(), ex); + } + } + + private void removePreviousVersion(final MinIoArtifactInfo minioObject) { + if (minioObject == null) { + return; + } + delete(minioObject); + } + + private void moveFile(final MinIoArtifactInfo minioObject, final String vspId, final String versionId) { + try { + copy(vspId, versionId, minioObject.getObjectName()); + } catch (final Exception e) { + throw new ArtifactStorageException("Failed to move", e); + } + delete(minioObject); + } + + private void copy(final String vspId, final String versionId, final String objectName) throws Exception { + minioClient.copyObject( + CopyObjectArgs.builder() + .bucket(vspId) + .object(versionId) + .source(CopySource.builder() + .bucket(vspId) + .object(objectName) + .build()) + .build()); + } + + private MinIoStorageArtifactStorageConfig readMinIoStorageArtifactStorageConfig() { + final var commonConfigurationManager = CommonConfigurationManager.getInstance(); + + final Map endpoint = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "endpoint", null); + final Map credentials = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "credentials", null); + final String tempPath = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "tempPath", null); + LOGGER.info("ArtifactConfig.endpoint: '{}'", endpoint); + LOGGER.info("ArtifactConfig.credentials: '{}'", credentials); + LOGGER.info("ArtifactConfig.tempPath: '{}'", tempPath); + + if (endpoint == null) { + throw new RuntimeException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage("endpoint")); + } + if (credentials == null) { + throw new RuntimeException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage("credentials")); + } + if (tempPath == null) { + throw new RuntimeException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage("tempPath")); + } + final String host = (String) endpoint.getOrDefault("host", null); + final int port = (int) endpoint.getOrDefault("port", 0); + final boolean secure = (boolean) endpoint.getOrDefault("secure", false); + + final String accessKey = (String) credentials.getOrDefault("accessKey", null); + final String secretKey = (String) credentials.getOrDefault("secretKey", null); + + return new MinIoStorageArtifactStorageConfig(true, new EndPoint(host, port, secure), new Credentials(accessKey, secretKey), tempPath); + } + + private MinioClient initMinioClient() { + final EndPoint endPoint = storageConfiguration.getEndPoint(); + final Credentials credentials = storageConfiguration.getCredentials(); + + final Builder builder = MinioClient.builder(); + return builder + .endpoint(endPoint.getHost(), endPoint.getPort(), endPoint.isSecure()) + .credentials(credentials.getAccessKey(), credentials.getSecretKey()) + .build(); + } + +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageCsarSizeReducer.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageCsarSizeReducer.java new file mode 100644 index 0000000000..3181b088c0 --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/MinIoStorageCsarSizeReducer.java @@ -0,0 +1,233 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.csar.storage; + +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; + +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; +import lombok.Getter; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.io.FilenameUtils; +import org.openecomp.sdc.be.csar.storage.exception.CsarSizeReducerException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MinIoStorageCsarSizeReducer implements PackageSizeReducer { + + private static final Logger LOGGER = LoggerFactory.getLogger(MinIoStorageCsarSizeReducer.class); + private static final Set ALLOWED_SIGNATURE_EXTENSIONS = Set.of("cms"); + private static final Set ALLOWED_CERTIFICATE_EXTENSIONS = Set.of("cert", "crt"); + private static final String CSAR_EXTENSION = "csar"; + private static final String UNEXPECTED_PROBLEM_HAPPENED_WHILE_READING_THE_CSAR = "An unexpected problem happened while reading the CSAR '%s'"; + @Getter + private final AtomicBoolean reduced = new AtomicBoolean(false); + + private final CsarPackageReducerConfiguration configuration; + + public MinIoStorageCsarSizeReducer(final CsarPackageReducerConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public byte[] reduce(final Path csarPackagePath) { + if (hasSignedPackageStructure(csarPackagePath)) { + return reduce(csarPackagePath, this::signedZipProcessingConsumer); + } else { + return reduce(csarPackagePath, this::unsignedZipProcessingConsumer); + } + } + + private byte[] reduce(final Path csarPackagePath, final ZipProcessFunction zipProcessingFunction) { + final var reducedCsarPath = Path.of(csarPackagePath + "." + UUID.randomUUID()); + + try (final var zf = new ZipFile(csarPackagePath.toString()); + final var zos = new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(reducedCsarPath)))) { + zf.entries().asIterator().forEachRemaining(zipProcessingFunction.getProcessZipConsumer(csarPackagePath, zf, zos)); + } catch (final IOException ex1) { + rollback(reducedCsarPath); + final var errorMsg = String.format(UNEXPECTED_PROBLEM_HAPPENED_WHILE_READING_THE_CSAR, csarPackagePath); + throw new CsarSizeReducerException(errorMsg, ex1); + } + final byte[] reducedCsarBytes; + try { + if (reduced.get()) { + reducedCsarBytes = Files.readAllBytes(reducedCsarPath); + } else { + reducedCsarBytes = Files.readAllBytes(csarPackagePath); + } + } catch (final IOException e) { + final var errorMsg = String.format("Could not read bytes of file '%s'", csarPackagePath); + throw new CsarSizeReducerException(errorMsg, e); + } + try { + Files.delete(reducedCsarPath); + } catch (final IOException e) { + final var errorMsg = String.format("Could not delete temporary file '%s'", reducedCsarPath); + throw new CsarSizeReducerException(errorMsg, e); + } + + return reducedCsarBytes; + } + + private Consumer signedZipProcessingConsumer(final Path csarPackagePath, final ZipFile zf, final ZipOutputStream zos) { + final var thresholdEntries = configuration.getThresholdEntries(); + final var totalEntryArchive = new AtomicInteger(0); + return zipEntry -> { + final var entryName = zipEntry.getName(); + try { + if (totalEntryArchive.getAndIncrement() > thresholdEntries) { + // too much entries in this archive, can lead to inodes exhaustion of the system + final var errorMsg = String.format("Failed to extract '%s' from zip '%s'", entryName, csarPackagePath); + throw new CsarSizeReducerException(errorMsg); + } + zos.putNextEntry(new ZipEntry(entryName)); + if (!zipEntry.isDirectory()) { + if (entryName.toLowerCase().endsWith(CSAR_EXTENSION)) { + final var internalCsarExtractPath = Path.of(csarPackagePath + "." + UUID.randomUUID()); + Files.copy(zf.getInputStream(zipEntry), internalCsarExtractPath, REPLACE_EXISTING); + zos.write(reduce(internalCsarExtractPath, this::unsignedZipProcessingConsumer)); + Files.delete(internalCsarExtractPath); + } else { + zos.write(zf.getInputStream(zipEntry).readAllBytes()); + } + } + zos.closeEntry(); + } catch (final IOException ei) { + final var errorMsg = String.format("Failed to extract '%s' from zip '%s'", entryName, csarPackagePath); + throw new CsarSizeReducerException(errorMsg, ei); + } + }; + } + + private Consumer unsignedZipProcessingConsumer(final Path csarPackagePath, final ZipFile zf, final ZipOutputStream zos) { + final var thresholdEntries = configuration.getThresholdEntries(); + final var totalEntryArchive = new AtomicInteger(0); + return zipEntry -> { + final var entryName = zipEntry.getName(); + if (totalEntryArchive.getAndIncrement() > thresholdEntries) { + // too much entries in this archive, can lead to inodes exhaustion of the system + final var errorMsg = String.format("Failed to extract '%s' from zip '%s'", entryName, csarPackagePath); + throw new CsarSizeReducerException(errorMsg); + } + try { + zos.putNextEntry(new ZipEntry(entryName)); + if (!zipEntry.isDirectory()) { + if (isCandidateToRemove(zipEntry)) { + // replace with EMPTY string to avoid package description inconsistency/validation errors + zos.write("".getBytes()); + reduced.set(true); + } else { + zos.write(zf.getInputStream(zipEntry).readAllBytes()); + } + } + zos.closeEntry(); + } catch (final IOException ei) { + final var errorMsg = String.format("Failed to extract '%s' from zip '%s'", entryName, csarPackagePath); + throw new CsarSizeReducerException(errorMsg, ei); + } + }; + } + + private void rollback(final Path reducedCsarPath) { + if (Files.exists(reducedCsarPath)) { + try { + Files.delete(reducedCsarPath); + } catch (final Exception ex2) { + LOGGER.warn("Could not delete temporary file '{}'", reducedCsarPath, ex2); + } + } + } + + private boolean isCandidateToRemove(final ZipEntry zipEntry) { + final String zipEntryName = zipEntry.getName(); + return configuration.getFoldersToStrip().stream().anyMatch(Path.of(zipEntryName)::startsWith) + || zipEntry.getSize() > configuration.getSizeLimit(); + } + + private boolean hasSignedPackageStructure(final Path csarPackagePath) { + final List packagePathList; + try (final var zf = new ZipFile(csarPackagePath.toString())) { + packagePathList = zf.stream() + .filter(zipEntry -> !zipEntry.isDirectory()) + .map(ZipEntry::getName).map(Path::of) + .collect(Collectors.toList()); + } catch (final IOException e) { + final var errorMsg = String.format(UNEXPECTED_PROBLEM_HAPPENED_WHILE_READING_THE_CSAR, csarPackagePath); + throw new CsarSizeReducerException(errorMsg, e); + } + + if (CollectionUtils.isEmpty(packagePathList)) { + return false; + } + final int numberOfFiles = packagePathList.size(); + if (numberOfFiles == 2) { + return hasOneInternalPackageFile(packagePathList) && hasOneSignatureFile(packagePathList); + } + if (numberOfFiles == 3) { + return hasOneInternalPackageFile(packagePathList) && hasOneSignatureFile(packagePathList) && hasOneCertificateFile(packagePathList); + } + return false; + } + + private boolean hasOneInternalPackageFile(final List packagePathList) { + return packagePathList.parallelStream() + .map(Path::toString) + .map(FilenameUtils::getExtension) + .map(String::toLowerCase) + .filter(extension -> extension.endsWith(CSAR_EXTENSION)).count() == 1; + } + + private boolean hasOneSignatureFile(final List packagePathList) { + return packagePathList.parallelStream() + .map(Path::toString) + .map(FilenameUtils::getExtension) + .map(String::toLowerCase) + .filter(ALLOWED_SIGNATURE_EXTENSIONS::contains).count() == 1; + } + + private boolean hasOneCertificateFile(final List packagePathList) { + return packagePathList.parallelStream() + .map(Path::toString) + .map(FilenameUtils::getExtension) + .map(String::toLowerCase) + .filter(ALLOWED_CERTIFICATE_EXTENSIONS::contains).count() == 1; + } + + @FunctionalInterface + private interface ZipProcessFunction { + + Consumer getProcessZipConsumer(Path csarPackagePath, ZipFile zf, ZipOutputStream zos); + } + +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/NoneStorageManager.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/NoneStorageManager.java new file mode 100644 index 0000000000..3fa22d41be --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/NoneStorageManager.java @@ -0,0 +1,54 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.csar.storage; + +import java.io.InputStream; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public class NoneStorageManager implements ArtifactStorageManager { + + @Override + public ArtifactInfo persist(final String vspId, final String versionId, final ArtifactInfo uploadedArtifactInfo) { + throw new UnsupportedOperationException(); + } + + @Override + public ArtifactInfo upload(final String vspId, final String versionId, final InputStream fileToUpload) { + throw new UnsupportedOperationException(); + } + + @Override + public ArtifactStorageConfig getStorageConfiguration() { + throw new UnsupportedOperationException(); + } + + @Override + public InputStream get(final ArtifactInfo artifactInfo) { + throw new UnsupportedOperationException(); + } + + @Override + public void delete(final ArtifactInfo artifactInfo) { + throw new UnsupportedOperationException(); + } + +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentStorageArtifactInfo.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentStorageArtifactInfo.java deleted file mode 100644 index 0472661fd9..0000000000 --- a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentStorageArtifactInfo.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.openecomp.sdc.be.csar.storage; - -import java.nio.file.Path; -import lombok.AllArgsConstructor; -import lombok.Getter; - -@AllArgsConstructor -public class PersistentStorageArtifactInfo implements ArtifactInfo { - - @Getter - private final Path path; - -} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageConfig.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageConfig.java deleted file mode 100644 index d3cd6fb302..0000000000 --- a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.openecomp.sdc.be.csar.storage; - -import java.nio.file.Path; -import lombok.Data; - -@Data -public class PersistentVolumeArtifactStorageConfig implements ArtifactStorageConfig { - - private final boolean isEnabled; - private final Path storagePath; - -} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageManager.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageManager.java deleted file mode 100644 index 10629b3edb..0000000000 --- a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/PersistentVolumeArtifactStorageManager.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.openecomp.sdc.be.csar.storage; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; -import java.util.Optional; -import java.util.UUID; -import org.openecomp.sdc.be.csar.storage.exception.PersistentVolumeArtifactStorageException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PersistentVolumeArtifactStorageManager implements ArtifactStorageManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(PersistentVolumeArtifactStorageManager.class); - - private final PersistentVolumeArtifactStorageConfig storageConfiguration; - - public PersistentVolumeArtifactStorageManager(final ArtifactStorageConfig storageConfiguration) { - this.storageConfiguration = (PersistentVolumeArtifactStorageConfig) storageConfiguration; - } - - @Override - public ArtifactInfo persist(final String vspId, final String versionId, final ArtifactInfo uploadedArtifactInfo) { - final var temporaryPath = uploadedArtifactInfo.getPath(); - if (!Files.exists(temporaryPath)) { - throw new PersistentVolumeArtifactStorageException(String.format("Given artifact does not exist '%s'", uploadedArtifactInfo.getPath())); - } - - final var filePath = buildFilePath(vspId, versionId); - final var backupPath = backupPreviousVersion(filePath).orElse(null); - try { - moveFile(temporaryPath, filePath); - } catch (final Exception e) { - rollback(backupPath, filePath); - final var errorMsg = String.format("Could not persist artifact for VSP '%s', version '%s'", vspId, versionId); - throw new PersistentVolumeArtifactStorageException(errorMsg, e); - } - - removePreviousVersion(backupPath); - - return new PersistentStorageArtifactInfo(filePath); - } - - @Override - public ArtifactInfo upload(final String vspId, final String versionId, final InputStream artifactInputStream) { - final var destinationFolder = buildDestinationFolder(vspId, versionId); - try { - Files.createDirectories(destinationFolder); - } catch (final IOException e) { - throw new PersistentVolumeArtifactStorageException(String.format("Could not create directory '%s'", destinationFolder), e); - } - - final var filePath = createTempFilePath(destinationFolder); - try { - persist(artifactInputStream, filePath); - } catch (final IOException e) { - throw new PersistentVolumeArtifactStorageException(String.format("Could not persist artifact '%s'", filePath), e); - } - - return new PersistentStorageArtifactInfo(filePath); - } - - private Path buildFilePath(final String vspId, final String versionId) { - return buildDestinationFolder(vspId, versionId).resolve(versionId); - } - - @Override - public boolean isEnabled() { - return storageConfiguration != null && storageConfiguration.isEnabled(); - } - - private Optional backupPreviousVersion(final Path filePath) { - if (!Files.exists(filePath)) { - return Optional.empty(); - } - - final var backupPath = Path.of(filePath + UUID.randomUUID().toString()); - moveFile(filePath, backupPath); - return Optional.ofNullable(backupPath); - } - - private void rollback(final Path backupPath, final Path filePath) { - try { - moveFile(backupPath, filePath); - } catch (final Exception ex) { - LOGGER.warn("Could not rollback the backup file '{}' to the original '{}'", backupPath, filePath, ex); - } - } - - private void removePreviousVersion(final Path filePath) { - if (filePath == null || !Files.exists(filePath)) { - return; - } - - try { - Files.delete(filePath); - } catch (final IOException e) { - throw new PersistentVolumeArtifactStorageException(String.format("Could not delete previous version '%s'", filePath), e); - } - } - - private Path createTempFilePath(final Path destinationFolder) { - final var retries = 10; - return createTempFilePath(destinationFolder, retries).orElseThrow(() -> { - throw new PersistentVolumeArtifactStorageException(String.format("Could not generate upload file path after '%s' retries", retries)); - }); - } - - private Optional createTempFilePath(final Path destinationFolder, int retries) { - for (var i = 0; i < retries; i++) { - final var filePath = destinationFolder.resolve(UUID.randomUUID().toString()); - if (Files.notExists(filePath)) { - return Optional.of(filePath); - } - } - return Optional.empty(); - } - - private Path buildDestinationFolder(final String vspId, final String versionId) { - return storageConfiguration.getStoragePath().resolve(vspId).resolve(versionId); - } - - private void persist(final InputStream artifactInputStream, final Path filePath) throws IOException { - try (final var inputStream = artifactInputStream; - final var fileOutputStream = new FileOutputStream(filePath.toFile());) { - inputStream.transferTo(fileOutputStream); - } - } - - private void moveFile(final Path from, final Path to) { - try { - Files.move(from, to, StandardCopyOption.REPLACE_EXISTING); - } catch (final IOException e) { - throw new PersistentVolumeArtifactStorageException(String.format("Could not move file '%s' to '%s'", from, to), e); - } - } - -} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/StorageFactory.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/StorageFactory.java new file mode 100644 index 0000000000..d120b3af8d --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/StorageFactory.java @@ -0,0 +1,91 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.csar.storage; + +import static org.openecomp.sdc.be.csar.storage.StorageFactory.StorageType.NONE; +import static org.openecomp.sdc.be.csar.storage.StorageFactory.StorageType.findByName; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.NoArgsConstructor; +import org.openecomp.sdc.common.CommonConfigurationManager; +import org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; + +@NoArgsConstructor +public class StorageFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(StorageFactory.class); + private static final String EXTERNAL_CSAR_STORE = "externalCsarStore"; + + public ArtifactStorageManager createArtifactStorageManager() { + switch (getConfiguredArtifactStorageType()) { + case MINIO: // MinIoStorage enabled + return new MinIoStorageArtifactStorageManager(); + default:// all configured, nothing enabled + return new NoneStorageManager(); + } + } + + public Optional createPackageSizeReducer() { + switch (getConfiguredArtifactStorageType()) { + case MINIO: // MinIoStorage enabled + return Optional.of(new MinIoStorageCsarSizeReducer(readPackageReducerConfiguration())); + default:// all configured, nothing enabled + return Optional.empty(); + } + } + + private StorageType getConfiguredArtifactStorageType() { + final var commonConfigurationManager = CommonConfigurationManager.getInstance(); + final String storageType = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "storageType", NONE.name()); + LOGGER.info("ArtifactConfig.storageType: '{}'", storageType); + return findByName(storageType); + } + + private CsarPackageReducerConfiguration readPackageReducerConfiguration() { + final var commonConfigurationManager = CommonConfigurationManager.getInstance(); + final List foldersToStrip = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "foldersToStrip", new ArrayList<>()); + final int sizeLimit = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "sizeLimit", 1000000); + final int thresholdEntries = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "thresholdEntries", 10000); + LOGGER.info("Folders to strip: '{}'", String.join(", ", foldersToStrip)); + final Set foldersToStripPathSet = foldersToStrip.stream().map(Path::of).collect(Collectors.toSet()); + return new CsarPackageReducerConfiguration(foldersToStripPathSet, sizeLimit, thresholdEntries); + } + + public enum StorageType { + NONE, + MINIO; + + public static StorageType findByName(String name) { + for (StorageType curr : StorageType.values()) { + if (curr.name().equals(name)) { + return curr; + } + } + return null; + } + } +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/exception/ArtifactStorageException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/exception/ArtifactStorageException.java new file mode 100644 index 0000000000..aa621611df --- /dev/null +++ b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/exception/ArtifactStorageException.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 Nordix Foundation + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.openecomp.sdc.be.csar.storage.exception; + +import org.openecomp.sdc.be.exception.BusinessException; + +public class ArtifactStorageException extends BusinessException { + + public ArtifactStorageException(final String message, final Throwable cause) { + super(message, cause); + } + + public ArtifactStorageException(final String message) { + super(message); + } +} diff --git a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/exception/PersistentVolumeArtifactStorageException.java b/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/exception/PersistentVolumeArtifactStorageException.java deleted file mode 100644 index 28fff65bb6..0000000000 --- a/common-be/src/main/java/org/openecomp/sdc/be/csar/storage/exception/PersistentVolumeArtifactStorageException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.openecomp.sdc.be.csar.storage.exception; - -import org.openecomp.sdc.be.exception.BusinessException; - -public class PersistentVolumeArtifactStorageException extends BusinessException { - - public PersistentVolumeArtifactStorageException(final String message, final Throwable cause) { - super(message, cause); - } - - public PersistentVolumeArtifactStorageException(final String message) { - super(message); - } -} -- cgit 1.2.3-korg