Implement improved MinIo client
[sdc.git] / common-be / src / main / java / org / openecomp / sdc / be / csar / storage / MinIoStorageArtifactStorageManager.java
1 /*
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
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  *  SPDX-License-Identifier: Apache-2.0
18  *  ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.csar.storage;
22
23 import static org.openecomp.sdc.common.errors.Messages.EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING;
24
25 import io.minio.BucketExistsArgs;
26 import io.minio.GetObjectArgs;
27 import io.minio.MakeBucketArgs;
28 import io.minio.MinioClient;
29 import io.minio.PutObjectArgs;
30 import io.minio.RemoveObjectArgs;
31 import io.minio.StatObjectArgs;
32 import java.io.InputStream;
33 import java.util.Map;
34 import lombok.Getter;
35 import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.Credentials;
36 import org.openecomp.sdc.be.csar.storage.MinIoStorageArtifactStorageConfig.EndPoint;
37 import org.openecomp.sdc.be.csar.storage.exception.ArtifactStorageException;
38 import org.openecomp.sdc.common.CommonConfigurationManager;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 public class MinIoStorageArtifactStorageManager implements ArtifactStorageManager {
43
44     private static final Logger LOGGER = LoggerFactory.getLogger(MinIoStorageArtifactStorageManager.class);
45     private static final String ENDPOINT = "endpoint";
46     private static final String CREDENTIALS = "credentials";
47     private static final String TEMP_PATH = "tempPath";
48     private static final String EXTERNAL_CSAR_STORE = "externalCsarStore";
49     @Getter
50     private final MinIoStorageArtifactStorageConfig storageConfiguration;
51     private final MinioClient minioClient;
52
53     public MinIoStorageArtifactStorageManager() {
54         this.storageConfiguration = readMinIoStorageArtifactStorageConfig();
55         this.minioClient = initMinioClient();
56     }
57
58     //for testing only
59     MinIoStorageArtifactStorageManager(final ArtifactStorageConfig storageConfiguration) {
60         this.storageConfiguration = (MinIoStorageArtifactStorageConfig) storageConfiguration;
61         this.minioClient = initMinioClient();
62     }
63
64     @Override
65     public ArtifactInfo persist(final String vspId, final String versionId, final ArtifactInfo uploadedArtifactInfo) {
66         final MinIoArtifactInfo minioObjectTemp = (MinIoArtifactInfo) uploadedArtifactInfo;
67         LOGGER.debug("PERSIST - bucket: '{}', object: '{}'", minioObjectTemp.getBucket(), minioObjectTemp.getObjectName());
68         try {
69             // Get information of an object.
70             minioClient.statObject(
71                 StatObjectArgs.builder()
72                     .bucket(minioObjectTemp.getBucket())
73                     .object(minioObjectTemp.getObjectName())
74                     .build()
75             );
76
77         } catch (final Exception e) {
78             LOGGER.error("Failed to retrieve uploaded artifact with bucket '{}' and name '{}' while persisting", minioObjectTemp.getBucket(),
79                 minioObjectTemp.getObjectName(), e);
80             throw new ArtifactStorageException(
81                 String.format("Failed to retrieve uploaded artifact with bucket '%s' and name '%s' while persisting",
82                     minioObjectTemp.getBucket(), minioObjectTemp.getObjectName()), e);
83         }
84         return new MinIoArtifactInfo(vspId, versionId);
85     }
86
87     @Override
88     public ArtifactInfo upload(final String vspId, final String versionId, final InputStream fileToUpload) {
89
90         try {
91             // Make bucket if not exist.
92             final boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(vspId).build());
93
94             if (!found) {
95                 // Make a new bucket ${vspId} .
96                 minioClient.makeBucket(MakeBucketArgs.builder().bucket(vspId).build());
97             } else {
98                 LOGGER.info("Bucket '{}' already exists.", vspId);
99             }
100
101             put(vspId, versionId, fileToUpload);
102
103         } catch (final Exception e) {
104             LOGGER.error("Failed to upload artifact - bucket: '{}', object: '{}'", vspId, versionId, e);
105             throw new ArtifactStorageException("Failed to upload artifact", e);
106         }
107
108         return new MinIoArtifactInfo(vspId, versionId);
109     }
110
111     @Override
112     public void put(final String vspId, final String name, final InputStream fileToUpload) {
113         LOGGER.debug("BEGIN -> PUT - bucket: '{}', object: '{}'", vspId, name);
114         try {
115             minioClient.putObject(
116                 PutObjectArgs.builder()
117                     .bucket(vspId)
118                     .object(name)
119                     .stream(fileToUpload, -1, storageConfiguration.getUploadPartSize())
120                     .build()
121             );
122         } catch (final Exception e) {
123             LOGGER.error("Failed to put - bucket: '{}', object: '{}'", vspId, name, e);
124             throw new ArtifactStorageException("Failed to upload artifact", e);
125         }
126         LOGGER.debug("SUCCESS -> PUT - bucket: '{}', object: '{}'", vspId, name);
127     }
128
129     @Override
130     public boolean isEnabled() {
131         return storageConfiguration != null && storageConfiguration.isEnabled();
132     }
133
134     @Override
135     public InputStream get(final ArtifactInfo artifactInfo) {
136         final MinIoArtifactInfo minioObject = (MinIoArtifactInfo) artifactInfo;
137         try {
138             return get(minioObject.getBucket(), minioObject.getObjectName());
139         } catch (final Exception e) {
140             LOGGER.error("Failed to get - bucket: '{}', object: '{}'", minioObject.getBucket(), minioObject.getObjectName(), e);
141             throw new ArtifactStorageException("Failed to get Object", e);
142         }
143     }
144
145     @Override
146     public InputStream get(final String bucketID, final String objectID) {
147         LOGGER.debug("GET - bucket: '{}', object: '{}'", bucketID, objectID);
148         try {
149             return minioClient.getObject(GetObjectArgs.builder()
150                 .bucket(bucketID)
151                 .object(objectID)
152                 .build());
153         } catch (final Exception e) {
154             LOGGER.error("Failed to get - bucket: '{}', object: '{}'", bucketID, objectID, e);
155             throw new ArtifactStorageException("Failed to get Object", e);
156         }
157     }
158
159     @Override
160     public void delete(final ArtifactInfo artifactInfo) {
161         final MinIoArtifactInfo minioObject = (MinIoArtifactInfo) artifactInfo;
162         LOGGER.debug("DELETE - bucket: '{}', object: '{}'", minioObject.getBucket(), minioObject.getObjectName());
163         try {
164             minioClient.removeObject(RemoveObjectArgs.builder()
165                 .bucket(minioObject.getBucket())
166                 .object(minioObject.getObjectName())
167                 .bypassGovernanceMode(true)
168                 .build());
169         } catch (final Exception e) {
170             LOGGER.error("Failed to delete - bucket: '{}', object: '{}'", minioObject.getBucket(), minioObject.getObjectName(), e);
171             throw new ArtifactStorageException(String.format("Failed to delete '%s'", minioObject.getObjectName()), e);
172         }
173
174     }
175
176     private MinIoStorageArtifactStorageConfig readMinIoStorageArtifactStorageConfig() {
177         final var commonConfigurationManager = CommonConfigurationManager.getInstance();
178         final Map<String, Object> endpoint = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, ENDPOINT, null);
179         final Map<String, Object> creds = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, CREDENTIALS, null);
180         final String tempPath = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, TEMP_PATH, null);
181         final int uploadPartSize = commonConfigurationManager.getConfigValue(EXTERNAL_CSAR_STORE, "uploadPartSize", 50_000_000);
182
183         if (endpoint == null) {
184             LOGGER.error(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage(ENDPOINT));
185             throw new ArtifactStorageException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage(ENDPOINT));
186         }
187         if (creds == null) {
188             LOGGER.error(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage(CREDENTIALS));
189             throw new ArtifactStorageException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage(CREDENTIALS));
190         }
191         if (tempPath == null) {
192             LOGGER.error(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage(TEMP_PATH));
193             throw new ArtifactStorageException(EXTERNAL_CSAR_STORE_CONFIGURATION_FAILURE_MISSING.formatMessage(TEMP_PATH));
194         }
195         LOGGER.info("ArtifactConfig.endpoint: '{}'", endpoint);
196         LOGGER.info("ArtifactConfig.credentials: '{}'", creds);
197         LOGGER.info("ArtifactConfig.tempPath: '{}'", tempPath);
198         LOGGER.info("ArtifactConfig.uploadPartSize: '{}'", uploadPartSize);
199
200         final String host = (String) endpoint.getOrDefault("host", null);
201         final int port = (int) endpoint.getOrDefault("port", 0);
202         final boolean secure = (boolean) endpoint.getOrDefault("secure", false);
203
204         final String accessKey = (String) creds.getOrDefault("accessKey", null);
205         final String secretKey = (String) creds.getOrDefault("secretKey", null);
206
207         return new MinIoStorageArtifactStorageConfig
208             (true, new EndPoint(host, port, secure), new Credentials(accessKey, secretKey), tempPath, uploadPartSize);
209     }
210
211     private MinioClient initMinioClient() {
212         final EndPoint storageConfigurationEndPoint = storageConfiguration.getEndPoint();
213         final Credentials storageConfigurationCredentials = storageConfiguration.getCredentials();
214
215         return MinioClient.builder()
216             .endpoint(storageConfigurationEndPoint.getHost(), storageConfigurationEndPoint.getPort(), storageConfigurationEndPoint.isSecure())
217             .credentials(storageConfigurationCredentials.getAccessKey(), storageConfigurationCredentials.getSecretKey())
218             .build();
219     }
220
221 }