2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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 * ================================================================================
22 package org.openecomp.sdc.be.components.csar;
24 import com.google.common.annotations.VisibleForTesting;
25 import fj.data.Either;
28 import org.apache.commons.collections.CollectionUtils;
29 import org.apache.commons.collections.MapUtils;
30 import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException;
31 import org.openecomp.sdc.be.config.NonManoArtifactType;
32 import org.openecomp.sdc.be.config.NonManoConfiguration;
33 import org.openecomp.sdc.be.config.NonManoConfigurationManager;
34 import org.openecomp.sdc.be.config.NonManoFolderType;
35 import org.openecomp.sdc.be.dao.api.ActionStatus;
36 import org.openecomp.sdc.be.model.NodeTypeInfo;
37 import org.openecomp.sdc.be.model.Resource;
38 import org.openecomp.sdc.be.model.User;
39 import org.openecomp.sdc.be.tosca.CsarUtils;
40 import org.openecomp.sdc.be.utils.TypeUtils;
41 import org.openecomp.sdc.common.api.Constants;
42 import org.openecomp.sdc.common.log.wrappers.Logger;
43 import org.yaml.snakeyaml.Yaml;
45 import java.util.ArrayList;
46 import java.util.HashMap;
47 import java.util.List;
49 import java.util.Optional;
50 import java.util.PriorityQueue;
51 import java.util.Queue;
52 import java.util.regex.Pattern;
54 import static org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum;
55 import static org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum;
56 import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement;
58 public class CsarInfo {
59 private static final Logger log = Logger.getLogger(CsarInfo.class);
63 private String vfResourceName;
66 private User modifier;
69 private String csarUUID;
72 private Map<String, byte[]> csar;
74 private String mainTemplateName;
76 private String mainTemplateContent;
78 private Map<String, Object> mappedToscaMainTemplate;
80 private Map<String, String> createdNodesToscaResourceNames;
81 private Queue<String> cvfcToCreateQueue;
82 private boolean isUpdate;
84 private Map<String, Resource> createdNodes;
85 private final NonManoConfiguration nonManoConfiguration;
87 @SuppressWarnings("unchecked")
88 public CsarInfo(User modifier, String csarUUID, Map<String, byte[]> csar, String vfResourceName, String mainTemplateName, String mainTemplateContent, boolean isUpdate){
89 this.vfResourceName = vfResourceName;
90 this.modifier = modifier;
91 this.csarUUID = csarUUID;
93 this.mainTemplateName = mainTemplateName;
94 this.mainTemplateContent = mainTemplateContent;
95 this.mappedToscaMainTemplate = (Map<String, Object>) new Yaml().load(mainTemplateContent);
96 this.createdNodesToscaResourceNames = new HashMap<>();
97 this.cvfcToCreateQueue = new PriorityQueue<>();
98 this.isUpdate = isUpdate;
99 this.createdNodes = new HashMap<>();
100 this.nonManoConfiguration = NonManoConfigurationManager.getInstance().getNonManoConfiguration();
104 CsarInfo(final NonManoConfiguration nonManoConfiguration) {
105 this.nonManoConfiguration = nonManoConfiguration;
108 public void addNodeToQueue(String nodeName) {
109 if(!cvfcToCreateQueue.contains(nodeName)) {
110 cvfcToCreateQueue.add(nodeName);
112 log.debug("Failed to validate complex VFC {}. Loop detected, VSP {}. ", nodeName,
113 getVfResourceName());
114 throw new ByActionStatusComponentException(ActionStatus.CFVC_LOOP_DETECTED,
115 getVfResourceName(), nodeName);
119 public void removeNodeFromQueue() {
120 cvfcToCreateQueue.remove();
123 public boolean isUpdate() {
127 public void setUpdate(boolean isUpdate) {
128 this.isUpdate = isUpdate;
131 public Map<String,NodeTypeInfo> extractNodeTypesInfo() {
132 Map<String, NodeTypeInfo> nodeTypesInfo = new HashMap<>();
133 List<Map.Entry<String, byte[]>> globalSubstitutes = new ArrayList<>();
134 for (Map.Entry<String, byte[]> entry : getCsar().entrySet()) {
135 extractNodeTypeInfo(nodeTypesInfo, globalSubstitutes, entry);
137 if (CollectionUtils.isNotEmpty(globalSubstitutes)) {
138 setDerivedFrom(nodeTypesInfo, globalSubstitutes);
140 markNestedVfc(getMappedToscaMainTemplate(), nodeTypesInfo);
141 return nodeTypesInfo;
144 @SuppressWarnings("unchecked")
145 private void extractNodeTypeInfo(Map<String, NodeTypeInfo> nodeTypesInfo,
146 List<Map.Entry<String, byte[]>> globalSubstitutes, Map.Entry<String, byte[]> entry) {
147 if (Pattern.compile(CsarUtils.SERVICE_TEMPLATE_PATH_PATTERN).matcher(entry.getKey()).matches()) {
148 if (!isGlobalSubstitute(entry.getKey())) {
149 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(new String(entry.getValue()));
150 findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.SUBSTITUTION_MAPPINGS, ToscaElementTypeEnum.MAP)
152 .on(sub->handleSubstitutionMappings(nodeTypesInfo, entry, mappedToscaTemplate, (Map<String, Object>)sub));
154 globalSubstitutes.add(entry);
159 private ResultStatusEnum handleSubstitutionMappings(Map<String, NodeTypeInfo> nodeTypesInfo, Map.Entry<String, byte[]> entry, Map<String, Object> mappedToscaTemplate, Map<String, Object> substitutionMappings) {
160 if (substitutionMappings.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName())) {
161 NodeTypeInfo nodeTypeInfo = new NodeTypeInfo();
162 nodeTypeInfo.setSubstitutionMapping(true);
163 nodeTypeInfo.setType(
164 (String) substitutionMappings.get(TypeUtils.ToscaTagNamesEnum.NODE_TYPE.getElementName()));
165 nodeTypeInfo.setTemplateFileName(entry.getKey());
166 nodeTypeInfo.setMappedToscaTemplate(mappedToscaTemplate);
167 nodeTypesInfo.put(nodeTypeInfo.getType(), nodeTypeInfo);
169 return ResultStatusEnum.OK;
172 private boolean isGlobalSubstitute(String fileName) {
173 return fileName.equalsIgnoreCase(Constants.GLOBAL_SUBSTITUTION_TYPES_SERVICE_TEMPLATE)
174 || fileName.equalsIgnoreCase(Constants.ABSTRACT_SUBSTITUTE_GLOBAL_TYPES_SERVICE_TEMPLATE);
177 @SuppressWarnings("unchecked")
178 private void setDerivedFrom(Map<String, NodeTypeInfo> nodeTypesInfo,
179 List<Map.Entry<String, byte[]>> globalSubstitutes) {
180 for (Map.Entry<String, byte[]> entry : globalSubstitutes) {
181 String yamlFileContents = new String(entry.getValue());
182 Map<String, Object> mappedToscaTemplate = (Map<String, Object>) new Yaml().load(yamlFileContents);
183 Either<Object, ResultStatusEnum> nodeTypesEither = findToscaElement(mappedToscaTemplate,
184 TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP);
185 if (nodeTypesEither.isLeft()) {
186 Map<String, Object> nodeTypes = (Map<String, Object>) nodeTypesEither.left().value();
187 for (Map.Entry<String, Object> nodeType : nodeTypes.entrySet()) {
188 processNodeType(nodeTypesInfo, nodeType);
194 @SuppressWarnings("unchecked")
195 private void processNodeType(Map<String, NodeTypeInfo> nodeTypesInfo, Map.Entry<String, Object> nodeType) {
196 Map<String, Object> nodeTypeMap = (Map<String, Object>) nodeType.getValue();
197 if (nodeTypeMap.containsKey(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()) && nodeTypesInfo.containsKey(nodeType.getKey())) {
198 NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(nodeType.getKey());
199 List<String> derivedFrom = new ArrayList<>();
200 derivedFrom.add((String) nodeTypeMap.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName()));
201 nodeTypeInfo.setDerivedFrom(derivedFrom);
205 @SuppressWarnings("unchecked")
206 public static void markNestedVfc(Map<String, Object> mappedToscaTemplate, Map<String, NodeTypeInfo> nodeTypesInfo) {
207 findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES,
208 ToscaElementTypeEnum.MAP)
210 .on(nts-> processNodeTemplates((Map<String, Object>)nts, nodeTypesInfo));
213 @SuppressWarnings("unchecked")
214 private static ResultStatusEnum processNodeTemplates( Map<String, Object> nodeTemplates, Map<String, NodeTypeInfo> nodeTypesInfo) {
215 nodeTemplates.values().forEach(nt->processNodeTemplate(nodeTypesInfo, (Map<String, Object>) nt));
216 return ResultStatusEnum.OK;
219 private static void processNodeTemplate(Map<String, NodeTypeInfo> nodeTypesInfo, Map<String, Object> nodeTemplate) {
220 if (nodeTemplate.containsKey(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())) {
221 String type = (String) nodeTemplate.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName());
222 if (nodeTypesInfo.containsKey(type)) {
223 NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(type);
224 if (nodeTypeInfo.isSubstitutionMapping() && type.contains(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX)) {
225 nodeTypeInfo.setNested(true);
232 * Gets the software information yaml path from the csar file map.
234 * @return the software information yaml path if it is present in the csar file map
236 public Optional<String> getSoftwareInformationPath() {
237 if (MapUtils.isEmpty(csar)) {
238 return Optional.empty();
240 final NonManoFolderType softwareInformationType =
241 nonManoConfiguration.getNonManoType(NonManoArtifactType.ONAP_SW_INFORMATION);
242 return csar.keySet().stream()
243 .filter(filePath -> filePath.startsWith(softwareInformationType.getPath()))