2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.validation.impl.validators;
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.openecomp.core.utilities.json.JsonUtil;
26 import org.openecomp.core.utilities.yaml.YamlUtil;
27 import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder;
28 import org.openecomp.core.validation.errors.Messages;
29 import org.openecomp.core.validation.interfaces.Validator;
30 import org.openecomp.core.validation.types.GlobalValidationContext;
31 import org.openecomp.sdc.common.utils.AsdcCommon;
32 import org.openecomp.sdc.datatypes.error.ErrorLevel;
33 import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes;
34 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
35 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
36 import org.openecomp.sdc.heat.datatypes.model.Environment;
37 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
38 import org.openecomp.sdc.heat.datatypes.model.HeatPseudoParameters;
39 import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes;
40 import org.openecomp.sdc.heat.datatypes.model.Output;
41 import org.openecomp.sdc.heat.datatypes.model.Parameter;
42 import org.openecomp.sdc.heat.datatypes.model.Resource;
43 import org.openecomp.sdc.heat.datatypes.model.ResourceReferenceFunctions;
44 import org.openecomp.sdc.heat.services.HeatStructureUtil;
45 import org.openecomp.sdc.heat.services.manifest.ManifestUtil;
46 import org.openecomp.sdc.validation.impl.util.HeatValidationService;
47 import org.openecomp.sdc.validation.impl.util.ResourceValidationHeatValidator;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
51 import java.io.InputStream;
52 import java.util.Collection;
53 import java.util.HashSet;
55 import java.util.Objects;
58 public class HeatValidator implements Validator {
60 protected static Logger logger = LoggerFactory.getLogger(HeatValidator.class);
63 private static void validateAllRequiredArtifactsExist(String fileName,
64 HeatOrchestrationTemplate heatOrchestrationTemplate,
65 Set<String> artifacts,
66 GlobalValidationContext globalContext) {
67 Collection<Resource> resourcesValues = heatOrchestrationTemplate.getResources() == null ? null
68 : heatOrchestrationTemplate.getResources().values();
70 if (CollectionUtils.isNotEmpty(resourcesValues)) {
71 for (Resource resource : resourcesValues) {
72 Collection<Object> properties =
73 resource.getProperties() == null ? null : resource.getProperties().values();
74 if (CollectionUtils.isNotEmpty(properties)) {
75 for (Object property : properties) {
76 if (property instanceof Map) {
77 Set<String> artifactNames = HeatStructureUtil
78 .getReferencedValuesByFunctionName(fileName,
79 ResourceReferenceFunctions.GET_FILE.getFunction(), property, globalContext);
80 artifacts.addAll(artifactNames);
81 HeatValidationService.checkArtifactsExistence(fileName, artifactNames, globalContext);
92 private static void validateAllResourceReferencesExist(String fileName,
93 HeatOrchestrationTemplate heatOrchestrationTemplate,
94 GlobalValidationContext globalContext) {
96 Set<String> resourcesNames = heatOrchestrationTemplate.getResources() == null ? null
97 : heatOrchestrationTemplate.getResources().keySet();
98 Collection<Resource> resourcesValues = heatOrchestrationTemplate.getResources() == null ? null
99 : heatOrchestrationTemplate.getResources().values();
100 Collection<Output> outputsValues = heatOrchestrationTemplate.getOutputs() == null ? null
101 : heatOrchestrationTemplate.getOutputs().values();
103 HeatValidationService
104 .checkResourceExistenceFromResourcesMap(fileName, resourcesNames, resourcesValues,
106 HeatValidationService
107 .checkResourceExistenceFromResourcesMap(fileName, resourcesNames, outputsValues,
113 private static void validateGetParamPointToParameter(String fileName,
114 HeatOrchestrationTemplate heatOrchestrationTemplate,
115 GlobalValidationContext globalContext) {
116 Set<String> parametersNames = heatOrchestrationTemplate.getParameters() == null ? null
117 : heatOrchestrationTemplate.getParameters().keySet();
118 Map<String, Resource> resourcesMap = heatOrchestrationTemplate.getResources();
120 if (CollectionUtils.isNotEmpty(parametersNames) && MapUtils.isNotEmpty(resourcesMap)) {
121 for (Map.Entry<String, Resource> resourceEntry : resourcesMap.entrySet()) {
122 Resource resource = resourceEntry.getValue();
123 Map<String, Object> properties = resource.getProperties();
124 if (MapUtils.isNotEmpty(properties)) {
125 Collection<Object> propertiesValues = properties.values();
126 if (CollectionUtils.isNotEmpty(propertiesValues)) {
127 for (Object propertyObject : propertiesValues) {
128 //Set<String> referencedParameterNames = HeatValidationService
129 // .getParameterNameFromGetParamMap(propertyObject);
130 Set<String> referencedParameterNames = HeatStructureUtil
131 .getReferencedValuesByFunctionName(fileName, "get_param", propertyObject,
134 validateReferenceParams(fileName, resourceEntry.getKey(), parametersNames,
135 referencedParameterNames, globalContext);
143 private static void validateReferenceParams(String fileName, String resourceName,
144 Set<String> parametersNamesFromFile,
145 Set<String> referencedParametersNames,
146 GlobalValidationContext globalContext) {
148 for (String parameterName : referencedParametersNames) {
149 if (!isHeatPseudoParameter(parameterName)
150 && !parametersNamesFromFile.contains(parameterName)) {
151 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
152 .getErrorWithParameters(Messages.REFERENCED_PARAMETER_NOT_FOUND.getErrorMessage(),
153 parameterName, resourceName));
158 private static boolean isHeatPseudoParameter(String parameterName) {
159 return HeatPseudoParameters.getPseudoParameterNames().contains(parameterName);
163 private static void validateGetAttr(String fileName,
164 HeatOrchestrationTemplate heatOrchestrationTemplate,
165 GlobalValidationContext globalContext) {
166 Map<String, Output> outputMap;
167 outputMap = heatOrchestrationTemplate.getOutputs();
169 if (MapUtils.isNotEmpty(outputMap)) {
170 HeatValidationService.loopOverOutputMapAndValidateGetAttrFromNested(fileName, outputMap,
171 heatOrchestrationTemplate, globalContext);
175 /* validation 17 + */
176 private static void validateEnvFile(String fileName, String envFileName,
177 HeatOrchestrationTemplate heatOrchestrationTemplate,
178 GlobalValidationContext globalContext) {
180 Environment envContent;
182 if (!envFileName.contains(".env")) {
183 globalContext.addMessage(envFileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
184 .getErrorWithParameters(Messages.WRONG_ENV_FILE_EXTENSION.getErrorMessage(),
188 envContent = HeatValidationService.validateEnvContent(fileName, envFileName, globalContext);
189 if (envContent != null) {
190 validateEnvContentIsSubSetOfHeatParameters(envFileName, envContent, globalContext,
191 heatOrchestrationTemplate);
192 validateEnvParametersMatchDefinedHeatParameterTypes(envFileName, envContent, globalContext,
193 heatOrchestrationTemplate);
198 private static void validateEnvContentIsSubSetOfHeatParameters(String envFile,
199 Environment envContent,
200 GlobalValidationContext globalContext,
201 HeatOrchestrationTemplate heatOrchestrationTemplate) {
202 Set<String> parametersNames = heatOrchestrationTemplate.getParameters() == null ? null
203 : heatOrchestrationTemplate.getParameters().keySet();
205 if (MapUtils.isNotEmpty(envContent.getParameters())) {
206 if (CollectionUtils.isNotEmpty(parametersNames)) {
207 for (Map.Entry<String, Object> envEntry : envContent.getParameters().entrySet()) {
208 String envParameter = envEntry.getKey();
209 if (!parametersNames.contains(envParameter)) {
210 globalContext.addMessage(envFile, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
211 .getErrorWithParameters(
212 Messages.ENV_INCLUDES_PARAMETER_NOT_IN_HEAT.getErrorMessage(), envFile,
217 for (Map.Entry<String, Object> envEntry : envContent.getParameters().entrySet()) {
218 globalContext.addMessage(envFile, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
219 .getErrorWithParameters(Messages.ENV_INCLUDES_PARAMETER_NOT_IN_HEAT.getErrorMessage(),
220 envFile, envEntry.getKey()));
226 private static void validateParameterDefaultTypeAlignWithType(String fileName,
227 HeatOrchestrationTemplate heatOrchestrationTemplate,
228 GlobalValidationContext globalContext) {
229 Map<String, Parameter> parametersMap = heatOrchestrationTemplate.getParameters() == null ? null
230 : heatOrchestrationTemplate.getParameters();
232 if (MapUtils.isNotEmpty(parametersMap)) {
233 for (Map.Entry<String, Parameter> parameterEntry : parametersMap.entrySet()) {
234 Parameter parameter = parameterEntry.getValue();
235 String parameterType = parameter.getType();
236 Object parameterDefault = parameter.get_default();
237 if (parameterDefault != null && parameterType != null) {
238 boolean isValueMatchDefault =
239 DefinedHeatParameterTypes.isValueIsFromGivenType(parameterDefault, parameterType);
240 if (!isValueMatchDefault) {
241 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
242 .getErrorWithParameters(
243 Messages.PARAMETER_DEFAULT_VALUE_NOT_ALIGN_WITH_TYPE.getErrorMessage(),
244 parameterEntry.getKey(), parameterType));
251 private static void validateEnvParametersMatchDefinedHeatParameterTypes(String envFile,
252 Environment envContent,
253 GlobalValidationContext globalContext,
254 HeatOrchestrationTemplate heatOrchestrationTemplate) {
255 Map<String, Parameter> heatParameters = heatOrchestrationTemplate.getParameters();
257 if (MapUtils.isNotEmpty(heatParameters) && MapUtils.isNotEmpty(envContent.getParameters())) {
258 for (Map.Entry<String, Object> envEntry : envContent.getParameters().entrySet()) {
259 String parameterName = envEntry.getKey();
260 Object parameterEnvValue = envEntry.getValue();
261 Parameter parameterFromHeatFile = heatParameters.get(parameterName);
262 if (parameterFromHeatFile != null) {
263 String parameterType = parameterFromHeatFile.getType();
264 if (!DefinedHeatParameterTypes.isEmptyValueInEnv(parameterEnvValue)
265 && !DefinedHeatParameterTypes.isValueIsFromGivenType(parameterEnvValue,
267 globalContext.addMessage(envFile, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
268 .getErrorWithParameters(
269 Messages.PARAMETER_ENV_VALUE_NOT_ALIGN_WITH_TYPE.getErrorMessage(),
278 public void validate(GlobalValidationContext globalContext) {
280 ManifestContent manifestContent;
282 manifestContent = checkValidationPreCondition(globalContext);
283 } catch (Exception e0) {
287 Map<String, FileData.Type> fileTypeMap = ManifestUtil.getFileTypeMap(manifestContent);
288 Map<String, FileData> fileEnvMap = ManifestUtil.getFileAndItsEnv(manifestContent);
289 Set<String> baseFiles = ManifestUtil.getBaseFiles(manifestContent);
290 Set<String> securityGroupsNamesFromBaseFileOutputs;
291 Set<String> artifacts = new HashSet<>();
294 baseFileName = CollectionUtils.isEmpty(baseFiles) ? null : baseFiles.iterator().next();
295 securityGroupsNamesFromBaseFileOutputs = baseFileName == null ? null
296 : checkForBaseFilePortsExistenceAndReturnSecurityGroupNamesFromOutputsIfNot(baseFileName,
300 globalContext.getFiles().stream()
301 .filter(fileName -> FileData.isHeatFile(fileTypeMap.get(fileName))).forEach(
302 fileName -> validate(fileName,
303 fileEnvMap.get(fileName) == null ? null : fileEnvMap.get(fileName).getFile(),
304 baseFileName == null ? null : baseFileName, artifacts,
305 securityGroupsNamesFromBaseFileOutputs, globalContext));
308 Set<String> manifestArtifacts = ManifestUtil.getArtifacts(manifestContent);
310 globalContext.getFiles().stream()
311 .filter(fileName -> manifestArtifacts.contains(fileName) && !artifacts.contains(fileName))
312 .forEach(fileName -> globalContext.addMessage(fileName, ErrorLevel.WARNING,
313 Messages.ARTIFACT_FILE_NOT_REFERENCED.getErrorMessage()));
315 ResourceValidationHeatValidator
316 .handleNotEmptyResourceNamesList(baseFileName, securityGroupsNamesFromBaseFileOutputs,
317 "SecurityGroup", globalContext);
321 private void validate(String fileName, String envFileName, String baseFileName,
322 Set<String> artifacts, Set<String> securityGroupsNamesFromBaseFileOutputs,
323 GlobalValidationContext globalContext) {
324 HeatOrchestrationTemplate heatOrchestrationTemplate =
325 checkHeatOrchestrationPreCondition(fileName, globalContext);
328 if (heatOrchestrationTemplate != null) {
329 if (!(fileName.contains(".yaml") || fileName.contains(".yml"))) {
330 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
331 .getErrorWithParameters(Messages.WRONG_HEAT_FILE_EXTENSION.getErrorMessage(),
335 validateHeatBaseStructure(fileName, heatOrchestrationTemplate, globalContext);
337 ResourceValidationHeatValidator
338 .validateResourceType(fileName, baseFileName, securityGroupsNamesFromBaseFileOutputs,
339 heatOrchestrationTemplate, globalContext);
340 validateParameterDefaultTypeAlignWithType(fileName, heatOrchestrationTemplate, globalContext);
341 validateAllResourceReferencesExist(fileName, heatOrchestrationTemplate, globalContext);
342 validateGetParamPointToParameter(fileName, heatOrchestrationTemplate, globalContext);
343 validateGetAttr(fileName, heatOrchestrationTemplate, globalContext);
344 validateAllRequiredArtifactsExist(fileName, heatOrchestrationTemplate, artifacts,
347 if (envFileName != null) {
348 validateEnvFile(fileName, envFileName, heatOrchestrationTemplate, globalContext);
353 private void validateHeatBaseStructure(String fileName,
354 HeatOrchestrationTemplate heatOrchestrationTemplate,
355 GlobalValidationContext globalContext) {
356 if (heatOrchestrationTemplate.getHeat_template_version() == null) {
357 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
358 .getErrorWithParameters(Messages.INVALID_HEAT_FORMAT_REASON.getErrorMessage(),
359 "missing template version"));
361 if (heatOrchestrationTemplate.getResources() == null
362 || heatOrchestrationTemplate.getResources().size() == 0) {
363 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
364 .getErrorWithParameters(Messages.INVALID_HEAT_FORMAT_REASON.getErrorMessage(),
365 "heat file must have minimum one resource"));
369 protected ManifestContent checkValidationPreCondition(GlobalValidationContext globalContext) {
370 InputStream manifest = globalContext.getFileContent(AsdcCommon.MANIFEST_NAME);
371 if (manifest == null) {
372 throw new RuntimeException("Can't load manifest file for Heat Validator");
374 ManifestContent manifestContent;
376 manifestContent = JsonUtil.json2Object(manifest, ManifestContent.class);
377 } catch (Exception e0) {
378 throw new RuntimeException("Can't load manifest file for Heat Validator");
381 return manifestContent;
385 private HeatOrchestrationTemplate checkHeatOrchestrationPreCondition(String fileName,
386 GlobalValidationContext globalContext) {
387 HeatOrchestrationTemplate heatOrchestrationTemplate;
389 heatOrchestrationTemplate = new YamlUtil()
390 .yamlToObject(globalContext.getFileContent(fileName), HeatOrchestrationTemplate.class);
391 } catch (Exception e0) {
392 globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
393 .getErrorWithParameters(Messages.INVALID_HEAT_FORMAT_REASON.getErrorMessage(),
394 getParserExceptionReason(e0)));
398 return heatOrchestrationTemplate;
402 private Set<String> checkForBaseFilePortsExistenceAndReturnSecurityGroupNamesFromOutputsIfNot(
403 String baseFileName, GlobalValidationContext globalContext) {
404 Set<String> securityGroupsNamesFromOutputsMap = new HashSet<>();
405 HeatOrchestrationTemplate heatOrchestrationTemplate =
406 checkHeatOrchestrationPreCondition(baseFileName, globalContext);
408 if (heatOrchestrationTemplate != null) {
409 Map<String, Resource> resourceMap = heatOrchestrationTemplate.getResources();
410 if (!isPortResourceExistInBaseFile(resourceMap)) {
411 getSecurityGroupsReferencedResourcesFromOutputs(securityGroupsNamesFromOutputsMap,
412 heatOrchestrationTemplate.getOutputs(), resourceMap);
416 return securityGroupsNamesFromOutputsMap;
420 @SuppressWarnings("unchecked")
421 private void getSecurityGroupsReferencedResourcesFromOutputs(
422 Set<String> securityGroupsNamesFromOutputsMap, Map<String, Output> outputMap,
423 Map<String, Resource> resourceMap) {
424 if (MapUtils.isNotEmpty(outputMap)) {
425 for (Map.Entry<String, Output> outputEntry : outputMap.entrySet()) {
426 Object outputValue = outputEntry.getValue().getValue();
427 if (Objects.nonNull(outputValue) && outputValue instanceof Map) {
428 String resourceName = (String) ((Map) outputValue)
429 .get(ResourceReferenceFunctions.GET_RESOURCE.getFunction());
430 if (Objects.nonNull(resourceName)) {
431 Resource resource = resourceMap.get(resourceName);
432 if (Objects.nonNull(resource) && resource.getType().equals(
433 HeatResourcesTypes.NEUTRON_SECURITY_GROUP_RESOURCE_TYPE.getHeatResource())) {
434 securityGroupsNamesFromOutputsMap.add(outputEntry.getKey());
443 private boolean isPortResourceExistInBaseFile(Map<String, Resource> resourceMap) {
444 for (Map.Entry<String, Resource> resourceEntry : resourceMap.entrySet()) {
445 if (resourceEntry.getValue().getType()
446 .equals(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource())) {
455 private String getParserExceptionReason(Exception e0) {
458 if (e0.getCause() != null && e0.getCause().getCause() != null) {
459 reason = e0.getCause().getCause().getMessage();
460 } else if (e0.getCause() != null) {
461 reason = e0.getCause().getMessage();
463 reason = Messages.GENERAL_HEAT_PARSER_ERROR.getErrorMessage();