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.ManifestContent;
33 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
34 import org.openecomp.sdc.vendorsoftwareproduct.services.HeatFileAnalyzer;
35 import org.openecomp.sdc.vendorsoftwareproduct.services.filedatastructuremodule.ManifestCreator;
36 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.AnalyzedZipHeatFiles;
37 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Constants;
38 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.FilesDataStructure;
39 import org.openecomp.sdc.vendorsoftwareproduct.types.candidateheat.Module;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 public class ManifestCreatorNamingConventionImpl implements ManifestCreator {
45 protected static final Logger logger = LoggerFactory.getLogger(ManifestCreatorNamingConventionImpl.class);
46 private static final String CLOUD_SPECIFIC_FIXED_KEY_WORD = "cloudtech";
47 private static final String[][] CLOUD_SPECIFIC_KEY_WORDS = {{"k8s", "azure", "aws"}, /* cloud specific technology */
48 {"charts", "day0", "configtemplate"} /*cloud specific sub type*/};
49 private static final String CONTROLLER_BLUEPRINT_ARCHIVE_FIXED_KEY_WORD = "CBA";
50 private static final String HELM_KEY_WORD = "HELM";
53 public Optional<ManifestContent> createManifest(VspDetails vspDetails, FilesDataStructure filesDataStructure) {
54 if (Objects.isNull(filesDataStructure)) {
55 return Optional.empty();
57 List<FileData> fileDataList = new ArrayList<>();
58 addModulesToManifestFileDataList(filesDataStructure, fileDataList);
59 addNestedToManifest(filesDataStructure, fileDataList);
60 addArtifactsToManifestFileDataList(filesDataStructure, fileDataList);
61 ManifestContent manifestContent = createManifest(vspDetails, fileDataList);
62 return Optional.of(manifestContent);
66 public Optional<ManifestContent> createManifestFromExisting(VspDetails vspDetails, FilesDataStructure filesDataStructure,
67 ManifestContent existingManifest) {
68 if (Objects.isNull(filesDataStructure)) {
69 return Optional.empty();
71 List<FileData> fileDataList = new ArrayList<>();
72 addModulesToManifestFileDataList(filesDataStructure, fileDataList);
73 addNestedToManifest(filesDataStructure, fileDataList);
74 addArtifactsToManifestFileDataList(filesDataStructure, fileDataList, existingManifest);
75 ManifestContent manifestContent = createManifest(vspDetails, fileDataList);
76 return Optional.of(manifestContent);
79 private void addArtifactsToManifestFileDataList(FilesDataStructure filesDataStructure, List<FileData> fileDataList,
80 ManifestContent existingManifest) {
81 Collection<String> forArtifacts = CollectionUtils.union(filesDataStructure.getArtifacts(), filesDataStructure.getUnassigned());
82 if (CollectionUtils.isNotEmpty(forArtifacts)) {
83 for (String artifact : forArtifacts) {
84 if (isCloudSpecificArtifact(artifact)) {
85 fileDataList.add(createBaseFileData(FileData.Type.CLOUD_TECHNOLOGY_SPECIFIC_ARTIFACT, artifact));
86 } else if (isControllerBlueprintArchive(artifact)) {
87 fileDataList.add(createBaseFileData(FileData.Type.CONTROLLER_BLUEPRINT_ARCHIVE, artifact));
88 } else if (isHelm(artifact)) {
89 fileDataList.add(createBaseFileData(FileData.Type.HELM, artifact));
90 } else if (isPmDictionary(artifact, existingManifest)) {
91 fileDataList.add(createBaseFileData(FileData.Type.PM_DICTIONARY, artifact));
93 fileDataList.add(createBaseFileData(FileData.Type.OTHER, artifact));
99 private boolean isPmDictionary(String artifact, ManifestContent existingManifest) {
100 return existingManifest.getData().stream().filter(fileData -> FileData.Type.PM_DICTIONARY.equals(fileData.getType())).map(FileData::getFile)
101 .anyMatch(pmDictionaryFile -> pmDictionaryFile.equals(artifact));
104 private void addNestedToManifest(FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
105 if (CollectionUtils.isNotEmpty(filesDataStructure.getNested())) {
106 for (String nested : filesDataStructure.getNested()) {
107 fileDataList.add(createBaseFileData(FileData.Type.HEAT, nested));
113 public Optional<ManifestContent> createManifest(VspDetails vspDetails, FileContentHandler fileContentHandler,
114 AnalyzedZipHeatFiles analyzedZipHeatFiles) {
115 logger.info("Trying to generate manifest");
116 if (Objects.isNull(fileContentHandler) || CollectionUtils.isEmpty(fileContentHandler.getFileList())) {
117 logger.info("fileContentHandler or filesList is empty. ManifestContent will not be created");
118 return Optional.empty();
120 Map<String, byte[]> files = fileContentHandler.getFiles();
121 List<FileData> fileDataList = createFileDataListFromZipFiles(fileContentHandler, files, analyzedZipHeatFiles.getFilesNotEligbleForModules());
122 ManifestContent manifestContent = createManifest(vspDetails, fileDataList);
123 return Optional.of(manifestContent);
126 private ManifestContent createManifest(VspDetails vspDetails, List<FileData> fileDataList) {
127 ManifestContent manifestContent = new ManifestContent();
128 manifestContent.setName(vspDetails.getName());
129 manifestContent.setDescription(vspDetails.getDescription());
130 manifestContent.setVersion(vspDetails.getVersion() == null ? null : vspDetails.getVersion().toString());
131 // vsp version, need to check in confluence
132 manifestContent.setData(fileDataList);
133 return manifestContent;
136 private List<FileData> createFileDataListFromZipFiles(FileContentHandler fileContentHandler, Map<String, byte[]> files,
137 Collection<String> filesNotEligibleForModules) {
138 Set<String> processedFiles = new HashSet<>();
139 List<FileData> fileDataList = new ArrayList<>();
140 for (String fileName : files.keySet()) {
141 if (processedFiles.contains(fileName)) {
144 if (isFileBaseFile(fileName)) {
145 fileDataList.add(createModuleFileData(fileName, true, processedFiles, fileContentHandler.getFileList(), fileDataList));
146 } else if (isFileModuleFile(fileName, filesNotEligibleForModules)) {
147 fileDataList.add(createModuleFileData(fileName, false, processedFiles, fileContentHandler.getFileList(), fileDataList));
149 if (HeatFileAnalyzer.isYamlFile(fileName)) {
150 fileDataList.add(createBasicFileData(fileName, FileData.Type.HEAT, null));
151 } else if (HeatFileAnalyzer.isEnvFile(fileName)) {
152 fileDataList.add(createBasicFileData(fileName, FileData.Type.HEAT_ENV, null));
154 fileDataList.add(createBasicFileData(fileName, FileData.Type.OTHER, null));
161 private boolean isFileModuleFile(String fileName, Collection<String> filesCannotBeModule) {
162 return !filesCannotBeModule.contains(fileName);
166 public boolean isFileBaseFile(String fileName) {
167 return Pattern.matches(Constants.BASE_HEAT_REGEX, fileName) && !isVolFile(fileName);
170 protected boolean isCloudSpecificArtifact(String artifact) {
171 if (artifact.contains(CLOUD_SPECIFIC_FIXED_KEY_WORD)) {
172 for (int i = 0; i < CLOUD_SPECIFIC_KEY_WORDS.length; i++) {
173 if (Arrays.stream(CLOUD_SPECIFIC_KEY_WORDS[i]).noneMatch(str -> artifact.contains(str))) {
183 private boolean isControllerBlueprintArchive(String artifact) {
184 return artifact.toUpperCase().contains(CONTROLLER_BLUEPRINT_ARCHIVE_FIXED_KEY_WORD);
187 private boolean isHelm(String artifact) {
188 return artifact.toUpperCase().contains(HELM_KEY_WORD);
191 private void addArtifactsToManifestFileDataList(FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
192 Collection<String> forArtifacts = CollectionUtils.union(filesDataStructure.getArtifacts(), filesDataStructure.getUnassigned());
193 if (CollectionUtils.isNotEmpty(forArtifacts)) {
194 for (String artifact : forArtifacts) {
195 if (isCloudSpecificArtifact(artifact)) {
196 fileDataList.add(createBaseFileData(FileData.Type.CLOUD_TECHNOLOGY_SPECIFIC_ARTIFACT, artifact));
197 } else if (isControllerBlueprintArchive(artifact)) {
198 fileDataList.add(createBaseFileData(FileData.Type.CONTROLLER_BLUEPRINT_ARCHIVE, artifact));
199 } else if (isHelm(artifact)) {
200 fileDataList.add(createBaseFileData(FileData.Type.HELM, artifact));
202 fileDataList.add(createBaseFileData(FileData.Type.OTHER, artifact));
208 private void addModulesToManifestFileDataList(FilesDataStructure filesDataStructure, List<FileData> fileDataList) {
209 if (CollectionUtils.isNotEmpty(filesDataStructure.getModules())) {
210 for (Module module : filesDataStructure.getModules()) {
211 FileData.Type type = module.getType();
213 type = FileData.Type.HEAT;
215 FileData fileData = createBaseFileData(type, module.getYaml());
216 fileData.setBase(module.getIsBase());
217 addEnv(module, fileData);
218 addVolume(module, fileData);
219 fileDataList.add(fileData);
224 private void addEnv(Module module, FileData fileData) {
225 if (Objects.nonNull(module.getEnv())) {
226 FileData env = createBaseFileData(FileData.Type.HEAT_ENV, module.getEnv());
227 fileData.addFileData(env);
231 private void addVolume(Module module, FileData fileData) {
232 String volModule = module.getVol();
233 if (Objects.nonNull(volModule)) {
234 FileData vol = createBaseFileData(FileData.Type.HEAT_VOL, volModule);
235 if (Objects.nonNull(module.getVolEnv())) {
236 vol.addFileData(createBaseFileData(FileData.Type.HEAT_ENV, module.getVolEnv()));
238 fileData.addFileData(vol);
242 private FileData createBaseFileData(FileData.Type heat, String yaml) {
243 FileData fileData = new FileData();
244 fileData.setType(heat);
245 fileData.setFile(yaml);
249 private FileData createModuleFileData(String moduleFileName, boolean isBase, Set<String> processedFiles, Set<String> fileNames,
250 List<FileData> fileDataList) {
251 FileData moduleFileData = createBasicFileData(moduleFileName, FileData.Type.HEAT, isBase);
252 Optional<String> volFile = fetchRelatedVolume(moduleFileName, fileNames);
253 volFile.ifPresent(vol -> {
254 markFileAsProcessed(vol, processedFiles);
255 removeFromFileDataListIfAlreadyProcessed(fileDataList, vol);
256 FileData volFileData = createBasicFileData(vol, FileData.Type.HEAT_VOL, null);
257 Optional<String> envFile = fetchRelatedEnv(vol, fileNames);
258 envFile.ifPresent(env -> {
259 markFileAsProcessed(env, processedFiles);
260 removeFromFileDataListIfAlreadyProcessed(fileDataList, env);
261 FileData envFileData = createBasicFileData(env, FileData.Type.HEAT_ENV, null);
262 volFileData.addFileData(envFileData);
264 moduleFileData.addFileData(volFileData);
266 Optional<String> envFile = fetchRelatedEnv(moduleFileName, fileNames);
267 envFile.ifPresent(env -> {
268 markFileAsProcessed(env, processedFiles);
269 FileData envFileData = createBasicFileData(env, FileData.Type.HEAT_ENV, null);
270 moduleFileData.addFileData(envFileData);
272 return moduleFileData;
275 private void removeFromFileDataListIfAlreadyProcessed(List<FileData> fileDataList, String vol) {
276 fileDataList.removeIf(fileData -> fileData.getFile().equals(vol));
279 private FileData createBasicFileData(String fileName, FileData.Type type, Boolean isBase) {
280 FileData fileData = new FileData();
281 if (isBase != null) {
282 fileData.setBase(isBase);
284 fileData.setType(type);
285 fileData.setFile(fileName);
289 private Optional<String> fetchRelatedEnv(String fileName, Set<String> fileNames) {
290 String envFileName = fileName.substring(0, fileName.lastIndexOf(".")) + Constants.ENV_FILE_EXTENSION;
291 return fileNames.contains(envFileName) ? Optional.of(envFileName) : Optional.empty();
294 private Optional<String> fetchRelatedVolume(String fileName, Set<String> fileNames) {
295 String volFile1stExt = extractVolFileName(fileName, ".yaml");
296 String volFile2ndExt = extractVolFileName(fileName, ".yml");
297 if (fileNames.contains(volFile1stExt)) {
298 return Optional.of(volFile1stExt);
300 if (fileNames.contains(volFile2ndExt)) {
301 return Optional.of(volFile2ndExt);
303 return Optional.empty();
306 private String extractVolFileName(String fileName, String fileExt) {
307 return fileName.substring(0, fileName.lastIndexOf(".")) + Constants.VOL_FILE_NAME_SUFFIX + fileExt;
310 private boolean isVolFile(String fileName) {
311 return fileName.endsWith(Constants.VOL_FILE_NAME_SUFFIX + ".yaml") || fileName.endsWith(Constants.VOL_FILE_NAME_SUFFIX + ".yml");
314 private void markFileAsProcessed(String fileName, Set<String> processedFiles) {
315 processedFiles.add(fileName);