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.MdcDataErrorMessage;
32 import org.openecomp.sdc.logging.types.LoggerConstants;
33 import org.openecomp.sdc.logging.types.LoggerErrorCode;
34 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
35 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
36 import org.openecomp.sdc.tosca.services.YamlUtil;
37 import org.openecomp.sdc.validation.impl.validators.HeatValidator;
39 import java.io.InputStream;
40 import java.util.Collection;
41 import java.util.HashMap;
42 import java.util.HashSet;
43 import java.util.List;
45 import java.util.Objects;
46 import java.util.Optional;
50 public class HeatValidationService {
52 private static final Logger LOGGER = LoggerFactory.getLogger(HeatValidator.class);
53 private static final String NESTED_FILE = "nested file";
54 private static final String NO_CONTENT_IN_FILE_MSG = "The file ' %s ' has no content";
55 private HeatValidationService(){
59 * Check artifacts existence.
61 * @param fileName the file name
62 * @param artifactsNames the artifacts names
63 * @param globalContext the global context
65 public static void checkArtifactsExistence(String fileName, Set<String> artifactsNames,
66 GlobalValidationContext globalContext) {
69 .filter(artifactName -> !globalContext.getFileContextMap().containsKey(artifactName))
70 .forEach(artifactName ->
71 globalContext.addMessage(fileName,
72 ErrorLevel.ERROR, ErrorMessagesFormatBuilder
73 .getErrorWithParameters(
74 globalContext.getMessageCode(),
75 Messages.MISSING_ARTIFACT.getErrorMessage(), artifactName),
76 LoggerTragetServiceName.VALIDATE_ARTIFACTS_EXISTENCE,
77 LoggerErrorDescription.MISSING_FILE));
81 * Draw files loop string.
83 * @param filesInPath the files in path
86 public static String drawFilesLoop(List<String> filesInPath) {
87 StringBuilder stringBuilder = new StringBuilder();
88 stringBuilder.append("[");
89 int pathSize = filesInPath.size();
91 for (int i = 0; i < pathSize; i++) {
92 stringBuilder.append(filesInPath.get(i));
93 if (i != pathSize - 1) {
94 stringBuilder.append(" -- ");
97 if (!filesInPath.get(0).equals(filesInPath.get(pathSize - 1))) {
98 stringBuilder.append(" -- ");
99 stringBuilder.append(filesInPath.get(0));
101 stringBuilder.append("]");
103 return stringBuilder.toString();
107 * Check nested parameters.
109 * @param parentFileName the calling nested file name
110 * @param nestedFileName the nested file name
111 * @param globalContext the global context
112 * @param parentParameters parent parameters.
113 * @param nestedParameters nested parameters.
114 * @param nestedParametersNames nested parameter names.
116 public static void checkNestedParameters(String parentFileName, String nestedFileName,
117 GlobalValidationContext globalContext,
118 Map<String, Parameter> parentParameters,
119 Map<String, Parameter> nestedParameters,
120 Set<String> nestedParametersNames) {
121 HeatOrchestrationTemplate parentHeatOrchestrationTemplate;
122 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
125 nestedHeatOrchestrationTemplate = getHeatOrchestrationTemplate(nestedFileName, globalContext);
126 parentHeatOrchestrationTemplate = getHeatOrchestrationTemplate(parentFileName, globalContext);
127 } catch (Exception exception) {
131 parentParameters.putAll(parentHeatOrchestrationTemplate.getParameters());
132 nestedParameters.putAll(nestedHeatOrchestrationTemplate.getParameters());
133 if (!nestedParameters.isEmpty()) {
134 nestedParametersNames.addAll(nestedHeatOrchestrationTemplate.getParameters().keySet());
138 private static HeatOrchestrationTemplate getHeatOrchestrationTemplate(String fileName,
139 GlobalValidationContext globalContext)
142 Optional<InputStream> fileContent = globalContext.getFileContent(fileName);
143 if (fileContent.isPresent()) {
144 return new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
146 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
147 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
148 ErrorLevel.ERROR.name(), LoggerErrorCode.DATA_ERROR.getErrorCode(),
149 LoggerErrorDescription.EMPTY_FILE);
150 Exception exception = new Exception(String.format(NO_CONTENT_IN_FILE_MSG, fileName));
151 LOGGER.error("Error while reading file : " + fileName , exception);
156 public static void checkNestedParametersNoMissingParameterInNested(String parentFileName,
157 String nestedFileName,
159 Set<String> resourceFileProperties,
160 GlobalValidationContext globalContext) {
161 Map<String, Parameter> parentParameters = new HashMap<>();
162 Map<String, Parameter> nestedParameters = new HashMap<>();
163 Set<String> nestedParametersNames = new HashSet<>();
164 checkNestedParameters(parentFileName, nestedFileName, globalContext, parentParameters,
165 nestedParameters, nestedParametersNames);
167 checkNoMissingParameterInNested(parentFileName, nestedFileName, resourceName,
168 resourceFileProperties, nestedParametersNames, globalContext);
171 public static void checkNestedInputValuesAlignWithType(String parentFileName,
172 String nestedFileName,
173 String resourceName, Resource resource,
174 Optional<String> indexVarValue,
175 GlobalValidationContext globalContext) {
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 checkNestedInputValuesAlignWithType(parentFileName, nestedFileName,
183 nestedParameters, resourceName, resource, indexVarValue, globalContext);
186 private static void checkNoMissingParameterInNested(String parentFileName, String nestedFileName,
188 Set<String> resourceFileProperties,
189 Set<String> nestedParametersNames,
190 GlobalValidationContext globalContext) {
191 if (CollectionUtils.isNotEmpty(nestedParametersNames)) {
192 resourceFileProperties
194 .filter(propertyName -> !nestedParametersNames.contains(propertyName))
195 .forEach(propertyName -> globalContext
196 .addMessage(parentFileName, ErrorLevel.ERROR, ErrorMessagesFormatBuilder
197 .getErrorWithParameters(
198 globalContext.getMessageCode(),
199 Messages.MISSING_PARAMETER_IN_NESTED.getErrorMessage(),
200 nestedFileName, resourceName, propertyName),
201 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
202 LoggerErrorDescription.MISSING_PARAMETER_IN_NESTED));
206 private static void checkNestedInputValuesAlignWithType(String parentFileName,
207 String nestedFileName,
208 Map<String, Parameter> nestedParameters,
209 String resourceName, Resource resource,
210 Optional<String> indexVarValue,
211 GlobalValidationContext globalContext) {
212 Map<String, Object> properties = resource.getProperties();
213 for (Map.Entry<String, Object> propertyEntry : properties.entrySet()) {
214 String parameterName = propertyEntry.getKey();
215 Object parameterInputValue = propertyEntry.getValue();
216 if (parameterInputValue instanceof String) {
217 if (indexVarValue.isPresent() && indexVarValue.get().equals(parameterInputValue)) {
218 parameterInputValue = 3; //indexVarValue is actually number value in runtime
220 validateStaticValueForNestedInputParameter(parentFileName, nestedFileName, resourceName,
221 parameterName, parameterInputValue, nestedParameters.get(parameterName),
227 private static void validateStaticValueForNestedInputParameter(String parentFileName,
228 String nestedFileName,
230 String parameterName,
232 Parameter parameterInNested,
233 GlobalValidationContext
235 if (parameterInNested == null) {
238 if (!DefinedHeatParameterTypes
239 .isValueIsFromGivenType(staticValue, parameterInNested.getType())) {
240 globalContext.addMessage(parentFileName, ErrorLevel.WARNING, ErrorMessagesFormatBuilder
241 .getErrorWithParameters(globalContext.getMessageCode(),
242 Messages.WRONG_VALUE_TYPE_ASSIGNED_NESTED_INPUT.getErrorMessage(),
243 resourceName, parameterName, nestedFileName),
244 LoggerTragetServiceName.VALIDATE_PROPERTIES_MATCH_NESTED_PARAMETERS,
245 LoggerErrorDescription.WRONG_VALUE_ASSIGNED_NESTED_PARAMETER);
251 * Is nested loop exist in file boolean.
253 * @param callingFileName the calling file name
254 * @param nestedFileName the nested file name
255 * @param filesInLoop the files in loop
256 * @param globalContext the global context
257 * @return the boolean
259 public static boolean isNestedLoopExistInFile(String callingFileName, String nestedFileName,
260 List<String> filesInLoop,
261 GlobalValidationContext globalContext) {
262 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
264 nestedHeatOrchestrationTemplate = getNestedHeatOrchestrationTemplate(nestedFileName,
266 } catch (Exception exception) {
267 LOGGER.error("Error while reading file : " + nestedFileName, exception);
268 LOGGER.warn("HEAT Validator will not be executed on file " + nestedFileName
269 + " due to illegal HEAT format");
272 filesInLoop.add(nestedFileName);
273 Collection<Resource> nestedResources =
274 nestedHeatOrchestrationTemplate.getResources() == null ? null
275 : nestedHeatOrchestrationTemplate.getResources().values();
276 boolean isNestedLoopExist = addNestedFilesInLoopAndCheckIfNestedLoopExist(nestedResources,
277 callingFileName, filesInLoop, globalContext);
278 return isNestedLoopExist;
280 private static boolean addNestedFilesInLoopAndCheckIfNestedLoopExist(
281 Collection<Resource> nestedResources,String callingFileName,
282 List<String> filesInLoop,
283 GlobalValidationContext globalContext){
284 if (CollectionUtils.isNotEmpty(nestedResources)) {
285 for (Resource resource : nestedResources) {
286 String resourceType = resource.getType();
288 if (Objects.nonNull(resourceType) && isNestedResource(resourceType)) {
289 return resourceType.equals(callingFileName) || !filesInLoop.contains(resourceType)
290 && isNestedLoopExistInFile(callingFileName, resourceType, filesInLoop, globalContext);
296 private static HeatOrchestrationTemplate getNestedHeatOrchestrationTemplate( String nestedFileName,
297 GlobalValidationContext globalContext) throws Exception {
298 Optional<InputStream> fileContent = globalContext.getFileContent(nestedFileName);
299 HeatOrchestrationTemplate nestedHeatOrchestrationTemplate;
300 if (fileContent.isPresent()) {
301 nestedHeatOrchestrationTemplate =
302 new YamlUtil().yamlToObject(fileContent.get(), HeatOrchestrationTemplate.class);
304 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
305 LoggerTragetServiceName.VALIDATE_NESTING_LOOPS, ErrorLevel.ERROR.name(),
306 LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.EMPTY_FILE);
307 throw new Exception(String.format(NO_CONTENT_IN_FILE_MSG, nestedFileName));
310 return nestedHeatOrchestrationTemplate;
313 public static boolean isNestedResource(String resourceType) {
314 return resourceType.contains(".yaml") || resourceType.contains(".yml");
318 * Validate env content environment.
320 * @param fileName the file name
321 * @param envFileName the env file name
322 * @param globalContext the global context
323 * @return the environment
325 public static Environment validateEnvContent(String fileName, String envFileName,
326 GlobalValidationContext globalContext) {
327 Environment envContent;
329 Optional<InputStream> fileContent = globalContext.getFileContent(envFileName);
330 if (fileContent.isPresent()) {
331 envContent = new YamlUtil().yamlToObject(fileContent.get(), Environment.class);
333 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_API,
334 LoggerTragetServiceName.VALIDATE_ENV_FILE, ErrorLevel.ERROR.name(),
335 LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.EMPTY_FILE);
336 throw new Exception(String.format(NO_CONTENT_IN_FILE_MSG, envFileName));
338 } catch (Exception exception) {
339 LOGGER.error("Error while reading env file : " + envFileName, exception);
346 public static String getResourceGroupResourceName(String resourceCallingToResourceGroup) {
347 return "OS::Heat::ResourceGroup in " + resourceCallingToResourceGroup;