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.sdc.heat.datatypes.model.*;
21 import org.openecomp.sdc.tosca.services.YamlUtil;
22 import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder;
23 import org.openecomp.core.validation.types.GlobalValidationContext;
24 import org.openecomp.sdc.common.errors.Messages;
25 import org.openecomp.sdc.datatypes.error.ErrorLevel;
26 import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes;
27 import org.openecomp.sdc.logging.api.Logger;
28 import org.openecomp.sdc.logging.api.LoggerFactory;
29 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
30 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
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.validation.impl.validators.HeatValidator;
37 import java.io.InputStream;
41 public class HeatValidationService {
43 private static final Logger LOGGER = LoggerFactory.getLogger(HeatValidator.class);
44 private static final String NESTED_FILE = "nested file";
45 private static final String NO_CONTENT_IN_FILE_MSG = "The file ' %s ' has no content";
46 private static final MdcDataDebugMessage MDC_DATA_DEBUG_MESSAGE = new MdcDataDebugMessage();
47 private HeatValidationService(){
51 * Check artifacts existence.
53 * @param fileName the file name
54 * @param artifactsNames the artifacts names
55 * @param globalContext the global context
57 public static void checkArtifactsExistence(String fileName, Set<String> artifactsNames,
58 GlobalValidationContext globalContext) {
61 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("file", fileName);
64 .filter(artifactName -> !globalContext.getFileContextMap().containsKey(artifactName))
65 .forEach(artifactName ->
66 globalContext.addMessage(fileName,
67 ErrorLevel.ERROR, ErrorMessagesFormatBuilder
68 .getErrorWithParameters(
69 globalContext.getMessageCode(),
70 Messages.MISSING_ARTIFACT.getErrorMessage(), artifactName),
71 LoggerTragetServiceName.VALIDATE_ARTIFACTS_EXISTENCE,
72 LoggerErrorDescription.MISSING_FILE));
74 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", fileName);
78 * Draw files loop string.
80 * @param filesInPath the files in path
83 public static String drawFilesLoop(List<String> filesInPath) {
84 StringBuilder stringBuilder = new StringBuilder();
85 stringBuilder.append("[");
86 int pathSize = filesInPath.size();
88 for (int i = 0; i < pathSize; i++) {
89 stringBuilder.append(filesInPath.get(i));
90 if (i != pathSize - 1) {
91 stringBuilder.append(" -- ");
94 if (!filesInPath.get(0).equals(filesInPath.get(pathSize - 1))) {
95 stringBuilder.append(" -- ");
96 stringBuilder.append(filesInPath.get(0));
98 stringBuilder.append("]");
100 return stringBuilder.toString();
104 * Check nested parameters.
106 * @param parentFileName the calling nested file name
107 * @param nestedFileName the nested file name
108 * @param globalContext the global context
109 * @param parentParameters parent parameters.
110 * @param nestedParameters nested parameters.
111 * @param nestedParametersNames nested parameter names.
113 public static void checkNestedParameters(String parentFileName, String nestedFileName,
114 GlobalValidationContext globalContext,
115 Map<String, Parameter> parentParameters,
116 Map<String, Parameter> nestedParameters,
117 Set<String> nestedParametersNames) {
119 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("file", parentFileName);
121 HeatOrchestrationTemplate parentHeatOrchestrationTemplate;
122 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
125 nestedHeatOrchestrationTemplate = getHeatOrchestrationTemplate(nestedFileName, globalContext);
126 parentHeatOrchestrationTemplate = getHeatOrchestrationTemplate(parentFileName, globalContext);
127 } catch (Exception exception) {
128 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", parentFileName);
132 parentParameters.putAll(parentHeatOrchestrationTemplate.getParameters());
133 nestedParameters.putAll(nestedHeatOrchestrationTemplate.getParameters());
134 if (!nestedParameters.isEmpty()) {
135 nestedParametersNames.addAll(nestedHeatOrchestrationTemplate.getParameters().keySet());
138 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", parentFileName);
141 private static HeatOrchestrationTemplate getHeatOrchestrationTemplate(String fileName,
142 GlobalValidationContext globalContext)
145 Optional<InputStream> fileContent = globalContext.getFileContent(fileName);
146 if (fileContent.isPresent()) {
147 return new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
149 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
150 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
151 ErrorLevel.ERROR.name(), LoggerErrorCode.DATA_ERROR.getErrorCode(),
152 LoggerErrorDescription.EMPTY_FILE);
153 Exception exception = new Exception(String.format(NO_CONTENT_IN_FILE_MSG, fileName));
154 LOGGER.error("Error while reading file : " + fileName , exception);
159 public static void checkNestedParametersNoMissingParameterInNested(String parentFileName,
160 String nestedFileName,
162 Set<String> resourceFileProperties,
163 GlobalValidationContext globalContext) {
164 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("file", parentFileName);
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);
172 checkNoMissingParameterInNested(parentFileName, nestedFileName, resourceName,
173 resourceFileProperties, nestedParametersNames, globalContext);
175 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", parentFileName);
178 public static void checkNestedInputValuesAlignWithType(String parentFileName,
179 String nestedFileName,
180 String resourceName, Resource resource,
181 Optional<String> indexVarValue,
182 GlobalValidationContext globalContext) {
183 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("file", parentFileName);
185 Map<String, Parameter> parentParameters = new HashMap<>();
186 Map<String, Parameter> nestedParameters = new HashMap<>();
187 Set<String> nestedParametersNames = new HashSet<>();
188 checkNestedParameters(parentFileName, nestedFileName, globalContext, parentParameters,
189 nestedParameters, nestedParametersNames);
191 checkNestedInputValuesAlignWithType(parentFileName, nestedFileName,
192 nestedParameters, resourceName, resource, indexVarValue, globalContext);
194 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", parentFileName);
197 private static void checkNoMissingParameterInNested(String parentFileName, String nestedFileName,
199 Set<String> resourceFileProperties,
200 Set<String> nestedParametersNames,
201 GlobalValidationContext globalContext) {
203 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("nested file", nestedFileName);
205 if (CollectionUtils.isNotEmpty(nestedParametersNames)) {
206 resourceFileProperties
208 .filter(propertyName -> !nestedParametersNames.contains(propertyName))
209 .forEach(propertyName -> globalContext
210 .addMessage(parentFileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
211 .getErrorWithParameters(
212 globalContext.getMessageCode(),
213 Messages.MISSING_PARAMETER_IN_NESTED.getErrorMessage(),
214 nestedFileName, resourceName, propertyName),
215 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
216 LoggerErrorDescription.MISSING_PARAMETER_IN_NESTED));
219 MDC_DATA_DEBUG_MESSAGE.debugExitMessage(NESTED_FILE, nestedFileName);
222 private static void checkNestedInputValuesAlignWithType(String parentFileName,
223 String nestedFileName,
224 Map<String, Parameter> nestedParameters,
225 String resourceName, Resource resource,
226 Optional<String> indexVarValue,
227 GlobalValidationContext globalContext) {
229 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage(NESTED_FILE, nestedFileName);
231 Map<String, Object> properties = resource.getProperties();
232 for (Map.Entry<String, Object> propertyEntry : properties.entrySet()) {
233 String parameterName = propertyEntry.getKey();
234 Object parameterInputValue = propertyEntry.getValue();
235 if (parameterInputValue instanceof String) {
236 if (indexVarValue.isPresent() && indexVarValue.get().equals(parameterInputValue)) {
237 parameterInputValue = 3; //indexVarValue is actually number value in runtime
239 validateStaticValueForNestedInputParameter(parentFileName, nestedFileName, resourceName,
240 parameterName, parameterInputValue, nestedParameters.get(parameterName),
245 MDC_DATA_DEBUG_MESSAGE.debugExitMessage(NESTED_FILE, nestedFileName);
248 private static void validateStaticValueForNestedInputParameter(String parentFileName,
249 String nestedFileName,
251 String parameterName,
253 Parameter parameterInNested,
254 GlobalValidationContext
257 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage(NESTED_FILE, nestedFileName);
259 if (parameterInNested == null) {
262 if (!DefinedHeatParameterTypes
263 .isValueIsFromGivenType(staticValue, parameterInNested.getType())) {
264 globalContext.addMessage(parentFileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder
265 .getErrorWithParameters(globalContext.getMessageCode(),
266 Messages.WRONG_VALUE_TYPE_ASSIGNED_NESTED_INPUT.getErrorMessage(),
267 resourceName, parameterName, nestedFileName),
268 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
269 LoggerErrorDescription.WRONG_VALUE_ASSIGNED_NESTED_PARAMETER);
272 MDC_DATA_DEBUG_MESSAGE.debugExitMessage(NESTED_FILE, nestedFileName);
277 * Is nested loop exist in file boolean.
279 * @param callingFileName the calling file name
280 * @param nestedFileName the nested file name
281 * @param filesInLoop the files in loop
282 * @param globalContext the global context
283 * @return the boolean
285 public static boolean isNestedLoopExistInFile(String callingFileName, String nestedFileName,
286 List<String> filesInLoop,
287 GlobalValidationContext globalContext) {
289 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("file", callingFileName);
291 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
293 nestedHeatOrchestrationTemplate = getNestedHeatOrchestrationTemplate(nestedFileName,
295 } catch (Exception exception) {
296 LOGGER.error("Error while reading file : " + nestedFileName, exception);
297 LOGGER.warn("HEAT Validator will not be executed on file " + nestedFileName
298 + " due to illegal HEAT format");
300 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", callingFileName);
303 filesInLoop.add(nestedFileName);
304 Collection<Resource> nestedResources =
305 nestedHeatOrchestrationTemplate.getResources() == null ? null
306 : nestedHeatOrchestrationTemplate.getResources().values();
307 boolean isNestedLoopExist = addNestedFilesInLoopAndCheckIfNestedLoopExist(nestedResources,
308 callingFileName, filesInLoop, globalContext);
310 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", callingFileName);
311 return isNestedLoopExist;
313 private static boolean addNestedFilesInLoopAndCheckIfNestedLoopExist(
314 Collection<Resource> nestedResources,String callingFileName,
315 List<String> filesInLoop,
316 GlobalValidationContext globalContext){
317 if (CollectionUtils.isNotEmpty(nestedResources)) {
318 for (Resource resource : nestedResources) {
319 String resourceType = resource.getType();
321 if (Objects.nonNull(resourceType) && isNestedResource(resourceType)) {
322 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("file", callingFileName);
323 return resourceType.equals(callingFileName) || !filesInLoop.contains(resourceType)
324 && isNestedLoopExistInFile(callingFileName, resourceType, filesInLoop, globalContext);
330 private static HeatOrchestrationTemplate getNestedHeatOrchestrationTemplate( String nestedFileName,
331 GlobalValidationContext globalContext) throws Exception {
332 Optional<InputStream> fileContent = globalContext.getFileContent(nestedFileName);
333 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
334 if (fileContent.isPresent()) {
335 nestedHeatOrchestrationTemplate =
336 new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
338 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
339 LoggerTragetServiceName.VALIDATE_NESTING_LOOPS, ErrorLevel.ERROR.name(),
340 LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.EMPTY_FILE);
341 throw new Exception(String.format(NO_CONTENT_IN_FILE_MSG, nestedFileName));
344 return nestedHeatOrchestrationTemplate;
347 public static boolean isNestedResource(String resourceType) {
348 return resourceType.contains(".yaml") || resourceType.contains(".yml");
352 * Validate env content environment.
354 * @param fileName the file name
355 * @param envFileName the env file name
356 * @param globalContext the global context
357 * @return the environment
359 public static Environment validateEnvContent(String fileName, String envFileName,
360 GlobalValidationContext globalContext) {
362 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("env file", envFileName);
364 Environment envContent;
366 Optional<InputStream> fileContent = globalContext.getFileContent(envFileName);
367 if (fileContent.isPresent()) {
368 envContent = new YamlUtil().yamlToObject(fileContent.get(), Environment.class);
370 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
371 LoggerTragetServiceName.VALIDATE_ENV_FILE, ErrorLevel.ERROR.name(),
372 LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.EMPTY_FILE);
373 throw new Exception(String.format(NO_CONTENT_IN_FILE_MSG, envFileName));
375 } catch (Exception exception) {
376 LOGGER.error("Error while reading env file : " + envFileName, exception);
377 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("env file", envFileName);
384 public static String getResourceGroupResourceName(String resourceCallingToResourceGroup) {
385 return "OS::Heat::ResourceGroup in " + resourceCallingToResourceGroup;