Fix 'Artifact type CONTROLLER_BLUEPRINT_ARCHIVE is not recognized based on its type...
[sdc.git] / openecomp-be / lib / openecomp-sdc-vendor-software-product-lib / openecomp-sdc-vendor-software-product-core / src / main / java / org / openecomp / sdc / vendorsoftwareproduct / services / impl / filedatastructuremodule / ManifestCreatorNamingConventionImpl.java
1 /*
2  * Copyright © 2016-2017 European Support Limited
3  * Modifications copyright (c) 2021 Nokia
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 package org.openecomp.sdc.vendorsoftwareproduct.services.impl.filedatastructuremodule;
18
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collection;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Objects;
26 import java.util.Optional;
27 import java.util.Set;
28 import java.util.regex.Pattern;
29 import org.apache.commons.collections4.CollectionUtils;
30 import org.openecomp.core.utilities.file.FileContentHandler;
31 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
32 import org.openecomp.sdc.heat.datatypes.manifest.FileData.Type;
33 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
34 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
35 import org.openecomp.sdc.vendorsoftwareproduct.services.HeatFileAnalyzer;
36 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.ManifestCreator;
37 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.AnalyzedZipHeatFiles;
38 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Constants;
39 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
40 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Module;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 public class ManifestCreatorNamingConventionImpl implements ManifestCreator {
45
46     protected static final Logger logger = LoggerFactory.getLogger(ManifestCreatorNamingConventionImpl.class);
47     private static final String CLOUD_SPECIFIC_FIXED_KEY_WORD = "cloudtech";
48     private static final String[][] CLOUD_SPECIFIC_KEY_WORDS = {
49         {"k8s", "azure", "aws"},  // cloud specific technology
50         {"charts", "day0", "configtemplate"} // cloud specific subtype
51     };
52     private static final String CONTROLLER_BLUEPRINT_ARCHIVE_FIXED_KEY_WORD = "CBA";
53     private static final String HELM_KEY_WORD = "HELM";
54     private static final String PM_DICTIONARY = "PM_DICTIONARY";
55
56     @Override
57     public Optional<ManifestContent> createManifest(VspDetails vspDetails, FilesDataStructure filesDataStructure) {
58         if (Objects.isNull(filesDataStructure)) {
59             return Optional.empty();
60         }
61         List<FileData> fileDataList = new ArrayList<>();
62         addModulesToManifestFileDataList(filesDataStructure, fileDataList);
63         addNestedToManifest(filesDataStructure, fileDataList);
64         addArtifactsToManifestFileDataList(filesDataStructure, fileDataList);
65         return Optional.of(createManifest(vspDetails, fileDataList));
66     }
67
68     @Override
69     public Optional<ManifestContent> createManifestFromExisting(VspDetails vspDetails, FilesDataStructure filesDataStructure,
70                                                                 ManifestContent existingManifest) {
71         if (Objects.isNull(filesDataStructure)) {
72             return Optional.empty();
73         }
74         List<FileData> fileDataList = new ArrayList<>();
75         addModulesToManifestFileDataList(filesDataStructure, fileDataList);
76         addNestedToManifest(filesDataStructure, fileDataList);
77         addArtifactsToManifestFileDataList(filesDataStructure, fileDataList, existingManifest);
78         return Optional.of(createManifest(vspDetails, fileDataList));
79     }
80
81     private void addArtifactsToManifestFileDataList(FilesDataStructure filesDataStructure, List<FileData> fileDataList,
82                                                     ManifestContent existingManifest) {
83         Collection<String> forArtifacts = CollectionUtils.union(filesDataStructure.getArtifacts(), filesDataStructure.getUnassigned());
84         if (CollectionUtils.isNotEmpty(forArtifacts)) {
85             for (String artifact : forArtifacts) {
86                 List<FileData> manifestData = existingManifest.getData();
87                 if (isCloudSpecificArtifact(artifact, manifestData)) {
88                     fileDataList.add(createBaseFileData(Type.CLOUD_TECHNOLOGY_SPECIFIC_ARTIFACT, artifact));
89                 } else if (isControllerBlueprintArchive(artifact, manifestData)) {
90                     fileDataList.add(createBaseFileData(Type.CONTROLLER_BLUEPRINT_ARCHIVE, artifact));
91                 } else if (isHelm(artifact, manifestData)) {
92                     fileDataList.add(createBaseFileData(Type.HELM, artifact));
93                 } else if (isPmDictionary(artifact, manifestData)) {
94                     fileDataList.add(createBaseFileData(Type.PM_DICTIONARY, artifact));
95                 } else {
96                     fileDataList.add(createBaseFileData(Type.OTHER, artifact));
97                 }
98             }
99         }
100     }
101
102     private boolean isPmDictionary(String artifact, List<FileData> data) {
103         if (CollectionUtils.isNotEmpty(data) && data.stream()
104             .anyMatch(fileData -> fileData.getFile().equals(artifact) && Type.PM_DICTIONARY.equals(fileData.getType()))) {
105             return true;
106         } else {
107             return artifact.toUpperCase().contains(PM_DICTIONARY);
108         }
109     }
110
111     private void addNestedToManifest(FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
112         if (CollectionUtils.isNotEmpty(filesDataStructure.getNested())) {
113             for (String nested : filesDataStructure.getNested()) {
114                 fileDataList.add(createBaseFileData(Type.HEAT, nested));
115             }
116         }
117     }
118
119     @Override
120     public Optional<ManifestContent> createManifest(VspDetails vspDetails, FileContentHandler fileContentHandler,
121                                                     AnalyzedZipHeatFiles analyzedZipHeatFiles) {
122         logger.info("Trying to generate manifest");
123         if (Objects.isNull(fileContentHandler) || CollectionUtils.isEmpty(fileContentHandler.getFileList())) {
124             logger.info("fileContentHandler or filesList is empty. ManifestContent will not be created");
125             return Optional.empty();
126         }
127         Map<String, byte[]> files = fileContentHandler.getFiles();
128         List<FileData> fileDataList = createFileDataListFromZipFiles(fileContentHandler, files, analyzedZipHeatFiles.getFilesNotEligbleForModules());
129         ManifestContent manifestContent = createManifest(vspDetails, fileDataList);
130         return Optional.of(manifestContent);
131     }
132
133     private ManifestContent createManifest(VspDetails vspDetails, List<FileData> fileDataList) {
134         ManifestContent manifestContent = new ManifestContent();
135         manifestContent.setName(vspDetails.getName());
136         manifestContent.setDescription(vspDetails.getDescription());
137         manifestContent.setVersion(vspDetails.getVersion() == null ? null : vspDetails.getVersion().toString());
138         // vsp version, need to check in confluence
139         manifestContent.setData(fileDataList);
140         return manifestContent;
141     }
142
143     private List<FileData> createFileDataListFromZipFiles(FileContentHandler fileContentHandler, Map<String, byte[]> files,
144                                                           Collection<String> filesNotEligibleForModules) {
145         Set<String> processedFiles = new HashSet<>();
146         List<FileData> fileDataList = new ArrayList<>();
147         for (String fileName : files.keySet()) {
148             if (processedFiles.contains(fileName)) {
149                 continue;
150             }
151             if (isFileBaseFile(fileName)) {
152                 fileDataList.add(createModuleFileData(fileName, true, processedFiles, fileContentHandler.getFileList(), fileDataList));
153             } else if (isFileModuleFile(fileName, filesNotEligibleForModules)) {
154                 fileDataList.add(createModuleFileData(fileName, false, processedFiles, fileContentHandler.getFileList(), fileDataList));
155             } else {
156                 if (HeatFileAnalyzer.isYamlFile(fileName)) {
157                     fileDataList.add(createBasicFileData(fileName, Type.HEAT, null));
158                 } else if (HeatFileAnalyzer.isEnvFile(fileName)) {
159                     fileDataList.add(createBasicFileData(fileName, Type.HEAT_ENV, null));
160                 } else {
161                     fileDataList.add(createBasicFileData(fileName, Type.OTHER, null));
162                 }
163             }
164         }
165         return fileDataList;
166     }
167
168     private boolean isFileModuleFile(String fileName, Collection<String> filesCannotBeModule) {
169         return !filesCannotBeModule.contains(fileName);
170     }
171
172     @Override
173     public boolean isFileBaseFile(String fileName) {
174         return Pattern.matches(Constants.BASE_HEAT_REGEX, fileName) && !isVolFile(fileName);
175     }
176
177     protected boolean isCloudSpecificArtifact(String artifact, List<FileData> data) {
178         if (CollectionUtils.isNotEmpty(data) && data.stream()
179             .anyMatch(fileData -> fileData.getFile().equals(artifact) && Type.CLOUD_TECHNOLOGY_SPECIFIC_ARTIFACT.equals(fileData.getType()))) {
180             return true;
181         } else {
182             if (artifact.contains(CLOUD_SPECIFIC_FIXED_KEY_WORD)) {
183                 for (final String[] cloudSpecificKeyWord : CLOUD_SPECIFIC_KEY_WORDS) {
184                     if (Arrays.stream(cloudSpecificKeyWord).noneMatch(artifact::contains)) {
185                         return false;
186                     }
187                 }
188                 return true;
189             } else {
190                 return false;
191             }
192         }
193     }
194
195     private boolean isControllerBlueprintArchive(String artifact, List<FileData> data) {
196         if (CollectionUtils.isNotEmpty(data) && data.stream()
197             .anyMatch(fileData -> fileData.getFile().equals(artifact) && Type.CONTROLLER_BLUEPRINT_ARCHIVE.equals(fileData.getType()))) {
198             return true;
199         } else {
200             return artifact.toUpperCase().contains(CONTROLLER_BLUEPRINT_ARCHIVE_FIXED_KEY_WORD);
201         }
202     }
203
204     private boolean isHelm(String artifact, List<FileData> data) {
205         if (CollectionUtils.isNotEmpty(data) && data.stream()
206             .anyMatch(fileData -> fileData.getFile().equals(artifact) && Type.HELM.equals(fileData.getType()))) {
207             return true;
208         } else {
209             return artifact.toUpperCase().contains(HELM_KEY_WORD);
210         }
211     }
212
213     private void addArtifactsToManifestFileDataList(FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
214         Collection<String> forArtifacts = CollectionUtils.union(filesDataStructure.getArtifacts(), filesDataStructure.getUnassigned());
215         if (CollectionUtils.isNotEmpty(forArtifacts)) {
216             for (String artifact : forArtifacts) {
217                 if (isCloudSpecificArtifact(artifact, null)) {
218                     fileDataList.add(createBaseFileData(Type.CLOUD_TECHNOLOGY_SPECIFIC_ARTIFACT, artifact));
219                 } else if (isControllerBlueprintArchive(artifact, null)) {
220                     fileDataList.add(createBaseFileData(Type.CONTROLLER_BLUEPRINT_ARCHIVE, artifact));
221                 } else if (isHelm(artifact, null)) {
222                     fileDataList.add(createBaseFileData(Type.HELM, artifact));
223                 } else if (isPmDictionary(artifact, null)) {
224                     fileDataList.add(createBaseFileData(Type.PM_DICTIONARY, artifact));
225                 } else {
226                     fileDataList.add(createBaseFileData(Type.OTHER, artifact));
227                 }
228             }
229         }
230     }
231
232     private void addModulesToManifestFileDataList(FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
233         if (CollectionUtils.isNotEmpty(filesDataStructure.getModules())) {
234             for (Module module : filesDataStructure.getModules()) {
235                 Type type = module.getType();
236                 if (type == null) {
237                     type = Type.HEAT;
238                 }
239                 FileData fileData = createBaseFileData(type, module.getYaml());
240                 fileData.setBase(module.getIsBase());
241                 addEnv(module, fileData);
242                 addVolume(module, fileData);
243                 fileDataList.add(fileData);
244             }
245         }
246     }
247
248     private void addEnv(Module module, FileData fileData) {
249         if (Objects.nonNull(module.getEnv())) {
250             FileData env = createBaseFileData(Type.HEAT_ENV, module.getEnv());
251             fileData.addFileData(env);
252         }
253     }
254
255     private void addVolume(Module module, FileData fileData) {
256         String volModule = module.getVol();
257         if (Objects.nonNull(volModule)) {
258             FileData vol = createBaseFileData(Type.HEAT_VOL, volModule);
259             if (Objects.nonNull(module.getVolEnv())) {
260                 vol.addFileData(createBaseFileData(Type.HEAT_ENV, module.getVolEnv()));
261             }
262             fileData.addFileData(vol);
263         }
264     }
265
266     private FileData createBaseFileData(Type heat, String yaml) {
267         FileData fileData = new FileData();
268         fileData.setType(heat);
269         fileData.setFile(yaml);
270         return fileData;
271     }
272
273     private FileData createModuleFileData(String moduleFileName, boolean isBase, Set<String> processedFiles, Set<String> fileNames,
274                                           List<FileData> fileDataList) {
275         FileData moduleFileData = createBasicFileData(moduleFileName, Type.HEAT, isBase);
276         Optional<String> volFile = fetchRelatedVolume(moduleFileName, fileNames);
277         volFile.ifPresent(vol -> {
278             markFileAsProcessed(vol, processedFiles);
279             removeFromFileDataListIfAlreadyProcessed(fileDataList, vol);
280             FileData volFileData = createBasicFileData(vol, Type.HEAT_VOL, null);
281             Optional<String> envFile = fetchRelatedEnv(vol, fileNames);
282             envFile.ifPresent(env -> {
283                 markFileAsProcessed(env, processedFiles);
284                 removeFromFileDataListIfAlreadyProcessed(fileDataList, env);
285                 FileData envFileData = createBasicFileData(env, Type.HEAT_ENV, null);
286                 volFileData.addFileData(envFileData);
287             });
288             moduleFileData.addFileData(volFileData);
289         });
290         Optional<String> envFile = fetchRelatedEnv(moduleFileName, fileNames);
291         envFile.ifPresent(env -> {
292             markFileAsProcessed(env, processedFiles);
293             FileData envFileData = createBasicFileData(env, Type.HEAT_ENV, null);
294             moduleFileData.addFileData(envFileData);
295         });
296         return moduleFileData;
297     }
298
299     private void removeFromFileDataListIfAlreadyProcessed(List<FileData> fileDataList, String vol) {
300         fileDataList.removeIf(fileData -> fileData.getFile().equals(vol));
301     }
302
303     private FileData createBasicFileData(String fileName, Type type, Boolean isBase) {
304         FileData fileData = new FileData();
305         if (isBase != null) {
306             fileData.setBase(isBase);
307         }
308         fileData.setType(type);
309         fileData.setFile(fileName);
310         return fileData;
311     }
312
313     private Optional<String> fetchRelatedEnv(String fileName, Set<String> fileNames) {
314         String envFileName = fileName.substring(0, fileName.lastIndexOf(".")) + Constants.ENV_FILE_EXTENSION;
315         return fileNames.contains(envFileName) ? Optional.of(envFileName) : Optional.empty();
316     }
317
318     private Optional<String> fetchRelatedVolume(String fileName, Set<String> fileNames) {
319         String volFile1stExt = extractVolFileName(fileName, ".yaml");
320         String volFile2ndExt = extractVolFileName(fileName, ".yml");
321         if (fileNames.contains(volFile1stExt)) {
322             return Optional.of(volFile1stExt);
323         }
324         if (fileNames.contains(volFile2ndExt)) {
325             return Optional.of(volFile2ndExt);
326         }
327         return Optional.empty();
328     }
329
330     private String extractVolFileName(String fileName, String fileExt) {
331         return fileName.substring(0, fileName.lastIndexOf(".")) + Constants.VOL_FILE_NAME_SUFFIX + fileExt;
332     }
333
334     private boolean isVolFile(String fileName) {
335         return fileName.endsWith(Constants.VOL_FILE_NAME_SUFFIX + ".yaml") || fileName.endsWith(Constants.VOL_FILE_NAME_SUFFIX + ".yml");
336     }
337
338     private void markFileAsProcessed(String fileName, Set<String> processedFiles) {
339         processedFiles.add(fileName);
340     }
341 }