da87a13eb4f1bbd785693713e56d8dd898b791ce
[sdc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.sdc.validation.impl.validators;
22
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.openecomp.core.validation.ErrorMessageCode;
26 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
27 import org.openecomp.sdc.logging.types.LoggerConstants;
28 import org.openecomp.sdc.logging.types.LoggerErrorCode;
29 import org.openecomp.sdc.tosca.services.YamlUtil;
30 import org.openecomp.sdc.validation.Validator;
31 import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder;
32 import org.openecomp.core.validation.types.GlobalValidationContext;
33 import org.openecomp.sdc.common.errors.Messages;
34 import org.openecomp.sdc.datatypes.error.ErrorLevel;
35 import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes;
36 import org.openecomp.sdc.heat.datatypes.manifest.FileData;
37 import org.openecomp.sdc.heat.datatypes.manifest.ManifestContent;
38 import org.openecomp.sdc.heat.datatypes.model.Environment;
39 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
40 import org.openecomp.sdc.heat.datatypes.model.HeatPseudoParameters;
41 import org.openecomp.sdc.heat.datatypes.model.HeatResourcesTypes;
42 import org.openecomp.sdc.heat.datatypes.model.Output;
43 import org.openecomp.sdc.heat.datatypes.model.Parameter;
44 import org.openecomp.sdc.heat.datatypes.model.Resource;
45 import org.openecomp.sdc.heat.datatypes.model.ResourceReferenceFunctions;
46 import org.openecomp.sdc.heat.services.HeatStructureUtil;
47 import org.openecomp.sdc.heat.services.manifest.ManifestUtil;
48 import org.openecomp.sdc.logging.api.Logger;
49 import org.openecomp.sdc.logging.api.LoggerFactory;
50 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
51 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
52 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
53 import org.openecomp.sdc.validation.impl.util.HeatValidationService;
54 import org.openecomp.sdc.validation.util.ValidationUtil;
55
56 import java.io.InputStream;
57 import java.util.*;
58
59 public class HeatValidator implements Validator {
60   public static final MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
61   protected static Logger logger = (Logger) LoggerFactory.getLogger(HeatValidator.class);
62   private static final ErrorMessageCode ERROR_CODE_HOT_1 = new ErrorMessageCode("HOT1");
63   private static final ErrorMessageCode ERROR_CODE_HOT_2 = new ErrorMessageCode("HOT2");
64   private static final ErrorMessageCode ERROR_CODE_HOT_3 = new ErrorMessageCode("HOT3");
65   private static final ErrorMessageCode ERROR_CODE_HOT_4 = new ErrorMessageCode("HOT4");
66   private static final ErrorMessageCode ERROR_CODE_HOT_5 = new ErrorMessageCode("HOT5");
67   private static final ErrorMessageCode ERROR_CODE_HOT_6 = new ErrorMessageCode("HOT6");
68   private static final ErrorMessageCode ERROR_CODE_HOT_7 = new ErrorMessageCode("HOT7");
69   private static final ErrorMessageCode ERROR_CODE_HOT_8 = new ErrorMessageCode("HOT8");
70   private static final ErrorMessageCode ERROR_CODE_HOT_9 = new ErrorMessageCode("HOT9");
71   private static final ErrorMessageCode ERROR_CODE_HOT_10 = new ErrorMessageCode("HOT10");
72   private static final ErrorMessageCode ERROR_CODE_HOT_11 = new ErrorMessageCode("HOT11");
73   private static final ErrorMessageCode ERROR_CODE_HOT_12 = new ErrorMessageCode("HOT12");
74   private static final ErrorMessageCode ERROR_CODE_HOT_13 = new ErrorMessageCode("HOT13");
75   private static final ErrorMessageCode ERROR_CODE_HOT_14 = new ErrorMessageCode("HOT14");
76   private static final ErrorMessageCode ERROR_CODE_HOT_15 = new ErrorMessageCode("HOT15");
77   private static final ErrorMessageCode ERROR_CODE_HOT_16 = new ErrorMessageCode("HOT16");
78   private static final ErrorMessageCode ERROR_CODE_HOT_17 = new ErrorMessageCode("HOT17");
79
80   private static void validateAllRequiredArtifactsExist(String fileName,
81                                                         HeatOrchestrationTemplate
82                                                             heatOrchestrationTemplate,
83                                                         Set<String> artifacts,
84                                                         GlobalValidationContext globalContext) {
85
86     mdcDataDebugMessage.debugEntryMessage("file", fileName);
87
88     Collection<Resource> resourcesValues = heatOrchestrationTemplate.getResources() == null ? null
89         : heatOrchestrationTemplate.getResources().values();
90
91     if (CollectionUtils.isNotEmpty(resourcesValues)) {
92       for (Resource resource : resourcesValues) {
93         Collection<Object> properties =
94             resource.getProperties() == null ? null : resource.getProperties().values();
95         if (CollectionUtils.isNotEmpty(properties)) {
96           for (Object property : properties) {
97             if (property instanceof Map) {
98               globalContext.setMessageCode(ERROR_CODE_HOT_14);
99               Set<String> artifactNames = HeatStructureUtil
100                   .getReferencedValuesByFunctionName(fileName,
101                       ResourceReferenceFunctions.GET_FILE.getFunction(), property, globalContext);
102               artifacts.addAll(artifactNames);
103               globalContext.setMessageCode(ERROR_CODE_HOT_15);
104               HeatValidationService.checkArtifactsExistence(fileName, artifactNames, globalContext);
105             }
106           }
107         }
108       }
109     }
110
111     mdcDataDebugMessage.debugExitMessage("file", fileName);
112   }
113
114   /* validation 14 */
115
116   private static void validateAllResourceReferencesExist(String fileName,
117                                                          HeatOrchestrationTemplate
118                                                              heatOrchestrationTemplate,
119                                                          GlobalValidationContext globalContext) {
120
121     mdcDataDebugMessage.debugEntryMessage("file", fileName);
122
123     Set<String> resourcesNames = heatOrchestrationTemplate.getResources() == null ? null
124         : heatOrchestrationTemplate.getResources().keySet();
125     Collection<Resource> resourcesValues = heatOrchestrationTemplate.getResources() == null ? null
126         : heatOrchestrationTemplate.getResources().values();
127     Collection<Output> outputsValues = heatOrchestrationTemplate.getOutputs() == null ? null
128         : heatOrchestrationTemplate.getOutputs().values();
129         checkResourceExistenceFromResourcesMap(fileName, resourcesNames, resourcesValues,
130             globalContext);
131         checkResourceExistenceFromResourcesMap(fileName, resourcesNames, outputsValues,
132             globalContext);
133
134     mdcDataDebugMessage.debugExitMessage("file", fileName);
135
136   }
137
138     private static void checkResourceExistenceFromResourcesMap(String fileName,
139                                                               Set<String> resourcesNames,
140                                                               Collection<?> valuesToSearchIn,
141                                                               GlobalValidationContext globalContext) {
142
143         mdcDataDebugMessage.debugEntryMessage("file", fileName);
144
145         if (CollectionUtils.isNotEmpty(valuesToSearchIn)) {
146             for (Object value : valuesToSearchIn) {
147                 if (value instanceof Resource) {
148                   extractResourceProperty(fileName, resourcesNames, globalContext, (Resource) value);
149                 } else if (value instanceof Output) {
150                     Output output = (Output) value;
151                     Object outputsValue = output.getValue();
152                     handleReferencedResources(fileName, outputsValue, resourcesNames,
153                         globalContext);
154                 }
155             }
156         }
157     }
158
159   private static void extractResourceProperty(String fileName, Set<String> resourcesNames,
160                                               GlobalValidationContext globalContext,
161                                               Resource value) {
162     Resource resource = value;
163     Collection<Object> resourcePropertiesValues =
164             resource.getProperties() == null ? null : resource.getProperties()
165                 .values();
166     if (CollectionUtils.isNotEmpty(resourcePropertiesValues)) {
167         for (Object propertyValue : resourcePropertiesValues) {
168             handleReferencedResources(fileName, propertyValue, resourcesNames,
169                 globalContext);
170         }
171     }
172   }
173
174   private static void handleReferencedResources(String fileName, Object valueToSearchReferencesIn,
175                                                   Set<String> resourcesNames,
176                                                   GlobalValidationContext globalContext) {
177
178
179         mdcDataDebugMessage.debugEntryMessage("file", fileName);
180         globalContext.setMessageCode(ERROR_CODE_HOT_13);
181         Set<String> referencedResourcesNames = HeatStructureUtil
182                 .getReferencedValuesByFunctionName(fileName,
183                         ResourceReferenceFunctions.GET_RESOURCE.getFunction(),
184                     valueToSearchReferencesIn, globalContext);
185         if (CollectionUtils.isNotEmpty(referencedResourcesNames)) {
186             checkIfResourceReferenceExist(fileName, resourcesNames, referencedResourcesNames,
187                     globalContext);
188         }
189
190         mdcDataDebugMessage.debugExitMessage("file", fileName);
191     }
192
193     private static void checkIfResourceReferenceExist(String fileName,
194                                                       Set<String> referencedResourcesNames,
195                                                       Set<String> referencedResources,
196                                                       GlobalValidationContext globalContext) {
197
198
199         mdcDataDebugMessage.debugEntryMessage("file", fileName);
200
201         referencedResources.stream()
202                 .filter(referencedResource -> !referencedResourcesNames.contains(referencedResource))
203                 .forEach(referencedResource -> {
204                     globalContext.addMessage(fileName,
205                         ErrorLevel.ERROR, ErrorMessagesFormatBuilder
206                             .getErrorWithParameters(ERROR_CODE_HOT_16,Messages
207                             .REFERENCED_RESOURCE_NOT_FOUND.getErrorMessage(), referencedResource),
208                             LoggerTragetServiceName.VALIDATE_RESOURCE_REFERENCE_EXISTENCE,
209                             LoggerErrorDescription.RESOURCE_NOT_FOUND);
210                 });
211
212         mdcDataDebugMessage.debugExitMessage("file", fileName);
213     }
214
215   /* validation 16 */
216
217   private static void validateGetParamPointToParameter(String fileName,
218                                                        HeatOrchestrationTemplate
219                                                            heatOrchestrationTemplate,
220                                                        GlobalValidationContext globalContext) {
221
222     mdcDataDebugMessage.debugEntryMessage("file", fileName);
223
224     Set<String> parametersNames = heatOrchestrationTemplate.getParameters() == null ? null
225         : heatOrchestrationTemplate.getParameters().keySet();
226     Map<String, Resource> resourcesMap = heatOrchestrationTemplate.getResources();
227
228     if (CollectionUtils.isNotEmpty(parametersNames) && MapUtils.isNotEmpty(resourcesMap)) {
229       for (Map.Entry<String, Resource> resourceEntry : resourcesMap.entrySet()) {
230         Resource resource = resourceEntry.getValue();
231         Map<String, Object> properties = resource.getProperties();
232         if (MapUtils.isNotEmpty(properties)) {
233           Collection<Object> propertiesValues = properties.values();
234           if (CollectionUtils.isNotEmpty(propertiesValues)) {
235             for (Object propertyObject : propertiesValues) {
236               Set<String> referencedParameterNames = HeatStructureUtil
237                   .getReferencedValuesByFunctionName(fileName, "get_param", propertyObject,
238                       globalContext);
239
240               validateReferenceParams(fileName, resourceEntry.getKey(), parametersNames,
241                   referencedParameterNames, globalContext);
242             }
243           }
244         }
245       }
246     }
247
248     mdcDataDebugMessage.debugExitMessage("file", fileName);
249   }
250
251   private static void validateReferenceParams(String fileName, String resourceName,
252                                               Set<String> parametersNamesFromFile,
253                                               Set<String> referencedParametersNames,
254                                               GlobalValidationContext globalContext) {
255
256
257     mdcDataDebugMessage.debugEntryMessage("file", fileName);
258
259     for (String parameterName : referencedParametersNames) {
260       if (!isHeatPseudoParameter(parameterName)
261           && !parametersNamesFromFile.contains(parameterName)) {
262         globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
263                 .getErrorWithParameters(ERROR_CODE_HOT_1,Messages.
264                         REFERENCED_PARAMETER_NOT_FOUND.getErrorMessage(),
265                     parameterName, resourceName),
266             LoggerTragetServiceName.VALIDATE_PARAMETER_REFERENCE_EXITENCE,
267             LoggerErrorDescription.PARAMETER_NOT_FOUND);
268       }
269     }
270
271     mdcDataDebugMessage.debugExitMessage("file", fileName);
272   }
273
274   private static boolean isHeatPseudoParameter(String parameterName) {
275     return HeatPseudoParameters.getPseudoParameterNames().contains(parameterName);
276   }
277
278   /* validation 18*/
279
280   private static void validateGetAttr(String fileName,
281                                       HeatOrchestrationTemplate heatOrchestrationTemplate,
282                                       GlobalValidationContext globalContext) {
283
284     mdcDataDebugMessage.debugEntryMessage("file", fileName);
285
286     Map<String, Output> outputMap;
287     outputMap = heatOrchestrationTemplate.getOutputs();
288
289     if (MapUtils.isNotEmpty(outputMap)) {
290       loopOverOutputMapAndValidateGetAttrFromNested(fileName, outputMap,
291           heatOrchestrationTemplate, globalContext);
292     }
293
294     mdcDataDebugMessage.debugExitMessage("file", fileName);
295   }
296
297     private static void loopOverOutputMapAndValidateGetAttrFromNested(String fileName,
298                                                                      Map<String, Output> outputMap,
299                                                                      HeatOrchestrationTemplate
300                                                                              heatOrchestrationTemplate,
301                                                                      GlobalValidationContext
302                                                                              globalContext) {
303         for (Output output : outputMap.values()) {
304             Object outputValue = output.getValue();
305             if (outputValue != null && outputValue instanceof Map) {
306                 Map<String, Object> outputValueMap = (Map<String, Object>) outputValue;
307                 List<String> getAttrValue =
308                         (List<String>) outputValueMap.get(
309                             ResourceReferenceFunctions.GET_ATTR.getFunction());
310                 if (!CollectionUtils.isEmpty(getAttrValue)) {
311                     String resourceName = getAttrValue.get(0);
312                     Object attNameObject = getAttrValue.get(1);
313                     if (!(attNameObject instanceof String)) {
314                         return;
315                     }
316                     String attName = getAttrValue.get(1);
317                     String resourceType =
318                             getResourceTypeFromResourcesMap(resourceName, heatOrchestrationTemplate);
319
320                     if (Objects.nonNull(resourceType)
321                             && HeatValidationService.isNestedResource(resourceType)) {
322                         handleGetAttrNestedResource(fileName, globalContext, resourceName, attName,
323                                 resourceType);
324                     }
325                 }
326             }
327         }
328     }
329
330     private static void handleGetAttrNestedResource(String fileName,
331                                                     GlobalValidationContext globalContext,
332                                                     String resourceName, String attName,
333                                                     String resourceType) {
334         Map<String, Output> nestedOutputMap;
335         HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
336         try {
337             Optional<InputStream> fileContent = globalContext.getFileContent(resourceType);
338             if (fileContent.isPresent()) {
339                 nestedHeatOrchestrationTemplate =
340                         new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
341             } else {
342                 MdcDataErrorMessage
343                         .createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
344                                 LoggerTragetServiceName.VALIDATE_GET_ATTR_FROM_NESTED,
345                                 ErrorLevel.ERROR.name(), LoggerErrorCode.DATA_ERROR.getErrorCode(),
346                                 LoggerErrorDescription.EMPTY_FILE);
347                 throw new Exception("The file '" + resourceType + "' has no content");
348             }
349         } catch (Exception exception) {
350             logger.debug("",exception);
351             return;
352         }
353         nestedOutputMap = nestedHeatOrchestrationTemplate.getOutputs();
354
355         if (MapUtils.isEmpty(nestedOutputMap) || !nestedOutputMap.containsKey(attName)) {
356             globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
357                             .getErrorWithParameters(ERROR_CODE_HOT_17,Messages.
358                                     GET_ATTR_NOT_FOUND.getErrorMessage(),
359                                     attName, resourceName),
360                     LoggerTragetServiceName.VALIDATE_GET_ATTR_FROM_NESTED,
361                     LoggerErrorDescription.GET_ATTR_NOT_FOUND);
362         }
363     }
364
365     private static String getResourceTypeFromResourcesMap(String resourceName,
366                                                           HeatOrchestrationTemplate
367                                                                   heatOrchestrationTemplate) {
368         return heatOrchestrationTemplate.getResources().get(resourceName).getType();
369     }
370
371   /* validation 17 + */
372   private static void validateEnvFile(String fileName, String envFileName,
373                                       HeatOrchestrationTemplate heatOrchestrationTemplate,
374                                       GlobalValidationContext globalContext) {
375
376
377     mdcDataDebugMessage.debugEntryMessage("file", fileName);
378
379     Environment envContent;
380
381     if (!envFileName.contains(".env")) {
382       globalContext.addMessage(envFileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
383               .getErrorWithParameters(ERROR_CODE_HOT_2,Messages
384                   .WRONG_ENV_FILE_EXTENSION.getErrorMessage(), envFileName),
385           LoggerTragetServiceName.VALIDATE_ENV_FILE, LoggerErrorDescription.WRONG_FILE_EXTENSION);
386     }
387
388     envContent = HeatValidationService.validateEnvContent(fileName, envFileName, globalContext);
389     if (envContent != null) {
390       validateEnvContentIsSubSetOfHeatParameters(envFileName, envContent, globalContext,
391           heatOrchestrationTemplate);
392       validateEnvParametersMatchDefinedHeatParameterTypes(envFileName, envContent, globalContext,
393           heatOrchestrationTemplate);
394     }
395
396     mdcDataDebugMessage.debugExitMessage("file", fileName);
397
398   }
399
400   private static void validateEnvContentIsSubSetOfHeatParameters(String envFile,
401                                                                  Environment envContent,
402                                                                  GlobalValidationContext
403                                                                      globalContext,
404                                                                  HeatOrchestrationTemplate
405                                                                      heatOrchestrationTemplate) {
406
407     mdcDataDebugMessage.debugEntryMessage("file", envFile);
408
409     Set<String> parametersNames = heatOrchestrationTemplate.getParameters() == null ? null
410         : heatOrchestrationTemplate.getParameters().keySet();
411
412     if (MapUtils.isNotEmpty(envContent.getParameters())) {
413       if (CollectionUtils.isNotEmpty(parametersNames)) {
414         for (Map.Entry<String, Object> envEntry : envContent.getParameters().entrySet()) {
415           String envParameter = envEntry.getKey();
416           if (parametersNames != null && !parametersNames.contains(envParameter)) {
417             globalContext.addMessage(envFile, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
418                     .getErrorWithParameters(
419                             ERROR_CODE_HOT_3,Messages.
420                             ENV_INCLUDES_PARAMETER_NOT_IN_HEAT.getErrorMessage(), envFile,
421                         envParameter), LoggerTragetServiceName.VALIDATE_ENV_FILE,
422                 LoggerErrorDescription.ENV_PARAMETER_NOT_IN_HEAT);
423           }
424         }
425       } else {
426         for (Map.Entry<String, Object> envEntry : envContent.getParameters().entrySet()) {
427           globalContext.addMessage(envFile, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
428                   .getErrorWithParameters(ERROR_CODE_HOT_3,Messages
429                           .ENV_INCLUDES_PARAMETER_NOT_IN_HEAT.getErrorMessage(),
430                       envFile, envEntry.getKey()), LoggerTragetServiceName.VALIDATE_ENV_FILE,
431               LoggerErrorDescription.ENV_PARAMETER_NOT_IN_HEAT);
432         }
433       }
434     }
435
436     mdcDataDebugMessage.debugExitMessage("file", envFile);
437   }
438
439
440   private static void validateParameterDefaultTypeAlignWithType(String fileName,
441                                                                 HeatOrchestrationTemplate
442                                                                     heatOrchestrationTemplate,
443                                                                 GlobalValidationContext
444                                                                     globalContext) {
445
446     mdcDataDebugMessage.debugEntryMessage("file", fileName);
447
448     Map<String, Parameter> parametersMap = heatOrchestrationTemplate.getParameters() == null ? null
449         : heatOrchestrationTemplate.getParameters();
450
451     if (parametersMap != null && MapUtils.isNotEmpty(parametersMap)) {
452       for (Map.Entry<String, Parameter> parameterEntry : parametersMap.entrySet()) {
453         Parameter parameter = parameterEntry.getValue();
454         String parameterType = parameter.getType();
455         Object parameterDefault = parameter.get_default();
456         if (parameterDefault != null && parameterType != null) {
457           boolean isValueMatchDefault =
458               DefinedHeatParameterTypes.isValueIsFromGivenType(parameterDefault, parameterType);
459           if (!isValueMatchDefault) {
460             globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
461                     .getErrorWithParameters(
462                             ERROR_CODE_HOT_4,Messages.
463                             PARAMETER_DEFAULT_VALUE_NOT_ALIGN_WITH_TYPE.getErrorMessage(),
464                         parameterEntry.getKey(), parameterType),
465                 LoggerTragetServiceName.VALIDATE_PARAMTER_DEFAULT_MATCH_TYPE,
466                 LoggerErrorDescription.PARAMETER_DEFAULT_VALUE_NOT_ALIGNED_WITH_TYPE);
467           }
468         }
469       }
470     }
471
472     mdcDataDebugMessage.debugExitMessage("file", fileName);
473   }
474
475
476   private static void validateEnvParametersMatchDefinedHeatParameterTypes(String envFile,
477                                                                           Environment envContent,
478                                                                           GlobalValidationContext globalContext,
479                                                                           HeatOrchestrationTemplate heatOrchestrationTemplate) {
480
481
482     mdcDataDebugMessage.debugEntryMessage("file", envFile);
483
484     Map<String, Parameter> heatParameters = heatOrchestrationTemplate.getParameters();
485
486     if (MapUtils.isNotEmpty(heatParameters) && MapUtils.isNotEmpty(envContent.getParameters())) {
487       for (Map.Entry<String, Object> envEntry : envContent.getParameters().entrySet()) {
488         String parameterName = envEntry.getKey();
489         Object parameterEnvValue = envEntry.getValue();
490         Parameter parameterFromHeatFile = heatParameters.get(parameterName);
491         if (parameterFromHeatFile != null) {
492           String parameterType = parameterFromHeatFile.getType();
493           if (!DefinedHeatParameterTypes.isEmptyValueInEnv(parameterEnvValue)
494               && !DefinedHeatParameterTypes
495               .isValueIsFromGivenType(parameterEnvValue, parameterType)) {
496             globalContext.addMessage(envFile, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
497                     .getErrorWithParameters(
498                             ERROR_CODE_HOT_5,Messages.
499                             PARAMETER_ENV_VALUE_NOT_ALIGN_WITH_TYPE.getErrorMessage(),
500                         parameterName), LoggerTragetServiceName.VALIDATE_ENV_PARAMETER_MATCH_TYPE,
501                 LoggerErrorDescription.PARAMETER_DEFAULT_VALUE_NOT_ALIGNED_WITH_TYPE);
502           }
503         }
504       }
505     }
506
507     mdcDataDebugMessage.debugExitMessage("file", envFile);
508   }
509
510   @Override
511
512   public void validate(GlobalValidationContext globalContext) {
513     mdcDataDebugMessage.debugEntryMessage(null, null);
514     ManifestContent manifestContent;
515     try {
516       manifestContent = ValidationUtil.checkValidationPreCondition(globalContext);
517     } catch (Exception exception) {
518       logger.debug("",exception);
519       return;
520     }
521     String baseFileName;
522     Map<String, FileData.Type> fileTypeMap = ManifestUtil.getFileTypeMap(manifestContent);
523     Map<String, FileData> fileEnvMap = ManifestUtil.getFileAndItsEnv(manifestContent);
524     Set<String> baseFiles = ManifestUtil.getBaseFiles(manifestContent);
525     Set<String> securityGroupsNamesFromBaseFileOutputs;
526     Set<String> artifacts = new HashSet<>();
527
528
529     baseFileName = CollectionUtils.isEmpty(baseFiles) ? null : baseFiles.iterator().next();
530     securityGroupsNamesFromBaseFileOutputs = baseFileName == null ? null
531         : checkForBaseFilePortsExistenceAndReturnSecurityGroupNamesFromOutputsIfNot(baseFileName,
532             globalContext);
533
534
535     globalContext.getFiles().stream()
536         .filter(fileName -> FileData.isHeatFile(fileTypeMap.get(fileName))).forEach(
537         fileName -> validate(fileName, fileEnvMap.get(fileName) == null ? null : fileEnvMap.get(
538             fileName).getFile(),
539             baseFileName == null ? null : baseFileName, artifacts,
540             securityGroupsNamesFromBaseFileOutputs, globalContext));
541
542
543     Set<String> manifestArtifacts = ManifestUtil.getArtifacts(manifestContent);
544
545     globalContext.getFiles().stream()
546         .filter(fileName -> isManifestArtifact(manifestArtifacts, fileName) &&
547             isNotArtifact(artifacts, fileName))
548         .forEach(fileName -> globalContext.addMessage(fileName, ErrorLevel.WARNING,
549                 ErrorMessagesFormatBuilder
550                         .getErrorWithParameters(ERROR_CODE_HOT_11,
551                                 Messages.ARTIFACT_FILE_NOT_REFERENCED.getErrorMessage()),
552             LoggerTragetServiceName.CHECK_FOR_ORPHAN_ARTIFACTS,
553             LoggerErrorDescription.ARTIFACT_NOT_REFERENCED));
554
555     mdcDataDebugMessage.debugExitMessage(null, null);
556
557   }
558
559   private boolean isManifestArtifact(Set<String> manifestArtifacts, String fileName) {
560     return manifestArtifacts.contains(fileName);
561   }
562
563   private boolean isNotArtifact(Set<String> artifacts, String fileName) {
564     return !artifacts.contains(fileName);
565   }
566
567   private void validate(String fileName, String envFileName, String baseFileName,
568                         Set<String> artifacts, Set<String> securityGroupsNamesFromBaseFileOutputs,
569                         GlobalValidationContext globalContext) {
570       globalContext.setMessageCode(ERROR_CODE_HOT_12);
571     HeatOrchestrationTemplate
572         heatOrchestrationTemplate = ValidationUtil.checkHeatOrchestrationPreCondition(
573             fileName, globalContext);
574
575
576     if (heatOrchestrationTemplate != null) {
577       if (!(fileName.contains(".yaml") || fileName.contains(".yml"))) {
578         globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
579                 .getErrorWithParameters(ERROR_CODE_HOT_6,Messages
580                     .WRONG_HEAT_FILE_EXTENSION.getErrorMessage(), fileName),
581             LoggerTragetServiceName.CHECK_FOR_VALID_FILE_EXTENTION,
582             LoggerErrorDescription.WRONG_FILE_EXTENSION);
583       }
584
585       validateHeatBaseStructure(fileName, heatOrchestrationTemplate, globalContext);
586       validateParameterDefaultTypeAlignWithType(fileName, heatOrchestrationTemplate, globalContext);
587       validateAllResourceReferencesExist(fileName, heatOrchestrationTemplate, globalContext);
588       validateResourceDependsOn(fileName, heatOrchestrationTemplate, globalContext);
589       validateGetParamPointToParameter(fileName, heatOrchestrationTemplate, globalContext);
590       validateGetAttr(fileName, heatOrchestrationTemplate, globalContext);
591       validateAllRequiredArtifactsExist(fileName, heatOrchestrationTemplate, artifacts,
592           globalContext);
593
594       if (envFileName != null) {
595         validateEnvFile(fileName, envFileName, heatOrchestrationTemplate, globalContext);
596       }
597     }
598   }
599
600   private void validateResourceDependsOn(String fileName,
601                                          HeatOrchestrationTemplate heatOrchestrationTemplate,
602                                          GlobalValidationContext globalContext) {
603     Map<String, Resource> resourcesMap = heatOrchestrationTemplate.getResources();
604     if(MapUtils.isEmpty(resourcesMap)){
605       return;
606     }
607
608     Set<String> resourcesNames = resourcesMap.keySet();
609
610     resourcesMap.entrySet().stream()
611         .forEach(entry -> checkResourceDependsOn(fileName, entry.getValue(),
612             resourcesNames, globalContext));
613   }
614
615   @SuppressWarnings("unchecked")
616   private static void checkResourceDependsOn(String fileName, Resource resource,
617                                              Set<String> resourcesNames,
618                                              GlobalValidationContext globalContext) {
619
620
621     mdcDataDebugMessage.debugEntryMessage("file", fileName);
622
623     Object dependencies = resource.getDepends_on();
624     if (dependencies instanceof Collection) {
625       ((Collection<String>) dependencies)
626           .stream()
627           .filter(resource_id -> !resourcesNames.contains(resource_id))
628           .forEach(resource_id -> globalContext.addMessage(fileName, ErrorLevel.ERROR,
629               ErrorMessagesFormatBuilder
630                   .getErrorWithParameters(ERROR_CODE_HOT_7,Messages.
631                           MISSING_RESOURCE_IN_DEPENDS_ON.getErrorMessage(),
632                       (String) resource_id), LoggerTragetServiceName.CHECK_RESOURCE_DEPENDS_ON,
633               LoggerErrorDescription.MISSING_RESOURCE_DEPENDS_ON));
634     } else if (dependencies instanceof String) {
635       if (!resourcesNames.contains(dependencies)) {
636         globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
637                 .getErrorWithParameters(ERROR_CODE_HOT_8,Messages.
638                         MISSING_RESOURCE_IN_DEPENDS_ON.getErrorMessage(),
639                     (String) dependencies), LoggerTragetServiceName.CHECK_RESOURCE_DEPENDS_ON,
640             LoggerErrorDescription.MISSING_RESOURCE_DEPENDS_ON);
641       }
642     }
643
644     mdcDataDebugMessage.debugExitMessage("file", fileName);
645   }
646
647
648   private void validateHeatBaseStructure(String fileName,
649                                          HeatOrchestrationTemplate heatOrchestrationTemplate,
650                                          GlobalValidationContext globalContext) {
651
652
653     mdcDataDebugMessage.debugEntryMessage("file", fileName);
654
655     if (heatOrchestrationTemplate.getHeat_template_version() == null) {
656       globalContext.addMessage(fileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
657               .getErrorWithParameters(ERROR_CODE_HOT_9,Messages.
658                       INVALID_HEAT_FORMAT_REASON.getErrorMessage(),
659                   "missing template version"), LoggerTragetServiceName.VALIDATE_HEAT_FORMAT,
660           LoggerErrorDescription.INVALID_HEAT_FORMAT);
661     }
662     if (heatOrchestrationTemplate.getResources() == null
663         || heatOrchestrationTemplate.getResources().size() == 0) {
664       globalContext.addMessage(fileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder
665               .getErrorWithParameters(ERROR_CODE_HOT_10,Messages.
666                       INVALID_HEAT_FORMAT_REASON.getErrorMessage(),
667                   "The heat file does not contain any resources"),
668           LoggerTragetServiceName.VALIDATE_HEAT_FORMAT, LoggerErrorDescription.INVALID_HEAT_FORMAT);
669     }
670
671     mdcDataDebugMessage.debugExitMessage("file", fileName);
672   }
673
674   private Set<String> checkForBaseFilePortsExistenceAndReturnSecurityGroupNamesFromOutputsIfNot(
675       String baseFileName, GlobalValidationContext globalContext) {
676     Set<String> securityGroupsNamesFromOutputsMap = new HashSet<>();
677     HeatOrchestrationTemplate heatOrchestrationTemplate =
678         ValidationUtil.checkHeatOrchestrationPreCondition(baseFileName, globalContext);
679
680     if (heatOrchestrationTemplate != null) {
681       Map<String, Resource> resourceMap = heatOrchestrationTemplate.getResources();
682       if (!isPortResourceExistInBaseFile(resourceMap)) {
683         getSecurityGroupsReferencedResourcesFromOutputs(securityGroupsNamesFromOutputsMap,
684             heatOrchestrationTemplate.getOutputs(), resourceMap);
685       }
686     }
687     return securityGroupsNamesFromOutputsMap;
688   }
689
690
691   @SuppressWarnings("unchecked")
692   private void getSecurityGroupsReferencedResourcesFromOutputs(
693       Set<String> securityGroupsNamesFromOutputsMap, Map<String, Output> outputMap,
694       Map<String, Resource> resourceMap) {
695     if (MapUtils.isNotEmpty(outputMap)) {
696       for (Map.Entry<String, Output> outputEntry : outputMap.entrySet()) {
697         Object outputValue = outputEntry.getValue().getValue();
698         if (Objects.nonNull(outputValue) && outputValue instanceof Map) {
699           String resourceName = (String) ((Map) outputValue)
700               .get(ResourceReferenceFunctions.GET_RESOURCE.getFunction());
701           if (Objects.nonNull(resourceName)) {
702             Resource resource = resourceMap.get(resourceName);
703             if (Objects.nonNull(resource) && resource.getType().equals(
704                 HeatResourcesTypes.NEUTRON_SECURITY_GROUP_RESOURCE_TYPE.getHeatResource())) {
705               securityGroupsNamesFromOutputsMap.add(outputEntry.getKey());
706             }
707           }
708         }
709       }
710     }
711   }
712
713
714   private boolean isPortResourceExistInBaseFile(Map<String, Resource> resourceMap) {
715     for (Map.Entry<String, Resource> resourceEntry : resourceMap.entrySet()) {
716       if (resourceEntry.getValue().getType()
717           .equals(HeatResourcesTypes.NEUTRON_PORT_RESOURCE_TYPE.getHeatResource())) {
718         return true;
719       }
720     }
721
722     return false;
723   }
724 }