f13821def750d706b0ff7959791a40622e7f2dff
[vvp/validation-scripts.git] / ice_validator / tests / test_environment_file_parameters.py
1 # -*- coding: utf8 -*-
2 # ============LICENSE_START====================================================
3 # org.onap.vvp/validation-scripts
4 # ===================================================================
5 # Copyright © 2019 AT&T Intellectual Property. All rights reserved.
6 # ===================================================================
7 #
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
12 #
13 #             http://www.apache.org/licenses/LICENSE-2.0
14 #
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.
20 #
21 #
22 #
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
27 #
28 #             https://creativecommons.org/licenses/by/4.0/
29 #
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.
35 #
36 # ============LICENSE_END============================================
37 #
38 # ECOMP is a trademark and service mark of AT&T Intellectual Property.
39 #
40 """ environment file structure
41 """
42 import os
43 from .helpers import validates, categories, get_environment_pair, find_environment_file
44 import re
45 import pytest
46 from tests import cached_yaml as yaml
47
48 VERSION = "1.0.0"
49
50 # pylint: disable=invalid-name
51
52
53 def check_parameter_exists(pattern, parameters):
54     if not parameters:
55         return False
56
57     for param in parameters:
58         if pattern.search(param):
59             return True
60
61     return False
62
63
64 def check_param_in_env_file(environment_pair, param, DESIRED, exclude_parameter=None):
65
66     # workaround for internal/external parameters
67     if exclude_parameter and re.match(exclude_parameter, param):
68         return False
69
70     if not environment_pair:
71         pytest.skip("No heat/env pair could be identified")
72
73     env_file = environment_pair.get("eyml")
74
75     pattern = re.compile(r"^{}$".format(param))
76
77     if "parameters" not in env_file:
78         pytest.skip("No parameters specified in the environment file")
79
80     return (
81         check_parameter_exists(pattern, env_file.get("parameters", {})) is not DESIRED
82     )
83
84
85 """
86 This function supports this structure, deviations
87 may or may not work without enhancement
88
89 resource_id:
90     type: <resource_type>
91     properties:
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]}
99 """
100
101
102 def check_resource_parameter(
103     environment_pair,
104     prop,
105     DESIRED,
106     resource_type,
107     resource_type_inverse=False,
108     nested_prop="",
109     exclude_resource="",
110     exclude_parameter="",
111 ):
112     if not environment_pair:
113         pytest.skip("No heat/env pair could be identified")
114
115     env_file = environment_pair.get("eyml")
116     template_file = environment_pair.get("yyml")
117
118     if "parameters" not in env_file:
119         pytest.skip("No parameters specified in the environment file")
120
121     invalid_parameters = []
122     if template_file:
123         for resource, resource_prop in template_file.get("resources", {}).items():
124
125             # workaround for subinterface resource groups
126             if exclude_resource and re.match(exclude_resource, resource):
127                 continue
128
129             if (
130                 resource_prop.get("type") == resource_type and not resource_type_inverse
131             ) or (resource_prop.get("type") != resource_type and resource_type_inverse):
132
133                 pattern = False
134
135                 if not resource_prop.get("properties"):
136                     continue
137
138                 resource_parameter = resource_prop.get("properties").get(prop)
139
140                 if not resource_parameter:
141                     continue
142                 if isinstance(resource_parameter, list) and nested_prop:
143                     for param in resource_parameter:
144                         nested_param = param.get(nested_prop)
145                         if not nested_param:
146                             continue
147
148                         if isinstance(nested_param, dict):
149                             pattern = nested_param.get("get_param")
150                         else:
151                             pattern = ""
152
153                         if not pattern:
154                             continue
155
156                         if isinstance(pattern, list):
157                             pattern = pattern[0]
158
159                         if check_param_in_env_file(
160                             environment_pair,
161                             pattern,
162                             DESIRED,
163                             exclude_parameter=exclude_parameter,
164                         ):
165                             invalid_parameters.append(pattern)
166
167                 elif isinstance(resource_parameter, dict):
168                     if nested_prop and nested_prop in resource_parameter:
169                         resource_parameter = resource_parameter.get(nested_prop)
170
171                     pattern = resource_parameter.get("get_param")
172                     if not pattern:
173                         continue
174
175                     if isinstance(pattern, list):
176                         pattern = pattern[0]
177
178                     if check_param_in_env_file(
179                         environment_pair,
180                         pattern,
181                         DESIRED,
182                         exclude_parameter=exclude_parameter,
183                     ):
184                         invalid_parameters.append(pattern)
185                 else:
186                     continue
187
188     return set(invalid_parameters)
189
190
191 def run_check_resource_parameter(
192     yaml_file, prop, DESIRED, resource_type, check_resource=True, **kwargs
193 ):
194
195     filepath, filename = os.path.split(yaml_file)
196     environment_pair = get_environment_pair(yaml_file)
197
198     if not environment_pair:
199         # this is a nested file
200
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")
205
206         environment_pair = find_environment_file(yaml_file)
207         if environment_pair:
208             with open(yaml_file, "r") as f:
209                 yml = yaml.load(f)
210             environment_pair["yyml"] = yml
211         else:
212             pytest.skip("unable to determine environment file for nested yaml file")
213
214     if check_resource:
215         invalid_parameters = check_resource_parameter(
216             environment_pair, prop, DESIRED, resource_type, **kwargs
217         )
218     else:
219         invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
220
221     if kwargs.get("resource_type_inverse"):
222         resource_type = "non-{}".format(resource_type)
223
224     assert not invalid_parameters, (
225         "{} {} parameters in template {}{}"
226         " found in {} environment file: {}".format(
227             resource_type,
228             prop,
229             filename,
230             " not" if DESIRED else "",
231             environment_pair.get("name"),
232             invalid_parameters,
233         )
234     )
235
236
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")
240
241
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")
245
246
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")
251
252
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"
258     )
259
260
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)
265
266
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
272     )
273
274
275 @categories("environment_file")
276 @validates("R-37039")
277 def test_nova_server_vf_module_index_parameter_doesnt_exist_in_environment_file(
278     yaml_file
279 ):
280     run_check_resource_parameter(
281         yaml_file, "vf_module_index", False, "", check_resource=False
282     )
283
284
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)
289
290
291 @categories("environment_file")
292 @validates("R-80374")
293 def test_nova_server_vf_module_name_parameter_doesnt_exist_in_environment_file(
294     yaml_file
295 ):
296     run_check_resource_parameter(
297         yaml_file, "vf_module_name", False, "", check_resource=False
298     )
299
300
301 @categories("environment_file")
302 @validates("R-02691")
303 def test_nova_server_workload_context_parameter_doesnt_exist_in_environment_file(
304     yaml_file
305 ):
306     run_check_resource_parameter(
307         yaml_file, "workload_context", False, "", check_resource=False
308     )
309
310
311 @categories("environment_file")
312 @validates("R-13194")
313 def test_nova_server_environment_context_parameter_doesnt_exist_in_environment_file(
314     yaml_file
315 ):
316     run_check_resource_parameter(
317         yaml_file, "environment_context", False, "", check_resource=False
318     )
319
320
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")
325
326
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(
330     yaml_file
331 ):
332     run_check_resource_parameter(
333         yaml_file,
334         "fixed_ips",
335         False,
336         "OS::Neutron::Port",
337         nested_prop="ip_address",
338         exclude_parameter=re.compile(r"^(.+?)_int_(.+?)$"),
339     )
340
341
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(
344     yaml_file
345 ):
346     run_check_resource_parameter(
347         yaml_file,
348         "fixed_ips",
349         True,
350         "OS::Neutron::Port",
351         nested_prop="ip_address",
352         exclude_parameter=re.compile(r"^((?!_int_).)*$"),
353     )
354
355
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(
359     yaml_file
360 ):
361     run_check_resource_parameter(
362         yaml_file, "fixed_ips", False, "OS::Neutron::Port", nested_prop="subnet"
363     )
364
365
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(
370         yaml_file,
371         "allowed_address_pairs",
372         False,
373         "OS::Neutron::Port",
374         nested_prop="ip_address",
375     )
376
377
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
383     )
384
385
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
391     )
392
393
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(
398         yaml_file,
399         "interface_route_table_routes",
400         False,
401         "OS::ContrailV2::InterfaceRouteTable",
402         nested_prop="interface_route_table_routes_route",
403     )
404
405
406 @validates("R-50011")
407 def test_heat_rg_count_parameter_exists_in_environment_file(yaml_file):
408     run_check_resource_parameter(
409         yaml_file,
410         "count",
411         True,
412         "OS::Heat::ResourceGroup",
413         exclude_resource=re.compile(r"^(.+?)_subint_(.+?)_port_(.+?)_subinterfaces$"),
414     )