2 * Copyright © 2016-2017 European Support Limited
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org.openecomp.sdc.validation.impl.util;
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.context.impl.MdcDataDebugMessage;
32 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
33 import org.openecomp.sdc.logging.types.LoggerConstants;
34 import org.openecomp.sdc.logging.types.LoggerErrorCode;
35 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
36 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
37 import org.openecomp.sdc.tosca.services.YamlUtil;
38 import org.openecomp.sdc.validation.impl.validators.HeatValidator;
40 import java.io.InputStream;
41 import java.util.Collection;
42 import java.util.HashMap;
43 import java.util.HashSet;
44 import java.util.List;
46 import java.util.Objects;
47 import java.util.Optional;
51 public class HeatValidationService {
53 private static final Logger LOGGER = LoggerFactory.getLogger(HeatValidator.class);
54 private static final String NESTED_FILE = "nested file";
55 private static final String NO_CONTENT_IN_FILE_MSG = "The file ' %s ' has no content";
56 private static final MdcDataDebugMessage MDC_DATA_DEBUG_MESSAGE = new MdcDataDebugMessage();
57 private HeatValidationService(){
61 * Check artifacts existence.
63 * @param fileName the file name
64 * @param artifactsNames the artifacts names
65 * @param globalContext the global context
67 public static void checkArtifactsExistence(String fileName, Set<String> artifactsNames,
68 GlobalValidationContext globalContext) {
71 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("file", fileName);
74 .filter(artifactName -> !globalContext.getFileContextMap().containsKey(artifactName))
75 .forEach(artifactName ->
76 globalContext.addMessage(fileName,
77 ErrorLevel.ERROR, ErrorMessagesFormatBuilder
78 .getErrorWithParameters(
79 globalContext.getMessageCode(),
80 Messages.MISSING_ARTIFACT.getErrorMessage(), artifactName),
81 LoggerTragetServiceName.VALIDATE_ARTIFACTS_EXISTENCE,
82 LoggerErrorDescription.MISSING_FILE));
84 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", fileName);
88 * Draw files loop string.
90 * @param filesInPath the files in path
93 public static String drawFilesLoop(List<String> filesInPath) {
94 StringBuilder stringBuilder = new StringBuilder();
95 stringBuilder.append("[");
96 int pathSize = filesInPath.size();
98 for (int i = 0; i < pathSize; i++) {
99 stringBuilder.append(filesInPath.get(i));
100 if (i != pathSize - 1) {
101 stringBuilder.append(" -- ");
104 if (!filesInPath.get(0).equals(filesInPath.get(pathSize - 1))) {
105 stringBuilder.append(" -- ");
106 stringBuilder.append(filesInPath.get(0));
108 stringBuilder.append("]");
110 return stringBuilder.toString();
114 * Check nested parameters.
116 * @param parentFileName the calling nested file name
117 * @param nestedFileName the nested file name
118 * @param globalContext the global context
119 * @param parentParameters parent parameters.
120 * @param nestedParameters nested parameters.
121 * @param nestedParametersNames nested parameter names.
123 public static void checkNestedParameters(String parentFileName, String nestedFileName,
124 GlobalValidationContext globalContext,
125 Map<String, Parameter> parentParameters,
126 Map<String, Parameter> nestedParameters,
127 Set<String> nestedParametersNames) {
129 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("file", parentFileName);
131 HeatOrchestrationTemplate parentHeatOrchestrationTemplate;
132 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
135 nestedHeatOrchestrationTemplate = getHeatOrchestrationTemplate(nestedFileName, globalContext);
136 parentHeatOrchestrationTemplate = getHeatOrchestrationTemplate(parentFileName, globalContext);
137 } catch (Exception exception) {
138 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", parentFileName);
142 parentParameters.putAll(parentHeatOrchestrationTemplate.getParameters());
143 nestedParameters.putAll(nestedHeatOrchestrationTemplate.getParameters());
144 if (!nestedParameters.isEmpty()) {
145 nestedParametersNames.addAll(nestedHeatOrchestrationTemplate.getParameters().keySet());
148 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", parentFileName);
151 private static HeatOrchestrationTemplate getHeatOrchestrationTemplate(String fileName,
152 GlobalValidationContext globalContext)
155 Optional<InputStream> fileContent = globalContext.getFileContent(fileName);
156 if (fileContent.isPresent()) {
157 return new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
159 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
160 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
161 ErrorLevel.ERROR.name(), LoggerErrorCode.DATA_ERROR.getErrorCode(),
162 LoggerErrorDescription.EMPTY_FILE);
163 Exception exception = new Exception(String.format(NO_CONTENT_IN_FILE_MSG, fileName));
164 LOGGER.error("Error while reading file : " + fileName , exception);
169 public static void checkNestedParametersNoMissingParameterInNested(String parentFileName,
170 String nestedFileName,
172 Set<String> resourceFileProperties,
173 GlobalValidationContext globalContext) {
174 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("file", parentFileName);
176 Map<String, Parameter> parentParameters = new HashMap<>();
177 Map<String, Parameter> nestedParameters = new HashMap<>();
178 Set<String> nestedParametersNames = new HashSet<>();
179 checkNestedParameters(parentFileName, nestedFileName, globalContext, parentParameters,
180 nestedParameters, nestedParametersNames);
182 checkNoMissingParameterInNested(parentFileName, nestedFileName, resourceName,
183 resourceFileProperties, nestedParametersNames, globalContext);
185 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", parentFileName);
188 public static void checkNestedInputValuesAlignWithType(String parentFileName,
189 String nestedFileName,
190 String resourceName, Resource resource,
191 Optional<String> indexVarValue,
192 GlobalValidationContext globalContext) {
193 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("file", parentFileName);
195 Map<String, Parameter> parentParameters = new HashMap<>();
196 Map<String, Parameter> nestedParameters = new HashMap<>();
197 Set<String> nestedParametersNames = new HashSet<>();
198 checkNestedParameters(parentFileName, nestedFileName, globalContext, parentParameters,
199 nestedParameters, nestedParametersNames);
201 checkNestedInputValuesAlignWithType(parentFileName, nestedFileName,
202 nestedParameters, resourceName, resource, indexVarValue, globalContext);
204 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", parentFileName);
207 private static void checkNoMissingParameterInNested(String parentFileName, String nestedFileName,
209 Set<String> resourceFileProperties,
210 Set<String> nestedParametersNames,
211 GlobalValidationContext globalContext) {
213 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("nested file", nestedFileName);
215 if (CollectionUtils.isNotEmpty(nestedParametersNames)) {
216 resourceFileProperties
218 .filter(propertyName -> !nestedParametersNames.contains(propertyName))
219 .forEach(propertyName -> globalContext
220 .addMessage(parentFileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
221 .getErrorWithParameters(
222 globalContext.getMessageCode(),
223 Messages.MISSING_PARAMETER_IN_NESTED.getErrorMessage(),
224 nestedFileName, resourceName, propertyName),
225 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
226 LoggerErrorDescription.MISSING_PARAMETER_IN_NESTED));
229 MDC_DATA_DEBUG_MESSAGE.debugExitMessage(NESTED_FILE, nestedFileName);
232 private static void checkNestedInputValuesAlignWithType(String parentFileName,
233 String nestedFileName,
234 Map<String, Parameter> nestedParameters,
235 String resourceName, Resource resource,
236 Optional<String> indexVarValue,
237 GlobalValidationContext globalContext) {
239 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage(NESTED_FILE, nestedFileName);
241 Map<String, Object> properties = resource.getProperties();
242 for (Map.Entry<String, Object> propertyEntry : properties.entrySet()) {
243 String parameterName = propertyEntry.getKey();
244 Object parameterInputValue = propertyEntry.getValue();
245 if (parameterInputValue instanceof String) {
246 if (indexVarValue.isPresent() && indexVarValue.get().equals(parameterInputValue)) {
247 parameterInputValue = 3; //indexVarValue is actually number value in runtime
249 validateStaticValueForNestedInputParameter(parentFileName, nestedFileName, resourceName,
250 parameterName, parameterInputValue, nestedParameters.get(parameterName),
255 MDC_DATA_DEBUG_MESSAGE.debugExitMessage(NESTED_FILE, nestedFileName);
258 private static void validateStaticValueForNestedInputParameter(String parentFileName,
259 String nestedFileName,
261 String parameterName,
263 Parameter parameterInNested,
264 GlobalValidationContext
267 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage(NESTED_FILE, nestedFileName);
269 if (parameterInNested == null) {
272 if (!DefinedHeatParameterTypes
273 .isValueIsFromGivenType(staticValue, parameterInNested.getType())) {
274 globalContext.addMessage(parentFileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder
275 .getErrorWithParameters(globalContext.getMessageCode(),
276 Messages.WRONG_VALUE_TYPE_ASSIGNED_NESTED_INPUT.getErrorMessage(),
277 resourceName, parameterName, nestedFileName),
278 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
279 LoggerErrorDescription.WRONG_VALUE_ASSIGNED_NESTED_PARAMETER);
282 MDC_DATA_DEBUG_MESSAGE.debugExitMessage(NESTED_FILE, nestedFileName);
287 * Is nested loop exist in file boolean.
289 * @param callingFileName the calling file name
290 * @param nestedFileName the nested file name
291 * @param filesInLoop the files in loop
292 * @param globalContext the global context
293 * @return the boolean
295 public static boolean isNestedLoopExistInFile(String callingFileName, String nestedFileName,
296 List<String> filesInLoop,
297 GlobalValidationContext globalContext) {
299 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("file", callingFileName);
301 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
303 nestedHeatOrchestrationTemplate = getNestedHeatOrchestrationTemplate(nestedFileName,
305 } catch (Exception exception) {
306 LOGGER.error("Error while reading file : " + nestedFileName, exception);
307 LOGGER.warn("HEAT Validator will not be executed on file " + nestedFileName
308 + " due to illegal HEAT format");
310 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", callingFileName);
313 filesInLoop.add(nestedFileName);
314 Collection<Resource> nestedResources =
315 nestedHeatOrchestrationTemplate.getResources() == null ? null
316 : nestedHeatOrchestrationTemplate.getResources().values();
317 boolean isNestedLoopExist = addNestedFilesInLoopAndCheckIfNestedLoopExist(nestedResources,
318 callingFileName, filesInLoop, globalContext);
320 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", callingFileName);
321 return isNestedLoopExist;
323 private static boolean addNestedFilesInLoopAndCheckIfNestedLoopExist(
324 Collection<Resource> nestedResources,String callingFileName,
325 List<String> filesInLoop,
326 GlobalValidationContext globalContext){
327 if (CollectionUtils.isNotEmpty(nestedResources)) {
328 for (Resource resource : nestedResources) {
329 String resourceType = resource.getType();
331 if (Objects.nonNull(resourceType) && isNestedResource(resourceType)) {
332 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", callingFileName);
333 return resourceType.equals(callingFileName) || !filesInLoop.contains(resourceType)
334 && isNestedLoopExistInFile(callingFileName, resourceType, filesInLoop, globalContext);
340 private static HeatOrchestrationTemplate getNestedHeatOrchestrationTemplate( String nestedFileName,
341 GlobalValidationContext globalContext) throws Exception {
342 Optional<InputStream> fileContent = globalContext.getFileContent(nestedFileName);
343 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
344 if (fileContent.isPresent()) {
345 nestedHeatOrchestrationTemplate =
346 new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
348 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
349 LoggerTragetServiceName.VALIDATE_NESTING_LOOPS, ErrorLevel.ERROR.name(),
350 LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.EMPTY_FILE);
351 throw new Exception(String.format(NO_CONTENT_IN_FILE_MSG, nestedFileName));
354 return nestedHeatOrchestrationTemplate;
357 public static boolean isNestedResource(String resourceType) {
358 return resourceType.contains(".yaml") || resourceType.contains(".yml");
362 * Validate env content environment.
364 * @param fileName the file name
365 * @param envFileName the env file name
366 * @param globalContext the global context
367 * @return the environment
369 public static Environment validateEnvContent(String fileName, String envFileName,
370 GlobalValidationContext globalContext) {
372 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("env file", envFileName);
374 Environment envContent;
376 Optional<InputStream> fileContent = globalContext.getFileContent(envFileName);
377 if (fileContent.isPresent()) {
378 envContent = new YamlUtil().yamlToObject(fileContent.get(), Environment.class);
380 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
381 LoggerTragetServiceName.VALIDATE_ENV_FILE, ErrorLevel.ERROR.name(),
382 LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.EMPTY_FILE);
383 throw new Exception(String.format(NO_CONTENT_IN_FILE_MSG, envFileName));
385 } catch (Exception exception) {
386 LOGGER.error("Error while reading env file : " + envFileName, exception);
387 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("env file", envFileName);
394 public static String getResourceGroupResourceName(String resourceCallingToResourceGroup) {
395 return "OS::Heat::ResourceGroup in " + resourceCallingToResourceGroup;