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