/*- * ============LICENSE_START======================================================= * SDC * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============LICENSE_END========================================================= * Modifications copyright (c) 2019 Nokia * ================================================================================ */ package org.openecomp.sdc.be.components.csar; import static org.openecomp.sdc.be.components.impl.ImportUtils.findToscaElement; import com.google.common.annotations.VisibleForTesting; import fj.data.Either; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.PriorityQueue; import java.util.Queue; import java.util.Set; import java.util.stream.Stream; import lombok.Getter; import lombok.Setter; import org.apache.commons.collections.MapUtils; import org.openecomp.sdc.be.components.impl.ImportUtils.ResultStatusEnum; import org.openecomp.sdc.be.components.impl.ImportUtils.ToscaElementTypeEnum; import org.openecomp.sdc.be.components.impl.exceptions.ByActionStatusComponentException; import org.openecomp.sdc.be.config.NonManoArtifactType; import org.openecomp.sdc.be.config.NonManoConfiguration; import org.openecomp.sdc.be.config.NonManoConfigurationManager; import org.openecomp.sdc.be.config.NonManoFolderType; import org.openecomp.sdc.be.dao.api.ActionStatus; import org.openecomp.sdc.be.model.NodeTypeInfo; import org.openecomp.sdc.be.model.Resource; import org.openecomp.sdc.be.model.User; import org.openecomp.sdc.be.utils.TypeUtils; import org.openecomp.sdc.common.api.Constants; import org.openecomp.sdc.common.log.wrappers.Logger; import org.yaml.snakeyaml.Yaml; /** * Provides access to the contents of a CSAR */ public abstract class CsarInfo { private static final Logger log = Logger.getLogger(CsarInfo.class); private final NonManoConfiguration nonManoConfiguration; @Getter @Setter private String vfResourceName; @Getter @Setter private User modifier; @Getter @Setter private String csarUUID; @Getter private String csarVersionId; @Getter @Setter protected Map csar; @Getter private String mainTemplateName; @Getter private String mainTemplateContent; @Getter protected Map mappedToscaMainTemplate; @Getter private Map createdNodesToscaResourceNames; private Queue cvfcToCreateQueue; private boolean isUpdate; @Getter private Map createdNodes; protected Map artifacttypeDefinitions; private Map policytypeDefinitions; protected CsarInfo(User modifier, String csarUUID, Map csar, String vfResourceName, String mainTemplateName, String mainTemplateContent, boolean isUpdate) { this.vfResourceName = vfResourceName; this.modifier = modifier; this.csarUUID = csarUUID; this.csar = csar; this.mainTemplateName = mainTemplateName; this.mainTemplateContent = mainTemplateContent; this.mappedToscaMainTemplate = new Yaml().load(mainTemplateContent); this.createdNodesToscaResourceNames = new HashMap<>(); this.cvfcToCreateQueue = new PriorityQueue<>(); this.isUpdate = isUpdate; this.createdNodes = new HashMap<>(); this.nonManoConfiguration = NonManoConfigurationManager.getInstance().getNonManoConfiguration(); } public String getVfResourceName() { return vfResourceName; } protected CsarInfo(final User modifier, final String csarUUID, final String csarVersionId, final Map csarContent, final String vfResourceName, final String mainTemplateName, final String mainTemplateContent, final boolean isUpdate) { this(modifier, csarUUID, csarContent, vfResourceName, mainTemplateName, mainTemplateContent, isUpdate); this.csarVersionId = csarVersionId; } @VisibleForTesting CsarInfo(final NonManoConfiguration nonManoConfiguration) { this.nonManoConfiguration = nonManoConfiguration; } @SuppressWarnings("unchecked") public static void markNestedVfc(Map mappedToscaTemplate, Map nodeTypesInfo) { findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TEMPLATES, ToscaElementTypeEnum.MAP).right() .on(nts -> processNodeTemplates((Map) nts, nodeTypesInfo)); } @SuppressWarnings("unchecked") private static ResultStatusEnum processNodeTemplates(Map nodeTemplates, Map nodeTypesInfo) { nodeTemplates.values().forEach(nt -> processNodeTemplate(nodeTypesInfo, (Map) nt)); return ResultStatusEnum.OK; } private static void processNodeTemplate(Map nodeTypesInfo, Map nodeTemplate) { if (nodeTemplate.containsKey(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())) { String type = (String) nodeTemplate.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName()); if (nodeTypesInfo.containsKey(type)) { NodeTypeInfo nodeTypeInfo = nodeTypesInfo.get(type); if (nodeTypeInfo.isSubstitutionMapping() && type.contains(Constants.USER_DEFINED_RESOURCE_NAMESPACE_PREFIX)) { nodeTypeInfo.setNested(true); } } } } public void addNodeToQueue(String nodeName) { if (!cvfcToCreateQueue.contains(nodeName)) { cvfcToCreateQueue.add(nodeName); } else { log.debug("Failed to validate complex VFC {}. Loop detected, VSP {}. ", nodeName, getVfResourceName()); throw new ByActionStatusComponentException(ActionStatus.CFVC_LOOP_DETECTED, getVfResourceName(), nodeName); } } public void removeNodeFromQueue() { cvfcToCreateQueue.remove(); } public boolean isUpdate() { return isUpdate; } public void setUpdate(boolean isUpdate) { this.isUpdate = isUpdate; } public abstract Map extractTypesInfo(); /** * Get the data types defined in the CSAR * * @return map with the data type name as key and representaion of the data type defintion as value */ public abstract Map getDataTypes(); public abstract Map getGroupTypes(); public abstract Map getCapabilityTypes(); public abstract Map getArtifactTypes(); /** * Get the interface types defined in the CSAR * * @return map with the interface type name as key and representation of the interface type definition as value */ public abstract Map getInterfaceTypes(); public Map getPolicyTypes() { if (policytypeDefinitions == null) { policytypeDefinitions = new HashMap<>(); policytypeDefinitions.putAll(getTypesFromTemplate(mappedToscaMainTemplate, TypeUtils.ToscaTagNamesEnum.POLICY_TYPES)); } return policytypeDefinitions; } @SuppressWarnings("unchecked") protected Map getTypesFromTemplate(final Map mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum type) { final Either dataTypesEither = findToscaElement(mappedToscaTemplate, type, ToscaElementTypeEnum.MAP); if (dataTypesEither != null && dataTypesEither.isLeft()) { return (Map) dataTypesEither.left().value(); } return Collections.emptyMap(); } @SuppressWarnings("unchecked") protected Map getTypesFromTemplate(final Map mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum type, Collection names) { Map allTypes = getTypesFromTemplate(mappedToscaTemplate, type); final Map typesToReturn = new HashMap<>(); final Stream> requestedTypes = allTypes.entrySet().stream().filter(entry -> names.contains(entry.getKey())); requestedTypes.forEach(requestedType -> typesToReturn.put(requestedType.getKey(), requestedType.getValue())); return typesToReturn; } protected Set findNodeTypesUsedInNodeTemplates(final Map> nodeTemplates) { final Set nodeTypes = new HashSet<>(); for (final Map nodeTemplate : nodeTemplates.values()) { nodeTypes.add((String) nodeTemplate.get(TypeUtils.ToscaTagNamesEnum.TYPE.getElementName())); } return nodeTypes; } @SuppressWarnings("unchecked") protected NodeTypeInfo buildNodeTypeInfo(final Map.Entry nodeType, final String templateFileName, final Map mappedToscaTemplate) { final NodeTypeInfo nodeTypeInfo = new NodeTypeInfo(); nodeTypeInfo.setSubstitutionMapping(false); nodeTypeInfo.setNested(true); nodeTypeInfo.setType(nodeType.getKey()); nodeTypeInfo.setTemplateFileName(templateFileName); nodeTypeInfo.setMappedToscaTemplate(buildToscaTemplateForNode(nodeType.getKey(), mappedToscaTemplate)); final Map nodeTypeMap = (Map) nodeType.getValue(); final List derivedFrom = new ArrayList<>(); derivedFrom.add((String) nodeTypeMap.get(TypeUtils.ToscaTagNamesEnum.DERIVED_FROM.getElementName())); nodeTypeInfo.setDerivedFrom(derivedFrom); return nodeTypeInfo; } @SuppressWarnings("unchecked") private Map buildToscaTemplateForNode(final String nodeTypeName, final Map mappedToscaTemplate) { final Map mappedToscaTemplateforNode = new HashMap<>(mappedToscaTemplate); final Either nodeTypesEither = findToscaElement(mappedToscaTemplate, TypeUtils.ToscaTagNamesEnum.NODE_TYPES, ToscaElementTypeEnum.MAP); final Map nodeTypes = new HashMap<>(); if (nodeTypesEither.isLeft()) { final Map allNodeTypes = (Map) nodeTypesEither.left().value(); nodeTypes.put(nodeTypeName, allNodeTypes.get(nodeTypeName)); } mappedToscaTemplateforNode.put(TypeUtils.ToscaTagNamesEnum.NODE_TYPES.getElementName(), nodeTypes); return mappedToscaTemplateforNode; } /** * Gets the software information yaml path from the csar file map. * * @return the software information yaml path if it is present in the csar file map */ public Optional getSoftwareInformationPath() { if (MapUtils.isEmpty(csar)) { return Optional.empty(); } final NonManoFolderType softwareInformationType = nonManoConfiguration.getNonManoType(NonManoArtifactType.ONAP_SW_INFORMATION); return csar.keySet().stream().filter(filePath -> filePath.startsWith(softwareInformationType.getPath())).findFirst(); } }