2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.validation.impl.util;
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.openecomp.sdc.tosca.services.YamlUtil;
25 import org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder;
26 import org.openecomp.core.validation.types.GlobalValidationContext;
27 import org.openecomp.sdc.common.errors.Messages;
28 import org.openecomp.sdc.datatypes.error.ErrorLevel;
29 import org.openecomp.sdc.heat.datatypes.DefinedHeatParameterTypes;
30 import org.openecomp.sdc.heat.datatypes.model.Environment;
31 import org.openecomp.sdc.heat.datatypes.model.HeatOrchestrationTemplate;
32 import org.openecomp.sdc.heat.datatypes.model.Parameter;
33 import org.openecomp.sdc.heat.datatypes.model.Resource;
34 import org.openecomp.sdc.logging.api.Logger;
35 import org.openecomp.sdc.logging.api.LoggerFactory;
36 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
37 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
38 import org.openecomp.sdc.logging.types.LoggerConstants;
39 import org.openecomp.sdc.logging.types.LoggerErrorCode;
40 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
41 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
42 import org.openecomp.sdc.validation.impl.validators.HeatValidator;
44 import java.io.InputStream;
45 import java.util.Collection;
46 import java.util.List;
48 import java.util.Objects;
49 import java.util.Optional;
53 public class HeatValidationService {
55 private static final Logger logger = (Logger) LoggerFactory.getLogger(HeatValidator.class);
56 private static final String NESTED_FILE = "nested file";
57 private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
60 * Check artifacts existence.
62 * @param fileName the file name
63 * @param artifactsNames the artifacts names
64 * @param globalContext the global context
66 public static void checkArtifactsExistence(String fileName, Set<String> artifactsNames,
67 GlobalValidationContext globalContext) {
70 mdcDataDebugMessage.debugEntryMessage("file", fileName);
73 .filter(artifactName -> !globalContext.getFileContextMap().containsKey(artifactName))
74 .forEach(artifactName -> {
75 globalContext.addMessage(fileName,
76 ErrorLevel.ERROR, ErrorMessagesFormatBuilder
77 .getErrorWithParameters(globalContext.getMessageCode(),Messages.MISSING_ARTIFACT.getErrorMessage()
79 LoggerTragetServiceName.VALIDATE_ARTIFACTS_EXISTENCE,
80 LoggerErrorDescription.MISSING_FILE);
83 mdcDataDebugMessage.debugExitMessage("file", fileName);
87 * Draw files loop string.
89 * @param filesInPath the files in path
92 public static String drawFilesLoop(List<String> filesInPath) {
93 StringBuilder stringBuilder = new StringBuilder();
94 stringBuilder.append("[");
95 int pathSize = filesInPath.size();
97 for (int i = 0; i < pathSize; i++) {
98 stringBuilder.append(filesInPath.get(i));
99 if (i != pathSize - 1) {
100 stringBuilder.append(" -- ");
103 if (!filesInPath.get(0).equals(filesInPath.get(pathSize - 1))) {
104 stringBuilder.append(" -- ");
105 stringBuilder.append(filesInPath.get(0));
107 stringBuilder.append("]");
109 return stringBuilder.toString();
114 * Check nested parameters.
116 * @param parentFileName the calling nested file name
117 * @param nestedFileName the nested file name
118 * @param resourceName the resource name
119 * @param globalContext the global context
120 * @param resourceFileProperties the resource file properties
122 public static void checkNestedParameters(String parentFileName, String nestedFileName,
123 String resourceName, Resource resource,
124 Set<String> resourceFileProperties,
125 Optional<String> indexVarValue,
126 GlobalValidationContext globalContext) {
129 mdcDataDebugMessage.debugEntryMessage("file", parentFileName);
131 HeatOrchestrationTemplate parentHeatOrchestrationTemplate;
132 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
134 Optional<InputStream> fileContent = globalContext.getFileContent(nestedFileName);
135 if (fileContent.isPresent()) {
136 nestedHeatOrchestrationTemplate =
137 new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
139 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
140 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
141 ErrorLevel.ERROR.name(), LoggerErrorCode.DATA_ERROR.getErrorCode(),
142 LoggerErrorDescription.EMPTY_FILE);
143 throw new Exception("The file '" + nestedFileName + "' has no content");
145 } catch (Exception exception) {
146 logger.debug("",exception);
147 mdcDataDebugMessage.debugExitMessage("file", parentFileName);
152 Optional<InputStream> fileContent = globalContext.getFileContent(parentFileName);
153 if (fileContent.isPresent()) {
154 parentHeatOrchestrationTemplate =
155 new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
157 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
158 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
159 ErrorLevel.ERROR.name(), LoggerErrorCode.DATA_ERROR.getErrorCode(),
160 LoggerErrorDescription.EMPTY_FILE);
161 throw new Exception("The file '" + parentFileName + "' has no content");
163 } catch (Exception exception) {
164 logger.debug("",exception);
165 mdcDataDebugMessage.debugExitMessage("file", parentFileName);
168 Map<String, Parameter> parentParameters = parentHeatOrchestrationTemplate.getParameters();
169 Map<String, Parameter> nestedParameters = nestedHeatOrchestrationTemplate.getParameters();
170 Set<String> nestedParametersNames =
171 nestedParameters == null ? null : nestedHeatOrchestrationTemplate.getParameters().keySet();
173 checkNoMissingParameterInNested(parentFileName, nestedFileName, resourceName,
174 resourceFileProperties, nestedParametersNames, globalContext);
175 checkNestedInputValuesAlignWithType(parentFileName, nestedFileName, parentParameters,
176 nestedParameters, resourceName, resource, indexVarValue, globalContext);
178 mdcDataDebugMessage.debugExitMessage("file", parentFileName);
182 private static void checkNoMissingParameterInNested(String parentFileName, String nestedFileName,
184 Set<String> resourceFileProperties,
185 Set<String> nestedParametersNames,
186 GlobalValidationContext globalContext) {
188 mdcDataDebugMessage.debugEntryMessage(NESTED_FILE, nestedFileName);
190 if (CollectionUtils.isNotEmpty(nestedParametersNames)) {
191 resourceFileProperties
193 .filter(propertyName -> !nestedParametersNames.contains(propertyName))
194 .forEach(propertyName -> globalContext
195 .addMessage(parentFileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
196 .getErrorWithParameters(Messages
197 .MISSING_PARAMETER_IN_NESTED.getErrorMessage(),
198 nestedFileName, resourceName, propertyName),
199 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
200 LoggerErrorDescription.MISSING_PARAMETER_IN_NESTED));
203 mdcDataDebugMessage.debugExitMessage(NESTED_FILE, nestedFileName);
207 private static void checkNestedInputValuesAlignWithType(String parentFileName,
208 String nestedFileName,
209 Map<String, Parameter> parentParameters,
210 Map<String, Parameter> nestedParameters,
211 String resourceName, Resource resource,
212 Optional<String> indexVarValue,
213 GlobalValidationContext globalContext) {
216 mdcDataDebugMessage.debugEntryMessage(NESTED_FILE, nestedFileName);
218 Map<String, Object> properties = resource.getProperties();
219 for (Map.Entry<String, Object> propertyEntry : properties.entrySet()) {
220 String parameterName = propertyEntry.getKey();
221 Object parameterInputValue = propertyEntry.getValue();
223 if (Objects.nonNull(parameterInputValue)) {
224 if (parameterInputValue instanceof String) {
225 if (indexVarValue.isPresent() && indexVarValue.get().equals(parameterInputValue)) {
226 parameterInputValue = 3; //indexVarValue is actually number value in runtime
228 validateStaticValueForNestedInputParameter(parentFileName, nestedFileName, resourceName,
229 parameterName, parameterInputValue, nestedParameters.get(parameterName),
235 mdcDataDebugMessage.debugExitMessage(NESTED_FILE, nestedFileName);
238 private static void validateStaticValueForNestedInputParameter(String parentFileName,
239 String nestedFileName,
241 String parameterName,
243 Parameter parameterInNested,
244 GlobalValidationContext
248 mdcDataDebugMessage.debugEntryMessage(NESTED_FILE, nestedFileName);
250 if (parameterInNested == null) {
253 if (!DefinedHeatParameterTypes
254 .isValueIsFromGivenType(staticValue, parameterInNested.getType())) {
255 globalContext.addMessage(parentFileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder
256 .getErrorWithParameters(Messages
257 .WRONG_VALUE_TYPE_ASSIGNED_NESTED_INPUT.getErrorMessage(),
258 resourceName, parameterName, nestedFileName),
259 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
260 LoggerErrorDescription.WRONG_VALUE_ASSIGNED_NESTED_PARAMETER);
263 mdcDataDebugMessage.debugExitMessage(NESTED_FILE, nestedFileName);
268 * Is nested loop exist in file boolean.
270 * @param callingFileName the calling file name
271 * @param nestedFileName the nested file name
272 * @param filesInLoop the files in loop
273 * @param globalContext the global context
274 * @return the boolean
276 public static boolean isNestedLoopExistInFile(String callingFileName, String nestedFileName,
277 List<String> filesInLoop,
278 GlobalValidationContext globalContext) {
281 mdcDataDebugMessage.debugEntryMessage("file", callingFileName);
283 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
285 Optional<InputStream> fileContent = globalContext.getFileContent(nestedFileName);
286 if (fileContent.isPresent()) {
287 nestedHeatOrchestrationTemplate =
288 new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
290 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
291 LoggerTragetServiceName.VALIDATE_NESTING_LOOPS, ErrorLevel.ERROR.name(),
292 LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.EMPTY_FILE);
293 throw new Exception("The file '" + nestedFileName + "' has no content");
296 } catch (Exception exception) {
297 logger.debug("",exception);
298 logger.warn("HEAT Validator will not be executed on file " + nestedFileName
299 + " due to illegal HEAT format");
301 mdcDataDebugMessage.debugExitMessage("file", callingFileName);
304 filesInLoop.add(nestedFileName);
305 Collection<Resource> nestedResources =
306 nestedHeatOrchestrationTemplate.getResources() == null ? null
307 : nestedHeatOrchestrationTemplate.getResources().values();
308 if (CollectionUtils.isNotEmpty(nestedResources)) {
309 for (Resource resource : nestedResources) {
310 String resourceType = resource.getType();
312 if (Objects.nonNull(resourceType) && isNestedResource(resourceType)) {
313 mdcDataDebugMessage.debugExitMessage("file", callingFileName);
314 return resourceType.equals(callingFileName) || !filesInLoop.contains(resourceType)
315 && isNestedLoopExistInFile(callingFileName, resourceType, filesInLoop, globalContext);
320 mdcDataDebugMessage.debugExitMessage("file", callingFileName);
324 public static boolean isNestedResource(String resourceType) {
325 return resourceType.contains(".yaml") || resourceType.contains(".yml");
329 * Validate env content environment.
331 * @param fileName the file name
332 * @param envFileName the env file name
333 * @param globalContext the global context
334 * @return the environment
336 public static Environment validateEnvContent(String fileName, String envFileName,
337 GlobalValidationContext globalContext) {
340 mdcDataDebugMessage.debugEntryMessage("env file", envFileName);
342 Environment envContent = null;
344 Optional<InputStream> fileContent = globalContext.getFileContent(envFileName);
345 if (fileContent.isPresent()) {
346 envContent = new YamlUtil().yamlToObject(fileContent.get(), Environment.class);
348 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
349 LoggerTragetServiceName.VALIDATE_ENV_FILE, ErrorLevel.ERROR.name(),
350 LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.EMPTY_FILE);
351 throw new Exception("The file '" + envFileName + "' has no content");
353 } catch (Exception exception) {
354 logger.debug("",exception);
355 mdcDataDebugMessage.debugExitMessage("env file", envFileName);
362 public static String getResourceGroupResourceName(String resourceCallingToResourceGroup) {
363 return "OS::Heat::ResourceGroup in " + resourceCallingToResourceGroup;