diff options
Diffstat (limited to 'openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HeatValidator.java')
-rw-r--r-- | openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-impl/src/main/java/org/openecomp/sdc/validation/impl/validators/HeatValidator.java | 469 |
1 files changed, 469 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/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; + } + + +} |