2 * Copyright © 2016-2017 European Support Limited
3 * Modifications copyright (c) 2021 Nokia
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 package org.openecomp.sdc.vendorsoftwareproduct.services.impl.filedatastructuremodule;
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;
25 import java.util.Objects;
26 import java.util.Optional;
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;
44 public class ManifestCreatorNamingConventionImpl implements ManifestCreator {
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
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";
57 public Optional<ManifestContent> createManifest(VspDetails vspDetails, FilesDataStructure filesDataStructure) {
58 if (Objects.isNull(filesDataStructure)) {
59 return Optional.empty();
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));
69 public Optional<ManifestContent> createManifestFromExisting(VspDetails vspDetails, FilesDataStructure filesDataStructure,
70 ManifestContent existingManifest) {
71 if (Objects.isNull(filesDataStructure)) {
72 return Optional.empty();
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));
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));
96 fileDataList.add(createBaseFileData(Type.OTHER, artifact));
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()))) {
107 return artifact.toUpperCase().contains(PM_DICTIONARY);
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));
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();
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);
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;
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)) {
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));
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));
161 fileDataList.add(createBasicFileData(fileName, Type.OTHER, null));
168 private boolean isFileModuleFile(String fileName, Collection<String> filesCannotBeModule) {
169 return !filesCannotBeModule.contains(fileName);
173 public boolean isFileBaseFile(String fileName) {
174 return Pattern.matches(Constants.BASE_HEAT_REGEX, fileName) && !isVolFile(fileName);
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()))) {
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)) {
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()))) {
200 return artifact.toUpperCase().contains(CONTROLLER_BLUEPRINT_ARCHIVE_FIXED_KEY_WORD);
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()))) {
209 return artifact.toUpperCase().contains(HELM_KEY_WORD);
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));
226 fileDataList.add(createBaseFileData(Type.OTHER, artifact));
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();
239 FileData fileData = createBaseFileData(type, module.getYaml());
240 fileData.setBase(module.getIsBase());
241 addEnv(module, fileData);
242 addVolume(module, fileData);
243 fileDataList.add(fileData);
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);
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()));
262 fileData.addFileData(vol);
266 private FileData createBaseFileData(Type heat, String yaml) {
267 FileData fileData = new FileData();
268 fileData.setType(heat);
269 fileData.setFile(yaml);
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);
288 moduleFileData.addFileData(volFileData);
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);
296 return moduleFileData;
299 private void removeFromFileDataListIfAlreadyProcessed(List<FileData> fileDataList, String vol) {
300 fileDataList.removeIf(fileData -> fileData.getFile().equals(vol));
303 private FileData createBasicFileData(String fileName, Type type, Boolean isBase) {
304 FileData fileData = new FileData();
305 if (isBase != null) {
306 fileData.setBase(isBase);
308 fileData.setType(type);
309 fileData.setFile(fileName);
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();
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);
324 if (fileNames.contains(volFile2ndExt)) {
325 return Optional.of(volFile2ndExt);
327 return Optional.empty();
330 private String extractVolFileName(String fileName, String fileExt) {
331 return fileName.substring(0, fileName.lastIndexOf(".")) + Constants.VOL_FILE_NAME_SUFFIX + fileExt;
334 private boolean isVolFile(String fileName) {
335 return fileName.endsWith(Constants.VOL_FILE_NAME_SUFFIX + ".yaml") || fileName.endsWith(Constants.VOL_FILE_NAME_SUFFIX + ".yml");
338 private void markFileAsProcessed(String fileName, Set<String> processedFiles) {
339 processedFiles.add(fileName);