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