2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Nordix Foundation
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.be.csar.storage;
23 import static org.openecomp.sdc.common.errors.Messages.EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING;
25 import io.minio.BucketExistsArgs;
26 import io.minio.CopyObjectArgs;
27 import io.minio.CopySource;
28 import io.minio.GetObjectArgs;
29 import io.minio.MakeBucketArgs;
30 import io.minio.MinioClient;
31 import io.minio.MinioClient.Builder;
32 import io.minio.PutObjectArgs;
33 import io.minio.RemoveObjectArgs;
34 import java.io.InputStream;
36 import java.util.Optional;
37 import java.util.UUID;
39 import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.Credentials;
40 import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.EndPoint;
41 import org.openecomp.sdc.be.csar.storage.exception.ArtifactStorageException;
42 import org.openecomp.sdc.common.CommonConfigurationManager;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
46 public class MinIoStorageArtifactStorageManager implements ArtifactStorageManager {
48 private static final Logger LOGGER = LoggerFactory.getLogger(MinIoStorageArtifactStorageManager.class);
49 private static final String EXTERNAL_CSAR_STORE = "externalCsarStore";
52 private final MinIoStorageArtifactStorageConfig storageConfiguration;
53 private final MinioClient minioClient;
55 public MinIoStorageArtifactStorageManager() {
56 this.storageConfiguration = readMinIoStorageArtifactStorageConfig();
57 minioClient = initMinioClient();
61 MinIoStorageArtifactStorageManager(final ArtifactStorageConfig storageConfiguration) {
62 this.storageConfiguration = (MinIoStorageArtifactStorageConfig) storageConfiguration;
63 minioClient = initMinioClient();
67 public ArtifactInfo persist(final String vspId, final String versionId, final ArtifactInfo uploadedArtifactInfo) {
68 final MinIoArtifactInfo minioObjectTemp = (MinIoArtifactInfo) uploadedArtifactInfo;
70 minioClient.getObject(
71 GetObjectArgs.builder()
72 .bucket(minioObjectTemp.getBucket())
73 .object(minioObjectTemp.getObjectName())
76 } catch (final Exception e) {
77 throw new ArtifactStorageException(
78 String.format("Failed to retrieve uploaded artifact with bucket '%s' and name '%s' while persisting",
79 minioObjectTemp.getBucket(), minioObjectTemp.getObjectName()), e);
82 final var backupPath = backupPreviousVersion(vspId, versionId).orElse(null);
84 moveFile(minioObjectTemp, vspId, versionId);
85 } catch (final Exception e) {
86 rollback(minioObjectTemp, vspId, versionId);
87 final var errorMsg = String.format("Could not persist artifact for VSP '%s', version '%s'", vspId, versionId);
88 throw new ArtifactStorageException(errorMsg, e);
91 removePreviousVersion(backupPath);
93 return new MinIoArtifactInfo(vspId, versionId);
97 public ArtifactInfo upload(final String vspId, final String versionId, final InputStream fileToUpload) {
99 final String name = versionId + "--" + UUID.randomUUID();
101 // Make bucket if not exist.
102 final boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(vspId).build());
105 // Make a new bucket ${vspId} .
106 minioClient.makeBucket(MakeBucketArgs.builder().bucket(vspId).build());
108 LOGGER.info("Bucket '{}' already exists.", vspId);
111 put(vspId, name, fileToUpload);
113 } catch (final Exception e) {
114 throw new ArtifactStorageException("Failed to upload artifact", e);
117 return new MinIoArtifactInfo(vspId, name);
121 public void put(final String vspId, final String name, final InputStream fileToUpload) {
123 minioClient.putObject(
124 PutObjectArgs.builder()
127 .stream(fileToUpload, fileToUpload.available(), -1)
130 } catch (final Exception e) {
131 throw new ArtifactStorageException("Failed to upload artifact", e);
136 public boolean isEnabled() {
137 return storageConfiguration != null && storageConfiguration.isEnabled();
141 public InputStream get(final ArtifactInfo artifactInfo) {
142 final MinIoArtifactInfo minioObject = (MinIoArtifactInfo) artifactInfo;
144 return get(minioObject.getBucket(), minioObject.getObjectName());
145 } catch (final Exception e) {
146 throw new ArtifactStorageException("Failed to get Object", e);
151 public InputStream get(final String bucketID, final String objectID) {
153 return minioClient.getObject(GetObjectArgs.builder()
157 } catch (final Exception e) {
158 throw new ArtifactStorageException("Failed to get Object", e);
163 public void delete(final ArtifactInfo artifactInfo) {
164 final MinIoArtifactInfo minioObject = (MinIoArtifactInfo) artifactInfo;
166 minioClient.removeObject(RemoveObjectArgs.builder()
167 .bucket(minioObject.getBucket())
168 .object(minioObject.getObjectName())
169 .bypassGovernanceMode(true)
171 } catch (final Exception e) {
172 throw new ArtifactStorageException(String.format("Failed to delete '%s'", minioObject.getObjectName()), e);
177 private Optional<MinIoArtifactInfo> backupPreviousVersion(final String vspId, final String versionId) {
179 final String tempName = versionId + "--" + UUID.randomUUID().toString();
181 copy(vspId, tempName, versionId);
182 } catch (final Exception e) {
183 return Optional.empty();
186 return Optional.of(new MinIoArtifactInfo(vspId, tempName));
189 private void rollback(final MinIoArtifactInfo minioObject, final String vspId, final String versionId) {
191 moveFile(minioObject, vspId, versionId);
192 } catch (final Exception ex) {
193 LOGGER.warn("Could not rollback the backup '{}' to the original '{}'", versionId, minioObject.getObjectName(), ex);
197 private void removePreviousVersion(final MinIoArtifactInfo minioObject) {
198 if (minioObject == null) {
204 private void moveFile(final MinIoArtifactInfo minioObject, final String vspId, final String versionId) {
206 copy(vspId, versionId, minioObject.getObjectName());
207 } catch (final Exception e) {
208 throw new ArtifactStorageException("Failed to move", e);
213 private void copy(final String vspId, final String versionId, final String objectName) throws Exception {
214 minioClient.copyObject(
215 CopyObjectArgs.builder()
218 .source(CopySource.builder()
225 private MinIoStorageArtifactStorageConfig readMinIoStorageArtifactStorageConfig() {
226 final var commonConfigurationManager = CommonConfigurationManager.getInstance();
228 final Map<String, Object> endpoint = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "endpoint", null);
229 final Map<String, Object> credentials = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "credentials", null);
230 final String tempPath = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "tempPath", null);
231 LOGGER.info("ArtifactConfig.endpoint: '{}'", endpoint);
232 LOGGER.info("ArtifactConfig.credentials: '{}'", credentials);
233 LOGGER.info("ArtifactConfig.tempPath: '{}'", tempPath);
235 if (endpoint == null) {
236 throw new RuntimeException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage("endpoint"));
238 if (credentials == null) {
239 throw new RuntimeException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage("credentials"));
241 if (tempPath == null) {
242 throw new RuntimeException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage("tempPath"));
244 final String host = (String) endpoint.getOrDefault("host", null);
245 final int port = (int) endpoint.getOrDefault("port", 0);
246 final boolean secure = (boolean) endpoint.getOrDefault("secure", false);
248 final String accessKey = (String) credentials.getOrDefault("accessKey", null);
249 final String secretKey = (String) credentials.getOrDefault("secretKey", null);
251 return new MinIoStorageArtifactStorageConfig(true, new EndPoint(host, port, secure), new Credentials(accessKey, secretKey), tempPath);
254 private MinioClient initMinioClient() {
255 final EndPoint endPoint = storageConfiguration.getEndPoint();
256 final Credentials credentials = storageConfiguration.getCredentials();
258 final Builder builder = MinioClient.builder();
260 .endpoint(endPoint.getHost(), endPoint.getPort(), endPoint.isSecure())
261 .credentials(credentials.getAccessKey(), credentials.getSecretKey())