e9a265d7bc3904f07b01a1606f155217156451ff
[sdc.git] / openecomp-be / lib / openecomp-sdc-validation-lib / openecomp-sdc-validation-impl / src / main / java / org / openecomp / sdc / validation / impl / util / HeatValidationService.java
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.validation.impl.util;
18
19 import org.apache.commons.collections4.CollectionUtils;
20 import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder;
21 import org.openecomp.core.validation.types.GlobalValidationContext;
22 import org.openecomp.sdc.common.errors.Messages;
23 import org.openecomp.sdc.datatypes.error.ErrorLevel;
24 import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes;
25 import org.openecomp.sdc.heat.datatypes.model.Environment;
26 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
27 import org.openecomp.sdc.heat.datatypes.model.Parameter;
28 import org.openecomp.sdc.heat.datatypes.model.Resource;
29 import org.openecomp.sdc.heat.services.HeatStructureUtil;
30 import org.openecomp.sdc.logging.api.Logger;
31 import org.openecomp.sdc.logging.api.LoggerFactory;
32 import org.openecomp.sdc.tosca.services.YamlUtil;
33 import org.openecomp.sdc.validation.impl.validators.HeatValidator;
34 import org.openecomp.sdc.validation.type.HeatResourceValidationContext;
35
36 import java.io.InputStream;
37 import java.util.Collection;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.Objects;
43 import java.util.Optional;
44 import java.util.Set;
45
46
47 public class HeatValidationService {
48
49   private static final Logger LOGGER = LoggerFactory.getLogger(HeatValidator.class);
50   private static final String NO_CONTENT_IN_FILE_MSG = "The file ' %s ' has no content";
51   private HeatValidationService(){
52
53   }
54   /**
55    * Check artifacts existence.
56    *
57    * @param fileName the file name
58    * @param artifactsNames the artifacts names
59    * @param globalContext the global context
60    */
61   public static void checkArtifactsExistence(String fileName, Set<String> artifactsNames,
62                                              GlobalValidationContext globalContext) {
63     artifactsNames
64             .stream()
65             .filter(artifactName -> !globalContext.getFileContextMap().containsKey(artifactName))
66             .forEach(artifactName ->
67               globalContext.addMessage(fileName,
68                       ErrorLevel.ERROR, ErrorMessagesFormatBuilder
69                               .getErrorWithParameters(
70                                       globalContext.getMessageCode(),
71                                       Messages.MISSING_ARTIFACT.getErrorMessage(), artifactName)));
72   }
73
74   /**
75    * Draw files loop string.
76    *
77    * @param filesInPath the files in path
78    * @return the string
79    */
80   public static String drawFilesLoop(List<String> filesInPath) {
81     StringBuilder stringBuilder = new StringBuilder();
82     stringBuilder.append("[");
83     int pathSize = filesInPath.size();
84
85     for (int i = 0; i < pathSize; i++) {
86       stringBuilder.append(filesInPath.get(i));
87       if (i != pathSize - 1) {
88         stringBuilder.append(" -- ");
89       }
90     }
91     if (!filesInPath.get(0).equals(filesInPath.get(pathSize - 1))) {
92       stringBuilder.append(" -- ");
93       stringBuilder.append(filesInPath.get(0));
94     }
95     stringBuilder.append("]");
96
97     return stringBuilder.toString();
98   }
99
100   /**
101    * Check nested parameters.
102    *
103    * @param parentFileName the calling nested file name
104    * @param nestedFileName the nested file name
105    * @param globalContext the global context
106    * @param parentParameters parent parameters.
107    * @param nestedParameters nested parameters.
108    * @param nestedParametersNames nested parameter names.
109    */
110   private static void checkNestedParameters(String parentFileName, String nestedFileName,
111                                             GlobalValidationContext globalContext,
112                                             Map<String, Parameter> parentParameters,
113                                             Map<String, Parameter> nestedParameters,
114                                             Set<String> nestedParametersNames) {
115     HeatOrchestrationTemplate parentHeatOrchestrationTemplate;
116     HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
117
118     try {
119       nestedHeatOrchestrationTemplate = getHeatOrchestrationTemplate(nestedFileName, globalContext);
120       parentHeatOrchestrationTemplate = getHeatOrchestrationTemplate(parentFileName, globalContext);
121     } catch (Exception exception) {
122       return;
123     }
124
125     parentParameters.putAll(parentHeatOrchestrationTemplate.getParameters());
126     nestedParameters.putAll(nestedHeatOrchestrationTemplate.getParameters());
127     if (!nestedParameters.isEmpty()) {
128       nestedParametersNames.addAll(nestedHeatOrchestrationTemplate.getParameters().keySet());
129     }
130   }
131
132   private static HeatOrchestrationTemplate getHeatOrchestrationTemplate(String fileName,
133                                                                         GlobalValidationContext globalContext)
134           throws Exception {
135
136     Optional<InputStream> fileContent = globalContext.getFileContent(fileName);
137     if (fileContent.isPresent()) {
138       return new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
139     } else {
140       Exception exception = new Exception(String.format(NO_CONTENT_IN_FILE_MSG, fileName));
141       LOGGER.error("Error while reading file : " + fileName , exception);
142       throw exception;
143     }
144   }
145
146   public static void checkNestedParametersNoMissingParameterInNested(String parentFileName,
147                                                                      String nestedFileName,
148                                                                      String resourceName,
149                                                                      Set<String> resourceFileProperties,
150                                                                      GlobalValidationContext globalContext) {
151     Map<String, Parameter> parentParameters = new HashMap<>();
152     Map<String, Parameter> nestedParameters = new HashMap<>();
153     Set<String> nestedParametersNames = new HashSet<>();
154     checkNestedParameters(parentFileName, nestedFileName, globalContext, parentParameters,
155             nestedParameters, nestedParametersNames);
156
157     checkNoMissingParameterInNested(parentFileName, nestedFileName, resourceName,
158             resourceFileProperties, nestedParametersNames, globalContext);
159   }
160
161   public static void checkNestedInputValuesAlignWithType(String parentFileName,
162                                                          String nestedFileName,
163                                                          String resourceName, Resource resource,
164                                                          Optional<String> indexVarValue,
165                                                          GlobalValidationContext globalContext) {
166     Map<String, Parameter> parentParameters = new HashMap<>();
167     Map<String, Parameter> nestedParameters = new HashMap<>();
168     Set<String> nestedParametersNames = new HashSet<>();
169     checkNestedParameters(parentFileName, nestedFileName, globalContext, parentParameters,
170             nestedParameters, nestedParametersNames);
171
172     checkNestedInputValuesAlignWithType(parentFileName, nestedFileName,
173             nestedParameters, resourceName, resource, indexVarValue, globalContext);
174   }
175
176   private static void checkNoMissingParameterInNested(String parentFileName, String nestedFileName,
177                                                       String resourceName,
178                                                       Set<String> resourceFileProperties,
179                                                       Set<String> nestedParametersNames,
180                                                       GlobalValidationContext globalContext) {
181     if (CollectionUtils.isNotEmpty(nestedParametersNames)) {
182       resourceFileProperties
183               .stream()
184               .filter(propertyName -> !nestedParametersNames.contains(propertyName))
185               .forEach(propertyName -> globalContext
186                       .addMessage(parentFileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
187                                       .getErrorWithParameters(
188                                               globalContext.getMessageCode(),
189                                               Messages.MISSING_PARAMETER_IN_NESTED.getErrorMessage(),
190                                               nestedFileName, resourceName, propertyName)));
191     }
192   }
193
194   private static void checkNestedInputValuesAlignWithType(String parentFileName,
195                                                           String nestedFileName,
196                                                           Map<String, Parameter> nestedParameters,
197                                                           String resourceName, Resource resource,
198                                                           Optional<String> indexVarValue,
199                                                           GlobalValidationContext globalContext) {
200     Map<String, Object> properties = resource.getProperties();
201     for (Map.Entry<String, Object> propertyEntry : properties.entrySet()) {
202       String parameterName = propertyEntry.getKey();
203       Object parameterInputValue = propertyEntry.getValue();
204       if (parameterInputValue instanceof String) {
205         if (indexVarValue.isPresent() && indexVarValue.get().equals(parameterInputValue)) {
206           parameterInputValue = 3; //indexVarValue is actually number value in runtime
207         }
208         validateStaticValueForNestedInputParameter(parentFileName, nestedFileName, resourceName,
209                 parameterName, parameterInputValue, nestedParameters.get(parameterName),
210                 globalContext);
211       }
212     }
213   }
214
215   private static void validateStaticValueForNestedInputParameter(String parentFileName,
216                                                                  String nestedFileName,
217                                                                  String resourceName,
218                                                                  String parameterName,
219                                                                  Object staticValue,
220                                                                  Parameter parameterInNested,
221                                                                  GlobalValidationContext
222                                                                          globalContext) {
223     if (parameterInNested == null) {
224       return;
225     }
226     if (!DefinedHeatParameterTypes
227             .isValueIsFromGivenType(staticValue, parameterInNested.getType())) {
228       globalContext.addMessage(parentFileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder
229                       .getErrorWithParameters(globalContext.getMessageCode(),
230                               Messages.WRONG_VALUE_TYPE_ASSIGNED_NESTED_INPUT.getErrorMessage(),
231                               resourceName, parameterName, nestedFileName));
232     }
233   }
234
235
236   /**
237    * Is nested loop exist in file boolean.
238    *
239    * @param callingFileName the calling file name
240    * @param nestedFileName the nested file name
241    * @param filesInLoop the files in loop
242    * @param globalContext the global context
243    * @return the boolean
244    */
245   public static boolean isNestedLoopExistInFile(String callingFileName, String nestedFileName,
246                                                 List<String> filesInLoop,
247                                                 GlobalValidationContext globalContext) {
248     HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
249     try {
250       nestedHeatOrchestrationTemplate = getNestedHeatOrchestrationTemplate(nestedFileName,
251                                           globalContext);
252     } catch (Exception exception) {
253       LOGGER.error("Error while reading file :  " + nestedFileName, exception);
254       LOGGER.warn("HEAT Validator will not be executed on file " + nestedFileName
255               + " due to illegal HEAT format");
256       return false;
257     }
258     filesInLoop.add(nestedFileName);
259     Collection<Resource> nestedResources =
260             nestedHeatOrchestrationTemplate.getResources() == null ? null
261                     : nestedHeatOrchestrationTemplate.getResources().values();
262     return addNestedFilesInLoopAndCheckIfNestedLoopExist(nestedResources,
263                     callingFileName, filesInLoop, globalContext);
264   }
265   private static boolean addNestedFilesInLoopAndCheckIfNestedLoopExist(
266                 Collection<Resource> nestedResources,String callingFileName,
267                 List<String> filesInLoop,
268                 GlobalValidationContext globalContext){
269     if (CollectionUtils.isNotEmpty(nestedResources)) {
270       for (Resource resource : nestedResources) {
271         String resourceType = resource.getType();
272
273         if (Objects.nonNull(resourceType) && isNestedResource(resourceType)) {
274           return resourceType.equals(callingFileName) || !filesInLoop.contains(resourceType)
275                   && isNestedLoopExistInFile(callingFileName, resourceType, filesInLoop, globalContext);
276         }
277       }
278     }
279     return false;
280   }
281
282
283
284
285   private static HeatOrchestrationTemplate getNestedHeatOrchestrationTemplate( String nestedFileName,
286                                           GlobalValidationContext globalContext) throws Exception {
287     Optional<InputStream> fileContent = globalContext.getFileContent(nestedFileName);
288     HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
289     if (fileContent.isPresent()) {
290       nestedHeatOrchestrationTemplate =
291               new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
292     } else {
293       throw new Exception(String.format(NO_CONTENT_IN_FILE_MSG, nestedFileName));
294     }
295
296     return nestedHeatOrchestrationTemplate;
297   }
298
299   public static boolean isNestedResource(String resourceType) {
300     return resourceType.contains(".yaml") || resourceType.contains(".yml");
301   }
302
303   /**
304    * Validate env content environment.
305    *
306    * @param fileName the file name
307    * @param envFileName the env file name
308    * @param globalContext the global context
309    * @return the environment
310    */
311   public static Environment validateEnvContent(String fileName, String envFileName,
312                                                GlobalValidationContext globalContext) {
313     Environment envContent;
314     try {
315       Optional<InputStream> fileContent = globalContext.getFileContent(envFileName);
316       if (fileContent.isPresent()) {
317         envContent = new YamlUtil().yamlToObject(fileContent.get(), Environment.class);
318       } else {
319         throw new Exception(String.format(NO_CONTENT_IN_FILE_MSG, envFileName));
320       }
321     } catch (Exception exception) {
322       LOGGER.error("Error while reading env file : " + envFileName, exception);
323       return null;
324     }
325     return envContent;
326   }
327
328   /**
329    *  This method verifies whether the propertyValue contains a single parent port
330    * @param fileName on which the validation is currently run
331    * @param globalContext global validation context
332    * @param heatResourceValidationContext heat resource validation context
333    * @param propertyValue the value which is examined
334    * @return whether the vlan has single parent port
335    */
336   public static boolean hasSingleParentPort(String fileName, GlobalValidationContext globalContext,
337                                             HeatResourceValidationContext heatResourceValidationContext,
338                                             Object propertyValue) {
339     final boolean isList = propertyValue instanceof List;
340     if (!isList || ((List) propertyValue).size() != 1) {
341       return false;
342     }
343
344     final Object listValue = ((List) propertyValue).get(0);
345
346     final Set<String> getParamValues =
347         HeatStructureUtil.getReferencedValuesByFunctionName(fileName, "get_param",
348             listValue, globalContext);
349
350     return getParamValues.isEmpty() || (getParamValues.size() == 1) &&
351         validateGetParamValueOfType(getParamValues, heatResourceValidationContext,
352             DefinedHeatParameterTypes.STRING.getType());
353
354   }
355
356
357   private static boolean validateGetParamValueOfType(Set<String> values,
358                                         HeatResourceValidationContext
359                                             heatResourceValidationContext, String type) {
360
361     return values.stream().anyMatch(e -> Objects.equals(
362         heatResourceValidationContext.getHeatOrchestrationTemplate().getParameters().get(e).getType(), type));
363   }
364
365 }