f92c1d10d2c655af94c7507258d77bd4b422c178
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / csar / CsarInfo.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22 package org.openecomp.sdc.be.components.csar;
23
24 import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement;
25
26 import com.google.common.annotations.VisibleForTesting;
27 import fj.data.Either;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Optional;
36 import java.util.PriorityQueue;
37 import java.util.Queue;
38 import java.util.Set;
39 import java.util.stream.Stream;
40 import lombok.Getter;
41 import lombok.Setter;
42 import org.apache.commons.collections.MapUtils;
43 import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
44 import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
45 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
46 import org.openecomp.sdc.be.config.NonManoArtifactType;
47 import org.openecomp.sdc.be.config.NonManoConfiguration;
48 import org.openecomp.sdc.be.config.NonManoConfigurationManager;
49 import org.openecomp.sdc.be.config.NonManoFolderType;
50 import org.openecomp.sdc.be.dao.api.ActionStatus;
51 import org.openecomp.sdc.be.model.NodeTypeInfo;
52 import org.openecomp.sdc.be.model.Resource;
53 import org.openecomp.sdc.be.model.User;
54 import org.openecomp.sdc.be.utils.TypeUtils;
55 import org.openecomp.sdc.common.api.Constants;
56 import org.openecomp.sdc.common.log.wrappers.Logger;
57 import org.yaml.snakeyaml.Yaml;
58
59 /**
60  * Provides access to the contents of a CSAR
61  */
62 public abstract class CsarInfo {
63
64     private static final Logger log = Logger.getLogger(CsarInfo.class);
65     private final NonManoConfiguration nonManoConfiguration;
66     @Getter
67     @Setter
68     private String vfResourceName;
69     @Getter
70     @Setter
71     private User modifier;
72     @Getter
73     @Setter
74     private String csarUUID;
75     @Getter
76     private String csarVersionId;
77     @Getter
78     @Setter
79     protected Map<String, byte[]> csar;
80     @Getter
81     private String mainTemplateName;
82     @Getter
83     private String mainTemplateContent;
84     @Getter
85     protected Map<String, Object> mappedToscaMainTemplate;
86     @Getter
87     private Map<String, String> createdNodesToscaResourceNames;
88     private Queue<String> cvfcToCreateQueue;
89     private boolean isUpdate;
90     @Getter
91     private Map<String, Resource> createdNodes;
92     protected Map<String, Object> artifacttypeDefinitions;
93     private Map<String, Object> policytypeDefinitions;
94
95     protected CsarInfo(User modifier, String csarUUID, Map<String, byte[]> csar, String vfResourceName, String mainTemplateName,
96                        String mainTemplateContent, boolean isUpdate) {
97         this.vfResourceName = vfResourceName;
98         this.modifier = modifier;
99         this.csarUUID = csarUUID;
100         this.csar = csar;
101         this.mainTemplateName = mainTemplateName;
102         this.mainTemplateContent = mainTemplateContent;
103         this.mappedToscaMainTemplate = new Yaml().load(mainTemplateContent);
104         this.createdNodesToscaResourceNames = new HashMap<>();
105         this.cvfcToCreateQueue = new PriorityQueue<>();
106         this.isUpdate = isUpdate;
107         this.createdNodes = new HashMap<>();
108         this.nonManoConfiguration = NonManoConfigurationManager.getInstance().getNonManoConfiguration();
109     }
110
111     public String getVfResourceName() {
112         return vfResourceName;
113     }
114
115     protected CsarInfo(final User modifier, final String csarUUID, final String csarVersionId, final Map<String, byte[]> csarContent,
116                        final String vfResourceName, final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) {
117         this(modifier, csarUUID, csarContent, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate);
118         this.csarVersionId = csarVersionId;
119     }
120
121     @VisibleForTesting
122     CsarInfo(final NonManoConfiguration nonManoConfiguration) {
123         this.nonManoConfiguration = nonManoConfiguration;
124     }
125
126     @SuppressWarnings("unchecked")
127     public static void markNestedVfc(Map<String, Object> mappedToscaTemplate, Map<String, NodeTypeInfo> nodeTypesInfo) {
128         findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES, ToscaElementTypeEnum.MAP).right()
129             .on(nts -> processNodeTemplates((Map<String, Object>) nts, nodeTypesInfo));
130     }
131
132     @SuppressWarnings("unchecked")
133     private static ResultStatusEnum processNodeTemplates(Map<String, Object> nodeTemplates, Map<String, NodeTypeInfo> nodeTypesInfo) {
134         nodeTemplates.values().forEach(nt -> processNodeTemplate(nodeTypesInfo, (Map<String, Object>) nt));
135         return ResultStatusEnum.OK;
136     }
137
138     private static void processNodeTemplate(Map<String, NodeTypeInfo> nodeTypesInfo, Map<String, Object> nodeTemplate) {
139         if (nodeTemplate.containsKey(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())) {
140             String type = (String) nodeTemplate.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName());
141             if (nodeTypesInfo.containsKey(type)) {
142                 NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(type);
143                 if (nodeTypeInfo.isSubstitutionMapping() && type.contains(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX)) {
144                     nodeTypeInfo.setNested(true);
145                 }
146             }
147         }
148     }
149
150     public void addNodeToQueue(String nodeName) {
151         if (!cvfcToCreateQueue.contains(nodeName)) {
152             cvfcToCreateQueue.add(nodeName);
153         } else {
154             log.debug("Failed to validate complex VFC {}. Loop detected, VSP {}. ", nodeName, getVfResourceName());
155             throw new ByActionStatusComponentException(ActionStatus.CFVC_LOOP_DETECTED, getVfResourceName(), nodeName);
156         }
157     }
158
159     public void removeNodeFromQueue() {
160         cvfcToCreateQueue.remove();
161     }
162
163     public boolean isUpdate() {
164         return isUpdate;
165     }
166
167     public void setUpdate(boolean isUpdate) {
168         this.isUpdate = isUpdate;
169     }
170
171     public abstract Map<String, NodeTypeInfo> extractTypesInfo();
172
173     /**
174      * Get the data types defined in the CSAR
175      *
176      * @return map with the data type name as key and representaion of the data type defintion as value
177      */
178     public abstract Map<String, Object> getDataTypes();
179
180     public abstract Map<String, Object> getGroupTypes();
181
182     public abstract Map<String, Object> getCapabilityTypes();
183
184     public abstract Map<String, Object> getArtifactTypes();
185
186     public Map<String, Object> getPolicyTypes() {
187         if (policytypeDefinitions == null) {
188             policytypeDefinitions = new HashMap<>();
189             policytypeDefinitions.putAll(getTypesFromTemplate(mappedToscaMainTemplate, TypeUtils.ToscaTagNamesEnum.POLICY_TYPES));
190         }
191         return policytypeDefinitions;
192     }
193
194     @SuppressWarnings("unchecked")
195     protected Map<String, Object> getTypesFromTemplate(final Map<String, Object> mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum type) {
196         final Either<Object, ResultStatusEnum> dataTypesEither = findToscaElement(mappedToscaTemplate, type, ToscaElementTypeEnum.MAP);
197         if (dataTypesEither != null && dataTypesEither.isLeft()) {
198             return (Map<String, Object>) dataTypesEither.left().value();
199         }
200         return Collections.emptyMap();
201     }
202
203     @SuppressWarnings("unchecked")
204     protected Map<String, Object> getTypesFromTemplate(final Map<String, Object> mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum type,
205                                                        Collection<String> names) {
206         Map<String, Object> allTypes = getTypesFromTemplate(mappedToscaTemplate, type);
207
208         final Map<String, Object> typesToReturn = new HashMap<>();
209         final Stream<Map.Entry<String, Object>> requestedTypes = allTypes.entrySet().stream().filter(entry -> names.contains(entry.getKey()));
210
211         requestedTypes.forEach(requestedType -> typesToReturn.put(requestedType.getKey(), requestedType.getValue()));
212
213         return typesToReturn;
214     }
215
216     protected Set<String> findNodeTypesUsedInNodeTemplates(final Map<String, Map<String, Object>> nodeTemplates) {
217         final Set<String> nodeTypes = new HashSet<>();
218         for (final Map<String, Object> nodeTemplate : nodeTemplates.values()) {
219             nodeTypes.add((String) nodeTemplate.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName()));
220         }
221         return nodeTypes;
222     }
223
224     @SuppressWarnings("unchecked")
225     protected NodeTypeInfo buildNodeTypeInfo(final Map.Entry<String, Object> nodeType, final String templateFileName,
226                                              final Map<String, Object> mappedToscaTemplate) {
227         final NodeTypeInfo nodeTypeInfo = new NodeTypeInfo();
228         nodeTypeInfo.setSubstitutionMapping(false);
229         nodeTypeInfo.setNested(true);
230         nodeTypeInfo.setType(nodeType.getKey());
231         nodeTypeInfo.setTemplateFileName(templateFileName);
232         nodeTypeInfo.setMappedToscaTemplate(buildToscaTemplateForNode(nodeType.getKey(), mappedToscaTemplate));
233         final Map<String, Object> nodeTypeMap = (Map<String, Object>) nodeType.getValue();
234         final List<String> derivedFrom = new ArrayList<>();
235         derivedFrom.add((String) nodeTypeMap.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()));
236         nodeTypeInfo.setDerivedFrom(derivedFrom);
237         return nodeTypeInfo;
238     }
239
240     @SuppressWarnings("unchecked")
241     private Map<String, Object> buildToscaTemplateForNode(final String nodeTypeName, final Map<String, Object> mappedToscaTemplate) {
242         final Map<String, Object> mappedToscaTemplateforNode = new HashMap<>(mappedToscaTemplate);
243         final Either<Object, ResultStatusEnum> nodeTypesEither = findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES,
244             ToscaElementTypeEnum.MAP);
245         final Map<String, Object> nodeTypes = new HashMap<>();
246         if (nodeTypesEither.isLeft()) {
247             final Map<String, Object> allNodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
248             nodeTypes.put(nodeTypeName, allNodeTypes.get(nodeTypeName));
249         }
250         mappedToscaTemplateforNode.put(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName(), nodeTypes);
251         return mappedToscaTemplateforNode;
252     }
253
254     /**
255      * Gets the software information yaml path from the csar file map.
256      *
257      * @return the software information yaml path if it is present in the csar file map
258      */
259     public Optional<String> getSoftwareInformationPath() {
260         if (MapUtils.isEmpty(csar)) {
261             return Optional.empty();
262         }
263         final NonManoFolderType softwareInformationType = nonManoConfiguration.getNonManoType(NonManoArtifactType.ONAP_SW_INFORMATION);
264         return csar.keySet().stream().filter(filePath -> filePath.startsWith(softwareInformationType.getPath())).findFirst();
265     }
266 }