1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
import os
import pytest
from tests.helpers import validates, traverse, load_yaml
from tests.structures import Resource
from tests.utils import nested_dict
class GetAttrValidator:
def __init__(self, yaml, base_dir):
self.yaml = yaml
self.base_dir = base_dir
self.errors = []
@property
def resources(self):
return self.yaml.get("resources", {})
def __call__(self, path, get_attr_arg):
if not isinstance(get_attr_arg, list):
self.add_error(path, get_attr_arg, "get_attr argument is not a list")
elif len(get_attr_arg) < 1:
self.add_error(
path, get_attr_arg, "get_attr argument must have a parameter"
)
elif get_attr_arg[0] not in self.resources:
self.add_error(
path,
get_attr_arg,
"Resource ID could not be found. Please ensure "
"the resource is spelled correctly and defined "
"under the resources section of the YAML file.",
)
else:
r_id = get_attr_arg[0]
r = Resource(r_id, self.yaml["resources"][r_id])
if not r.is_nested():
return
if len(get_attr_arg) < 2:
self.add_error(
path,
get_attr_arg,
"get_attr used on nested "
"resource, but no attribute "
"value specified",
)
return
expected_param = get_attr_arg[1]
nested_yaml = r.get_nested_yaml(self.base_dir)
param = nested_dict.get(nested_yaml, "outputs", expected_param)
if not param:
self.add_error(
path,
get_attr_arg,
"Attribute key "
+ expected_param
+ " not found in outputs "
+ r.get_nested_filename(),
)
def add_error(self, path, arg, message):
path_str = ".".join(path)
self.errors.append("{} {}: {}".format(path_str, arg, message))
@property
def error_message(self):
errs = ", ".join(self.errors)
return "Invalid get_attr usage detected: {}".format(errs)
@pytest.mark.base
@validates("R-95303")
def test_08_validate_get_attr_usage(yaml_file):
"""Ensures that every get_attr refers to a valid resource name,
and if that resource is a nested YAML that the attribute exists as
an output of the nested YAML file. It does not validate the
attribute keys are always valid because of the attributes could
refer to intrinsic attributes of the resource that are not present
in the YAML file."""
yml = load_yaml(yaml_file)
base_dir, _ = os.path.split(yaml_file)
validator = GetAttrValidator(yml, base_dir)
traverse(yml, "get_attr", validator)
assert not validator.errors, validator.error_message
|