diff options
Diffstat (limited to 'openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java')
6 files changed, 2443 insertions, 0 deletions
diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HeatValidationService.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HeatValidationService.java new file mode 100644 index 0000000000..920724ed3b --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/HeatValidationService.java @@ -0,0 +1,323 @@ +/*- + * ============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.validation.impl.util; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.openecomp.core.utilities.yaml.YamlUtil; +import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder; +import org.openecomp.core.validation.errors.Messages; +import org.openecomp.core.validation.types.GlobalValidationContext; +import org.openecomp.sdc.datatypes.error.ErrorLevel; +import org.openecomp.sdc.heat.datatypes.model.Environment; +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.heat.datatypes.model.ResourceReferenceFunctions; +import org.openecomp.sdc.heat.services.HeatStructureUtil; +import org.openecomp.sdc.validation.impl.validators.HeatValidator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +public class HeatValidationService { + + private static final Logger logger = LoggerFactory.getLogger(HeatValidator.class); + + /** + * Check artifacts existence. + * + * @param fileName the file name + * @param artifactsNames the artifacts names + * @param globalContext the global context + */ + public static void checkArtifactsExistence(String fileName, Set<String> artifactsNames, + GlobalValidationContext globalContext) { + artifactsNames + .stream() + .filter(artifactName -> !globalContext.getFileContextMap().containsKey(artifactName)) + .forEach(artifactName -> { + globalContext + .addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_ARTIFACT.getErrorMessage(), + artifactName)); + }); + } + + + /** + * Check resource existence from resources map. + * + * @param fileName the file name + * @param resourcesNames the resources names + * @param valuesToSearchIn the values to search in + * @param globalContext the global context + */ + public static void checkResourceExistenceFromResourcesMap(String fileName, + Set<String> resourcesNames, + Collection<?> valuesToSearchIn, + GlobalValidationContext globalContext) { + if (CollectionUtils.isNotEmpty(valuesToSearchIn)) { + for (Object value : valuesToSearchIn) { + if (value instanceof Resource) { + Resource resource = (Resource) value; + //checkResourceDependsOn(fileName,resource,resourcesNames,globalContext); + + Collection<Object> resourcePropertiesValues = + resource.getProperties() == null ? null : resource.getProperties().values(); + if (CollectionUtils.isNotEmpty(resourcePropertiesValues)) { + for (Object propertyValue : resourcePropertiesValues) { + handleReferencedResources(fileName, propertyValue, resourcesNames, globalContext); + } + } + } else if (value instanceof Output) { + Output output = (Output) value; + Object outputsValue = output.getValue(); + handleReferencedResources(fileName, outputsValue, resourcesNames, globalContext); + } + } + } + } + + + private static void handleReferencedResources(String fileName, Object valueToSearchReferencesIn, + Set<String> resourcesNames, + GlobalValidationContext globalContext) { + Set<String> referencedResourcesNames = HeatStructureUtil + .getReferencedValuesByFunctionName(fileName, + ResourceReferenceFunctions.GET_RESOURCE.getFunction(), valueToSearchReferencesIn, + globalContext); + if (CollectionUtils.isNotEmpty(referencedResourcesNames)) { + HeatValidationService + .checkIfResourceReferenceExist(fileName, resourcesNames, referencedResourcesNames, + globalContext); + } + } + + + private static void checkIfResourceReferenceExist(String fileName, + Set<String> referencedResourcesNames, + Set<String> referencedResources, + GlobalValidationContext globalContext) { + referencedResources.stream() + .filter(referencedResource -> !referencedResourcesNames.contains(referencedResource)) + .forEach(referencedResource -> { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.REFERENCED_RESOURCE_NOT_FOUND.getErrorMessage(), + referencedResource)); + }); + } + + /** + * Draw files loop string. + * + * @param filesInPath the files in path + * @return the string + */ + public static String drawFilesLoop(List<String> filesInPath) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("["); + int pathSize = filesInPath.size(); + + for (int i = 0; i < pathSize; i++) { + stringBuilder.append(filesInPath.get(i)); + if (i != pathSize - 1) { + stringBuilder.append(" -- "); + } + } + if (!filesInPath.get(0).equals(filesInPath.get(pathSize - 1))) { + stringBuilder.append(" -- "); + stringBuilder.append(filesInPath.get(0)); + } + stringBuilder.append("]"); + + return stringBuilder.toString(); + } + + + /** + * Check nested parameters. + * + * @param callingNestedFileName the calling nested file name + * @param nestedFileName the nested file name + * @param resourceName the resource name + * @param globalContext the global context + * @param resourceFileProperties the resource file properties + */ + public static void checkNestedParameters(String callingNestedFileName, String nestedFileName, + String resourceName, + GlobalValidationContext globalContext, + Set<String> resourceFileProperties) { + HeatOrchestrationTemplate heatOrchestrationTemplate; + try { + heatOrchestrationTemplate = new YamlUtil() + .yamlToObject(globalContext.getFileContent(nestedFileName), + HeatOrchestrationTemplate.class); + } catch (Exception e0) { + return; + } + Set<String> nestedParametersNames = heatOrchestrationTemplate.getParameters() == null ? null + : heatOrchestrationTemplate.getParameters().keySet(); + + if (CollectionUtils.isNotEmpty(nestedParametersNames)) { + resourceFileProperties + .stream() + .filter(propertyName -> !nestedParametersNames.contains(propertyName)) + .forEach(propertyName -> globalContext + .addMessage(callingNestedFileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_PARAMETER_IN_NESTED.getErrorMessage(), + nestedFileName, resourceName, propertyName))); + } + } + + + /** + * Is nested loop exist in file boolean. + * + * @param callingFileName the calling file name + * @param nestedFileName the nested file name + * @param filesInLoop the files in loop + * @param globalContext the global context + * @return the boolean + */ + public static boolean isNestedLoopExistInFile(String callingFileName, String nestedFileName, + List<String> filesInLoop, + GlobalValidationContext globalContext) { + HeatOrchestrationTemplate nestedHeatOrchestrationTemplate; + try { + nestedHeatOrchestrationTemplate = new YamlUtil() + .yamlToObject(globalContext.getFileContent(nestedFileName), + HeatOrchestrationTemplate.class); + } catch (Exception e0) { + logger.warn("HEAT Validator will not be executed on file " + nestedFileName + + " due to illegal HEAT format"); + return false; + } + filesInLoop.add(nestedFileName); + Collection<Resource> nestedResources = + nestedHeatOrchestrationTemplate.getResources() == null ? null + : nestedHeatOrchestrationTemplate.getResources().values(); + if (CollectionUtils.isNotEmpty(nestedResources)) { + for (Resource resource : nestedResources) { + String resourceType = resource.getType(); + + if (Objects.nonNull(resourceType) && isNestedResource(resourceType)) { + return resourceType.equals(callingFileName) || !filesInLoop.contains(resourceType) + && isNestedLoopExistInFile(callingFileName, resourceType, filesInLoop, globalContext); + } + } + } + return false; + } + + + /** + * Loop over output map and validate get attr from nested. + * + * @param fileName the file name + * @param outputMap the output map + * @param heatOrchestrationTemplate the heat orchestration template + * @param globalContext the global context + */ + @SuppressWarnings("unchecked") + public static void loopOverOutputMapAndValidateGetAttrFromNested(String fileName, + Map<String, Output> outputMap, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + for (Output output : outputMap.values()) { + Object outputValue = output.getValue(); + if (outputValue != null && outputValue instanceof Map) { + Map<String, Object> outputValueMap = (Map<String, Object>) outputValue; + List<String> getAttrValue = + (List<String>) outputValueMap.get(ResourceReferenceFunctions.GET_ATTR.getFunction()); + if (!CollectionUtils.isEmpty(getAttrValue)) { + String resourceName = getAttrValue.get(0); + String propertyName = getAttrValue.get(1); + String resourceType = + getResourceTypeFromResourcesMap(resourceName, heatOrchestrationTemplate); + + if (Objects.nonNull(resourceType) + && HeatValidationService.isNestedResource(resourceType)) { + Map<String, Output> nestedOutputMap; + HeatOrchestrationTemplate nestedHeatOrchestrationTemplate; + try { + nestedHeatOrchestrationTemplate = new YamlUtil() + .yamlToObject(globalContext.getFileContent(resourceType), + HeatOrchestrationTemplate.class); + } catch (Exception e0) { + return; + } + nestedOutputMap = nestedHeatOrchestrationTemplate.getOutputs(); + + if (MapUtils.isEmpty(nestedOutputMap) || !nestedOutputMap.containsKey(propertyName)) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.GET_ATTR_NOT_FOUND.getErrorMessage(), + propertyName, resourceName)); + } + } + } + } + } + } + + + public static boolean isNestedResource(String resourceType) { + return resourceType.contains(".yaml") || resourceType.contains(".yml"); + } + + + private static String getResourceTypeFromResourcesMap(String resourceName, + HeatOrchestrationTemplate heatOrchestrationTemplate) { + return heatOrchestrationTemplate.getResources().get(resourceName).getType(); + } + + /** + * Validate env content environment. + * + * @param fileName the file name + * @param envFileName the env file name + * @param globalContext the global context + * @return the environment + */ + public static Environment validateEnvContent(String fileName, String envFileName, + GlobalValidationContext globalContext) { + Environment envContent = null; + try { + envContent = + new YamlUtil().yamlToObject(globalContext.getFileContent(envFileName), Environment.class); + } catch (Exception e0) { + return null; + } + return envContent; + } + + + public static String getResourceGroupResourceName(String resourceCallingToResourceGroup) { + return "OS::Heat::ResourceGroup in " + resourceCallingToResourceGroup; + } + +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/ResourceValidationHeatValidator.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/ResourceValidationHeatValidator.java new file mode 100644 index 0000000000..3457bed1e9 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/util/ResourceValidationHeatValidator.java @@ -0,0 +1,617 @@ +/*- + * ============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.validation.impl.util; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder; +import org.openecomp.core.validation.errors.Messages; +import org.openecomp.core.validation.types.GlobalValidationContext; +import org.openecomp.sdc.datatypes.error.ErrorLevel; +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.PolicyTypes; +import org.openecomp.sdc.heat.datatypes.model.PropertiesMapKeyTypes; +import org.openecomp.sdc.heat.datatypes.model.Resource; +import org.openecomp.sdc.heat.datatypes.model.ResourceReferenceFunctions; +import org.openecomp.sdc.heat.datatypes.model.ResourceTypeToMessageString; +import org.openecomp.sdc.heat.services.HeatStructureUtil; + +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.Objects; +import java.util.Set; + + +public class ResourceValidationHeatValidator { + + /** + * Validate resource type. + * + * @param fileName the file name + * @param baseFileName the base file name + * @param securityGroupsNamesFromBaseFileOutputs the security groups names from base file outputs + * @param heatOrchestrationTemplate the heat orchestration template + * @param globalContext the global context + */ + public static void validateResourceType(String fileName, String baseFileName, + Set<String> securityGroupsNamesFromBaseFileOutputs, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + Map<String, Resource> resourceMap = + heatOrchestrationTemplate.getResources() == null ? new HashMap<>() + : heatOrchestrationTemplate.getResources(); + Map<String, Integer> numberOfVisitsInPort = new HashMap<>(); + Set<String> resourcesNames = resourceMap.keySet(); + Set<String> sharedResourcesFromOutputMap = + getSharedResourcesNamesFromOutputs(fileName, heatOrchestrationTemplate.getOutputs(), + globalContext); + boolean isBaseFile = baseFileName != null && fileName.equals(baseFileName); + + Map<HeatResourcesTypes, List<String>> resourceTypeToNamesListMap = HeatResourcesTypes + .getListForResourceType(HeatResourcesTypes.NOVA_SERVER_GROUP_RESOURCE_TYPE, + HeatResourcesTypes.NEUTRON_SECURITY_GROUP_RESOURCE_TYPE, + HeatResourcesTypes.CONTRAIL_NETWORK_RULE_RESOURCE_TYPE); + + initResourceTypeListWithItsResourcesNames(fileName, resourceTypeToNamesListMap, resourceMap, + sharedResourcesFromOutputMap, globalContext); + initVisitedPortsMap(fileName, resourceMap, numberOfVisitsInPort, globalContext); + + + for (Map.Entry<String, Resource> resourceEntry : resourceMap.entrySet()) { + String resourceType = resourceEntry.getValue().getType(); + validateSecurityGroupsFromBaseOutput(fileName, resourceEntry, isBaseFile, + securityGroupsNamesFromBaseFileOutputs, globalContext); + checkResourceDependsOn(fileName, resourceEntry.getValue(), resourcesNames, globalContext); + + if (Objects.isNull(resourceType)) { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.INVALID_RESOURCE_TYPE.getErrorMessage(), "null", + resourceEntry.getKey())); + } else { + HeatResourcesTypes heatResourceType = HeatResourcesTypes.findByHeatResource(resourceType); + + if (heatResourceType != null) { + switch (heatResourceType) { + case NOVA_SERVER_RESOURCE_TYPE: + validateNovaServerResourceType(fileName, resourceEntry, numberOfVisitsInPort, + resourceTypeToNamesListMap + .get(HeatResourcesTypes.NOVA_SERVER_GROUP_RESOURCE_TYPE), + heatOrchestrationTemplate, globalContext); + break; + + case NOVA_SERVER_GROUP_RESOURCE_TYPE: + validateNovaServerGroupPolicy(fileName, resourceEntry, globalContext); + break; + + case RESOURCE_GROUP_RESOURCE_TYPE: + validateResourceGroupType(fileName, resourceEntry, globalContext); + break; + + case NEUTRON_PORT_RESOURCE_TYPE: + validateNeutronPortType(fileName, resourceEntry, resourceTypeToNamesListMap + .get(HeatResourcesTypes.NEUTRON_SECURITY_GROUP_RESOURCE_TYPE), globalContext); + break; + + case CONTRAIL_NETWORK_ATTACH_RULE_RESOURCE_TYPE: + validateContrailAttachPolicyType(resourceEntry, resourceTypeToNamesListMap + .get(HeatResourcesTypes.CONTRAIL_NETWORK_RULE_RESOURCE_TYPE)); + break; + default: + } + } else { + if (HeatValidationService.isNestedResource(resourceType)) { + handleNestedResourceType(fileName, resourceEntry.getKey(), resourceEntry.getValue(), + globalContext); + } + } + } + } + + checkForEmptyResourceNamesInMap(fileName, + CollectionUtils.isEmpty(securityGroupsNamesFromBaseFileOutputs), resourceTypeToNamesListMap, + globalContext); + handleOrphanPorts(fileName, numberOfVisitsInPort, globalContext); + } + + + private static void validateNovaServerResourceType(String fileName, + Map.Entry<String, Resource> resourceEntry, + Map<String, Integer> numberOfVisitsInPort, + List<String> serverGroupResourcesNames, + HeatOrchestrationTemplate + heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + validateAssignedValueForImageOrFlavorFromNova(fileName, resourceEntry, globalContext); + validateNovaServerPortBinding(fileName, resourceEntry.getValue(), numberOfVisitsInPort, + globalContext); + validateAllServerGroupsPointedByServerExistAndDefined(fileName, resourceEntry, + serverGroupResourcesNames, heatOrchestrationTemplate, globalContext); + + } + + + private static void handleNestedResourceType(String fileName, String resourceName, + Resource resource, + GlobalValidationContext globalContext) { + validateAllPropertiesMatchNestedParameters(fileName, resourceName, resource, globalContext); + validateLoopsOfNestingFromFile(fileName, resource.getType(), globalContext); + } + + + private static void validateResourceGroupType(String fileName, + Map.Entry<String, Resource> resourceEntry, + GlobalValidationContext globalContext) { + Resource resourceDef = HeatStructureUtil + .getResourceDef(fileName, resourceEntry.getKey(), resourceEntry.getValue(), globalContext); + // validateResourceGroupTypeIsSupported(fileName, resourceEntry.getKey(),resourceDef.getType(), + // globalContext); + if (resourceDef != null) { + if (Objects.nonNull(resourceDef.getType()) + && HeatValidationService.isNestedResource(resourceDef.getType())) { + handleNestedResourceType(fileName, resourceDef.getType(), resourceDef, globalContext); + } + } + } + + + private static void validateAllPropertiesMatchNestedParameters(String fileName, + String resourceName, + Resource resource, + GlobalValidationContext + globalContext) { + + String resourceType = resource.getType(); + if (globalContext.getFileContextMap().containsKey(resourceType)) { + Set<String> propertiesNames = + resource.getProperties() == null ? null : resource.getProperties().keySet(); + if (CollectionUtils.isNotEmpty(propertiesNames)) { + HeatValidationService + .checkNestedParameters(fileName, resourceType, resourceName, globalContext, + propertiesNames); + } + } else { + globalContext.addMessage(resourceType, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_NESTED_FILE.getErrorMessage(), resourceType)); + } + } + + + private static void validateAssignedValueForImageOrFlavorFromNova(String fileName, + Map.Entry<String, Resource> + resourceEntry, + GlobalValidationContext + globalContext) { + + Resource resource = resourceEntry.getValue(); + Map<String, Object> propertiesMap = resource.getProperties(); + if (propertiesMap.get(PropertiesMapKeyTypes.IMAGE.getKeyMap()) == null + && propertiesMap.get(PropertiesMapKeyTypes.FLAVOR.getKeyMap()) == null) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_IMAGE_AND_FLAVOR.getErrorMessage(), + resourceEntry.getKey())); + } + } + + + private static void validateLoopsOfNestingFromFile(String fileName, String resourceType, + GlobalValidationContext globalContext) { + List<String> filesInLoop = new ArrayList<>(Collections.singletonList(fileName)); + if (HeatValidationService + .isNestedLoopExistInFile(fileName, resourceType, filesInLoop, globalContext)) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.NESTED_LOOP.getErrorMessage(), + HeatValidationService.drawFilesLoop(filesInLoop))); + } + } + + + /* validation 22*/ + @SuppressWarnings("unchecked") + private static void validateNovaServerPortBinding(String fileName, Resource resource, + Map<String, Integer> numberOfVisitsInPort, + GlobalValidationContext globalContext) { + + Map<String, Object> propertiesMap = resource.getProperties(); + List<Object> networksList = + (List<Object>) propertiesMap.get(PropertiesMapKeyTypes.NETWORKS.getKeyMap()); + + if (CollectionUtils.isNotEmpty(networksList)) { + networksList + .stream() + .filter(networkObject -> networkObject instanceof Map) + .forEach(networkObject -> { + Map<String, Object> portValueMap = + (Map<String, Object>) ((Map) networkObject).get("port"); + if (MapUtils.isNotEmpty(portValueMap)) { + checkPortBindingFromMap(fileName, portValueMap, numberOfVisitsInPort, globalContext); + } + }); + } + } + + /* validation 23*/ + @SuppressWarnings("unchecked") + private static void validateAllServerGroupsPointedByServerExistAndDefined(String fileName, + Map.Entry<String, Resource> resourceEntry, + List<String> serverGroupNamesList, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + Map<String, Resource> resourcesMap = heatOrchestrationTemplate.getResources(); + + Map<String, Object> resourceProperties = resourceEntry.getValue().getProperties(); + Map<String, Object> schedulerHintsMap = resourceProperties == null ? null + : (Map<String, Object>) resourceProperties + .get(ResourceReferenceFunctions.SCHEDULER_HINTS.getFunction()); + + if (MapUtils.isNotEmpty(schedulerHintsMap)) { + for (Object serverGroupMap : schedulerHintsMap.values()) { + Map<String, Object> currentServerMap = (Map<String, Object>) serverGroupMap; + String serverResourceName = currentServerMap == null ? null + : (String) currentServerMap.get(ResourceReferenceFunctions.GET_RESOURCE.getFunction()); + Resource serverResource = serverResourceName == null || resourcesMap == null ? null + : resourcesMap.get(serverResourceName); + if (serverResource != null && !serverResource.getType() + .equals(HeatResourcesTypes.NOVA_SERVER_GROUP_RESOURCE_TYPE.getHeatResource())) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.SERVER_NOT_DEFINED_FROM_NOVA.getErrorMessage(), + serverResourceName, resourceEntry.getKey())); + } else { + serverGroupNamesList.remove(serverResourceName); + } + } + } + } + + + /* validation 24*/ + @SuppressWarnings("unchecked") + private static void validateNovaServerGroupPolicy(String fileName, + Map.Entry<String, Resource> resourceEntry, + GlobalValidationContext globalContext) { + + Resource resource = resourceEntry.getValue(); + List<String> policiesList = resource.getProperties() == null ? null + : (List<String>) resource.getProperties().get("policies"); + + if (CollectionUtils.isNotEmpty(policiesList)) { + if (policiesList.size() == 1) { + String policy = policiesList.get(0); + if (!PolicyTypes.isGivenPolicyValid(policy)) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.WRONG_POLICY_IN_SERVER_GROUP.getErrorMessage(), + resourceEntry.getKey())); + } + } else { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.WRONG_POLICY_IN_SERVER_GROUP.getErrorMessage(), + resourceEntry.getKey())); + } + } + } + + + private static void validateNeutronPortType(String filename, + Map.Entry<String, Resource> resourceEntry, + List<String> securityGroupResourceNameList, + GlobalValidationContext globalContext) { + validateAllSecurityGroupsAreUsed(filename, resourceEntry, securityGroupResourceNameList, + globalContext); + + } + + + @SuppressWarnings("unchecked") + private static void validateAllSecurityGroupsAreUsed(String filename, + Map.Entry<String, Resource> resourceEntry, + List<String> securityGroupResourceNameList, + GlobalValidationContext globalContext) { + Map<String, Object> propertiesMap = resourceEntry.getValue().getProperties(); + + if (MapUtils.isEmpty(propertiesMap)) { + return; + } + + Object securityGroupsValue = propertiesMap.get("security_groups"); + + if (Objects.isNull(securityGroupsValue)) { + return; + } + + if (securityGroupsValue instanceof List) { + List<Object> securityGroupsListFromCurrResource = + (List<Object>) propertiesMap.get("security_groups"); + for (Object securityGroup : securityGroupsListFromCurrResource) { + removeSecurityGroupNamesFromListByGivenFunction(filename, + ResourceReferenceFunctions.GET_RESOURCE.getFunction(), securityGroup, + securityGroupResourceNameList, globalContext); + } + } + } + + + private static void validateSecurityGroupsFromBaseOutput(String filename, + Map.Entry<String, Resource> resourceEntry, + boolean isBaseFile, + Set<String> securityGroupNamesFromBaseOutput, + GlobalValidationContext globalContext) { + if (!isBaseFile && CollectionUtils.isNotEmpty(securityGroupNamesFromBaseOutput)) { + Map<String, Object> propertiesMap = resourceEntry.getValue().getProperties(); + + if (MapUtils.isEmpty(propertiesMap)) { + return; + } + + for (Map.Entry<String, Object> propertyEntry : propertiesMap.entrySet()) { + removeSecurityGroupNamesFromListByGivenFunction(filename, + ResourceReferenceFunctions.GET_PARAM.getFunction(), propertyEntry.getValue(), + securityGroupNamesFromBaseOutput, globalContext); + } + } + } + + + private static void removeSecurityGroupNamesFromListByGivenFunction(String filename, + String functionName, + Object securityGroup, + Collection<String> securityGroupResourceNameList, + GlobalValidationContext globalContext) { + Set<String> securityGroupsNamesFromFunction = HeatStructureUtil + .getReferencedValuesByFunctionName(filename, functionName, securityGroup, globalContext); + securityGroupsNamesFromFunction.forEach(securityGroupResourceNameList::remove); + } + + + @SuppressWarnings("unchecked") + private static void validateContrailAttachPolicyType(Map.Entry<String, Resource> resourceEntry, + List<String> networkPolicyResourceNames) { + Map<String, Object> propertiesMap = resourceEntry.getValue().getProperties(); + + if (MapUtils.isNotEmpty(propertiesMap)) { + Map<String, Object> policyMap = (Map<String, Object>) propertiesMap.get("policy"); + if (MapUtils.isNotEmpty(policyMap)) { + List<Object> securityGroupList = + (List<Object>) policyMap.get(ResourceReferenceFunctions.GET_ATTR.getFunction()); + //noinspection SuspiciousMethodCalls + if (CollectionUtils.isNotEmpty(securityGroupList)) { + //noinspection SuspiciousMethodCalls + networkPolicyResourceNames.remove(securityGroupList.get(0)); + } + } + } + } + + + private static void getResourceNamesListFromSpecificResource(String filename, + List<String> resourcesNames, + HeatResourcesTypes heatResourcesType, + Map<String, Resource> resourcesMap, + Set<String> sharedResourcesFromOutputMap, + GlobalValidationContext globalContext) { + + for (Map.Entry<String, Resource> resourceEntry : resourcesMap.entrySet()) { + String resourceType = resourceEntry.getValue().getType(); + if (Objects.isNull(resourceType)) { + globalContext.addMessage(filename, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.INVALID_RESOURCE_TYPE.getErrorMessage(), null, + resourceEntry.getKey())); + } else { + if (resourceType.equals(heatResourcesType.getHeatResource()) + && !isSharedResource(resourceEntry.getKey(), sharedResourcesFromOutputMap)) { + resourcesNames.add(resourceEntry.getKey()); + } + } + } + } + + + private static boolean isSharedResource(String resourceName, + Set<String> sharedResourcesFromOutputMap) { + return !CollectionUtils.isEmpty(sharedResourcesFromOutputMap) + && sharedResourcesFromOutputMap.contains(resourceName); + } + + /** + * Handle not empty resource names list. + * + * @param fileName the file name + * @param resourcesNameList the resources name list + * @param securityOrServerGroup the security or server group + * @param globalContext the global context + */ + public static void handleNotEmptyResourceNamesList(String fileName, + Collection<String> resourcesNameList, + String securityOrServerGroup, + GlobalValidationContext globalContext) { + if (CollectionUtils.isNotEmpty(resourcesNameList)) { + resourcesNameList.forEach(name -> + globalContext + .addMessage( + fileName, + ErrorLevel.WARNING, + ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.SERVER_OR_SECURITY_GROUP_NOT_IN_USE.getErrorMessage(), + securityOrServerGroup, name))); + } + } + + + private static void initVisitedPortsMap(String filename, Map<String, Resource> resourceMap, + Map<String, Integer> numberOfVisitsInPort, + GlobalValidationContext globalContext) { + for (Map.Entry<String, Resource> resourceEntry : resourceMap.entrySet()) { + String resourceType = resourceEntry.getValue().getType(); + + if (Objects.isNull(resourceType)) { + globalContext.addMessage(filename, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.INVALID_RESOURCE_TYPE.getErrorMessage(), "null", + resourceEntry.getKey())); + } else { + if (resourceType.equals(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource())) { + numberOfVisitsInPort.put(resourceEntry.getKey(), 0); + } + } + } + } + + private static boolean checkIfPortWasVisited(String resourcePortName, + Map<String, Integer> numberOfVisitsInPort) { + return numberOfVisitsInPort.containsKey(resourcePortName) + && numberOfVisitsInPort.get(resourcePortName) == 1; + } + + + private static void incrementNumberOfVisitsInPort(String resourcePortName, + Map<String, Integer> numberOfVisitsInPort) { + if (numberOfVisitsInPort.containsKey(resourcePortName)) { + numberOfVisitsInPort.put(resourcePortName, numberOfVisitsInPort.get(resourcePortName) + 1); + } + } + + + private static void handleOrphanPorts(String fileName, Map<String, Integer> numberOfVisitsInPort, + GlobalValidationContext globalContext) { + numberOfVisitsInPort + .entrySet() + .stream() + .filter(entry -> entry.getValue() == 0) + .forEach(entry -> + globalContext + .addMessage( + fileName, + ErrorLevel.WARNING, + ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.PORT_NO_BIND_TO_ANY_NOVA_SERVER.getErrorMessage(), + entry.getKey()))); + } + + @SuppressWarnings("unchecked") + private static void checkResourceDependsOn(String fileName, Resource resource, + Set<String> resourcesNames, + GlobalValidationContext globalContext) { + Object dependencies = resource.getDepends_on(); + if (dependencies instanceof Collection) { + ((Collection<String>) dependencies) + .stream() + .filter(resource_id -> !resourcesNames.contains(resource_id)) + .forEach(resource_id -> globalContext.addMessage(fileName, ErrorLevel.ERROR, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_RESOURCE_IN_DEPENDS_ON.getErrorMessage(), + (String) resource_id))); + } else if (dependencies instanceof String) { + if (!resourcesNames.contains(dependencies)) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_RESOURCE_IN_DEPENDS_ON.getErrorMessage(), + (String) dependencies)); + } + } + } + + + private static void checkPortBindingFromMap(String fileName, Map<String, Object> portValueMap, + Map<String, Integer> numberOfVisitsInPort, + GlobalValidationContext globalContext) { + String resourcePortName = + (String) portValueMap.get(ResourceReferenceFunctions.GET_RESOURCE.getFunction()); + if (checkIfPortWasVisited(resourcePortName, numberOfVisitsInPort)) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MORE_THAN_ONE_BIND_FROM_NOVA_TO_PORT.getErrorMessage(), + (String) portValueMap.get(ResourceReferenceFunctions.GET_RESOURCE.getFunction()))); + } else { + incrementNumberOfVisitsInPort(resourcePortName, numberOfVisitsInPort); + } + } + + + private static void initResourceTypeListWithItsResourcesNames(String filename, + Map<HeatResourcesTypes, List<String>> resourcesTypesListMap, + Map<String, Resource> resourcesMap, + Set<String> sharedResourcesFromOutputsMap, + GlobalValidationContext globalContext) { + for (Map.Entry<HeatResourcesTypes, List<String>> resourcesTypesToListEntry + : resourcesTypesListMap.entrySet()) { + HeatResourcesTypes currentType = resourcesTypesToListEntry.getKey(); + List<String> currNamesList = new ArrayList<>(); + getResourceNamesListFromSpecificResource(filename, currNamesList, currentType, resourcesMap, + sharedResourcesFromOutputsMap, globalContext); + resourcesTypesListMap.put(currentType, currNamesList); + } + } + + + private static void checkForEmptyResourceNamesInMap(String fileName, + boolean isBaseFileContainPorts, + Map<HeatResourcesTypes, List<String>> resourcesTypesListMap, + GlobalValidationContext globalContext) { + if (isBaseFileContainPorts) { + for (Map.Entry<HeatResourcesTypes, List<String>> resourcesTypesListEntry + : resourcesTypesListMap.entrySet()) { + handleNotEmptyResourceNamesList(fileName, resourcesTypesListEntry.getValue(), + ResourceTypeToMessageString + .getTypeForMessageFromResourceType(resourcesTypesListEntry.getKey()), + globalContext); + } + } + } + + + private static Set<String> getSharedResourcesNamesFromOutputs(String filename, + Map<String, Output> outputsMap, + GlobalValidationContext globalContext) { + Set<String> sharedResources = new HashSet<>(); + + if (MapUtils.isEmpty(outputsMap)) { + return null; + } + + for (Map.Entry<String, Output> outputEntry : outputsMap.entrySet()) { + Output output = outputEntry.getValue(); + Object valueObject = output.getValue(); + if (valueObject instanceof Map) { + Map<String, Object> outputValueMap = (Map<String, Object>) valueObject; + Object getResourceValue = + outputValueMap.get(ResourceReferenceFunctions.GET_RESOURCE.getFunction()); + if (Objects.nonNull(getResourceValue)) { + if (getResourceValue instanceof String) { + String resourceName = + (String) outputValueMap.get(ResourceReferenceFunctions.GET_RESOURCE.getFunction()); + sharedResources.add(resourceName); + } else { + globalContext.addMessage(filename, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.INVALID_GET_RESOURCE_SYNTAX.getErrorMessage(), + getResourceValue.toString())); + } + } + + } + } + + return sharedResources; + } +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/EcompGuideLineValidator.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/EcompGuideLineValidator.java new file mode 100644 index 0000000000..5be56e4b38 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/EcompGuideLineValidator.java @@ -0,0 +1,784 @@ +/*- + * ============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.validation.impl.validators; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.openecomp.core.utilities.CommonMethods; +import org.openecomp.core.utilities.yaml.YamlUtil; +import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder; +import org.openecomp.core.validation.errors.Messages; +import org.openecomp.core.validation.interfaces.Validator; +import org.openecomp.core.validation.types.GlobalValidationContext; +import org.openecomp.sdc.common.utils.AsdcCommon; +import org.openecomp.sdc.datatypes.error.ErrorLevel; +import org.openecomp.sdc.datatypes.model.heat.ForbiddenHeatResourceTypes; +import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes; +import org.openecomp.sdc.heat.datatypes.manifest.FileData; +import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent; +import org.openecomp.sdc.heat.datatypes.model.Environment; +import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate; +import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes; +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 java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.TreeMap; +import java.util.regex.Pattern; + +public class EcompGuideLineValidator extends HeatValidator implements Validator { + @Override + public void validate(GlobalValidationContext globalContext) { + + ManifestContent manifestContent; + try { + manifestContent = checkValidationPreCondition(globalContext); + } catch (Exception exception) { + return; + } + + //global validations + Set<String> baseFiles = validateManifest(manifestContent, globalContext); + + Map<String, FileData.Type> fileTypeMap = ManifestUtil.getFileTypeMap(manifestContent); + Map<String, FileData> fileEnvMap = ManifestUtil.getFileAndItsEnv(manifestContent); + globalContext + .getFiles() + .stream() + .filter(fileName -> FileData + .isHeatFile(fileTypeMap.get(fileName))) + .forEach(fileName -> validate(fileName, + fileEnvMap.get(fileName) != null ? fileEnvMap.get(fileName).getFile() : null, + fileTypeMap, baseFiles, globalContext)); + } + + private void validate(String fileName, String envFileName, Map<String, FileData.Type> fileTypeMap, + Set<String> baseFiles, GlobalValidationContext globalContext) { + HeatOrchestrationTemplate heatOrchestrationTemplate = + checkHeatOrchestrationPreCondition(fileName, globalContext); + if (heatOrchestrationTemplate == null) { + return; + } + + validateBaseFile(fileName, baseFiles, heatOrchestrationTemplate, globalContext); + validateHeatVolumeFile(fileName, fileTypeMap, heatOrchestrationTemplate, globalContext); + validateHeatNamingConvention(fileName, heatOrchestrationTemplate, globalContext); + validateHeatNovaResource(fileName, envFileName, heatOrchestrationTemplate, globalContext); + validateResourceTypeIsForbidden(fileName, heatOrchestrationTemplate, globalContext); + validateFixedIpsNamingConvention(fileName, heatOrchestrationTemplate, globalContext); + } + + private void validateHeatNovaResource(String fileName, String envFileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + Map<String, String> uniqueResourcePortNetworkRole = new HashMap<>(); + //if no resources exist return + if (heatOrchestrationTemplate.getResources() == null + || heatOrchestrationTemplate.getResources().size() == 0) { + return; + } + + heatOrchestrationTemplate + .getResources() + .entrySet() + .stream() + .filter(entry -> entry.getValue().getType() + .equals(HeatResourcesTypes.NOVA_SERVER_RESOURCE_TYPE.getHeatResource())) + .forEach(entry -> validateNovaServerResourceType(entry.getKey(), fileName, envFileName, + entry, uniqueResourcePortNetworkRole, heatOrchestrationTemplate, globalContext)); + } + + private void validateNovaServerResourceType(String resourceId, String fileName, + String envFileName, + Map.Entry<String, Resource> resourceEntry, + Map<String, String> uniqueResourcePortNetworkRole, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalValidationContext) { + validateNovaServerResourceMetaData(fileName, resourceId, + heatOrchestrationTemplate.getResources().get(resourceId), globalValidationContext); + validateNovaServerResourceNetworkUniqueRole(fileName, resourceId, heatOrchestrationTemplate, + globalValidationContext); + validateNovaServerNamingConvention(fileName, envFileName, resourceEntry, + globalValidationContext); + validateNovaServerAvailabilityZoneName(fileName, resourceEntry, globalValidationContext); + validateImageAndFlavorFromNovaServer(fileName, resourceEntry, globalValidationContext); + } + + @SuppressWarnings("unchecked") + private void validateNovaServerResourceMetaData(String fileName, String resourceId, + Resource resource, + GlobalValidationContext globalValidationContext) { + Map<String, Object> novaServerProp = resource.getProperties(); + Object novaServerPropMetadata; + if (MapUtils.isNotEmpty(novaServerProp)) { + novaServerPropMetadata = novaServerProp.get("metadata"); + if (novaServerPropMetadata == null) { + globalValidationContext.addMessage( + fileName, + ErrorLevel.WARNING, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_NOVA_SERVER_METADATA.getErrorMessage(), + resourceId)); + } else if (novaServerPropMetadata instanceof Map) { + TreeMap<String, Object> propertyMap = new TreeMap(new Comparator<String>() { + + @Override + public int compare(String o1, String o2) { + return o1.compareToIgnoreCase(o2); + } + + @Override + public boolean equals(Object obj) { + return false; + } + }); + propertyMap.putAll((Map) novaServerPropMetadata); + if (!propertyMap.containsKey("vf_module_id")) { + globalValidationContext.addMessage(fileName, ErrorLevel.WARNING, + ErrorMessagesFormatBuilder.getErrorWithParameters( + Messages.MISSING_NOVA_SERVER_VF_MODULE_ID.getErrorMessage(), resourceId)); + } + if (!propertyMap.containsKey("vnf_id")) { + globalValidationContext.addMessage(fileName, ErrorLevel.WARNING, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_NOVA_SERVER_VNF_ID.getErrorMessage(), + resourceId)); + } + } + } + } + + private void validateNovaServerResourceNetworkUniqueRole(String fileName, String resourceId, + HeatOrchestrationTemplate + heatOrchestrationTemplate, + GlobalValidationContext + globalValidationContext) { + + String network; + String role; + Map<String, String> uniqueResourcePortNetworkRole = new HashMap<>(); + + Object propertyNetworkValue = + heatOrchestrationTemplate.getResources().get(resourceId).getProperties().get("networks"); + if (propertyNetworkValue != null && propertyNetworkValue instanceof List) { + List<String> portResourceIdList = + getNovaNetworkPortResourceList(fileName, (List) propertyNetworkValue, + globalValidationContext); + for (String portResourceId : portResourceIdList) { + Resource portResource = heatOrchestrationTemplate.getResources().get(portResourceId); + if (portResource != null && portResource.getType() + .equals(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource())) { + Map portNetwork = + getPortNetwork(fileName, resourceId, portResource, globalValidationContext); + if (Objects.nonNull(portNetwork)) { + network = (String) portNetwork.get("get_param"); + if (Objects.nonNull(network)) { + role = getNetworkRole(network); + if (role != null && uniqueResourcePortNetworkRole.containsKey(role)) { + globalValidationContext.addMessage(fileName, ErrorLevel.WARNING, + ErrorMessagesFormatBuilder.getErrorWithParameters( + Messages.RESOURCE_CONNECTED_TO_TWO_EXTERNAL_NETWORKS_WITH_SAME_ROLE + .getErrorMessage(), resourceId, role)); + } else { + uniqueResourcePortNetworkRole.put(role, portResourceId); + } + } + } + } + } + } + } + + + private Map getPortNetwork(String fileName, String resourceId, Resource portResource, + GlobalValidationContext globalValidationContext) { + Object portNetwork = portResource.getProperties().get("network_id"); + if (portNetwork == null) { + portNetwork = portResource.getProperties().get("network"); + } + if (!(portNetwork instanceof Map)) { + globalValidationContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_GET_PARAM.getErrorMessage(), + "network or network_id", resourceId)); + return null; + } + return (Map) portNetwork; + } + + private List<String> getNovaNetworkPortResourceList(String filename, List propertyNetworkValue, + GlobalValidationContext globalContext) { + List<String> portResourceIdList = new ArrayList<>(); + for (Object propValue : propertyNetworkValue) { + Object portPropValue = ((Map) propValue).get("port"); + Collection<String> portResourceIds = HeatStructureUtil + .getReferencedValuesByFunctionName(filename, "get_resource", portPropValue, + globalContext); + if (portResourceIds != null) { + portResourceIdList.addAll(portResourceIds); + } + } + + return portResourceIdList; + } + + private String getNetworkRole(String network) { + if (network == null) { + return null; + } + if (network.contains("_net_id")) { + return network.substring(0, network.indexOf("_net_id")); + } else if (network.contains("net_name")) { + return network.substring(0, network.indexOf("_net_name")); + } else if (network.contains("net_fqdn")) { + return network.substring(0, network.indexOf("_net_fqdn")); + } + return null; + } + + private void validateHeatNamingConvention(String fileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + validatePortNetworkNamingConvention(fileName, heatOrchestrationTemplate, globalContext); + } + + private void validatePortNetworkNamingConvention(String fileName, + HeatOrchestrationTemplate + heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + if (MapUtils.isEmpty(heatOrchestrationTemplate.getResources())) { + return; + } + String[] regexList = new String[]{".*_net_id", ".*_net_name", ".*_net_fqdn"}; + + heatOrchestrationTemplate + .getResources() + .entrySet() + .stream() + .filter(entry -> entry.getValue().getType() != null && entry.getValue().getType() + .equals(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource())) + .forEach(entry -> entry.getValue() + .getProperties() + .entrySet() + .stream() + .filter(propertyEntry -> propertyEntry != null + && (propertyEntry.getKey().toLowerCase().equals("network".toLowerCase()) + || + propertyEntry.getKey().equals("network_id"))) + .forEach(propertyEntry -> validateParamNamingConvention(fileName, entry.getKey(), + propertyEntry.getValue(), regexList, + Messages.NETWORK_PARAM_NOT_ALIGNED_WITH_GUIDE_LINE, globalContext))); + } + + private void validateParamNamingConvention(String fileName, String resourceId, + Object propertyValue, String[] regexList, + Messages message, + GlobalValidationContext globalContext) { + Object paramName; + if (propertyValue instanceof Map) { + paramName = ((Map) propertyValue).get("get_param"); + if (paramName instanceof String) { + if (!evalPattern((String) paramName, regexList)) { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters(message.getErrorMessage(), (String) paramName, resourceId)); + } + } + } else { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_GET_PARAM.getErrorMessage(), + "network or network_id", resourceId)); + } + } + + private boolean evalPattern(Object paramVal, String[] regexList) { + String value = ""; + if (paramVal instanceof String) { + value = ((String) paramVal); + } + if (paramVal instanceof Integer) { + value = paramVal.toString(); + } + return evalPattern(value, regexList); + } + + private boolean evalPattern(String paramVal, String[] regexList) { + + for (String regex : regexList) { + if (Pattern.matches(regex, paramVal)) { + return true; + } + } + + return false; + } + + + private void validateHeatVolumeFile(String fileName, Map<String, FileData.Type> fileTypeMap, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + //if not heat volume return + if (!fileTypeMap.get(fileName).equals(FileData.Type.HEAT_VOL)) { + return; + } + + //if no resources exist return + if (heatOrchestrationTemplate.getResources() == null + || heatOrchestrationTemplate.getResources().size() == 0) { + return; + } + + Set<String> expectedExposedResources = new HashSet<>(); + Set<String> actualExposedResources = new HashSet<>(); + heatOrchestrationTemplate.getResources() + .entrySet() + .stream() + .filter(entry -> entry.getValue().getType() + .equals(HeatResourcesTypes.CINDER_VOLUME_RESOURCE_TYPE.getHeatResource())) + .forEach(entry -> expectedExposedResources.add(entry.getKey())); + + if (heatOrchestrationTemplate.getOutputs() != null) { + + heatOrchestrationTemplate.getOutputs().entrySet() + .stream() + .filter(entry -> isPropertyValueGetResource(fileName, entry.getValue().getValue(), + globalContext)) + .forEach(entry -> actualExposedResources.add( + getResourceIdFromPropertyValue(fileName, entry.getValue().getValue(), + globalContext))); + } + + actualExposedResources.stream().forEach(expectedExposedResources::remove); + + if (expectedExposedResources.size() > 0) { + expectedExposedResources + .stream() + .forEach(name -> globalContext.addMessage(fileName, ErrorLevel.WARNING, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.VOLUME_HEAT_NOT_EXPOSED.getErrorMessage(), + name))); + } + } + + private void validateBaseFile(String fileName, Set<String> baseFiles, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + + //if not base return + if (baseFiles == null || !baseFiles.contains(fileName)) { + return; + } + + //if no resources exist return + if (heatOrchestrationTemplate.getResources() == null + || heatOrchestrationTemplate.getResources().size() == 0) { + return; + } + + Set<String> expectedExposedResources = new HashSet<>(); + Set<String> actualExposedResources = new HashSet<>(); + heatOrchestrationTemplate.getResources() + .entrySet() + .stream() + .filter(entry -> isExpectedToBeExposed(entry.getValue().getType())) + .forEach(entry -> expectedExposedResources.add(entry.getKey())); + + if (heatOrchestrationTemplate.getOutputs() != null) { + + heatOrchestrationTemplate.getOutputs().entrySet() + .stream() + .filter(entry -> isPropertyValueGetResource(fileName, entry.getValue().getValue(), + globalContext)) + .forEach(entry -> actualExposedResources.add( + getResourceIdFromPropertyValue(fileName, entry.getValue().getValue(), + globalContext))); + } + actualExposedResources.stream().forEach(expectedExposedResources::remove); + + if (expectedExposedResources.size() > 0) { + expectedExposedResources + .stream() + .forEach(name -> globalContext.addMessage(fileName, ErrorLevel.WARNING, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.RESOURCE_NOT_DEFINED_IN_OUTPUT.getErrorMessage(), + name))); + } + } + + private void validateResourceTypeIsForbidden(String fileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + if (MapUtils.isEmpty(heatOrchestrationTemplate.getResources())) { + return; + } + + heatOrchestrationTemplate.getResources() + .entrySet() + .stream() + .filter(entry -> + ForbiddenHeatResourceTypes.findByForbiddenHeatResource(entry.getValue().getType()) + != null) + .filter(entry -> ForbiddenHeatResourceTypes + .findByForbiddenHeatResource(entry.getValue().getType()) + .equals(ForbiddenHeatResourceTypes.HEAT_FLOATING_IP_TYPE)) + .forEach(entry -> globalContext.addMessage(fileName, ErrorLevel.WARNING, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.FLOATING_IP_NOT_IN_USE.getErrorMessage(), + entry.getKey()))); + } + + + private void validateFixedIpsNamingConvention(String fileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + if (MapUtils.isEmpty(heatOrchestrationTemplate.getResources())) { + return; + } + + heatOrchestrationTemplate.getResources() + .entrySet() + .stream() + .filter(entry -> HeatResourcesTypes.findByHeatResource(entry.getValue().getType()) != null) + .filter(entry -> HeatResourcesTypes.findByHeatResource(entry.getValue().getType()) + .equals(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE)) + .forEach(entry -> checkNeutronPortFixedIpsName(fileName, entry, globalContext)); + } + + private void validateImageAndFlavorFromNovaServer(String fileName, + Map.Entry<String, Resource> resourceEntry, + GlobalValidationContext globalContext) { + if (MapUtils.isEmpty(resourceEntry.getValue().getProperties())) { + return; + } + + String[] imageOrFlavorAsParameters = new String[]{"image", "flavor"}; + Map<String, Object> propertiesMap = resourceEntry.getValue().getProperties(); + + for (String imageOrFlavor : imageOrFlavorAsParameters) { + checkImageAndFlavorNames(fileName, imageOrFlavor, resourceEntry.getKey(), propertiesMap, + globalContext); + } + } + + private void checkImageAndFlavorNames(String fileName, String imageOrFlavor, String resourceId, + Map<String, Object> propertiesMap, + GlobalValidationContext globalContext) { + Object nameValue = + propertiesMap.get(imageOrFlavor) == null ? null : propertiesMap.get(imageOrFlavor); + String[] regexList = new String[]{".*_" + imageOrFlavor + "_name"}; + + if (Objects.nonNull(nameValue)) { + if (nameValue instanceof Map) { + String imageOrFlavorName = getWantedNameFromPropertyValueGetParam(nameValue); + if (Objects.nonNull(imageOrFlavorName)) { + if (!evalPattern(imageOrFlavorName, regexList)) { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.WRONG_IMAGE_OR_FLAVOR_NAME_NOVA_SERVER.getErrorMessage(), + imageOrFlavor, resourceId)); + } + } + } else { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_GET_PARAM.getErrorMessage(), imageOrFlavor, + resourceId)); + } + } + } + + + @SuppressWarnings("unchecked") + private void checkNeutronPortFixedIpsName(String fileName, + Map.Entry<String, Resource> resourceEntry, + GlobalValidationContext globalContext) { + String[] regexList = + new String[]{"[^_]+_[^_]+_ips", "[^_]+_[^_]+_v6_ips", "[^_]+_[^_]+_ip_(\\d+)", + "[^_]+_[^_]+_v6_ip_(\\d+)"}; + + if (MapUtils.isEmpty(resourceEntry.getValue().getProperties())) { + return; + } + + Map<String, Object> propertiesMap = resourceEntry.getValue().getProperties(); + Object fixedIps = propertiesMap.get("fixed_ips"); + if (Objects.nonNull(fixedIps) && fixedIps instanceof List) { + List<Object> fixedIpsList = (List<Object>) fixedIps; + for (Object fixedIpsObject : fixedIpsList) { + Map.Entry<String, Object> fixedIpsEntry = + ((Map<String, Object>) fixedIpsObject).entrySet().iterator().next(); + if (Objects.nonNull(fixedIpsEntry)) { + if (fixedIpsEntry.getValue() instanceof Map) { + String fixedIpsName = getWantedNameFromPropertyValueGetParam(fixedIpsEntry.getValue()); + if (Objects.nonNull(fixedIpsName)) { + if (!evalPattern(fixedIpsName, regexList)) { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.FIXED_IPS_NOT_ALIGNED_WITH_GUIDE_LINES.getErrorMessage(), + resourceEntry.getKey())); + } + } + } else { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_GET_PARAM.getErrorMessage(), "fixed_ips", + resourceEntry.getKey())); + } + } + } + } + } + + + private void validateNovaServerNamingConvention(String fileName, String envFileName, + Map.Entry<String, Resource> resourceEntry, + GlobalValidationContext globalContext) { + if (MapUtils.isEmpty(resourceEntry.getValue().getProperties())) { + return; + } + + checkIfNovaNameByGuidelines(fileName, envFileName, resourceEntry, globalContext); + } + + private void checkIfNovaNameByGuidelines(String fileName, String envFileName, + Map.Entry<String, Resource> resourceEntry, + GlobalValidationContext globalContext) { + if (MapUtils.isEmpty(resourceEntry.getValue().getProperties())) { + return; + } + + Object novaServerName = resourceEntry.getValue().getProperties().get("name"); + Map novaNameMap; + String novaName; + if (Objects.nonNull(novaServerName)) { + if (novaServerName instanceof Map) { + novaNameMap = (Map) novaServerName; + Object novaNameGetParam = + novaNameMap.get(ResourceReferenceFunctions.GET_PARAM.getFunction()) == null ? null + : novaNameMap.get(ResourceReferenceFunctions.GET_PARAM.getFunction()); + if (Objects.nonNull(novaNameGetParam)) { + checkNovaNameGetParamValueMap(fileName, novaNameGetParam, resourceEntry, globalContext); + novaName = novaNameGetParam instanceof List ? (String) ((List) novaNameGetParam).get(0) + : (String) novaNameGetParam; + checkIfNovaNameParameterInEnvIsStringOrList(fileName, envFileName, resourceEntry, + novaName, globalContext); + } + } else { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_GET_PARAM.getErrorMessage(), + "nova server name", resourceEntry.getKey())); + } + } + + } + + private void checkIfNovaNameParameterInEnvIsStringOrList(String fileName, String envFileName, + Map.Entry<String, Resource> + resourceEntry, + String novaServerName, + GlobalValidationContext globalContext) { + if (Objects.nonNull(envFileName)) { + Environment environment = validateEnvContent(envFileName, globalContext); + + if (environment != null && MapUtils.isNotEmpty(environment.getParameters())) { + Object novaServerNameEnvValue = + environment.getParameters().containsKey(novaServerName) ? environment.getParameters() + .get(novaServerName) : null; + if (Objects.nonNull(novaServerNameEnvValue)) { + if (!DefinedHeatParameterTypes + .isNovaServerEnvValueIsFromRightType(novaServerNameEnvValue)) { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.NOVA_SERVER_NAME_NOT_ALIGNED_WITH_GUIDE_LINES.getErrorMessage(), + resourceEntry.getKey())); + } + } + } + } + } + + + private void validateNovaServerAvailabilityZoneName(String fileName, + Map.Entry<String, Resource> resourceEntry, + GlobalValidationContext globalContext) { + String[] regexList = new String[]{"availability_zone_(\\d+)"}; + + if (MapUtils.isEmpty(resourceEntry.getValue().getProperties())) { + return; + } + + Object availabilityZoneMap = + resourceEntry.getValue().getProperties().containsKey("availability_zone") ? resourceEntry + .getValue().getProperties().get("availability_zone") : null; + + if (Objects.nonNull(availabilityZoneMap)) { + if (availabilityZoneMap instanceof Map) { + String availabilityZoneName = getWantedNameFromPropertyValueGetParam(availabilityZoneMap); + + if (availabilityZoneName != null) { + if (!evalPattern(availabilityZoneName, regexList)) { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.AVAILABILITY_ZONE_NOT_ALIGNED_WITH_GUIDE_LINES.getErrorMessage(), + resourceEntry.getKey())); + } + } + } else { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSING_GET_PARAM.getErrorMessage(), + "availability_zone", resourceEntry.getKey())); + } + } + + } + + @SuppressWarnings("unchecked") + private void checkNovaNameGetParamValueMap(String fileName, Object getParamValue, + Map.Entry<String, Resource> resourceEntry, + GlobalValidationContext globalContext) { + if (getParamValue instanceof List) { + List<Object> getParamNameList = (List) getParamValue; + String[] regexName = new String[]{".*_names"}; + isNovaNameAsListLegal(fileName, getParamNameList, regexName, resourceEntry, globalContext); + } else if (getParamValue instanceof String) { + String[] regexName = new String[]{".*_name_(\\d+)"}; + isNovaNameAsStringLegal(fileName, (String) getParamValue, regexName, resourceEntry, + globalContext); + } + + } + + + private void isNovaNameAsListLegal(String fileName, List<Object> getParamNameList, + String[] regexName, Map.Entry<String, Resource> resourceEntry, + GlobalValidationContext globalContext) { + + if (getParamNameList.size() != 2 || !evalPattern(getParamNameList.get(0), regexName)) { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.NOVA_SERVER_NAME_NOT_ALIGNED_WITH_GUIDE_LINES.getErrorMessage(), + resourceEntry.getKey())); + } + } + + private boolean isNovaNameAsStringLegal(String fileName, String novaName, String[] regexName, + Map.Entry<String, Resource> resourceEntry, + GlobalValidationContext globalContext) { + if (!evalPattern(novaName, regexName)) { + globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.NOVA_SERVER_NAME_NOT_ALIGNED_WITH_GUIDE_LINES.getErrorMessage(), + resourceEntry.getKey())); + return false; + } + return true; + } + + private String getWantedNameFromPropertyValueGetParam(Object value) { + Set<String> paramName = HeatStructureUtil + .getReferencedValuesByFunctionName(null, ResourceReferenceFunctions.GET_PARAM.getFunction(), + value, null); + if (paramName != null && CollectionUtils.isNotEmpty(paramName)) { + return (String) paramName.toArray()[0]; + } + return null; + } + + private String getResourceIdFromPropertyValue(String filename, Object value, + GlobalValidationContext globalContext) { + Set<String> referenceValues = HeatStructureUtil.getReferencedValuesByFunctionName(filename, + ResourceReferenceFunctions.GET_RESOURCE.getFunction(), value, globalContext); + if (referenceValues != null && CollectionUtils.isNotEmpty(referenceValues)) { + return (String) referenceValues.toArray()[0]; + } + return null; + } + + private boolean isPropertyValueGetResource(String filename, Object value, + GlobalValidationContext globalContext) { + Set<String> referenceValues = HeatStructureUtil.getReferencedValuesByFunctionName(filename, + ResourceReferenceFunctions.GET_RESOURCE.getFunction(), value, globalContext); + return referenceValues != null && (referenceValues.size() > 0); + } + + private boolean isExpectedToBeExposed(String type) { + return HeatResourcesTypes.isResourceExpectedToBeExposed(type); + } + + private Set<String> validateManifest(ManifestContent manifestContent, + GlobalValidationContext globalContext) { + Set<String> baseFiles = ManifestUtil.getBaseFiles(manifestContent); + if (baseFiles == null || baseFiles.size() == 0) { + globalContext.addMessage( + AsdcCommon.MANIFEST_NAME, + ErrorLevel.WARNING, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MISSIN_BASE_HEAT_FILE.getErrorMessage())); + } else if (baseFiles.size() > 1) { + String baseFileList = getElementListAsString(baseFiles); + globalContext.addMessage( + AsdcCommon.MANIFEST_NAME, + ErrorLevel.WARNING, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.MULTI_BASE_HEAT_FILE.getErrorMessage(), + baseFileList)); + } + return baseFiles; + } + + private String getElementListAsString(Set<String> elementCollection) { + + return "[" + CommonMethods.collectionToCommaSeparatedString(elementCollection) + "]"; + } + + + private Environment validateEnvContent(String envFileName, + GlobalValidationContext globalContext) { + Environment envContent; + try { + envContent = + new YamlUtil().yamlToObject(globalContext.getFileContent(envFileName), Environment.class); + } catch (Exception exception) { + return null; + } + return envContent; + } + + private HeatOrchestrationTemplate checkHeatOrchestrationPreCondition(String fileName, + GlobalValidationContext + globalContext) { + HeatOrchestrationTemplate heatOrchestrationTemplate; + try { + heatOrchestrationTemplate = new YamlUtil() + .yamlToObject(globalContext.getFileContent(fileName), HeatOrchestrationTemplate.class); + + } catch (Exception exception) { + return null; + } + return heatOrchestrationTemplate; + } +}
\ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HeatValidator.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HeatValidator.java new file mode 100644 index 0000000000..c287394a54 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HeatValidator.java @@ -0,0 +1,469 @@ +/*- + * ============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.validation.impl.validators; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.openecomp.core.utilities.json.JsonUtil; +import org.openecomp.core.utilities.yaml.YamlUtil; +import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder; +import org.openecomp.core.validation.errors.Messages; +import org.openecomp.core.validation.interfaces.Validator; +import org.openecomp.core.validation.types.GlobalValidationContext; +import org.openecomp.sdc.common.utils.AsdcCommon; +import org.openecomp.sdc.datatypes.error.ErrorLevel; +import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes; +import org.openecomp.sdc.heat.datatypes.manifest.FileData; +import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent; +import org.openecomp.sdc.heat.datatypes.model.Environment; +import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate; +import org.openecomp.sdc.heat.datatypes.model.HeatPseudoParameters; +import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes; +import org.openecomp.sdc.heat.datatypes.model.Output; +import org.openecomp.sdc.heat.datatypes.model.Parameter; +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.validation.impl.util.HeatValidationService; +import org.openecomp.sdc.validation.impl.util.ResourceValidationHeatValidator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStream; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +public class HeatValidator implements Validator { + + protected static Logger logger = LoggerFactory.getLogger(HeatValidator.class); + + /* validation 9*/ + private static void validateAllRequiredArtifactsExist(String fileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + Set<String> artifacts, + GlobalValidationContext globalContext) { + Collection<Resource> resourcesValues = heatOrchestrationTemplate.getResources() == null ? null + : heatOrchestrationTemplate.getResources().values(); + + if (CollectionUtils.isNotEmpty(resourcesValues)) { + for (Resource resource : resourcesValues) { + Collection<Object> properties = + resource.getProperties() == null ? null : resource.getProperties().values(); + if (CollectionUtils.isNotEmpty(properties)) { + for (Object property : properties) { + if (property instanceof Map) { + Set<String> artifactNames = HeatStructureUtil + .getReferencedValuesByFunctionName(fileName, + ResourceReferenceFunctions.GET_FILE.getFunction(), property, globalContext); + artifacts.addAll(artifactNames); + HeatValidationService.checkArtifactsExistence(fileName, artifactNames, globalContext); + } + } + } + } + } + + + } + + /* validation 14 */ + private static void validateAllResourceReferencesExist(String fileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + + Set<String> resourcesNames = heatOrchestrationTemplate.getResources() == null ? null + : heatOrchestrationTemplate.getResources().keySet(); + Collection<Resource> resourcesValues = heatOrchestrationTemplate.getResources() == null ? null + : heatOrchestrationTemplate.getResources().values(); + Collection<Output> outputsValues = heatOrchestrationTemplate.getOutputs() == null ? null + : heatOrchestrationTemplate.getOutputs().values(); + + HeatValidationService + .checkResourceExistenceFromResourcesMap(fileName, resourcesNames, resourcesValues, + globalContext); + HeatValidationService + .checkResourceExistenceFromResourcesMap(fileName, resourcesNames, outputsValues, + globalContext); + + } + + /* validation 16 */ + private static void validateGetParamPointToParameter(String fileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + Set<String> parametersNames = heatOrchestrationTemplate.getParameters() == null ? null + : heatOrchestrationTemplate.getParameters().keySet(); + Map<String, Resource> resourcesMap = heatOrchestrationTemplate.getResources(); + + if (CollectionUtils.isNotEmpty(parametersNames) && MapUtils.isNotEmpty(resourcesMap)) { + for (Map.Entry<String, Resource> resourceEntry : resourcesMap.entrySet()) { + Resource resource = resourceEntry.getValue(); + Map<String, Object> properties = resource.getProperties(); + if (MapUtils.isNotEmpty(properties)) { + Collection<Object> propertiesValues = properties.values(); + if (CollectionUtils.isNotEmpty(propertiesValues)) { + for (Object propertyObject : propertiesValues) { + //Set<String> referencedParameterNames = HeatValidationService + // .getParameterNameFromGetParamMap(propertyObject); + Set<String> referencedParameterNames = HeatStructureUtil + .getReferencedValuesByFunctionName(fileName, "get_param", propertyObject, + globalContext); + + validateReferenceParams(fileName, resourceEntry.getKey(), parametersNames, + referencedParameterNames, globalContext); + } + } + } + } + } + } + + private static void validateReferenceParams(String fileName, String resourceName, + Set<String> parametersNamesFromFile, + Set<String> referencedParametersNames, + GlobalValidationContext globalContext) { + + for (String parameterName : referencedParametersNames) { + if (!isHeatPseudoParameter(parameterName) + && !parametersNamesFromFile.contains(parameterName)) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.REFERENCED_PARAMETER_NOT_FOUND.getErrorMessage(), + parameterName, resourceName)); + } + } + } + + private static boolean isHeatPseudoParameter(String parameterName) { + return HeatPseudoParameters.getPseudoParameterNames().contains(parameterName); + } + + /* validation 18*/ + private static void validateGetAttr(String fileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + Map<String, Output> outputMap; + outputMap = heatOrchestrationTemplate.getOutputs(); + + if (MapUtils.isNotEmpty(outputMap)) { + HeatValidationService.loopOverOutputMapAndValidateGetAttrFromNested(fileName, outputMap, + heatOrchestrationTemplate, globalContext); + } + } + + /* validation 17 + */ + private static void validateEnvFile(String fileName, String envFileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + + Environment envContent; + + if (!envFileName.contains(".env")) { + globalContext.addMessage(envFileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.WRONG_ENV_FILE_EXTENSION.getErrorMessage(), + envFileName)); + } + + envContent = HeatValidationService.validateEnvContent(fileName, envFileName, globalContext); + if (envContent != null) { + validateEnvContentIsSubSetOfHeatParameters(envFileName, envContent, globalContext, + heatOrchestrationTemplate); + validateEnvParametersMatchDefinedHeatParameterTypes(envFileName, envContent, globalContext, + heatOrchestrationTemplate); + } + + } + + private static void validateEnvContentIsSubSetOfHeatParameters(String envFile, + Environment envContent, + GlobalValidationContext globalContext, + HeatOrchestrationTemplate heatOrchestrationTemplate) { + Set<String> parametersNames = heatOrchestrationTemplate.getParameters() == null ? null + : heatOrchestrationTemplate.getParameters().keySet(); + + if (MapUtils.isNotEmpty(envContent.getParameters())) { + if (CollectionUtils.isNotEmpty(parametersNames)) { + for (Map.Entry<String, Object> envEntry : envContent.getParameters().entrySet()) { + String envParameter = envEntry.getKey(); + if (!parametersNames.contains(envParameter)) { + globalContext.addMessage(envFile, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.ENV_INCLUDES_PARAMETER_NOT_IN_HEAT.getErrorMessage(), envFile, + envParameter)); + } + } + } else { + for (Map.Entry<String, Object> envEntry : envContent.getParameters().entrySet()) { + globalContext.addMessage(envFile, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.ENV_INCLUDES_PARAMETER_NOT_IN_HEAT.getErrorMessage(), + envFile, envEntry.getKey())); + } + } + } + } + + private static void validateParameterDefaultTypeAlignWithType(String fileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + Map<String, Parameter> parametersMap = heatOrchestrationTemplate.getParameters() == null ? null + : heatOrchestrationTemplate.getParameters(); + + if (MapUtils.isNotEmpty(parametersMap)) { + for (Map.Entry<String, Parameter> parameterEntry : parametersMap.entrySet()) { + Parameter parameter = parameterEntry.getValue(); + String parameterType = parameter.getType(); + Object parameterDefault = parameter.get_default(); + if (parameterDefault != null && parameterType != null) { + boolean isValueMatchDefault = + DefinedHeatParameterTypes.isValueIsFromGivenType(parameterDefault, parameterType); + if (!isValueMatchDefault) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.PARAMETER_DEFAULT_VALUE_NOT_ALIGN_WITH_TYPE.getErrorMessage(), + parameterEntry.getKey(), parameterType)); + } + } + } + } + } + + private static void validateEnvParametersMatchDefinedHeatParameterTypes(String envFile, + Environment envContent, + GlobalValidationContext globalContext, + HeatOrchestrationTemplate heatOrchestrationTemplate) { + Map<String, Parameter> heatParameters = heatOrchestrationTemplate.getParameters(); + + if (MapUtils.isNotEmpty(heatParameters) && MapUtils.isNotEmpty(envContent.getParameters())) { + for (Map.Entry<String, Object> envEntry : envContent.getParameters().entrySet()) { + String parameterName = envEntry.getKey(); + Object parameterEnvValue = envEntry.getValue(); + Parameter parameterFromHeatFile = heatParameters.get(parameterName); + if (parameterFromHeatFile != null) { + String parameterType = parameterFromHeatFile.getType(); + if (!DefinedHeatParameterTypes.isEmptyValueInEnv(parameterEnvValue) + && !DefinedHeatParameterTypes.isValueIsFromGivenType(parameterEnvValue, + parameterType)) { + globalContext.addMessage(envFile, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters( + Messages.PARAMETER_ENV_VALUE_NOT_ALIGN_WITH_TYPE.getErrorMessage(), + parameterName)); + } + } + } + } + } + + @Override + public void validate(GlobalValidationContext globalContext) { + + ManifestContent manifestContent; + try { + manifestContent = checkValidationPreCondition(globalContext); + } catch (Exception e0) { + return; + } + String baseFileName; + Map<String, FileData.Type> fileTypeMap = ManifestUtil.getFileTypeMap(manifestContent); + Map<String, FileData> fileEnvMap = ManifestUtil.getFileAndItsEnv(manifestContent); + Set<String> baseFiles = ManifestUtil.getBaseFiles(manifestContent); + Set<String> securityGroupsNamesFromBaseFileOutputs; + Set<String> artifacts = new HashSet<>(); + + + baseFileName = CollectionUtils.isEmpty(baseFiles) ? null : baseFiles.iterator().next(); + securityGroupsNamesFromBaseFileOutputs = baseFileName == null ? null + : checkForBaseFilePortsExistenceAndReturnSecurityGroupNamesFromOutputsIfNot(baseFileName, + globalContext); + + + globalContext.getFiles().stream() + .filter(fileName -> FileData.isHeatFile(fileTypeMap.get(fileName))).forEach( + fileName -> validate(fileName, + fileEnvMap.get(fileName) == null ? null : fileEnvMap.get(fileName).getFile(), + baseFileName == null ? null : baseFileName, artifacts, + securityGroupsNamesFromBaseFileOutputs, globalContext)); + + + Set<String> manifestArtifacts = ManifestUtil.getArtifacts(manifestContent); + + globalContext.getFiles().stream() + .filter(fileName -> manifestArtifacts.contains(fileName) && !artifacts.contains(fileName)) + .forEach(fileName -> globalContext.addMessage(fileName, ErrorLevel.WARNING, + Messages.ARTIFACT_FILE_NOT_REFERENCED.getErrorMessage())); + + ResourceValidationHeatValidator + .handleNotEmptyResourceNamesList(baseFileName, securityGroupsNamesFromBaseFileOutputs, + "SecurityGroup", globalContext); + + } + + private void validate(String fileName, String envFileName, String baseFileName, + Set<String> artifacts, Set<String> securityGroupsNamesFromBaseFileOutputs, + GlobalValidationContext globalContext) { + HeatOrchestrationTemplate heatOrchestrationTemplate = + checkHeatOrchestrationPreCondition(fileName, globalContext); + + + if (heatOrchestrationTemplate != null) { + if (!(fileName.contains(".yaml") || fileName.contains(".yml"))) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.WRONG_HEAT_FILE_EXTENSION.getErrorMessage(), + fileName)); + } + + validateHeatBaseStructure(fileName, heatOrchestrationTemplate, globalContext); + + ResourceValidationHeatValidator + .validateResourceType(fileName, baseFileName, securityGroupsNamesFromBaseFileOutputs, + heatOrchestrationTemplate, globalContext); + validateParameterDefaultTypeAlignWithType(fileName, heatOrchestrationTemplate, globalContext); + validateAllResourceReferencesExist(fileName, heatOrchestrationTemplate, globalContext); + validateGetParamPointToParameter(fileName, heatOrchestrationTemplate, globalContext); + validateGetAttr(fileName, heatOrchestrationTemplate, globalContext); + validateAllRequiredArtifactsExist(fileName, heatOrchestrationTemplate, artifacts, + globalContext); + + if (envFileName != null) { + validateEnvFile(fileName, envFileName, heatOrchestrationTemplate, globalContext); + } + } + } + + private void validateHeatBaseStructure(String fileName, + HeatOrchestrationTemplate heatOrchestrationTemplate, + GlobalValidationContext globalContext) { + if (heatOrchestrationTemplate.getHeat_template_version() == null) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.INVALID_HEAT_FORMAT_REASON.getErrorMessage(), + "missing template version")); + } + if (heatOrchestrationTemplate.getResources() == null + || heatOrchestrationTemplate.getResources().size() == 0) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.INVALID_HEAT_FORMAT_REASON.getErrorMessage(), + "heat file must have minimum one resource")); + } + } + + protected ManifestContent checkValidationPreCondition(GlobalValidationContext globalContext) { + InputStream manifest = globalContext.getFileContent(AsdcCommon.MANIFEST_NAME); + if (manifest == null) { + throw new RuntimeException("Can't load manifest file for Heat Validator"); + } + ManifestContent manifestContent; + try { + manifestContent = JsonUtil.json2Object(manifest, ManifestContent.class); + } catch (Exception e0) { + throw new RuntimeException("Can't load manifest file for Heat Validator"); + } + + return manifestContent; + } + + + private HeatOrchestrationTemplate checkHeatOrchestrationPreCondition(String fileName, + GlobalValidationContext globalContext) { + HeatOrchestrationTemplate heatOrchestrationTemplate; + try { + heatOrchestrationTemplate = new YamlUtil() + .yamlToObject(globalContext.getFileContent(fileName), HeatOrchestrationTemplate.class); + } catch (Exception e0) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.INVALID_HEAT_FORMAT_REASON.getErrorMessage(), + getParserExceptionReason(e0))); + return null; + } + + return heatOrchestrationTemplate; + } + + + private Set<String> checkForBaseFilePortsExistenceAndReturnSecurityGroupNamesFromOutputsIfNot( + String baseFileName, GlobalValidationContext globalContext) { + Set<String> securityGroupsNamesFromOutputsMap = new HashSet<>(); + HeatOrchestrationTemplate heatOrchestrationTemplate = + checkHeatOrchestrationPreCondition(baseFileName, globalContext); + + if (heatOrchestrationTemplate != null) { + Map<String, Resource> resourceMap = heatOrchestrationTemplate.getResources(); + if (!isPortResourceExistInBaseFile(resourceMap)) { + getSecurityGroupsReferencedResourcesFromOutputs(securityGroupsNamesFromOutputsMap, + heatOrchestrationTemplate.getOutputs(), resourceMap); + } + } + + return securityGroupsNamesFromOutputsMap; + } + + + @SuppressWarnings("unchecked") + private void getSecurityGroupsReferencedResourcesFromOutputs( + Set<String> securityGroupsNamesFromOutputsMap, Map<String, Output> outputMap, + Map<String, Resource> resourceMap) { + if (MapUtils.isNotEmpty(outputMap)) { + for (Map.Entry<String, Output> 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()); + } + } + } + } + } + } + + + private boolean isPortResourceExistInBaseFile(Map<String, Resource> resourceMap) { + for (Map.Entry<String, Resource> resourceEntry : resourceMap.entrySet()) { + if (resourceEntry.getValue().getType() + .equals(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource())) { + return true; + } + } + + return false; + } + + + private String getParserExceptionReason(Exception e0) { + String reason; + + if (e0.getCause() != null && e0.getCause().getCause() != null) { + reason = e0.getCause().getCause().getMessage(); + } else if (e0.getCause() != null) { + reason = e0.getCause().getMessage(); + } else { + reason = Messages.GENERAL_HEAT_PARSER_ERROR.getErrorMessage(); + } + return reason; + } + + +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/ManifestValidator.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/ManifestValidator.java new file mode 100644 index 0000000000..4ce40f0007 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/ManifestValidator.java @@ -0,0 +1,153 @@ +/*- + * ============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.validation.impl.validators; + +import org.openecomp.core.utilities.json.JsonUtil; +import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder; +import org.openecomp.core.validation.errors.Messages; +import org.openecomp.core.validation.interfaces.Validator; +import org.openecomp.core.validation.types.GlobalValidationContext; +import org.openecomp.sdc.common.utils.AsdcCommon; +import org.openecomp.sdc.datatypes.error.ErrorLevel; +import org.openecomp.sdc.heat.datatypes.manifest.FileData; +import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +public class ManifestValidator implements Validator { + + private static Logger logger = LoggerFactory.getLogger(YamlValidator.class); + + + @Override + public void validate(GlobalValidationContext globalContext) { + + + InputStream content = globalContext.getFileContent(AsdcCommon.MANIFEST_NAME); + ManifestContent manifestContent; + + try { + manifestContent = JsonUtil.json2Object(content, ManifestContent.class); + } catch (RuntimeException re) { + globalContext.addMessage(AsdcCommon.MANIFEST_NAME, ErrorLevel.ERROR, + Messages.INVALID_MANIFEST_FILE.getErrorMessage()); + return; + } + + List<String> manifestFiles = getManifestFileList(manifestContent, globalContext); + manifestFiles.stream().filter(name -> + !globalContext.getFileContextMap().containsKey(name) + ).forEach(name -> globalContext + .addMessage(name, ErrorLevel.ERROR, Messages.MISSING_FILE_IN_ZIP.getErrorMessage())); + + globalContext.getFileContextMap().keySet().stream().filter(name -> + !manifestFiles.contains(name) && !AsdcCommon.MANIFEST_NAME.equals(name) + ).forEach(name -> + globalContext.addMessage(name, ErrorLevel.WARNING, + Messages.MISSING_FILE_IN_MANIFEST.getErrorMessage()) + ); + + } + + private List<String> getManifestFileList(ManifestContent manifestContent, + GlobalValidationContext context) { + ManifestScanner manifestScanner = new ManifestScanner(); + manifestScanner.init(context); + manifestScanner.scan(null, manifestContent.getData(), context); + return manifestScanner.getFileList(); + } + + + private class ManifestScanner { + private GlobalValidationContext globalValidationContext; + private List<String> fileList; + + public void init(GlobalValidationContext globalValidationContext) { + this.globalValidationContext = globalValidationContext; + this.fileList = new ArrayList<>(); + } + + + public void scan(FileData fileData, List<FileData> data, + GlobalValidationContext globalContext) { + if (fileData == null) { + for (FileData childFileData : data) { + if (childFileData.getType() != null + && childFileData.getType().equals(FileData.Type.HEAT_ENV)) { + globalContext.addMessage(childFileData.getFile(), ErrorLevel.ERROR, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.ENV_NOT_ASSOCIATED_TO_HEAT.getErrorMessage())); + } + } + } + if (fileData != null) { + fileList.add(fileData.getFile()); + validateFileTypeVsFileName(fileData); + } + if (data == null) { + return; + } + data.stream().forEach(chileFileData -> { + scan(chileFileData, chileFileData.getData(), globalContext); + }); + } + + + public List<String> getFileList() { + return this.fileList; + } + + private void validateFileTypeVsFileName(FileData fileData) { + String fileName = fileData.getFile(); + if (fileName == null) { + this.globalValidationContext.addMessage(AsdcCommon.MANIFEST_NAME, ErrorLevel.ERROR, + Messages.MISSING_FILE_NAME_IN_MANIFEST.getErrorMessage()); + + } + FileData.Type type = fileData.getType(); + if (type == null) { + this.globalValidationContext + .addMessage(fileName, ErrorLevel.ERROR, Messages.INVALID_FILE_TYPE.getErrorMessage()); + } else if (type.equals(FileData.Type.HEAT_NET) || type.equals(FileData.Type.HEAT_VOL) + || type.equals(FileData.Type.HEAT)) { + if (fileName != null && !fileName.endsWith(".yml") && !fileName.endsWith(".yaml")) { + this.globalValidationContext.addMessage(fileName, ErrorLevel.ERROR, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.WRONG_HEAT_FILE_EXTENSION.getErrorMessage(), + fileName)); + } + } else if (type.equals(FileData.Type.HEAT_ENV)) { + if (fileName != null && !fileName.endsWith(".env")) { + this.globalValidationContext.addMessage(fileName, ErrorLevel.ERROR, + ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.WRONG_ENV_FILE_EXTENSION.getErrorMessage(), + fileName)); + } + } + } + } + + +} diff --git a/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/YamlValidator.java b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/YamlValidator.java new file mode 100644 index 0000000000..4d05b2b066 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/YamlValidator.java @@ -0,0 +1,97 @@ +/*- + * ============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.validation.impl.validators; + +import org.openecomp.core.utilities.yaml.YamlUtil; +import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder; +import org.openecomp.core.validation.errors.Messages; +import org.openecomp.core.validation.interfaces.Validator; +import org.openecomp.core.validation.types.GlobalValidationContext; +import org.openecomp.sdc.datatypes.error.ErrorLevel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.error.MarkedYAMLException; +import org.yaml.snakeyaml.parser.ParserException; + +import java.io.InputStream; +import java.util.Collection; +import java.util.Map; + +public class YamlValidator implements Validator { + + private static final Logger logger = LoggerFactory.getLogger(YamlValidator.class); + + @Override + public void validate(GlobalValidationContext globalContext) { + + Collection<String> files = globalContext.files( + (fileName, globalValidationContext) -> (fileName.endsWith(".yaml") + || fileName.endsWith(".yml") || fileName.endsWith(".env"))); + + files.stream().forEach(fileName -> validate(fileName, globalContext)); + } + + private void validate(String fileName, GlobalValidationContext globalContext) { + InputStream rowContent = globalContext.getFileContent(fileName); + if (rowContent == null) { + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.INVALID_YAML_FORMAT_REASON.getErrorMessage(), + Messages.EMPTY_YAML_FILE.getErrorMessage())); + return; /* no need to continue validation */ + } + + try { + convert(rowContent, Map.class); + } catch (Exception exception) { + + globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder + .getErrorWithParameters(Messages.INVALID_YAML_FORMAT_REASON.getErrorMessage(), + getParserExceptionReason(exception))); + logger.error("Exception in yaml parser. message:" + exception.getMessage()); + } + } + + private String getParserExceptionReason(Exception exception) { + String reason = null; + + if (exception.getCause() instanceof MarkedYAMLException) { + if (exception.getCause() != null) { + if (exception.getCause().getCause() instanceof ParserException) { + reason = exception.getCause().getCause().getMessage(); + } else { + reason = exception.getCause().getMessage(); + } + } + } else if (exception instanceof MarkedYAMLException) { + + reason = exception.getMessage(); + + } else { + reason = Messages.GENERAL_YAML_PARSER_ERROR.getErrorMessage(); + } + return reason; + } + + + private <T> T convert(InputStream content, Class<T> type) { + return new YamlUtil().yamlToObject(content, type); + } +} |