/*- * ============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========================================================= */ package org.openecomp.sdc.translator.services.heattotosca.impl; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.openecomp.core.utilities.yaml.YamlUtil; import org.openecomp.sdc.common.errors.CoreException; import org.openecomp.sdc.heat.datatypes.manifest.FileData; import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate; import org.openecomp.sdc.heat.datatypes.model.Output; import org.openecomp.sdc.heat.datatypes.model.Resource; import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType; import org.openecomp.sdc.tosca.datatypes.ToscaRelationshipType; import org.openecomp.sdc.tosca.datatypes.model.ArtifactDefinition; import org.openecomp.sdc.tosca.datatypes.model.AttributeDefinition; import org.openecomp.sdc.tosca.datatypes.model.CapabilityDefinition; import org.openecomp.sdc.tosca.datatypes.model.Import; import org.openecomp.sdc.tosca.datatypes.model.InterfaceDefinition; import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate; import org.openecomp.sdc.tosca.datatypes.model.NodeType; import org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition; import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment; import org.openecomp.sdc.tosca.datatypes.model.RequirementDefinition; import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate; import org.openecomp.sdc.tosca.services.DataModelUtil; import org.openecomp.sdc.tosca.services.ToscaConstants; import org.openecomp.sdc.tosca.services.ToscaNativeTypesServiceTemplate; import org.openecomp.sdc.translator.datatypes.heattotosca.AttachedResourceId; import org.openecomp.sdc.translator.datatypes.heattotosca.to.ResourceFileDataAndIDs; import org.openecomp.sdc.translator.datatypes.heattotosca.to.TranslateTo; import org.openecomp.sdc.translator.services.heattotosca.HeatToToscaUtil; import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslation; import org.openecomp.sdc.translator.services.heattotosca.ResourceTranslationFactory; import org.openecomp.sdc.translator.services.heattotosca.TranslationContext; import org.openecomp.sdc.translator.services.heattotosca.TranslationService; import org.openecomp.sdc.translator.services.heattotosca.errors.ResourceNotFoundInHeatFileErrorBuilder; import org.openecomp.sdc.translator.services.heattotosca.globaltypes.GlobalTypesGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Collectors; public abstract class ResourceTranslationBase implements ResourceTranslation { protected static Logger logger = LoggerFactory.getLogger(ResourceTranslationBase.class); static Optional getFileDataContainingResource( List filesToSearch, String resourceId, TranslationContext context, FileData.Type... types) { if (CollectionUtils.isEmpty(filesToSearch)) { return Optional.empty(); } List fileDatas = Objects.isNull(types) ? filesToSearch : HeatToToscaUtil.getFilteredListOfFileDataByTypes(filesToSearch, types); for (FileData data : fileDatas) { HeatOrchestrationTemplate heatOrchestrationTemplate = new YamlUtil() .yamlToObject(context.getFiles().getFileContent(data.getFile()), HeatOrchestrationTemplate.class); Map outputs = heatOrchestrationTemplate.getOutputs(); if (Objects.isNull(outputs)) { continue; } Output output = outputs.get(resourceId); if (Objects.nonNull(output)) { Optional attachedOutputId = HeatToToscaUtil .extractAttachedResourceId(data.getFile(), heatOrchestrationTemplate, context, output.getValue()); if (attachedOutputId.isPresent()) { AttachedResourceId attachedResourceId = attachedOutputId.get(); if (!attachedResourceId.isGetResource()) { logger.warn("output: '" + resourceId + "' in file '" + data.getFile() + "' is not defined as get_resource and therefor not supported."); continue; } ResourceFileDataAndIDs fileDataAndIDs = new ResourceFileDataAndIDs((String) attachedResourceId.getEntityId(), (String) attachedResourceId.getTranslatedId(), data); return Optional.of(fileDataAndIDs); } } } return Optional.empty(); } /** * Gets resource translated id. * * @param heatFileName the heat file name * @param heatOrchestrationTemplate the heat orchestration template * @param resourceId the resource id * @param context the context * @return the resource translated id */ public static Optional getResourceTranslatedId(String heatFileName, HeatOrchestrationTemplate heatOrchestrationTemplate, String resourceId, TranslationContext context) { if (!context.getTranslatedIds().containsKey(heatFileName)) { context.getTranslatedIds().put(heatFileName, new HashMap<>()); } Map translatedIdsPerFile = context.getTranslatedIds().get(heatFileName); String translatedId = translatedIdsPerFile.get(resourceId); if (translatedId != null) { return Optional.of(translatedId); } Resource resource = heatOrchestrationTemplate.getResources().get(resourceId); if (resource == null) { throw new CoreException( new ResourceNotFoundInHeatFileErrorBuilder(resourceId, heatFileName).build()); } TranslateTo translateTo = generateTranslationTo(heatFileName, null, heatOrchestrationTemplate, resource, resourceId, null, context); translatedId = ResourceTranslationFactory.getInstance(resource).generateTranslatedId(translateTo); if (translatedId != null) { context.getTranslatedIds().get(heatFileName).put(resourceId, translatedId); } return Optional.ofNullable(translatedId); } private static TranslateTo generateTranslationTo(String heatFileName, ServiceTemplate serviceTemplate, HeatOrchestrationTemplate heatOrchestrationTemplate, Resource resource, String resourceId, String translatedId, TranslationContext context) { TranslateTo to = new TranslateTo(); to.setHeatFileName(heatFileName); to.setServiceTemplate(serviceTemplate); to.setHeatOrchestrationTemplate(heatOrchestrationTemplate); to.setResource(resource); to.setResourceId(resourceId); to.setTranslatedId(translatedId); to.setContext(context); return to; } protected abstract void translate(TranslateTo translateTo); protected String generateTranslatedId(TranslateTo translateTo) { isEssentialRequirementsValid(translateTo); return translateTo.getResourceId(); } protected boolean isEssentialRequirementsValid(TranslateTo translateTo) { return true; } @Override public Optional translateResource(String heatFileName, ServiceTemplate serviceTemplate, HeatOrchestrationTemplate heatOrchestrationTemplate, Resource resource, String resourceId, TranslationContext context) { Optional translatedId = getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, resourceId, context); context.getTranslatedResources().putIfAbsent(heatFileName, new HashSet<>()); if (context.getTranslatedResources().get(heatFileName).contains(resourceId)) { return translatedId; } if (!translatedId.isPresent()) { return Optional.empty(); } logger.debug("Translate- file:" + heatFileName + " resource Id:" + resourceId + " translated resource id:" + translatedId.get()); translate(new TranslateTo(heatFileName, serviceTemplate, heatOrchestrationTemplate, resource, resourceId, translatedId.get(), context)); context.getTranslatedResources().get(heatFileName).add(resourceId); if (isNodeTemplate(translatedId.get(), serviceTemplate)) { if (!context.getHeatStackGroupMembers().containsKey(heatFileName)) { context.getHeatStackGroupMembers().put(heatFileName, new HashSet<>()); } context.getHeatStackGroupMembers().get(heatFileName).add(translatedId.get()); updateResourceDependency(heatFileName, resource, heatOrchestrationTemplate, translatedId.get(), serviceTemplate, context); } return translatedId; } private void updateResourceDependency(String heatFileName, Resource resource, HeatOrchestrationTemplate heatOrchestrationTemplate, String translatedId, ServiceTemplate serviceTemplate, TranslationContext context) { if (resource.getDepends_on() == null) { return; } if (resource.getDepends_on() instanceof List) { List dependsOnList = (List) resource.getDepends_on(); for (String dependsOnResourceId : dependsOnList) { addDependOnRequirement(dependsOnResourceId, translatedId, serviceTemplate, heatFileName, heatOrchestrationTemplate, context); } } else { String dependsOnResourceId = (String) resource.getDepends_on(); addDependOnRequirement(dependsOnResourceId, translatedId, serviceTemplate, heatFileName, heatOrchestrationTemplate, context); } } private void addDependOnRequirement(String dependsOnResourceId, String nodeTemplateId, ServiceTemplate serviceTemplate, String heatFileName, HeatOrchestrationTemplate heatOrchestrationTemplate, TranslationContext context) { RequirementAssignment requirementAssignment = new RequirementAssignment(); Optional resourceTranslatedId = getResourceTranslatedId(heatFileName, heatOrchestrationTemplate, dependsOnResourceId, context); if (resourceTranslatedId.isPresent() && isNodeTemplate(resourceTranslatedId.get(), serviceTemplate)) { requirementAssignment.setNode(resourceTranslatedId.get()); requirementAssignment.setCapability(ToscaCapabilityType.NODE.getDisplayName()); requirementAssignment.setRelationship(ToscaRelationshipType.DEPENDS_ON.getDisplayName()); DataModelUtil.addRequirementAssignment( serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId), ToscaConstants.DEPENDS_ON_REQUIREMENT_ID, requirementAssignment); } } private boolean isNodeTemplate(String entryId, ServiceTemplate serviceTemplate) { return serviceTemplate.getTopology_template().getNode_templates() != null && serviceTemplate.getTopology_template().getNode_templates().get(entryId) != null; } FileData getFileData(String fileName, TranslationContext context) { List fileDataList = context.getManifest().getContent().getData(); for (FileData fileData : fileDataList) { if (TranslationService.getTypesToProcessByTranslator().contains(fileData.getType()) && fileData.getFile().equals(fileName)) { return fileData; } } return null; } NodeType getNodeTypeWithFlatHierarchy(String nodeTypeId, ServiceTemplate serviceTemplate, TranslationContext context) { NodeType nodeType; if (serviceTemplate != null && serviceTemplate.getNode_types() != null) { nodeType = serviceTemplate.getNode_types().get(nodeTypeId); if (nodeType != null) { return enrichNodeType(nodeType, serviceTemplate, context); } } Map> globalNodeTypesMap = new HashMap<>(); Collection globalNodeTypes = GlobalTypesGenerator.getGlobalTypesServiceTemplate().values(); ServiceTemplate nativeNodeTypeServiceTemplate = ToscaNativeTypesServiceTemplate.createServiceTemplate(); for (ServiceTemplate globalNodeType : globalNodeTypes) { globalNodeTypesMap .put(globalNodeType.getMetadata().getTemplate_name(), globalNodeType.getNode_types()); } if (Objects.nonNull(serviceTemplate) && MapUtils.isNotEmpty(serviceTemplate.getImports())) { for (Map.Entry entry : serviceTemplate.getImports().entrySet()) { if (globalNodeTypesMap.containsKey(entry.getKey())) { Map nodeTypes = globalNodeTypesMap.get(entry.getKey()); if (nodeTypes != null && nodeTypes.containsKey(nodeTypeId)) { return enrichNodeType(nodeTypes.get(nodeTypeId), serviceTemplate, context); } } if (context.getGlobalSubstitutionServiceTemplate() != null && context.getGlobalSubstitutionServiceTemplate().getNode_types() != null && context.getGlobalSubstitutionServiceTemplate().getNode_types() .containsKey(nodeTypeId)) { return enrichNodeType( context.getGlobalSubstitutionServiceTemplate().getNode_types().get(nodeTypeId), serviceTemplate, context); } if (nativeNodeTypeServiceTemplate.getNode_types().containsKey(nodeTypeId)) { return enrichNodeType(nativeNodeTypeServiceTemplate.getNode_types().get(nodeTypeId), serviceTemplate, context); } } } return new NodeType(); } private NodeType enrichNodeType(NodeType nodeType, ServiceTemplate serviceTemplate, TranslationContext context) { NodeType clonedNodeType; if (StringUtils.isEmpty(nodeType.getDerived_from())) { return nodeType.clone(); } clonedNodeType = enrichNodeType( getNodeTypeWithFlatHierarchy(nodeType.getDerived_from(), serviceTemplate, context), serviceTemplate, context); mergeNodeTypes(clonedNodeType, nodeType); return clonedNodeType; } private void mergeNodeTypes(NodeType target, NodeType source) { target.setDerived_from(source.getDerived_from()); target.setDescription(source.getDescription()); target.setVersion(source.getVersion()); target.setProperties( mergeMaps(target.getProperties(), source.getProperties(), PropertyDefinition.class)); target.setInterfaces( mergeMaps(target.getInterfaces(), source.getInterfaces(), InterfaceDefinition.class)); target.setArtifacts( mergeMaps(target.getArtifacts(), source.getArtifacts(), ArtifactDefinition.class)); target.setAttributes( mergeMaps(target.getAttributes(), source.getAttributes(), AttributeDefinition.class)); target.setCapabilities( mergeMaps(target.getCapabilities(), source.getCapabilities(), CapabilityDefinition.class)); target.setRequirements(mergeLists(target.getRequirements(), source.getRequirements(), RequirementDefinition.class)); } private List> mergeLists(List> target, List> source, Class value) { List> retList = new ArrayList<>(); if (Objects.nonNull(target)) { retList.addAll(target); } if (Objects.nonNull(source)) { for (Map sourceMap : source) { for (Map.Entry entry : sourceMap.entrySet()) { mergeEntryInList(entry.getKey(), entry.getValue(), retList); } } } return retList; } void mergeEntryInList(T key, S value, List> target) { boolean found = false; for (Map map : target) { if (map.containsKey(key)) { map.put(key, value); found = true; } } if (!found) { Map newMap = new HashMap<>(); newMap.put(key, value); target.add(newMap); } } private Map mergeMaps(Map target, Map source, Class value) { Map retMap = new HashMap<>(); if (MapUtils.isNotEmpty(target)) { retMap.putAll(target); } if (MapUtils.isNotEmpty(source)) { retMap.putAll(source); } return retMap; } Optional>> getResourceByTranslatedResourceId( String fileName, HeatOrchestrationTemplate heatOrchestrationTemplate, String translatedResourceId,TranslateTo translateTo,String heatResourceType) { List> list = heatOrchestrationTemplate.getResources().entrySet() .stream() .filter( entry -> getPredicatesForTranslatedIdToResourceId(fileName, heatOrchestrationTemplate, translatedResourceId, translateTo.getContext(), heatResourceType) .stream() .allMatch(p -> p.test(entry))) .collect(Collectors.toList()); if (CollectionUtils.isEmpty(list)) { return Optional.empty(); } else { return Optional.of(list); } } private List>> getPredicatesForTranslatedIdToResourceId( String fileName, HeatOrchestrationTemplate heatOrchestrationTemplate, String translatedResourceId, TranslationContext context, String heatResourceType) { List>> list = new ArrayList<>(); list.add(entry -> entry.getValue().getType().equals(heatResourceType)); list.add(entry -> { Optional resourceTranslatedId = getResourceTranslatedId(fileName, heatOrchestrationTemplate, entry.getKey(), context); return resourceTranslatedId.isPresent() && resourceTranslatedId.get().equals(translatedResourceId); }); return list; } void addBindingReqFromPortToCompute(String computeNodeTemplateId, NodeTemplate portNodeTemplate) { RequirementAssignment requirementAssignment = new RequirementAssignment(); requirementAssignment.setCapability(ToscaCapabilityType.NETWORK_BINDABLE.getDisplayName()); requirementAssignment.setRelationship(ToscaRelationshipType.NETWORK_BINDS_TO.getDisplayName()); requirementAssignment.setNode(computeNodeTemplateId); DataModelUtil.addRequirementAssignment(portNodeTemplate, ToscaConstants.BINDING_REQUIREMENT_ID, requirementAssignment); } void addLinkReqFromPortToNetwork(NodeTemplate nodeTemplate, String translatedId) { RequirementAssignment requirement = new RequirementAssignment(); requirement.setCapability(ToscaCapabilityType.NETWORK_LINKABLE.getDisplayName()); requirement.setRelationship(ToscaRelationshipType.NETWORK_LINK_TO.getDisplayName()); requirement.setNode(translatedId); DataModelUtil .addRequirementAssignment(nodeTemplate, ToscaConstants.LINK_REQUIREMENT_ID, requirement); } boolean isResourceTypeSupported(Resource resource, List supportedTypes) { return Objects.nonNull(resource) && supportedTypes.contains(resource.getType()); } }