[VVP] updating validation scripts in dublin
[vvp/validation-scripts.git] / ice_validator / tests / test_initial_configuration.py
1 # -*- coding: utf8 -*-
2 # ============LICENSE_START=======================================================
3 # org.onap.vvp/validation-scripts
4 # ===================================================================
5 # Copyright © 2017 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 import os
41 from os import listdir
42 from os import path
43
44 import pytest
45 from yaml.constructor import ConstructorError
46
47 from tests import cached_yaml as yaml
48 from tests.utils import yaml_custom_utils
49
50 from .helpers import validates
51 from yamllint.config import YamlLintConfig
52 from yamllint import linter
53 from .utils.nested_files import check_for_invalid_nesting
54 from .utils.nested_files import get_list_of_nested_files
55 from .utils.nested_iterables import find_all_get_resource_in_yml
56 from .utils.nested_iterables import find_all_get_param_in_yml
57
58 """
59 Order tests by number so they execute in order for base tests
60 """
61
62
63 @pytest.mark.base
64 @validates("R-95303")
65 def test_00_valid_yaml(filename):
66     """
67     Read in each .yaml or .env file. If it is successfully parsed as yaml, save
68     contents, else add filename to list of bad yaml files. Log the result of
69     parse attempt.
70     """
71     conf = YamlLintConfig("rules: {}")
72
73     if path.splitext(filename)[-1] in [".yml", ".yaml", ".env"]:
74         gen = linter.run(open(filename), conf)
75         errors = list(gen)
76
77         assert not errors, "Error parsing file {} with error {}".format(
78             filename, errors
79         )
80     else:
81         pytest.skip(
82             "The file does not have any of the extensions .yml,\
83             .yaml, or .env"
84         )
85
86
87 @pytest.mark.base
88 @validates("R-92635")
89 def test_02_no_duplicate_keys_in_file(yaml_file):
90     """
91     Checks that no duplicate keys exist in a given YAML file.
92     """
93     import yaml as normal_yaml  # we can't use the caching version in this test
94
95     normal_yaml.add_constructor(
96         yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
97         yaml_custom_utils.raise_duplicates_keys,
98     )
99
100     try:
101         with open(yaml_file) as fh:
102             normal_yaml.load(fh)
103     except ConstructorError as e:
104         pytest.fail("{} {}".format(e.problem, e.problem_mark))
105
106
107 @pytest.mark.base
108 def test_03_all_referenced_resources_exists(yaml_file):
109     """
110     Check that all resources referenced by get_resource
111     actually exists in all yaml files
112     """
113     with open(yaml_file) as fh:
114         yml = yaml.load(fh)
115
116     # skip if resources are not defined
117     if "resources" not in yml:
118         pytest.skip("No resources specified in the yaml file")
119
120     resources = yml.get("resources")
121     if resources:
122         resource_ids = resources.keys()
123         referenced_resource_ids = find_all_get_resource_in_yml(yml)
124
125         missing_referenced_resources = set()
126         for referenced_resource_id in referenced_resource_ids:
127             if referenced_resource_id not in resource_ids:
128                 missing_referenced_resources.add(referenced_resource_id)
129
130         assert not missing_referenced_resources, (
131             "Unable to resolve get_resource for the following "
132             "resource IDS: {}. Please ensure the resource ID is defined and "
133             "nested under the resources section of the template".format(
134                 ", ".join(missing_referenced_resources)
135             )
136         )
137
138
139 @pytest.mark.base
140 def test_04_valid_nesting(yaml_file):
141     """
142     Check that the nesting is following the proper format and
143     that all nested files exists and are parsable
144     """
145     invalid_nesting = []
146
147     with open(yaml_file) as fh:
148         yml = yaml.load(fh)
149     if "resources" in yml:
150         try:
151             invalid_nesting.extend(
152                 check_for_invalid_nesting(
153                     yml["resources"], yaml_file, path.dirname(yaml_file)
154                 )
155             )
156         except Exception:
157             invalid_nesting.append(yaml_file)
158
159     assert not invalid_nesting, "invalid nested file detected in file {}\n\n".format(
160         invalid_nesting
161     )
162
163
164 @pytest.mark.base
165 def test_05_all_get_param_have_defined_parameter(yaml_file):
166     """
167     Check that all referenced parameters are actually defined
168     as parameters
169     """
170     invalid_get_params = []
171     with open(yaml_file) as fh:
172         yml = yaml.load(fh)
173
174     resource_params = find_all_get_param_in_yml(yml)
175
176     parameters = set(yml.get("parameters", {}).keys())
177     if not parameters:
178         pytest.skip("no parameters detected")
179
180     for rp in resource_params:
181         if rp not in parameters:
182             invalid_get_params.append(rp)
183
184     assert (
185         not invalid_get_params
186     ), "get_param reference detected without corresponding parameter defined {}".format(
187         invalid_get_params
188     )
189
190
191 @validates("R-90152")
192 @pytest.mark.base
193 def test_06_heat_template_resource_section_has_resources(heat_template):
194
195     found_resource = False
196
197     with open(heat_template) as fh:
198         yml = yaml.load(fh)
199
200     resources = yml.get("resources")
201     if resources:
202         for k1, v1 in yml["resources"].items():
203             if not isinstance(v1, dict):
204                 continue
205
206             found_resource = True
207             break
208
209     assert found_resource, "Heat templates must contain at least one resource"
210
211
212 @validates("R-52530")
213 @pytest.mark.base
214 def test_07_nested_template_in_same_directory(yaml_file):
215
216     missing_files = []
217
218     with open(yaml_file) as fh:
219         yml = yaml.load(fh)
220
221     # skip if resources are not defined
222     if "resources" not in yml:
223         pytest.skip("No resources specified in the heat template")
224
225     dirname = os.path.dirname(yaml_file)
226     list_of_files = get_list_of_nested_files(yml, dirname)
227     dir_files = listdir(dirname)
228     for file in list_of_files:
229         base_name = path.basename(file)
230         if base_name not in dir_files:
231             missing_files.append(base_name)
232
233     assert (
234         not missing_files
235     ), "Missing nested files in heat template directory {}".format(missing_files)