Fix CBA artifact recognition by SDC
[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  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.vendorsoftwareproduct.services.impl.filedatastructuremodule;
18
19 import org.apache.commons.collections4.CollectionUtils;
20 import org.openecomp.core.utilities.file.FileContentHandler;
21 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
22 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
23 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
24 import org.openecomp.sdc.vendorsoftwareproduct.services.HeatFileAnalyzer;
25 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.ManifestCreator;
26 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.AnalyzedZipHeatFiles;
27 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Constants;
28 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
29 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Module;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 import java.util.*;
34 import java.util.regex.Pattern;
35
36 public class ManifestCreatorNamingConventionImpl implements ManifestCreator {
37   protected static final Logger logger =
38       LoggerFactory.getLogger(ManifestCreatorNamingConventionImpl.class);
39
40   private static final String CLOUD_SPECIFIC_FIXED_KEY_WORD = "cloudtech";
41   private static final String[][] CLOUD_SPECIFIC_KEY_WORDS = {{"k8s", "azure", "aws"}, /* cloud specific technology */
42                                                               {"charts", "day0", "configtemplate"} /*cloud specific sub type*/};
43   private static final String CONTROLLER_BLUEPRINT_ARCHIVE_FIXED_KEY_WORD = "CBA";
44
45   @Override
46   public Optional<ManifestContent> createManifest(
47       VspDetails vspDetails, FilesDataStructure filesDataStructure) {
48     if (Objects.isNull(filesDataStructure)) {
49       return Optional.empty();
50     }
51
52     List<FileData> fileDataList = new ArrayList<>();
53     addModulesToManifestFileDataList(filesDataStructure, fileDataList);
54     addNestedToManifest(filesDataStructure, fileDataList);
55     addArtifactsToManifestFileDataList(filesDataStructure, fileDataList);
56     ManifestContent manifestContent = createManifest(vspDetails, fileDataList);
57     return Optional.of(manifestContent);
58   }
59
60   private void addNestedToManifest(
61       FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
62     if (CollectionUtils.isNotEmpty(filesDataStructure.getNested())) {
63       for (String nested : filesDataStructure.getNested()) {
64         fileDataList.add(createBaseFileData(FileData.Type.HEAT, nested));
65       }
66     }
67   }
68
69   @Override
70   public Optional<ManifestContent> createManifest(VspDetails vspDetails,
71                                                   FileContentHandler fileContentHandler,
72                                                   AnalyzedZipHeatFiles analyzedZipHeatFiles) {
73     logger.info("Trying to generate manifest");
74     if (Objects.isNull(fileContentHandler)
75         || CollectionUtils.isEmpty(fileContentHandler.getFileList())) {
76       logger.info("fileContentHandler or filesList is empty. ManifestContent will not be created");
77       return Optional.empty();
78     }
79
80     Map<String, byte[]> files = fileContentHandler.getFiles();
81
82     List<FileData> fileDataList =
83         createFileDataListFromZipFiles(fileContentHandler, files,
84             analyzedZipHeatFiles.getFilesNotEligbleForModules());
85     ManifestContent manifestContent = createManifest(vspDetails, fileDataList);
86
87     return Optional.of(manifestContent);
88   }
89
90   private ManifestContent createManifest(VspDetails vspDetails, List<FileData> fileDataList) {
91     ManifestContent manifestContent = new ManifestContent();
92     manifestContent.setName(vspDetails.getName());
93     manifestContent.setDescription(vspDetails.getDescription());
94     manifestContent
95         .setVersion(vspDetails.getVersion() == null ? null : vspDetails.getVersion().toString());
96     // vsp version, need to check in confluence
97     manifestContent.setData(fileDataList);
98     return manifestContent;
99   }
100
101   private List<FileData> createFileDataListFromZipFiles(FileContentHandler fileContentHandler,
102                                                         Map<String, byte[]> files,
103                                                         Collection<String> filesNotEligibleForModules) {
104
105     Set<String> processedFiles = new HashSet<>();
106     List<FileData> fileDataList = new ArrayList<>();
107     for (String fileName : files.keySet()) {
108       if (processedFiles.contains(fileName)) {
109         continue;
110       }
111       if (isFileBaseFile(fileName)) {
112         fileDataList
113             .add(createModuleFileData(
114                 fileName, true, processedFiles, fileContentHandler.getFileList(), fileDataList));
115       } else if (isFileModuleFile(fileName, filesNotEligibleForModules)) {
116         fileDataList
117             .add(createModuleFileData(
118                 fileName, false, processedFiles, fileContentHandler.getFileList(), fileDataList));
119       } else {
120         if (HeatFileAnalyzer.isYamlFile(fileName)) {
121           fileDataList.add(createBasicFileData(fileName, FileData.Type.HEAT, null));
122         } else if (HeatFileAnalyzer.isEnvFile(fileName)) {
123           fileDataList.add(createBasicFileData(fileName, FileData.Type.HEAT_ENV, null));
124         } else {
125           fileDataList.add(createBasicFileData(fileName, FileData.Type.OTHER, null));
126         }
127       }
128     }
129     return fileDataList;
130   }
131
132   private boolean isFileModuleFile(String fileName, Collection<String> filesCannotBeModule) {
133     return !filesCannotBeModule.contains(fileName);
134   }
135
136   @Override
137   public boolean isFileBaseFile(String fileName) {
138     return Pattern.matches(Constants.BASE_HEAT_REGEX, fileName) && !isVolFile(fileName);
139   }
140
141   protected boolean isCloudSpecificArtifact(String artifact) {
142       if (artifact.contains(CLOUD_SPECIFIC_FIXED_KEY_WORD)) {
143           for (int i = 0; i < CLOUD_SPECIFIC_KEY_WORDS.length; i++) {
144               if (Arrays.stream(CLOUD_SPECIFIC_KEY_WORDS[i]).noneMatch(str -> artifact.contains(str))) {
145                   return false;
146               }
147           }
148           return true;
149       } else {
150           return false;
151       }
152   }
153
154   private boolean isControllerBlueprintArchive(String artifact) {
155     return artifact.toUpperCase().contains(CONTROLLER_BLUEPRINT_ARCHIVE_FIXED_KEY_WORD);
156   }
157
158   private void addArtifactsToManifestFileDataList(
159       FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
160     Collection<String> forArtifacts = CollectionUtils
161         .union(filesDataStructure.getArtifacts(), filesDataStructure.getUnassigned());
162     if (CollectionUtils.isNotEmpty(forArtifacts)) {
163       for (String artifact : forArtifacts) {
164         if (isCloudSpecificArtifact(artifact)) {
165             fileDataList.add(createBaseFileData(FileData.Type.CLOUD_TECHNOLOGY_SPECIFIC_ARTIFACT, artifact));
166         } else if (isControllerBlueprintArchive(artifact)) {
167           fileDataList.add(createBaseFileData(FileData.Type.CONTROLLER_BLUEPRINT_ARCHIVE, artifact));
168         } else {
169           fileDataList.add(createBaseFileData(FileData.Type.OTHER, artifact));
170         }
171       }
172     }
173   }
174
175   private void addModulesToManifestFileDataList(
176       FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
177     if (CollectionUtils.isNotEmpty(filesDataStructure.getModules())) {
178       for (Module module : filesDataStructure.getModules()) {
179         FileData fileData = createBaseFileData(FileData.Type.HEAT, module.getYaml());
180         fileData.setBase(module.getIsBase());
181         addEnv(module, fileData);
182         addVolume(module, fileData);
183         fileDataList.add(fileData);
184       }
185     }
186   }
187
188   private void addEnv(Module module, FileData fileData) {
189     if (Objects.nonNull(module.getEnv())) {
190       FileData env = createBaseFileData(FileData.Type.HEAT_ENV, module.getEnv());
191       fileData.addFileData(env);
192     }
193   }
194
195   private void addVolume(Module module, FileData fileData) {
196     String volModule = module.getVol();
197     if (Objects.nonNull(volModule)) {
198       FileData vol = createBaseFileData(FileData.Type.HEAT_VOL, volModule);
199       if (Objects.nonNull(module.getVolEnv())) {
200         vol.addFileData(createBaseFileData(FileData.Type.HEAT_ENV, module.getVolEnv()));
201       }
202       fileData.addFileData(vol);
203     }
204   }
205
206   private FileData createBaseFileData(FileData.Type heat, String yaml) {
207     FileData fileData = new FileData();
208     fileData.setType(heat);
209     fileData.setFile(yaml);
210     return fileData;
211   }
212
213   private FileData createModuleFileData(
214       String moduleFileName, boolean isBase, Set<String> processedFiles,
215       Set<String> fileNames, List<FileData> fileDataList) {
216     FileData moduleFileData = createBasicFileData(moduleFileName, FileData.Type.HEAT, isBase);
217     Optional<String> volFile = fetchRelatedVolume(moduleFileName, fileNames);
218     volFile.ifPresent(vol -> {
219       markFileAsProcessed(vol, processedFiles);
220       removeFromFileDataListIfAlreadyProcessed(fileDataList, vol);
221       FileData volFileData = createBasicFileData(vol, FileData.Type.HEAT_VOL, null);
222       Optional<String> envFile = fetchRelatedEnv(vol, fileNames);
223       envFile.ifPresent(env -> {
224         markFileAsProcessed(env, processedFiles);
225         removeFromFileDataListIfAlreadyProcessed(fileDataList, env);
226         FileData envFileData = createBasicFileData(env, FileData.Type.HEAT_ENV, null);
227         volFileData.addFileData(envFileData);
228       });
229       moduleFileData.addFileData(volFileData);
230     });
231     Optional<String> envFile = fetchRelatedEnv(moduleFileName, fileNames);
232     envFile.ifPresent(env -> {
233       markFileAsProcessed(env, processedFiles);
234       FileData envFileData = createBasicFileData(env, FileData.Type.HEAT_ENV, null);
235       moduleFileData.addFileData(envFileData);
236     });
237     return moduleFileData;
238   }
239
240   private void removeFromFileDataListIfAlreadyProcessed(List<FileData> fileDataList, String vol) {
241     fileDataList.removeIf(fileData -> fileData.getFile().equals(vol));
242   }
243
244   private FileData createBasicFileData(String fileName, FileData.Type type, Boolean isBase) {
245     FileData fileData = new FileData();
246     if (isBase != null) {
247       fileData.setBase(isBase);
248     }
249     fileData.setType(type);
250     fileData.setFile(fileName);
251     return fileData;
252   }
253
254   private Optional<String> fetchRelatedEnv(String fileName, Set<String> fileNames) {
255     String envFileName
256         = fileName.substring(0, fileName.lastIndexOf(".")) + Constants.ENV_FILE_EXTENSION;
257     return fileNames.contains(envFileName) ? Optional.of(envFileName) : Optional.empty();
258   }
259
260   private Optional<String> fetchRelatedVolume(String fileName, Set<String> fileNames) {
261
262     String volFile1stExt =
263         extractVolFileName(fileName, ".yaml");
264     String volFile2ndExt =
265         extractVolFileName(fileName, ".yml");
266
267     if (fileNames.contains(volFile1stExt)) {
268       return Optional.of(volFile1stExt);
269     }
270     if (fileNames.contains(volFile2ndExt)) {
271       return Optional.of(volFile2ndExt);
272     }
273     return Optional.empty();
274   }
275
276   private String extractVolFileName(String fileName, String fileExt) {
277     return fileName.substring(
278         0, fileName.lastIndexOf("."))
279         + Constants.VOL_FILE_NAME_SUFFIX + fileExt;
280   }
281
282
283   private boolean isVolFile(String fileName) {
284     return fileName
285         .endsWith(
286             Constants.VOL_FILE_NAME_SUFFIX + ".yaml")
287         || fileName.endsWith(Constants.VOL_FILE_NAME_SUFFIX + ".yml");
288   }
289
290
291   private void markFileAsProcessed(String fileName, Set<String> processedFiles) {
292     processedFiles.add(fileName);
293   }
294 }