org.openecomp.sdc.validation.impl.validators.HeatValidator.java Source code

Java tutorial

Introduction

Here is the source code for org.openecomp.sdc.validation.impl.validators.HeatValidator.java

Source

/*-
 * ============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;
    }

}