469bfad3aff85e288fe5dc49e66b5b3718acf5e4
[sdc.git] /
1 /*
2  * Copyright © 2016-2017 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.logging.api.Logger;
30 import org.openecomp.sdc.logging.api.LoggerFactory;
31 import org.openecomp.sdc.tosca.services.YamlUtil;
32 import org.openecomp.sdc.validation.impl.validators.HeatValidator;
33
34 import java.io.InputStream;
35 import java.util.Collection;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Objects;
41 import java.util.Optional;
42 import java.util.Set;
43
44
45 public class HeatValidationService {
46
47   private static final Logger LOGGER = LoggerFactory.getLogger(HeatValidator.class);
48   private static final String NO_CONTENT_IN_FILE_MSG = "The file ' %s ' has no content";
49   private HeatValidationService(){
50
51   }
52   /**
53    * Check artifacts existence.
54    *
55    * @param fileName the file name
56    * @param artifactsNames the artifacts names
57    * @param globalContext the global context
58    */
59   public static void checkArtifactsExistence(String fileName, Set<String> artifactsNames,
60                                              GlobalValidationContext globalContext) {
61     artifactsNames
62             .stream()
63             .filter(artifactName -> !globalContext.getFileContextMap().containsKey(artifactName))
64             .forEach(artifactName ->
65               globalContext.addMessage(fileName,
66                       ErrorLevel.ERROR, ErrorMessagesFormatBuilder
67                               .getErrorWithParameters(
68                                       globalContext.getMessageCode(),
69                                       Messages.MISSING_ARTIFACT.getErrorMessage(), artifactName)));
70   }
71
72   /**
73    * Draw files loop string.
74    *
75    * @param filesInPath the files in path
76    * @return the string
77    */
78   public static String drawFilesLoop(List<String> filesInPath) {
79     StringBuilder stringBuilder = new StringBuilder();
80     stringBuilder.append("[");
81     int pathSize = filesInPath.size();
82
83     for (int i = 0; i < pathSize; i++) {
84       stringBuilder.append(filesInPath.get(i));
85       if (i != pathSize - 1) {
86         stringBuilder.append(" -- ");
87       }
88     }
89     if (!filesInPath.get(0).equals(filesInPath.get(pathSize - 1))) {
90       stringBuilder.append(" -- ");
91       stringBuilder.append(filesInPath.get(0));
92     }
93     stringBuilder.append("]");
94
95     return stringBuilder.toString();
96   }
97
98   /**
99    * Check nested parameters.
100    *
101    * @param parentFileName the calling nested file name
102    * @param nestedFileName the nested file name
103    * @param globalContext the global context
104    * @param parentParameters parent parameters.
105    * @param nestedParameters nested parameters.
106    * @param nestedParametersNames nested parameter names.
107    */
108   public static void checkNestedParameters(String parentFileName, String nestedFileName,
109                                            GlobalValidationContext globalContext,
110                                            Map<String, Parameter> parentParameters,
111                                            Map<String, Parameter> nestedParameters,
112                                            Set<String> nestedParametersNames) {
113     HeatOrchestrationTemplate parentHeatOrchestrationTemplate;
114     HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
115
116     try {
117       nestedHeatOrchestrationTemplate = getHeatOrchestrationTemplate(nestedFileName, globalContext);
118       parentHeatOrchestrationTemplate = getHeatOrchestrationTemplate(parentFileName, globalContext);
119     } catch (Exception exception) {
120       return;
121     }
122
123     parentParameters.putAll(parentHeatOrchestrationTemplate.getParameters());
124     nestedParameters.putAll(nestedHeatOrchestrationTemplate.getParameters());
125     if (!nestedParameters.isEmpty()) {
126       nestedParametersNames.addAll(nestedHeatOrchestrationTemplate.getParameters().keySet());
127     }
128   }
129
130   private static HeatOrchestrationTemplate getHeatOrchestrationTemplate(String fileName,
131                                                                         GlobalValidationContext globalContext)
132           throws Exception {
133
134     Optional<InputStream> fileContent = globalContext.getFileContent(fileName);
135     if (fileContent.isPresent()) {
136       return new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
137     } else {
138       Exception exception = new Exception(String.format(NO_CONTENT_IN_FILE_MSG, fileName));
139       LOGGER.error("Error while reading file : " + fileName , exception);
140       throw exception;
141     }
142   }
143
144   public static void checkNestedParametersNoMissingParameterInNested(String parentFileName,
145                                                                      String nestedFileName,
146                                                                      String resourceName,
147                                                                      Set<String> resourceFileProperties,
148                                                                      GlobalValidationContext globalContext) {
149     Map<String, Parameter> parentParameters = new HashMap<>();
150     Map<String, Parameter> nestedParameters = new HashMap<>();
151     Set<String> nestedParametersNames = new HashSet<>();
152     checkNestedParameters(parentFileName, nestedFileName, globalContext, parentParameters,
153             nestedParameters, nestedParametersNames);
154
155     checkNoMissingParameterInNested(parentFileName, nestedFileName, resourceName,
156             resourceFileProperties, nestedParametersNames, globalContext);
157   }
158
159   public static void checkNestedInputValuesAlignWithType(String parentFileName,
160                                                          String nestedFileName,
161                                                          String resourceName, Resource resource,
162                                                          Optional<String> indexVarValue,
163                                                          GlobalValidationContext globalContext) {
164     Map<String, Parameter> parentParameters = new HashMap<>();
165     Map<String, Parameter> nestedParameters = new HashMap<>();
166     Set<String> nestedParametersNames = new HashSet<>();
167     checkNestedParameters(parentFileName, nestedFileName, globalContext, parentParameters,
168             nestedParameters, nestedParametersNames);
169
170     checkNestedInputValuesAlignWithType(parentFileName, nestedFileName,
171             nestedParameters, resourceName, resource, indexVarValue, globalContext);
172   }
173
174   private static void checkNoMissingParameterInNested(String parentFileName, String nestedFileName,
175                                                       String resourceName,
176                                                       Set<String> resourceFileProperties,
177                                                       Set<String> nestedParametersNames,
178                                                       GlobalValidationContext globalContext) {
179     if (CollectionUtils.isNotEmpty(nestedParametersNames)) {
180       resourceFileProperties
181               .stream()
182               .filter(propertyName -> !nestedParametersNames.contains(propertyName))
183               .forEach(propertyName -> globalContext
184                       .addMessage(parentFileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
185                                       .getErrorWithParameters(
186                                               globalContext.getMessageCode(),
187                                               Messages.MISSING_PARAMETER_IN_NESTED.getErrorMessage(),
188                                               nestedFileName, resourceName, propertyName)));
189     }
190   }
191
192   private static void checkNestedInputValuesAlignWithType(String parentFileName,
193                                                           String nestedFileName,
194                                                           Map<String, Parameter> nestedParameters,
195                                                           String resourceName, Resource resource,
196                                                           Optional<String> indexVarValue,
197                                                           GlobalValidationContext globalContext) {
198     Map<String, Object> properties = resource.getProperties();
199     for (Map.Entry<String, Object> propertyEntry : properties.entrySet()) {
200       String parameterName = propertyEntry.getKey();
201       Object parameterInputValue = propertyEntry.getValue();
202       if (parameterInputValue instanceof String) {
203         if (indexVarValue.isPresent() && indexVarValue.get().equals(parameterInputValue)) {
204           parameterInputValue = 3; //indexVarValue is actually number value in runtime
205         }
206         validateStaticValueForNestedInputParameter(parentFileName, nestedFileName, resourceName,
207                 parameterName, parameterInputValue, nestedParameters.get(parameterName),
208                 globalContext);
209       }
210     }
211   }
212
213   private static void validateStaticValueForNestedInputParameter(String parentFileName,
214                                                                  String nestedFileName,
215                                                                  String resourceName,
216                                                                  String parameterName,
217                                                                  Object staticValue,
218                                                                  Parameter parameterInNested,
219                                                                  GlobalValidationContext
220                                                                          globalContext) {
221     if (parameterInNested == null) {
222       return;
223     }
224     if (!DefinedHeatParameterTypes
225             .isValueIsFromGivenType(staticValue, parameterInNested.getType())) {
226       globalContext.addMessage(parentFileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder
227                       .getErrorWithParameters(globalContext.getMessageCode(),
228                               Messages.WRONG_VALUE_TYPE_ASSIGNED_NESTED_INPUT.getErrorMessage(),
229                               resourceName, parameterName, nestedFileName));
230     }
231   }
232
233
234   /**
235    * Is nested loop exist in file boolean.
236    *
237    * @param callingFileName the calling file name
238    * @param nestedFileName the nested file name
239    * @param filesInLoop the files in loop
240    * @param globalContext the global context
241    * @return the boolean
242    */
243   public static boolean isNestedLoopExistInFile(String callingFileName, String nestedFileName,
244                                                 List<String> filesInLoop,
245                                                 GlobalValidationContext globalContext) {
246     HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
247     try {
248       nestedHeatOrchestrationTemplate = getNestedHeatOrchestrationTemplate(nestedFileName,
249                                           globalContext);
250     } catch (Exception exception) {
251       LOGGER.error("Error while reading file :  " + nestedFileName, exception);
252       LOGGER.warn("HEAT Validator will not be executed on file " + nestedFileName
253               + " due to illegal HEAT format");
254       return false;
255     }
256     filesInLoop.add(nestedFileName);
257     Collection<Resource> nestedResources =
258             nestedHeatOrchestrationTemplate.getResources() == null ? null
259                     : nestedHeatOrchestrationTemplate.getResources().values();
260     return addNestedFilesInLoopAndCheckIfNestedLoopExist(nestedResources,
261                     callingFileName, filesInLoop, globalContext);
262   }
263   private static boolean addNestedFilesInLoopAndCheckIfNestedLoopExist(
264                 Collection<Resource> nestedResources,String callingFileName,
265                 List<String> filesInLoop,
266                 GlobalValidationContext globalContext){
267     if (CollectionUtils.isNotEmpty(nestedResources)) {
268       for (Resource resource : nestedResources) {
269         String resourceType = resource.getType();
270
271         if (Objects.nonNull(resourceType) && isNestedResource(resourceType)) {
272           return resourceType.equals(callingFileName) || !filesInLoop.contains(resourceType)
273                   && isNestedLoopExistInFile(callingFileName, resourceType, filesInLoop, globalContext);
274         }
275       }
276     }
277     return false;
278   }
279   private static HeatOrchestrationTemplate getNestedHeatOrchestrationTemplate( String nestedFileName,
280                                           GlobalValidationContext globalContext) throws Exception {
281     Optional<InputStream> fileContent = globalContext.getFileContent(nestedFileName);
282     HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
283     if (fileContent.isPresent()) {
284       nestedHeatOrchestrationTemplate =
285               new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
286     } else {
287       throw new Exception(String.format(NO_CONTENT_IN_FILE_MSG, nestedFileName));
288     }
289
290     return nestedHeatOrchestrationTemplate;
291   }
292
293   public static boolean isNestedResource(String resourceType) {
294     return resourceType.contains(".yaml") || resourceType.contains(".yml");
295   }
296
297   /**
298    * Validate env content environment.
299    *
300    * @param fileName the file name
301    * @param envFileName the env file name
302    * @param globalContext the global context
303    * @return the environment
304    */
305   public static Environment validateEnvContent(String fileName, String envFileName,
306                                                GlobalValidationContext globalContext) {
307     Environment envContent;
308     try {
309       Optional<InputStream> fileContent = globalContext.getFileContent(envFileName);
310       if (fileContent.isPresent()) {
311         envContent = new YamlUtil().yamlToObject(fileContent.get(), Environment.class);
312       } else {
313         throw new Exception(String.format(NO_CONTENT_IN_FILE_MSG, envFileName));
314       }
315     } catch (Exception exception) {
316       LOGGER.error("Error while reading env file : " + envFileName, exception);
317       return null;
318     }
319     return envContent;
320   }
321
322
323   public static String getResourceGroupResourceName(String resourceCallingToResourceGroup) {
324     return "OS::Heat::ResourceGroup in " + resourceCallingToResourceGroup;
325   }
326
327 }