2 # ============LICENSE_START====================================================
3 # org.onap.vvp/validation-scripts
4 # ===================================================================
5 # Copyright © 2019 AT&T Intellectual Property. All rights reserved.
6 # ===================================================================
8 # Unless otherwise specified, all software contained herein is licensed
9 # under the Apache License, Version 2.0 (the "License");
10 # you may not use this software except in compliance with the License.
11 # You may obtain a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS,
17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 # See the License for the specific language governing permissions and
19 # limitations under the License.
23 # Unless otherwise specified, all documentation contained herein is licensed
24 # under the Creative Commons License, Attribution 4.0 Intl. (the "License");
25 # you may not use this documentation except in compliance with the License.
26 # You may obtain a copy of the License at
28 # https://creativecommons.org/licenses/by/4.0/
30 # Unless required by applicable law or agreed to in writing, documentation
31 # distributed under the License is distributed on an "AS IS" BASIS,
32 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33 # See the License for the specific language governing permissions and
34 # limitations under the License.
36 # ============LICENSE_END============================================
38 # ECOMP is a trademark and service mark of AT&T Intellectual Property.
40 """ environment file structure
43 from .helpers import validates, categories, get_environment_pair, find_environment_file
46 from tests import cached_yaml as yaml
50 # pylint: disable=invalid-name
53 def check_parameter_exists(pattern, parameters):
57 for param in parameters:
58 if pattern.search(param):
64 def check_param_in_env_file(environment_pair, param, DESIRED, exclude_parameter=None):
66 # workaround for internal/external parameters
67 if exclude_parameter and re.match(exclude_parameter, param):
70 if not environment_pair:
71 pytest.skip("No heat/env pair could be identified")
73 env_file = environment_pair.get("eyml")
75 pattern = re.compile(r"^{}$".format(param))
77 if "parameters" not in env_file:
78 pytest.skip("No parameters specified in the environment file")
81 check_parameter_exists(pattern, env_file.get("parameters", {})) is not DESIRED
86 This function supports this structure, deviations
87 may or may not work without enhancement
92 prop0: { get_param: parameter_0 }
93 prop1: # this is a list of dicts
94 - nested_prop_0: { get_param: parameter_1 }
95 - nested_prop_1: { get_param: [parameter_2, {index}] }
96 prop2: # this is a dict of dicts
97 nested_prop_0: { get_param: parameter_1 }
98 prop3: { get_param: [parameter_3, 0]}
102 def check_resource_parameter(
107 resource_type_inverse=False,
110 exclude_parameter="",
112 if not environment_pair:
113 pytest.skip("No heat/env pair could be identified")
115 env_file = environment_pair.get("eyml")
116 template_file = environment_pair.get("yyml")
118 if "parameters" not in env_file:
119 pytest.skip("No parameters specified in the environment file")
121 invalid_parameters = []
123 for resource, resource_prop in template_file.get("resources", {}).items():
125 # workaround for subinterface resource groups
126 if exclude_resource and re.match(exclude_resource, resource):
130 resource_prop.get("type") == resource_type and not resource_type_inverse
131 ) or (resource_prop.get("type") != resource_type and resource_type_inverse):
135 if not resource_prop.get("properties"):
138 resource_parameter = resource_prop.get("properties").get(prop)
140 if not resource_parameter:
142 if isinstance(resource_parameter, list) and nested_prop:
143 for param in resource_parameter:
144 nested_param = param.get(nested_prop)
148 if isinstance(nested_param, dict):
149 pattern = nested_param.get("get_param")
156 if isinstance(pattern, list):
159 if check_param_in_env_file(
163 exclude_parameter=exclude_parameter,
165 invalid_parameters.append(pattern)
167 elif isinstance(resource_parameter, dict):
168 if nested_prop and nested_prop in resource_parameter:
169 resource_parameter = resource_parameter.get(nested_prop)
171 pattern = resource_parameter.get("get_param")
175 if isinstance(pattern, list):
178 if check_param_in_env_file(
182 exclude_parameter=exclude_parameter,
184 invalid_parameters.append(pattern)
188 return set(invalid_parameters)
191 def run_check_resource_parameter(
192 yaml_file, prop, DESIRED, resource_type, check_resource=True, **kwargs
195 filepath, filename = os.path.split(yaml_file)
196 environment_pair = get_environment_pair(yaml_file)
198 if not environment_pair:
199 # this is a nested file
201 if not check_resource:
202 # dont check env for nested files
203 # This will be tested separately for parent template
204 pytest.skip("This test doesn't apply to nested files")
206 environment_pair = find_environment_file(yaml_file)
208 with open(yaml_file, "r") as f:
210 environment_pair["yyml"] = yml
212 pytest.skip("unable to determine environment file for nested yaml file")
215 invalid_parameters = check_resource_parameter(
216 environment_pair, prop, DESIRED, resource_type, **kwargs
219 invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
221 if kwargs.get("resource_type_inverse"):
222 resource_type = "non-{}".format(resource_type)
224 assert not invalid_parameters, (
225 "{} {} parameters in template {}{}"
226 " found in {} environment file: {}".format(
230 " not" if DESIRED else "",
231 environment_pair.get("name"),
237 @validates("R-91125")
238 def test_nova_server_image_parameter_exists_in_environment_file(yaml_file):
239 run_check_resource_parameter(yaml_file, "image", True, "OS::Nova::Server")
242 @validates("R-69431")
243 def test_nova_server_flavor_parameter_exists_in_environment_file(yaml_file):
244 run_check_resource_parameter(yaml_file, "flavor", True, "OS::Nova::Server")
247 @categories("environment_file")
248 @validates("R-22838")
249 def test_nova_server_name_parameter_doesnt_exist_in_environment_file(yaml_file):
250 run_check_resource_parameter(yaml_file, "name", False, "OS::Nova::Server")
253 @categories("environment_file")
254 @validates("R-59568")
255 def test_nova_server_az_parameter_doesnt_exist_in_environment_file(yaml_file):
256 run_check_resource_parameter(
257 yaml_file, "availability_zone", False, "OS::Nova::Server"
261 @categories("environment_file")
262 @validates("R-20856")
263 def test_nova_server_vnf_id_parameter_doesnt_exist_in_environment_file(yaml_file):
264 run_check_resource_parameter(yaml_file, "vnf_id", False, "", check_resource=False)
267 @categories("environment_file")
268 @validates("R-72871")
269 def test_nova_server_vf_module_id_parameter_doesnt_exist_in_environment_file(yaml_file):
270 run_check_resource_parameter(
271 yaml_file, "vf_module_id", False, "", check_resource=False
275 @categories("environment_file")
276 @validates("R-37039")
277 def test_nova_server_vf_module_index_parameter_doesnt_exist_in_environment_file(
280 run_check_resource_parameter(
281 yaml_file, "vf_module_index", False, "", check_resource=False
285 @categories("environment_file")
286 @validates("R-36542")
287 def test_nova_server_vnf_name_parameter_doesnt_exist_in_environment_file(yaml_file):
288 run_check_resource_parameter(yaml_file, "vnf_name", False, "", check_resource=False)
291 @categories("environment_file")
292 @validates("R-80374")
293 def test_nova_server_vf_module_name_parameter_doesnt_exist_in_environment_file(
296 run_check_resource_parameter(
297 yaml_file, "vf_module_name", False, "", check_resource=False
301 @categories("environment_file")
302 @validates("R-02691")
303 def test_nova_server_workload_context_parameter_doesnt_exist_in_environment_file(
306 run_check_resource_parameter(
307 yaml_file, "workload_context", False, "", check_resource=False
311 @categories("environment_file")
312 @validates("R-13194")
313 def test_nova_server_environment_context_parameter_doesnt_exist_in_environment_file(
316 run_check_resource_parameter(
317 yaml_file, "environment_context", False, "", check_resource=False
321 @categories("environment_file")
322 @validates("R-29872")
323 def test_neutron_port_network_parameter_doesnt_exist_in_environment_file(yaml_file):
324 run_check_resource_parameter(yaml_file, "network", False, "OS::Neutron::Port")
327 @categories("environment_file")
328 @validates("R-39841", "R-87123", "R-62590", "R-98905", "R-93030", "R-62590")
329 def test_neutron_port_external_fixedips_ipaddress_parameter_doesnt_exist_in_environment_file(
332 run_check_resource_parameter(
337 nested_prop="ip_address",
338 exclude_parameter=re.compile(r"^(.+?)_int_(.+?)$"),
342 @validates("R-28795", "R-97201", "R-93496", "R-90206", "R-98569", "R-93496")
343 def test_neutron_port_internal_fixedips_ipaddress_parameter_exists_in_environment_file(
346 run_check_resource_parameter(
351 nested_prop="ip_address",
352 exclude_parameter=re.compile(r"^((?!_int_).)*$"),
356 @categories("environment_file")
357 @validates("R-83677", "R-80829", "R-69634", "R-22288")
358 def test_neutron_port_fixedips_subnet_parameter_doesnt_exist_in_environment_file(
361 run_check_resource_parameter(
362 yaml_file, "fixed_ips", False, "OS::Neutron::Port", nested_prop="subnet"
366 @categories("environment_file")
367 @validates("R-83412", "R-83418")
368 def test_neutron_port_aap_ip_parameter_doesnt_exist_in_environment_file(yaml_file):
369 run_check_resource_parameter(
371 "allowed_address_pairs",
374 nested_prop="ip_address",
378 @categories("environment_file")
379 @validates("R-99812")
380 def test_non_nova_server_name_parameter_doesnt_exist_in_environment_file(yaml_file):
381 run_check_resource_parameter(
382 yaml_file, "name", False, "OS::Nova::Server", resource_type_inverse=True
386 @categories("environment_file")
387 @validates("R-92193")
388 def test_network_fqdn_parameter_doesnt_exist_in_environment_file(yaml_file):
389 run_check_resource_parameter(
390 yaml_file, r"^(.+?)_net_fqdn$", False, "", check_resource=False
394 @categories("environment_file")
395 @validates("R-76682")
396 def test_contrail_route_prefixes_parameter_doesnt_exist_in_environment_file(yaml_file):
397 run_check_resource_parameter(
399 "interface_route_table_routes",
401 "OS::ContrailV2::InterfaceRouteTable",
402 nested_prop="interface_route_table_routes_route",
406 @validates("R-50011")
407 def test_heat_rg_count_parameter_exists_in_environment_file(yaml_file):
408 run_check_resource_parameter(
412 "OS::Heat::ResourceGroup",
413 exclude_resource=re.compile(r"^(.+?)_subint_(.+?)_port_(.+?)_subinterfaces$"),