From e99347bb14318a57307e2809c3d9577fc29bcb68 Mon Sep 17 00:00:00 2001 From: "stark, steven" Date: Thu, 19 Jul 2018 14:23:39 -0700 Subject: [PATCH] [VNFRQTS] update decorator for validation script update decorator for validation script corresponding to 5.2.1 of VNFRTQS update decorator for validation script corresponding to 5.2.2 of VNFRTQS Change-Id: I063e799a27c76bb58c031273aca48031965849d9 Issue-ID: VVP-88 Signed-off-by: stark, steven --- .../test_env_no_resource_registry/fail/bad.env | 65 ++++++++++++++++ .../test_env_no_resource_registry/pass/good.env | 63 +++++++++++++++ .../fail/parameter_default_value_specified.yaml | 4 +- .../fail/parameter_invalid_keys.yaml | 4 +- ice_validator/tests/test_base_template_names.py | 9 ++- .../tests/test_env_no_resource_registry.py | 58 ++++++++++++++ ice_validator/tests/test_heat_parameter_section.py | 25 ++++++ .../tests/test_heat_template_structure.py | 31 +++++++- ..._unused_parameters_between_env_and_templates.py | 2 +- .../tests/test_nova_servers_resource_ids.py | 2 + ice_validator/tests/test_port_resource_ids.py | 12 +++ ice_validator/tests/utils/nested_files.py | 91 +++++++++++----------- 12 files changed, 307 insertions(+), 59 deletions(-) create mode 100644 ice_validator/tests/fixtures/test_env_no_resource_registry/fail/bad.env create mode 100644 ice_validator/tests/fixtures/test_env_no_resource_registry/pass/good.env create mode 100644 ice_validator/tests/test_env_no_resource_registry.py diff --git a/ice_validator/tests/fixtures/test_env_no_resource_registry/fail/bad.env b/ice_validator/tests/fixtures/test_env_no_resource_registry/fail/bad.env new file mode 100644 index 0000000..7be0e88 --- /dev/null +++ b/ice_validator/tests/fixtures/test_env_no_resource_registry/fail/bad.env @@ -0,0 +1,65 @@ +# -*- coding: utf8 -*- +# ============LICENSE_START==================================================== +# org.onap.vvp/validation-scripts +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the License); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the License); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# + +# VERSION = '1.0.0' + +--- +parameters: + KeyName: heat_key + InstanceType: m1.micro + ImageId: F18-x86_64-cfntools + +resource_registry: {} # not allowed + +parameter_defaults: + default_key: heat_key + +encrypted_parameters: + g: "" + +event_sinks: + - type: zaqar-queue + target: myqueue + ttl: 1200 + +parameter_merge_strategies: + default: merge + param1: overwrite + param2: deep_merge diff --git a/ice_validator/tests/fixtures/test_env_no_resource_registry/pass/good.env b/ice_validator/tests/fixtures/test_env_no_resource_registry/pass/good.env new file mode 100644 index 0000000..44a70dc --- /dev/null +++ b/ice_validator/tests/fixtures/test_env_no_resource_registry/pass/good.env @@ -0,0 +1,63 @@ +# -*- coding: utf8 -*- +# ============LICENSE_START==================================================== +# org.onap.vvp/validation-scripts +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the License); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the License); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# + +# VERSION = '1.0.0' + +--- +parameters: + KeyName: heat_key + InstanceType: m1.micro + ImageId: F18-x86_64-cfntools + +parameter_defaults: + default_key: heat_key + +encrypted_parameters: + g: "" + +event_sinks: + - type: zaqar-queue + target: myqueue + ttl: 1200 + +parameter_merge_strategies: + default: merge + param1: overwrite + param2: deep_merge diff --git a/ice_validator/tests/fixtures/test_heat_parameter_section/fail/parameter_default_value_specified.yaml b/ice_validator/tests/fixtures/test_heat_parameter_section/fail/parameter_default_value_specified.yaml index d9b1c8b..09ca0b9 100644 --- a/ice_validator/tests/fixtures/test_heat_parameter_section/fail/parameter_default_value_specified.yaml +++ b/ice_validator/tests/fixtures/test_heat_parameter_section/fail/parameter_default_value_specified.yaml @@ -39,7 +39,7 @@ # --- parameters: - a: + a!: type: string label: human-readable name of the parameter description: description of the parameter @@ -50,4 +50,4 @@ parameters: description: User name must be between 6 and 8 characters - allowed_pattern: "[A-Z]+[a-zA-Z0-9]*" description: User name must start with an uppercase character - immutable: true \ No newline at end of file + immutable: true diff --git a/ice_validator/tests/fixtures/test_heat_parameter_section/fail/parameter_invalid_keys.yaml b/ice_validator/tests/fixtures/test_heat_parameter_section/fail/parameter_invalid_keys.yaml index 99d8531..4be087d 100644 --- a/ice_validator/tests/fixtures/test_heat_parameter_section/fail/parameter_invalid_keys.yaml +++ b/ice_validator/tests/fixtures/test_heat_parameter_section/fail/parameter_invalid_keys.yaml @@ -39,7 +39,7 @@ # --- parameters: - a: + a!: type: string label: human-readable name of the parameter description: description of the parameter @@ -51,4 +51,4 @@ parameters: - allowed_pattern: "[A-Z]+[a-zA-Z0-9]*" description: User name must start with an uppercase character immutable: true - dummy_key: "dummy_key" \ No newline at end of file + dummy_key: "dummy_key" diff --git a/ice_validator/tests/test_base_template_names.py b/ice_validator/tests/test_base_template_names.py index 27be5fc..cc7ab0b 100644 --- a/ice_validator/tests/test_base_template_names.py +++ b/ice_validator/tests/test_base_template_names.py @@ -40,9 +40,13 @@ from os import listdir from os import path +import re from .helpers import check_basename_ending from .helpers import validates +# is 'base', starts with 'base_', contains '_base_', ends with '_base' +RE_BASE = re.compile(r'(^base$)|(^base_)|(_base_)|(_base$)') + @validates('R-37028', 'R-87485', 'R-81339', 'R-87247', 'R-76057') def test_base_template_names(template_dir): @@ -60,9 +64,6 @@ def test_base_template_names(template_dir): if check_basename_ending('volume', filename): continue - if (filename.endswith("_base") or - filename.startswith("base_") or - filename == "base" or - filename.find("_base_") > 0): + if RE_BASE.search(filename): base_template_count += 1 assert base_template_count == 1 diff --git a/ice_validator/tests/test_env_no_resource_registry.py b/ice_validator/tests/test_env_no_resource_registry.py new file mode 100644 index 0000000..1d03d74 --- /dev/null +++ b/ice_validator/tests/test_env_no_resource_registry.py @@ -0,0 +1,58 @@ +# -*- coding: utf8 -*- +# ============LICENSE_START======================================================= +# org.onap.vvp/validation-scripts +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# =================================================================== +# +# Unless otherwise specified, all software contained herein is licensed +# under the Apache License, Version 2.0 (the “License”); +# you may not use this software except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# +# Unless otherwise specified, all documentation contained herein is licensed +# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# you may not use this documentation except in compliance with the License. +# You may obtain a copy of the License at +# +# https://creativecommons.org/licenses/by/4.0/ +# +# Unless required by applicable law or agreed to in writing, documentation +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ============LICENSE_END============================================ +# +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# + +import yaml + +from .helpers import validates + +VERSION = '1.0.0' + + +@validates('R-67231') +def test_env_no_resource_registry(env_files): + ''' + A VNF's Heat Orchestration template's Environment File's + **MUST NOT** contain the "resource_registry:" section. + ''' + for filename in env_files: + with open(filename) as fi: + yml = yaml.load(fi) + assert 'resource_registry' not in yml, ( + '%s contains "resource_registry"' % filename) diff --git a/ice_validator/tests/test_heat_parameter_section.py b/ice_validator/tests/test_heat_parameter_section.py index e5792fc..2aab7d3 100644 --- a/ice_validator/tests/test_heat_parameter_section.py +++ b/ice_validator/tests/test_heat_parameter_section.py @@ -39,8 +39,12 @@ # from .helpers import validates import pytest +import re import yaml +# one or more (alphanumeric or underscore) +RE_VALID_PARAMETER_NAME = re.compile(r'[\w_]+$') + def test_parameter_valid_keys(yaml_file): ''' @@ -88,3 +92,24 @@ def test_default_values(yaml_file): invalid_params.append(str(v1)) assert not set(invalid_params) + + +@validates('R-25877') +def test_parameter_names(yaml_file): + ''' + A VNF's Heat Orchestration Template's parameter name + (i.e., ) **MUST** contain only alphanumeric + characters and underscores ('_'). + ''' + with open(yaml_file) as fh: + yml = yaml.load(fh) + + # skip if parameters are not defined + if "parameters" not in yml: + pytest.skip("No parameters specified in the heat template") + + for key in yml['parameters']: + assert RE_VALID_PARAMETER_NAME.match(key), ( + '%s parameter "%s" not alphanumeric or underscore' % ( + yaml_file, + key)) diff --git a/ice_validator/tests/test_heat_template_structure.py b/ice_validator/tests/test_heat_template_structure.py index 0d8242e..cc05df9 100644 --- a/ice_validator/tests/test_heat_template_structure.py +++ b/ice_validator/tests/test_heat_template_structure.py @@ -51,10 +51,10 @@ def test_heat_template_structure(yaml_file): with open(yaml_file) as fh: yml = yaml.load(fh) - assert any(map(lambda v: v in yml, key_values)) + assert all([k in key_values for k in yml]) -@validates('27078', 'R-39402', 'R-35414') +@validates('R-27078', 'R-39402', 'R-35414') def test_heat_template_structure_contains_required_sections(yaml_file): ''' Check that all heat templates have the required sections @@ -64,7 +64,7 @@ def test_heat_template_structure_contains_required_sections(yaml_file): with open(yaml_file) as fh: yml = yaml.load(fh) - assert any(map(lambda v: v in yml, required_key_values)) + assert all([k in yml for k in required_key_values]) def test_heat_template_structure_sections_have_the_right_format(yaml_file): @@ -96,3 +96,28 @@ def test_heat_template_structure_sections_have_the_right_format(yaml_file): should_not_be_dict += 1 assert (is_dict == should_be_dict and is_not_dict == should_not_be_dict) + + +@validates('R-11441') +def test_parameter_type(yaml_file): + types = [ + 'string', + 'number', + 'json', + 'comma_delimited_list', + 'boolean', + ] + with open(yaml_file) as fh: + yml = yaml.load(fh) + for key, param in yml.get('parameters', {}).items(): + assert isinstance(param, dict), '%s parameter %s is not dict' % ( + yaml_file, + key) + assert 'type' in param, '%s parameter %s has no "type"' % ( + yaml_file, + key) + typ = param['type'] + assert typ in types, '%s parameter %s has invalid type "%s"' % ( + yaml_file, + key, + typ) diff --git a/ice_validator/tests/test_no_unused_parameters_between_env_and_templates.py b/ice_validator/tests/test_no_unused_parameters_between_env_and_templates.py index f6ccd77..4845751 100644 --- a/ice_validator/tests/test_no_unused_parameters_between_env_and_templates.py +++ b/ice_validator/tests/test_no_unused_parameters_between_env_and_templates.py @@ -40,7 +40,7 @@ from .helpers import validates -@validates('R-90279') +@validates('R-90279', 'R-01896', 'R-26124') def test_no_unused_parameters_between_env_and_templates(environment_pair): ''' Check all defined parameters are used in the appropiate Heat template. diff --git a/ice_validator/tests/test_nova_servers_resource_ids.py b/ice_validator/tests/test_nova_servers_resource_ids.py index 6cd4363..3f588dc 100644 --- a/ice_validator/tests/test_nova_servers_resource_ids.py +++ b/ice_validator/tests/test_nova_servers_resource_ids.py @@ -40,9 +40,11 @@ import pytest import yaml +from .helpers import validates from .utils.vm_types import get_vm_type_for_nova_server +@validates('R-01455', 'R-48067', 'R-00977') def test_nova_servers_valid_resource_ids(heat_template): ''' Make sure all nova servers have valid resource ids diff --git a/ice_validator/tests/test_port_resource_ids.py b/ice_validator/tests/test_port_resource_ids.py index f8f55ed..a6f7093 100644 --- a/ice_validator/tests/test_port_resource_ids.py +++ b/ice_validator/tests/test_port_resource_ids.py @@ -41,12 +41,24 @@ import re import pytest import yaml +from .helpers import validates from .utils.vm_types import get_vm_type_for_nova_server from .utils.network_roles import get_network_role_from_port,\ get_network_type_from_port,\ property_uses_get_resource +@validates('R-29865', + 'R-69014', + 'R-05201', + 'R-68936', + 'R-32025', + 'R-11168', + 'R-84322', + 'R-96983', + 'R-26506', + 'R-20453', + 'R-26351') def test_port_resource_ids(heat_template): ''' Check that all resource ids for ports follow the right diff --git a/ice_validator/tests/utils/nested_files.py b/ice_validator/tests/utils/nested_files.py index cc506d0..e2c9ed3 100644 --- a/ice_validator/tests/utils/nested_files.py +++ b/ice_validator/tests/utils/nested_files.py @@ -1,12 +1,12 @@ # -*- coding: utf8 -*- -# ============LICENSE_START======================================================= +# ============LICENSE_START==================================================== # org.onap.vvp/validation-scripts # =================================================================== -# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. # =================================================================== # # Unless otherwise specified, all software contained herein is licensed -# under the Apache License, Version 2.0 (the “License”); +# under the Apache License, Version 2.0 (the “License”); # you may not use this software except in compliance with the License. # You may obtain a copy of the License at # @@ -21,7 +21,7 @@ # # # Unless otherwise specified, all documentation contained herein is licensed -# under the Creative Commons License, Attribution 4.0 Intl. (the “License”); +# under the Creative Commons License, Attribution 4.0 Intl. (the License); # you may not use this documentation except in compliance with the License. # You may obtain a copy of the License at # @@ -38,9 +38,14 @@ # ECOMP is a trademark and service mark of AT&T Intellectual Property. # -import yaml -import re +"""nested files +""" + from os import path +import re +import yaml + +VERSION = '1.0.2' def get_list_of_nested_files(yml, dirpath): @@ -53,7 +58,7 @@ def get_list_of_nested_files(yml, dirpath): nested_files = [] - for k, v in yml.items(): + for v in yml.values(): if isinstance(v, dict) and "type" in v: t = v["type"] if t.endswith(".yml") or t.endswith(".yaml"): @@ -63,8 +68,10 @@ def get_list_of_nested_files(yml, dirpath): nested_files.append(filepath) nested_files.extend(get_list_of_nested_files(t_yml, dirpath)) elif t == "OS::Heat::ResourceGroup": - rdt = v["properties"]["resource_def"]["type"] - if rdt.endswith(".yml") or rdt.endswith(".yaml"): + rdt = (v.get("properties", {}) + .get("resource_def", {}) + .get("type", None)) + if rdt and (rdt.endswith(".yml") or rdt.endswith(".yaml")): filepath = path.join(dirpath, rdt) with open(filepath) as fh: rdt_yml = yaml.load(fh) @@ -85,58 +92,48 @@ def check_for_invalid_nesting(yml, yaml_file, dirpath): ''' return a list of all nested files ''' - if not hasattr(yml, 'items'): return [] - invalid_nesting = [] p = re.compile('^[A-z]*::[A-z]*::[A-z]*$') - for k, v in yml.items(): + for v in yml.values(): if isinstance(v, dict) and "type" in v: t = v["type"] - if t.endswith(".yml") or t.endswith(".yaml"): filepath = path.join(dirpath, t) - try: - with open(filepath) as fh: - t_yml = yaml.load(fh) - except Exception as e: - invalid_nesting.append(filepath) - print(e) - invalid_nesting.extend( - check_for_invalid_nesting(t_yml, - filepath, - dirpath)) elif t == "OS::Heat::ResourceGroup": rd = v["properties"]["resource_def"] - if not isinstance(rd, dict): - invalid_nesting.append(yaml_file) - elif "type" not in rd: + if not isinstance(rd, dict) or "type" not in rd: invalid_nesting.append(yaml_file) - elif not p.match(rd["type"]) and not \ - (rd["type"].endswith(".yml") - or rd["type"].endswith(".yaml")): + continue + elif not p.match(rd["type"]) and not ( + rd["type"].endswith(".yml") + or rd["type"].endswith(".yaml")): filepath = path.join(dirpath, rd["type"]) - try: - with open(filepath) as fh: - rdt_yml = yaml.load(fh) - except Exception as e: - invalid_nesting.append(filepath) - print(e) - invalid_nesting.extend( - check_for_invalid_nesting(rdt_yml, - filepath, - dirpath)) + else: + continue + else: + continue + try: + with open(filepath) as fh: + yml = yaml.load(fh) + except yaml.YAMLError as e: + invalid_nesting.append(filepath) + print(e) # pylint: disable=superfluous-parens + invalid_nesting.extend(check_for_invalid_nesting( + yml, + filepath, + dirpath)) if isinstance(v, dict): - invalid_nesting.extend( - check_for_invalid_nesting(v, - yaml_file, - dirpath)) + invalid_nesting.extend(check_for_invalid_nesting( + v, + yaml_file, + dirpath)) elif isinstance(v, list): for d in v: - invalid_nesting.extend( - check_for_invalid_nesting(d, - yaml_file, - dirpath)) + invalid_nesting.extend(check_for_invalid_nesting( + d, + yaml_file, + dirpath)) return invalid_nesting -- 2.16.6