package org.openecomp.sdc.validation.impl.validators; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.openecomp.core.validation.types.GlobalValidationContext; import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent; import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate; import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes; import org.openecomp.sdc.heat.datatypes.model.Output; import org.openecomp.sdc.heat.datatypes.model.Resource; import org.openecomp.sdc.heat.datatypes.model.ResourceReferenceFunctions; import org.openecomp.sdc.heat.services.HeatStructureUtil; import org.openecomp.sdc.heat.services.manifest.ManifestUtil; import org.openecomp.sdc.logging.api.Logger; import org.openecomp.sdc.logging.api.LoggerFactory; import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage; import org.openecomp.sdc.validation.ValidationContext; import org.openecomp.sdc.validation.base.ResourceBaseValidator; import org.openecomp.sdc.validation.type.ConfigConstants; import org.openecomp.sdc.validation.type.HeatResourceValidationContext; import org.openecomp.sdc.validation.util.ValidationUtil; 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.Set; public class HeatResourceValidator extends ResourceBaseValidator { public static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage(); private static Logger logger = (Logger) LoggerFactory.getLogger(ResourceBaseValidator.class); @Override public void init(Map properties) { super.init((Map) properties.get(ConfigConstants.Resource_Base_Validator)); } @Override public ValidationContext createValidationContext(String fileName, String envFileName, HeatOrchestrationTemplate heatOrchestrationTemplate, GlobalValidationContext globalContext) { ManifestContent manifestContent = new ManifestContent(); try { manifestContent = ValidationUtil.checkValidationPreCondition(globalContext); } catch (Exception exception) { } Set baseFiles = ManifestUtil.getBaseFiles(manifestContent); String baseFileName = CollectionUtils.isEmpty(baseFiles) ? null : baseFiles.iterator().next(); HeatOrchestrationTemplate baseHot = ValidationUtil.checkHeatOrchestrationPreCondition(baseFileName, globalContext); Set securityGroupsNamesFromBaseFileOutputs = baseFileName == null ? new HashSet<>() : checkForBaseFilePortsExistenceAndReturnSecurityGroupNamesFromOutputsIfNot (baseFileName, baseHot, globalContext); Map resourcesMap = heatOrchestrationTemplate.getResources() == null ? new HashMap<>() : heatOrchestrationTemplate.getResources(); Map outputMap = heatOrchestrationTemplate.getOutputs() == null ? new HashMap<>() : heatOrchestrationTemplate.getOutputs(); Map>>> typeToPointingResourcesMap = new HashMap<>(); initTypeRelationsMap (fileName, resourcesMap, outputMap, securityGroupsNamesFromBaseFileOutputs, typeToPointingResourcesMap, globalContext); return new HeatResourceValidationContext (heatOrchestrationTemplate, typeToPointingResourcesMap, envFileName); } private void initTypeRelationsMap(String fileName, Map resourceMap, Map outputMap, Set securityGroupsNamesFromBaseFileOutputs, Map>>> typeToPointingResourcesMap, GlobalValidationContext globalContext) { initTypeRelationsMapFromResourcesMap (fileName, resourceMap, securityGroupsNamesFromBaseFileOutputs, typeToPointingResourcesMap, globalContext); initTypeRelationsMapFromOutputsMap (fileName, resourceMap, outputMap, typeToPointingResourcesMap, globalContext); } private void initTypeRelationsMapFromOutputsMap(String fileName, Map resourceMap, Map outputMap, Map>>> typeToPointingResourcesMap, GlobalValidationContext globalContext) { for (Map.Entry outputEntry : outputMap.entrySet()) { Object outputValue = outputEntry.getValue().getValue(); Set referencedResources = HeatStructureUtil .getReferencedValuesByFunctionName(fileName, ResourceReferenceFunctions.GET_RESOURCE.getFunction(), outputValue, globalContext); updateRelationsMapWithOutputsReferences (outputEntry, resourceMap, referencedResources, typeToPointingResourcesMap); } } private void updateRelationsMapWithOutputsReferences(Map.Entry outputEntry, Map resourceMap, Set referencedResources, Map>>> typeToPointingResourcesMap) { for (String pointedResourceName : referencedResources) { Resource pointedResource = resourceMap.get(pointedResourceName); if (Objects.nonNull(pointedResource)) { initCurrentResourceTypeInMap(pointedResourceName, pointedResource.getType(), "output", typeToPointingResourcesMap); typeToPointingResourcesMap .get(pointedResource.getType()).get(pointedResourceName) .get("output").add(outputEntry.getKey()); } } } private void initTypeRelationsMapFromResourcesMap(String fileName, Map resourceMap, Set securityGroupsNamesFromBaseFileOutputs, Map>>> typeToPointingResourcesMap, GlobalValidationContext globalContext) { for (Map.Entry resourceEntry : resourceMap.entrySet()) { Resource pointingResource = resourceEntry.getValue(); Map properties = pointingResource.getProperties() == null ? new HashMap<>() : pointingResource.getProperties(); Set referencedResourcesByGetResource = getResourcesIdsPointedByCurrentResource(fileName, ResourceReferenceFunctions.GET_RESOURCE, properties, globalContext); Set referencedResourcesByGetAttr = handleGetAttrBetweenResources(properties); referencedResourcesByGetResource.addAll(referencedResourcesByGetAttr); updateRelationsMapWithCurrentResourceReferences (resourceMap, resourceEntry, referencedResourcesByGetResource, typeToPointingResourcesMap); } } private void updateRelationsMapWithSecurityGroupsFromBaseFileOutput(String fileName, Map resourcesMap, Map.Entry resourceEntry, Map properties, Set securityGroupsNamesFromBaseFileOutputs, Map>>> typeToPointingResourcesMap, GlobalValidationContext globalContext) { Set candidateSecurityGroupUsedFromBaseFile = getResourcesIdsPointedByCurrentResource (fileName, ResourceReferenceFunctions.GET_PARAM, properties, globalContext); removeNonSecurityGroupNamesFromList (candidateSecurityGroupUsedFromBaseFile, securityGroupsNamesFromBaseFileOutputs); for (String usedSecurityGroupId : candidateSecurityGroupUsedFromBaseFile) { updateMapWithRelationsBetweenResources (usedSecurityGroupId, HeatResourcesTypes.NEUTRON_SECURITY_GROUP_RESOURCE_TYPE.getHeatResource(), resourceEntry, typeToPointingResourcesMap); } } private void removeNonSecurityGroupNamesFromList( Set candidateSecurityGroupUsedFromBaseFile, Set securityGroupsNamesFromBaseFileOutputs) { Set nonSecurityGroupNames = new HashSet<>(); for (String candidateSecurityGroup : candidateSecurityGroupUsedFromBaseFile) { if (!securityGroupsNamesFromBaseFileOutputs.contains(candidateSecurityGroup)) { nonSecurityGroupNames.add(candidateSecurityGroup); } } candidateSecurityGroupUsedFromBaseFile.removeAll(nonSecurityGroupNames); } private void updateRelationsMapWithCurrentResourceReferences(Map resourceMap, Map.Entry currentResourceEntry, Set referencedResourcesFromCurrentResource, Map>>> typeToPointingResourcesMap) { for (String pointedResourceName : referencedResourcesFromCurrentResource) { Resource pointedResource = resourceMap.get(pointedResourceName); if (Objects.nonNull(pointedResource)) { String pointedResourceType = pointedResource.getType(); updateMapWithRelationsBetweenResources (pointedResourceName, pointedResourceType, currentResourceEntry, typeToPointingResourcesMap); } } } private void updateMapWithRelationsBetweenResources(String pointedResourceName, String pointedResourceType, Map.Entry currentResourceEntry, Map>>> typeToPointingResourcesMap) { initCurrentResourceTypeInMap(pointedResourceName, pointedResourceType, currentResourceEntry.getValue().getType(), typeToPointingResourcesMap); typeToPointingResourcesMap.get(pointedResourceType).get(pointedResourceName).get (currentResourceEntry.getValue().getType()).add(currentResourceEntry.getKey()); } private void initCurrentResourceTypeInMap(String resourceName, String resourceType, String pointingResourceType, Map>>> typeToPointingResourcesMap) { typeToPointingResourcesMap.putIfAbsent(resourceType, new HashMap<>()); typeToPointingResourcesMap.get(resourceType).putIfAbsent(resourceName, new HashMap<>()); typeToPointingResourcesMap.get(resourceType).get(resourceName).putIfAbsent (pointingResourceType, new ArrayList<>()); } private Set handleGetAttrBetweenResources(Map properties){ Set referencedResourcesByGetAttr = new HashSet<>(); for(Map.Entry proprtyEntry : properties.entrySet()){ referencedResourcesByGetAttr.addAll(getGetAttrReferencesInCaseOfContrail(proprtyEntry .getValue())); } return referencedResourcesByGetAttr; } private Set getGetAttrReferencesInCaseOfContrail(Object propertyValue){ Object value; Set getAttrReferences = new HashSet<>(); if (propertyValue instanceof Map) { if (((Map) propertyValue).containsKey("get_attr")) { value = ((Map) propertyValue).get("get_attr"); if (value instanceof List) { if (((List) value).size() == 2 && ((List) value).get(1).equals("fq_name")) { if (((List) value).get(0) instanceof String) { getAttrReferences.add((String) ((List) value).get(0)); return getAttrReferences; } else { logger.warn("invalid format of 'get_attr' function - " + propertyValue.toString()); } } } }else { Collection valCollection = ((Map) propertyValue).values(); for (Object entryValue : valCollection) { getAttrReferences.addAll(getGetAttrReferencesInCaseOfContrail(entryValue)); } } } else if (propertyValue instanceof List) { for (Object prop : (List) propertyValue) { getAttrReferences.addAll(getGetAttrReferencesInCaseOfContrail(prop)); } } return getAttrReferences; } private Set getResourcesIdsPointedByCurrentResource(String fileName, ResourceReferenceFunctions function, Map properties, GlobalValidationContext globalContext) { Set referencedResources = new HashSet<>(); for (Map.Entry propertyEntry : properties.entrySet()) { referencedResources .addAll(HeatStructureUtil .getReferencedValuesByFunctionName(fileName, function.getFunction(), propertyEntry.getValue(), globalContext)); } return referencedResources; } private Set checkForBaseFilePortsExistenceAndReturnSecurityGroupNamesFromOutputsIfNot( String baseFileName, HeatOrchestrationTemplate heatOrchestrationTemplate, GlobalValidationContext globalContext) { Set securityGroupsNamesFromOutputsMap = new HashSet<>(); if (heatOrchestrationTemplate != null) { Map resourceMap = heatOrchestrationTemplate.getResources(); if (!isPortResourceExistInBaseFile(resourceMap)) { getSecurityGroupsReferencedResourcesFromOutputs(securityGroupsNamesFromOutputsMap, heatOrchestrationTemplate.getOutputs(), resourceMap); } } return securityGroupsNamesFromOutputsMap; } private boolean isPortResourceExistInBaseFile(Map resourceMap) { for (Map.Entry resourceEntry : resourceMap.entrySet()) { if (resourceEntry.getValue().getType() .equals(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource())) { return true; } } return false; } private void getSecurityGroupsReferencedResourcesFromOutputs( Set securityGroupsNamesFromOutputsMap, Map outputMap, Map resourceMap) { if (MapUtils.isNotEmpty(outputMap)) { for (Map.Entry outputEntry : outputMap.entrySet()) { Object outputValue = outputEntry.getValue().getValue(); if (Objects.nonNull(outputValue) && outputValue instanceof Map) { String resourceName = (String) ((Map) outputValue) .get(ResourceReferenceFunctions.GET_RESOURCE.getFunction()); if (Objects.nonNull(resourceName)) { Resource resource = resourceMap.get(resourceName); if (Objects.nonNull(resource) && resource.getType().equals( HeatResourcesTypes.NEUTRON_SECURITY_GROUP_RESOURCE_TYPE.getHeatResource())) { securityGroupsNamesFromOutputsMap.add(outputEntry.getKey()); } } } } } } }