e8fe0341767d8e4a5e1c901ed40a94365bfc8603
[sdc.git] /
1 /*
2  * Copyright © 2018 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.heat.services.tree;
18
19 import org.onap.sdc.tosca.services.YamlUtil;
20 import org.openecomp.core.utilities.file.FileContentHandler;
21 import org.openecomp.core.utilities.file.FileUtils;
22 import org.openecomp.core.utilities.json.JsonUtil;
23 import org.openecomp.core.validation.types.GlobalValidationContext;
24 import org.openecomp.sdc.common.utils.SdcCommon;
25 import org.openecomp.sdc.datatypes.error.ErrorMessage;
26 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
27 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
28 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
29 import org.openecomp.sdc.heat.datatypes.structure.Artifact;
30 import org.openecomp.sdc.heat.datatypes.structure.HeatStructureTree;
31 import org.openecomp.sdc.logging.api.Logger;
32 import org.openecomp.sdc.logging.api.LoggerFactory;
33
34 import java.io.InputStream;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.List;
38 import java.util.Map;
39 import java.util.Objects;
40 import java.util.Set;
41
42
43 public class HeatTreeManager {
44
45   private static final Logger LOGGER = LoggerFactory.getLogger(HeatTreeManager.class);
46
47
48   private FileContentHandler heatContentMap = new FileContentHandler();
49   private byte[] manifest;
50   private HeatStructureTree tree = new HeatStructureTree();
51   private Map<String, HeatStructureTree> fileTreeRef = new HashMap<>();
52   private Map<String, Artifact> artifactRef = new HashMap<>();
53   private Map<String, Artifact> candidateOrphanArtifacts = new HashMap<>();
54   private Map<String, HeatStructureTree> nestedFiles = new HashMap<>();
55   private Map<HeatStructureTree, HeatStructureTree> volumeFileToParent = new HashMap<>();
56   private Map<HeatStructureTree, HeatStructureTree> networkFileToParent = new HashMap<>();
57   private Set<String> manifestFiles = new HashSet<>();
58
59   /**
60    * Add file.
61    *
62    * @param fileName the file name
63    * @param content  the content
64    */
65   public void addFile(String fileName, InputStream content) {
66     if (fileName.equals(SdcCommon.MANIFEST_NAME)) {
67       manifest = FileUtils.toByteArray(content);
68
69     } else {
70       heatContentMap.addFile(fileName, content);
71     }
72   }
73
74   /**
75    * Create tree.
76    */
77   public void createTree() {
78     if (manifest == null) {
79       LOGGER.error("Missing manifest file in the zip.");
80       return;
81     }
82     ManifestContent manifestData =
83         JsonUtil.json2Object(new String(manifest), ManifestContent.class);
84     scanTree(null, manifestData.getData());
85     addNonNestedVolumeNetworkToTree(volumeFileToParent, nestedFiles.keySet(), true);
86     addNonNestedVolumeNetworkToTree(networkFileToParent, nestedFiles.keySet(), false);
87     handleOrphans();
88
89     tree = fileTreeRef.get(SdcCommon.PARENT);
90   }
91
92   private void handleOrphans() {
93     tree = fileTreeRef.get(SdcCommon.PARENT);
94     candidateOrphanArtifacts.entrySet().stream()
95         .forEach(entry -> tree.addArtifactToArtifactList(entry.getValue()));
96     nestedFiles
97         .values().stream().filter(tree.getHeat()::contains)
98         .forEach(tree.getHeat()::remove);
99
100     heatContentMap.getFileList().stream().filter(this::isNotInManifestFiles)
101         .forEach(this::addTreeOther);
102   }
103
104   private boolean isNotInManifestFiles(String fileName) {
105     return !manifestFiles.contains(fileName);
106   }
107
108   private void addTreeOther(String fileName) {
109     if (tree.getOther() == null) {
110       tree.setOther(new HashSet<>());
111     }
112     HeatStructureTree other = new HeatStructureTree(fileName, false);
113     fileTreeRef.put(fileName, other);
114     tree.getOther().add(other);
115   }
116
117
118   private void handleHeatContentReference(HeatStructureTree fileHeatStructureTree,
119                                           GlobalValidationContext globalContext) {
120
121     String fileName = fileHeatStructureTree.getFileName();
122
123     try (InputStream fileContent = this.heatContentMap.getFileContent(fileName)) {
124       HeatOrchestrationTemplate hot =
125           new YamlUtil().yamlToObject(fileContent, HeatOrchestrationTemplate.class);
126
127       Set<String> nestedSet = HeatTreeManagerUtil.getNestedFiles(fileName, hot, globalContext);
128       addHeatNestedFiles(fileHeatStructureTree, nestedSet);
129
130       Set<String> artifactSet = HeatTreeManagerUtil.getArtifactFiles(fileName, hot, globalContext);
131       addHeatArtifactFiles(fileHeatStructureTree, artifactSet);
132     } catch (Exception ignore) {
133       LOGGER.debug("Invalid YAML received. No need to process content reference - ignoring", ignore);
134     }
135   }
136
137
138   private void addHeatArtifactFiles(HeatStructureTree fileHeatStructureTree,
139                                     Set<String> artifactSet) {
140     Artifact artifact;
141     for (String artifactName : artifactSet) {
142       FileData.Type type =
143           candidateOrphanArtifacts.get(artifactName) != null ? candidateOrphanArtifacts
144               .get(artifactName).getType() : null;
145       artifact = new Artifact(artifactName, type);
146       artifactRef.put(artifactName, artifact);
147       candidateOrphanArtifacts.remove(artifactName);
148       fileHeatStructureTree.addArtifactToArtifactList(artifact);
149     }
150   }
151
152
153   private void addHeatNestedFiles(HeatStructureTree fileHeatStructureTree, Set<String> nestedSet) {
154     HeatStructureTree childHeatStructureTree;
155     for (String nestedName : nestedSet) {
156       childHeatStructureTree = fileTreeRef.get(nestedName);
157       if (childHeatStructureTree == null) {
158         childHeatStructureTree = new HeatStructureTree();
159         childHeatStructureTree.setFileName(nestedName);
160         fileTreeRef.put(nestedName, childHeatStructureTree);
161       }
162       fileHeatStructureTree.addHeatStructureTreeToNestedHeatList(childHeatStructureTree);
163       nestedFiles.put(childHeatStructureTree.getFileName(), childHeatStructureTree);
164     }
165   }
166
167
168   /**
169    * Add errors.
170    *
171    * @param validationErrors the validation errors
172    */
173   public void addErrors(Map<String, List<ErrorMessage>> validationErrors) {
174
175     validationErrors.entrySet().stream().filter(entry ->{
176       return fileTreeRef.get(entry.getKey()) != null;
177     }).forEach(entry -> entry.getValue().stream().forEach(fileTreeRef.get(entry.getKey())::addErrorToErrorsList));
178
179     validationErrors.entrySet().stream().filter(entry -> {
180       return artifactRef.get(entry.getKey()) != null;
181     }).forEach(entry -> artifactRef.get(entry.getKey()).setErrors(entry.getValue()));
182
183   }
184
185   /**
186    * Scan tree.
187    *
188    * @param parent the parent
189    * @param data   the data
190    */
191   public void scanTree(String parent, List<FileData> data) {
192     String fileName;
193     FileData.Type type;
194     HeatStructureTree parentHeatStructureTree;
195     HeatStructureTree fileHeatStructureTree;
196     HeatStructureTree childHeatStructureTree;
197     Artifact artifact;
198     if (parent == null) {
199       parentHeatStructureTree = new HeatStructureTree();
200       fileTreeRef.put(SdcCommon.PARENT, parentHeatStructureTree);
201     } else {
202       parentHeatStructureTree = fileTreeRef.get(parent);
203     }
204
205     for (FileData fileData : data) {
206       fileName = fileData.getFile();
207       manifestFiles.add(fileName);
208       type = fileData.getType();
209
210       if (Objects.nonNull(type) && FileData.Type.HEAT.equals(type)) {
211         fileHeatStructureTree = fileTreeRef.get(fileName);
212         if (fileHeatStructureTree == null) {
213           fileHeatStructureTree = new HeatStructureTree();
214           fileTreeRef.put(fileName, fileHeatStructureTree);
215         }
216         fileHeatStructureTree.setFileName(fileName);
217         fileHeatStructureTree.setBase(fileData.getBase());
218         fileHeatStructureTree.setType(type);
219         handleHeatContentReference(fileHeatStructureTree, null);
220         parentHeatStructureTree.addHeatToHeatList(fileHeatStructureTree);
221         if (fileData.getData() != null) {
222           scanTree(fileName, fileData.getData());
223         }
224       } else {
225         childHeatStructureTree = new HeatStructureTree();
226         childHeatStructureTree.setFileName(fileName);
227         childHeatStructureTree.setBase(fileData.getBase());
228         childHeatStructureTree.setType(type);
229         fileTreeRef.put(childHeatStructureTree.getFileName(), childHeatStructureTree);
230
231         if (type == null) {
232           parentHeatStructureTree.addOtherToOtherList(childHeatStructureTree);
233         } else if (FileData.Type.HEAT_NET.equals(type)) {
234           networkFileToParent.put(childHeatStructureTree, parentHeatStructureTree);
235           if (fileData.getData() != null) {
236             scanTree(fileName, fileData.getData());
237           }
238           handleHeatContentReference(childHeatStructureTree, null);
239
240         } else if (FileData.Type.HEAT_VOL.equals(type)) {
241           volumeFileToParent.put(childHeatStructureTree, parentHeatStructureTree);
242           if (fileData.getData() != null) {
243             scanTree(fileName, fileData.getData());
244           }
245           handleHeatContentReference(childHeatStructureTree, null);
246         } else if (FileData.Type.HEAT_ENV.equals(type)) {
247           if (parentHeatStructureTree != null && parentHeatStructureTree.getFileName() != null) {
248             parentHeatStructureTree.setEnv(childHeatStructureTree);
249           } else {
250             if (parentHeatStructureTree.getOther() == null) {
251               parentHeatStructureTree.setOther(new HashSet<>());
252             }
253             parentHeatStructureTree.getOther().add(childHeatStructureTree);
254           }
255         } else {
256           artifact = new Artifact(fileName, type);
257           if (!artifactRef.keySet().contains(fileName)) {
258             artifactRef.put(fileName, artifact);
259             candidateOrphanArtifacts.put(fileName, artifact);
260           }
261         }
262       }
263     }
264   }
265
266
267   private void addNonNestedVolumeNetworkToTree(
268       Map<HeatStructureTree, HeatStructureTree> netVolToParent, Set<String> nestedFileNames,
269       boolean isVolume) {
270     for (Map.Entry<HeatStructureTree, HeatStructureTree> entry : netVolToParent.entrySet()) {
271       HeatStructureTree netOrVolNode = entry.getKey();
272       HeatStructureTree parent = entry.getValue();
273       if (!nestedFileNames.contains(netOrVolNode.getFileName())) {
274         if (isVolume) {
275           parent.addVolumeFileToVolumeList(netOrVolNode);
276         } else {
277           parent.addNetworkToNetworkList(netOrVolNode);
278         }
279       }
280     }
281   }
282
283
284   public HeatStructureTree getTree() {
285     return tree;
286   }
287 }