2 # ============LICENSE_START====================================================
3 # org.onap.vvp/validation-scripts
4 # ===================================================================
5 # Copyright © 2017 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 from functools import lru_cache
39 from os import path, listdir
41 from tests import cached_yaml as yaml
43 from tests.helpers import load_yaml
48 def check_for_invalid_nesting( # pylint: disable=too-many-branches
49 yml, yaml_file, dirpath
52 return a list of all nested files
54 if not hasattr(yml, "items"):
57 p = re.compile("^[A-z]*::[A-z]*::[A-z]*$")
59 for v in yml.values():
60 if isinstance(v, dict) and "type" in v:
62 if t.lower().endswith(".yml") or t.lower().endswith(".yaml"):
63 filepath = path.join(dirpath, t)
64 elif t == "OS::Heat::ResourceGroup":
65 rd = v["properties"]["resource_def"]
66 if not isinstance(rd, dict) or "type" not in rd:
67 invalid_nesting.append(yaml_file)
69 elif not p.match(rd["type"]):
70 filepath = path.join(dirpath, rd["type"])
76 with open(filepath) as fh:
78 except yaml.YAMLError as e:
79 invalid_nesting.append(filepath)
80 print(e) # pylint: disable=superfluous-parens
81 invalid_nesting.extend(check_for_invalid_nesting(yml, filepath, dirpath))
82 if isinstance(v, dict):
83 invalid_nesting.extend(check_for_invalid_nesting(v, yaml_file, dirpath))
84 elif isinstance(v, list):
86 invalid_nesting.extend(check_for_invalid_nesting(d, yaml_file, dirpath))
87 return invalid_nesting
90 @lru_cache(maxsize=None)
91 def get_list_of_nested_files(yml_path, dirpath):
93 return a list of all nested files
96 yml = load_yaml(yml_path)
98 resources = yml.get("resources") or {}
100 for v in resources.values():
101 if isinstance(v, dict) and "type" in v:
103 if t.endswith(".yml") or t.endswith(".yaml"):
104 filepath = path.join(dirpath, t)
105 if path.exists(filepath):
106 nested_files.append(filepath)
107 nested_files.extend(get_list_of_nested_files(filepath, dirpath))
108 elif t == "OS::Heat::ResourceGroup":
109 rdt = v.get("properties", {}).get("resource_def", {}).get("type", None)
110 if rdt and (rdt.endswith(".yml") or rdt.endswith(".yaml")):
111 filepath = path.join(dirpath, rdt)
112 if path.exists(filepath):
113 nested_files.append(filepath)
114 nested_files.extend(get_list_of_nested_files(filepath, dirpath))
118 def get_resourcegroup_nested_files(yml, dirpath):
121 key: key in yml which references a nested ResourceGroup file.
122 (resource->type is ResourceGroup
123 and resource->properties->resource_def->type is a yaml file)
124 value: the nested file name.
126 The keys are assumed to be unique across files.
127 A separate test checks for that.
130 if not hasattr(yml, "get"):
134 for rid, r in yml.get("resources", {}).items():
135 if isinstance(r, dict) and "type" in r:
138 if t == "OS::Heat::ResourceGroup":
139 rdt = r.get("properties", {}).get("resource_def", {}).get("type", None)
140 if rdt and (rdt.endswith(".yml") or rdt.endswith(".yaml")):
143 filepath = path.join(dirpath, nested_file)
144 if path.exists(filepath):
145 nested_files[rid] = nested_file
149 def get_type_nested_files(yml, dirpath):
152 key: key in yml which references a nested type file.
153 (the resource "type" is a yaml file.)
154 value: the nested file name.
156 The keys are assumed to be unique across files.
157 A separate test checks for that.
160 if not hasattr(yml, "get"):
164 for rid, r in yml.get("resources", {}).items():
165 if isinstance(r, dict) and "type" in r:
168 if t.endswith(".yml") or t.endswith(".yaml"):
171 filepath = path.join(dirpath, nested_file)
172 if path.exists(filepath):
173 nested_files[rid] = nested_file
177 def get_nested_files(filenames):
179 returns all the nested files for a set of filenames
182 for filename in filenames:
183 if file_is_a_nested_template(filename):
184 nested_files.append(filename)
188 @lru_cache(maxsize=None)
189 def file_is_a_nested_template(file):
190 directory = path.dirname(file)
192 for filename in listdir(directory):
193 if filename.endswith(".yaml") or filename.endswith(".yml"):
194 filename = "{}/{}".format(directory, filename)
197 get_list_of_nested_files(filename, path.dirname(filename))
199 except yaml.YAMLError as e:
200 print(e) # pylint: disable=superfluous-parens
202 return file in nested_files