Service import - Import unknown interface types
[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     /**
187      * Get the interface types defined in the CSAR
188      *
189      * @return map with the interface type name as key and representation of the interface type definition as value
190      */
191     public abstract Map<String, Object> getInterfaceTypes();
192
193     public Map<String, Object> getPolicyTypes() {
194         if (policytypeDefinitions == null) {
195             policytypeDefinitions = new HashMap<>();
196             policytypeDefinitions.putAll(getTypesFromTemplate(mappedToscaMainTemplate, TypeUtils.ToscaTagNamesEnum.POLICY_TYPES));
197         }
198         return policytypeDefinitions;
199     }
200
201     @SuppressWarnings("unchecked")
202     protected Map<String, Object> getTypesFromTemplate(final Map<String, Object> mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum type) {
203         final Either<Object, ResultStatusEnum> dataTypesEither = findToscaElement(mappedToscaTemplate, type, ToscaElementTypeEnum.MAP);
204         if (dataTypesEither != null && dataTypesEither.isLeft()) {
205             return (Map<String, Object>) dataTypesEither.left().value();
206         }
207         return Collections.emptyMap();
208     }
209
210     @SuppressWarnings("unchecked")
211     protected Map<String, Object> getTypesFromTemplate(final Map<String, Object> mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum type,
212                                                        Collection<String> names) {
213         Map<String, Object> allTypes = getTypesFromTemplate(mappedToscaTemplate, type);
214
215         final Map<String, Object> typesToReturn = new HashMap<>();
216         final Stream<Map.Entry<String, Object>> requestedTypes = allTypes.entrySet().stream().filter(entry -> names.contains(entry.getKey()));
217
218         requestedTypes.forEach(requestedType -> typesToReturn.put(requestedType.getKey(), requestedType.getValue()));
219
220         return typesToReturn;
221     }
222
223     protected Set<String> findNodeTypesUsedInNodeTemplates(final Map<String, Map<String, Object>> nodeTemplates) {
224         final Set<String> nodeTypes = new HashSet<>();
225         for (final Map<String, Object> nodeTemplate : nodeTemplates.values()) {
226             nodeTypes.add((String) nodeTemplate.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName()));
227         }
228         return nodeTypes;
229     }
230
231     @SuppressWarnings("unchecked")
232     protected NodeTypeInfo buildNodeTypeInfo(final Map.Entry<String, Object> nodeType, final String templateFileName,
233                                              final Map<String, Object> mappedToscaTemplate) {
234         final NodeTypeInfo nodeTypeInfo = new NodeTypeInfo();
235         nodeTypeInfo.setSubstitutionMapping(false);
236         nodeTypeInfo.setNested(true);
237         nodeTypeInfo.setType(nodeType.getKey());
238         nodeTypeInfo.setTemplateFileName(templateFileName);
239         nodeTypeInfo.setMappedToscaTemplate(buildToscaTemplateForNode(nodeType.getKey(), mappedToscaTemplate));
240         final Map<String, Object> nodeTypeMap = (Map<String, Object>) nodeType.getValue();
241         final List<String> derivedFrom = new ArrayList<>();
242         derivedFrom.add((String) nodeTypeMap.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()));
243         nodeTypeInfo.setDerivedFrom(derivedFrom);
244         return nodeTypeInfo;
245     }
246
247     @SuppressWarnings("unchecked")
248     private Map<String, Object> buildToscaTemplateForNode(final String nodeTypeName, final Map<String, Object> mappedToscaTemplate) {
249         final Map<String, Object> mappedToscaTemplateforNode = new HashMap<>(mappedToscaTemplate);
250         final Either<Object, ResultStatusEnum> nodeTypesEither = findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES,
251             ToscaElementTypeEnum.MAP);
252         final Map<String, Object> nodeTypes = new HashMap<>();
253         if (nodeTypesEither.isLeft()) {
254             final Map<String, Object> allNodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
255             nodeTypes.put(nodeTypeName, allNodeTypes.get(nodeTypeName));
256         }
257         mappedToscaTemplateforNode.put(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName(), nodeTypes);
258         return mappedToscaTemplateforNode;
259     }
260
261     /**
262      * Gets the software information yaml path from the csar file map.
263      *
264      * @return the software information yaml path if it is present in the csar file map
265      */
266     public Optional<String> getSoftwareInformationPath() {
267         if (MapUtils.isEmpty(csar)) {
268             return Optional.empty();
269         }
270         final NonManoFolderType softwareInformationType = nonManoConfiguration.getNonManoType(NonManoArtifactType.ONAP_SW_INFORMATION);
271         return csar.keySet().stream().filter(filePath -> filePath.startsWith(softwareInformationType.getPath())).findFirst();
272     }
273 }