# ============LICENSE_START====================================================
# org.onap.vvp/validation-scripts
# ===================================================================
-# Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# Copyright © 2019 AT&T Intellectual Property. All rights reserved.
# ===================================================================
#
# Unless otherwise specified, all software contained herein is licensed
#
# ============LICENSE_END============================================
#
-# ECOMP is a trademark and service mark of AT&T Intellectual Property.
#
-
""" environment file structure
"""
+import os
+
+from tests.structures import Heat
+from tests.utils import nested_dict
+from .helpers import (
+ validates,
+ categories,
+ get_environment_pair,
+ find_environment_file,
+ get_param,
+)
import re
import pytest
+from tests import cached_yaml as yaml
-from .helpers import validates, get_environment_pair
-
-
-VERSION = '1.0.0'
+VERSION = "1.0.0"
# pylint: disable=invalid-name
return False
-def check_param_in_env_file(environment_pair, param, DESIRED):
+def check_param_in_env_file(environment_pair, param, DESIRED, exclude_parameter=None):
+
+ # workaround for internal/external parameters
+ if exclude_parameter and re.match(exclude_parameter, param):
+ return False
if not environment_pair:
pytest.skip("No heat/env pair could be identified")
env_file = environment_pair.get("eyml")
- pattern = re.compile(r'^{}$'.format(param))
+ pattern = re.compile(r"^{}$".format(param))
if "parameters" not in env_file:
pytest.skip("No parameters specified in the environment file")
- return check_parameter_exists(pattern,
- env_file.get("parameters", {})
- ) is not DESIRED
+ return (
+ check_parameter_exists(pattern, env_file.get("parameters", {})) is not DESIRED
+ )
"""
- nested_prop_1: { get_param: [parameter_2, {index}] }
prop2: # this is a dict of dicts
nested_prop_0: { get_param: parameter_1 }
+ prop3: { get_param: [parameter_3, 0]}
"""
-def check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type,
- resource_type_inverse=False,
- nested_prop='',
- exclude_resource=''):
-
+def check_resource_parameter(
+ environment_pair,
+ prop,
+ DESIRED,
+ resource_type,
+ resource_type_inverse=False,
+ nested_prop="",
+ exclude_resource="",
+ exclude_parameter="",
+):
if not environment_pair:
pytest.skip("No heat/env pair could be identified")
pytest.skip("No parameters specified in the environment file")
invalid_parameters = []
-
if template_file:
for resource, resource_prop in template_file.get("resources", {}).items():
+ # workaround for subinterface resource groups
if exclude_resource and re.match(exclude_resource, resource):
continue
- if resource_prop.get("type") == resource_type or \
- (resource_prop.get("type") != resource_type
- and resource_type_inverse):
+ if (
+ resource_prop.get("type") == resource_type and not resource_type_inverse
+ ) or (resource_prop.get("type") != resource_type and resource_type_inverse):
pattern = False
if not resource_parameter:
continue
-
if isinstance(resource_parameter, list) and nested_prop:
for param in resource_parameter:
-
nested_param = param.get(nested_prop)
if not nested_param:
continue
- pattern = nested_param.get("get_param")
+ if isinstance(nested_param, dict):
+ pattern = nested_param.get("get_param")
+ else:
+ pattern = ""
if not pattern:
continue
if isinstance(pattern, list):
pattern = pattern[0]
- elif isinstance(resource_parameter, dict):
+ if check_param_in_env_file(
+ environment_pair,
+ pattern,
+ DESIRED,
+ exclude_parameter=exclude_parameter,
+ ):
+ invalid_parameters.append(pattern)
+ elif isinstance(resource_parameter, dict):
if nested_prop and nested_prop in resource_parameter:
resource_parameter = resource_parameter.get(nested_prop)
pattern = resource_parameter.get("get_param")
-
+ if not pattern:
+ continue
+
+ if isinstance(pattern, list):
+ pattern = pattern[0]
+
+ if check_param_in_env_file(
+ environment_pair,
+ pattern,
+ DESIRED,
+ exclude_parameter=exclude_parameter,
+ ):
+ invalid_parameters.append(pattern)
else:
continue
- if not pattern:
- continue
-
- if check_param_in_env_file(environment_pair, pattern, DESIRED):
- invalid_parameters.append(pattern)
-
return set(invalid_parameters)
-@validates('R-91125')
-def test_nova_server_image_parameter_exists_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "image"
- DESIRED = True
- resource_type = "OS::Nova::Server"
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type)
-
- assert not invalid_parameters, ("OS::Nova::Server {} parameters not"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-69431')
-def test_nova_server_flavor_parameter_exists_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "flavor"
- DESIRED = True
- resource_type = "OS::Nova::Server"
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type)
-
- assert not invalid_parameters, ("OS::Nova::Server {} parameters not"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-22838')
-def test_nova_server_name_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "name"
- DESIRED = False
- resource_type = "OS::Nova::Server"
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type)
-
- assert not invalid_parameters, ("OS::Nova::Server {} parameters"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-59568')
-def test_nova_server_az_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "availability_zone"
- DESIRED = False
- resource_type = "OS::Nova::Server"
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type)
-
- assert not invalid_parameters, ("OS::Nova::Server {} parameters"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-20856')
-def test_nova_server_vnf_id_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "vnf_id"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair,
- prop,
- DESIRED)
-
- assert not invalid_parameters, ("{} parameters"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-72871')
-def test_nova_server_vf_module_id_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "vf_module_id"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair,
- prop,
- DESIRED)
-
- assert not invalid_parameters, ("{} parameters"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-36542')
-def test_nova_server_vnf_name_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "vnf_name"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair,
- prop,
- DESIRED)
-
- assert not invalid_parameters, ("{} parameters"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-80374')
-def test_nova_server_vf_module_name_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
+def run_check_resource_parameter(
+ yaml_file, prop, DESIRED, resource_type, check_resource=True, **kwargs
+):
+ filepath, filename = os.path.split(yaml_file)
+ environment_pair = get_environment_pair(yaml_file)
- environment_pair = get_environment_pair(heat_template)
-
- prop = "vf_module_name"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair,
- prop,
- DESIRED)
-
- assert not invalid_parameters, ("{} parameters"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-02691')
-def test_nova_server_workload_context_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "workload_context"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair,
- prop,
- DESIRED)
-
- assert not invalid_parameters, ("{} parameters"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-13194')
-def test_nova_server_environment_context_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "environment_context"
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair,
- prop,
- DESIRED)
-
- assert not invalid_parameters, ("{} parameters"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-29872')
-def test_nova_server_network_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "networks"
- nested_prop = "network"
- DESIRED = False
- resource_type = "OS::Nova::Server"
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type,
- nested_prop=nested_prop)
-
- assert not invalid_parameters, ("{} {} parameters"
- " found in {} environment file {}"
- .format(resource_type,
- nested_prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-39841',
- 'R-87123',
- 'R-28795',
- 'R-97201',
- 'R-62590',
- 'R-93496',
- 'R-98905',
- 'R-93030',
- 'R-90206',
- 'R-98569',
- 'R-62590',
- 'R-93496')
-def test_neutron_port_fixedips_ipaddress_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "fixed_ips"
- nested_prop = "ip_address"
- DESIRED = False
- resource_type = "OS::Neutron::Port"
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type,
- nested_prop=nested_prop)
-
- assert not invalid_parameters, ("{} {} parameters"
- " found in {} environment file {}"
- .format(resource_type,
- nested_prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-83677',
- 'R-80829',
- 'R-69634',
- 'R-22288')
-def test_neutron_port_fixedips_subnet_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "fixed_ips"
- nested_prop = "subnet_id"
- DESIRED = False
- resource_type = "OS::Neutron::Port"
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type,
- nested_prop=nested_prop)
-
- assert not invalid_parameters, ("{} {} parameters"
- " found in {} environment file {}"
- .format(resource_type,
- nested_prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-83412',
- 'R-83418')
-def test_neutron_port_aap_ip_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "allowed_address_pairs"
- nested_prop = "ip_address"
- DESIRED = False
- resource_type = "OS::Neutron::Port"
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type,
- nested_prop=nested_prop)
-
- assert not invalid_parameters, ("{} {} parameters"
- " found in {} environment file {}"
- .format(resource_type,
- nested_prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-99812')
-def test_non_nova_server_name_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "name"
- DESIRED = False
- resource_type = "OS::Nova::Server"
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type,
- resource_type_inverse=True)
-
- assert not invalid_parameters, ("non-{} {} parameters"
- " found in {} environment file {}"
- .format(resource_type,
- prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-92193')
-def test_network_fqdn_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = r'^(.+?)_net_fqdn$'
- DESIRED = False
-
- invalid_parameters = check_param_in_env_file(environment_pair,
- prop,
- DESIRED)
-
- assert not invalid_parameters, ("{} parameters"
- " found in {} environment file {}"
- .format(prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-76682')
-def test_contrail_route_prefixes_parameter_doesnt_exist_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "interface_route_table_routes"
- nested_prop = "interface_route_table_routes_route"
- DESIRED = False
- resource_type = "OS::ContrailV2::InterfaceRouteTable"
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type,
- nested_prop=nested_prop)
-
- assert not invalid_parameters, ("{} {} parameters"
- " found in {} environment file {}"
- .format(resource_type,
- nested_prop,
- environment_pair.get("name"),
- invalid_parameters))
-
-
-@validates('R-50011')
-def test_heat_rg_count_parameter_exists_in_environment_file(heat_template):
-
- if pytest.config.getoption("validation_profile") == "heat_only":
- pytest.skip("skipping test because validation profile is heat only")
-
- environment_pair = get_environment_pair(heat_template)
-
- prop = "count"
- DESIRED = True
- resource_type = "OS::Heat::ResourceGroup"
- exclude_resource = re.compile(r'^(.+?)_subint_(.+?)_port_(.+?)_subinterfaces$')
-
- invalid_parameters = check_resource_parameter(environment_pair,
- prop,
- DESIRED,
- resource_type,
- exclude_resource=exclude_resource)
+ if not environment_pair:
+ # this is a nested file
- assert not invalid_parameters, ("{} {} parameters not"
- " found in {} environment file {}"
- .format(resource_type,
- prop,
- environment_pair.get("name"),
- invalid_parameters))
+ if not check_resource:
+ # dont check env for nested files
+ # This will be tested separately for parent template
+ pytest.skip("This test doesn't apply to nested files")
+
+ environment_pair = find_environment_file(yaml_file)
+ if environment_pair:
+ with open(yaml_file, "r") as f:
+ yml = yaml.load(f)
+ environment_pair["yyml"] = yml
+ else:
+ pytest.skip("unable to determine environment file for nested yaml file")
+
+ if check_resource:
+ invalid_parameters = check_resource_parameter(
+ environment_pair, prop, DESIRED, resource_type, **kwargs
+ )
+ else:
+ invalid_parameters = check_param_in_env_file(environment_pair, prop, DESIRED)
+
+ if kwargs.get("resource_type_inverse"):
+ resource_type = "non-{}".format(resource_type)
+
+ assert not invalid_parameters, (
+ "{} {} parameters in template {}{}"
+ " found in {} environment file: {}".format(
+ resource_type,
+ prop,
+ filename,
+ " not" if DESIRED else "",
+ environment_pair.get("name"),
+ ", ".join(invalid_parameters),
+ )
+ )
+
+
+@validates("R-91125")
+def test_nova_server_image_parameter_exists_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "image", True, "OS::Nova::Server")
+
+
+@validates("R-69431")
+def test_nova_server_flavor_parameter_exists_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "flavor", True, "OS::Nova::Server")
+
+
+@categories("environment_file")
+@validates("R-22838")
+def test_nova_server_name_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "name", False, "OS::Nova::Server")
+
+
+@categories("environment_file")
+@validates("R-59568")
+def test_nova_server_az_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file, "availability_zone", False, "OS::Nova::Server"
+ )
+
+
+@categories("environment_file")
+@validates("R-20856")
+def test_nova_server_vnf_id_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "vnf_id", False, "", check_resource=False)
+
+
+@categories("environment_file")
+@validates("R-72871")
+def test_nova_server_vf_module_id_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file, "vf_module_id", False, "", check_resource=False
+ )
+
+
+@categories("environment_file")
+@validates("R-37039")
+def test_nova_server_vf_module_index_parameter_doesnt_exist_in_environment_file(
+ yaml_file
+):
+ run_check_resource_parameter(
+ yaml_file, "vf_module_index", False, "", check_resource=False
+ )
+
+
+@categories("environment_file")
+@validates("R-36542")
+def test_nova_server_vnf_name_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "vnf_name", False, "", check_resource=False)
+
+
+@categories("environment_file")
+@validates("R-80374")
+def test_nova_server_vf_module_name_parameter_doesnt_exist_in_environment_file(
+ yaml_file
+):
+ run_check_resource_parameter(
+ yaml_file, "vf_module_name", False, "", check_resource=False
+ )
+
+
+@categories("environment_file")
+@validates("R-02691")
+def test_nova_server_workload_context_parameter_doesnt_exist_in_environment_file(
+ yaml_file
+):
+ run_check_resource_parameter(
+ yaml_file, "workload_context", False, "", check_resource=False
+ )
+
+
+@categories("environment_file")
+@validates("R-13194")
+def test_nova_server_environment_context_parameter_doesnt_exist_in_environment_file(
+ yaml_file
+):
+ run_check_resource_parameter(
+ yaml_file, "environment_context", False, "", check_resource=False
+ )
+
+
+@categories("environment_file")
+@validates("R-29872")
+def test_neutron_port_network_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(yaml_file, "network", False, "OS::Neutron::Port")
+
+
+@categories("environment_file")
+@validates("R-39841", "R-87123", "R-62590", "R-98905", "R-93030", "R-62590")
+def test_neutron_port_external_fixedips_ipaddress_parameter_doesnt_exist_in_environment_file(
+ yaml_file
+):
+ run_check_resource_parameter(
+ yaml_file,
+ "fixed_ips",
+ False,
+ "OS::Neutron::Port",
+ nested_prop="ip_address",
+ exclude_parameter=re.compile(r"^(.+?)_int_(.+?)$"),
+ )
+
+
+@validates("R-28795", "R-97201", "R-93496", "R-90206", "R-98569", "R-93496")
+def test_neutron_port_internal_fixedips_ipaddress_parameter_exists_in_environment_file(
+ yaml_file
+):
+ run_check_resource_parameter(
+ yaml_file,
+ "fixed_ips",
+ True,
+ "OS::Neutron::Port",
+ nested_prop="ip_address",
+ exclude_parameter=re.compile(r"^((?!_int_).)*$"),
+ )
+
+
+@categories("environment_file")
+@validates("R-83677", "R-80829", "R-69634", "R-22288")
+def test_neutron_port_fixedips_subnet_parameter_doesnt_exist_in_environment_file(
+ yaml_file
+):
+ run_check_resource_parameter(
+ yaml_file, "fixed_ips", False, "OS::Neutron::Port", nested_prop="subnet"
+ )
+
+
+@categories("environment_file")
+@validates("R-83412", "R-83418")
+def test_neutron_port_external_aap_ip_parameter_doesnt_exist_in_environment_file(
+ yaml_file
+):
+ run_check_resource_parameter(
+ yaml_file,
+ "allowed_address_pairs",
+ False,
+ "OS::Neutron::Port",
+ nested_prop="ip_address",
+ exclude_parameter=re.compile(r"^(.+?)_int_(.+?)$"),
+ )
+
+
+@categories("environment_file")
+@validates("R-99812")
+def test_non_nova_server_name_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file, "name", False, "OS::Nova::Server", resource_type_inverse=True
+ )
+
+
+@categories("environment_file")
+@validates("R-92193")
+def test_network_fqdn_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file, r"^(.+?)_net_fqdn$", False, "", check_resource=False
+ )
+
+
+@categories("environment_file")
+@validates("R-76682")
+def test_contrail_route_prefixes_parameter_doesnt_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file,
+ "interface_route_table_routes",
+ False,
+ "OS::ContrailV2::InterfaceRouteTable",
+ nested_prop="interface_route_table_routes_route",
+ )
+
+
+@validates("R-50011")
+def test_heat_rg_count_parameter_exists_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file,
+ "count",
+ True,
+ "OS::Heat::ResourceGroup",
+ exclude_resource=re.compile(r"^(.+?)_subint_(.+?)_port_(.+?)_subinterfaces$"),
+ )
+
+
+@categories("environment_file")
+@validates("R-100020", "R-100040", "R-100060", "R-100080", "R-100170")
+def test_contrail_external_instance_ip_does_not_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file,
+ "instance_ip_address",
+ False,
+ "OS::ContrailV2::InstanceIp",
+ exclude_resource=re.compile(r"^.*_int_.*$"), # exclude internal IPs
+ )
+
+
+@validates("R-100100", "R-100120", "R-100140", "R-100160", "R-100180")
+def test_contrail_internal_instance_ip_does_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file,
+ "instance_ip_address",
+ True,
+ "OS::ContrailV2::InstanceIp",
+ exclude_resource=re.compile(r"(?!.*_int_.*)"), # exclude external IPs
+ )
+
+
+@categories("environment_file")
+@validates("R-100210", "R-100230", "R-100250", "R-100270")
+def test_contrail_subnet_uuid_does_not_exist_in_environment_file(yaml_file):
+ run_check_resource_parameter(
+ yaml_file, "subnet_uuid", False, "OS::ContrailV2::InstanceIp"
+ )
+
+
+@categories("environment_file")
+@validates("R-100320", "R-100340")
+def test_contrail_vmi_aap_does_not_exist_in_environment_file(yaml_file):
+ # This test needs to check a more complex structure. Rather than try to force
+ # that into the existing run_check_resource_parameter logic we'll just check it
+ # directly
+ pairs = get_environment_pair(yaml_file)
+ if not pairs:
+ pytest.skip("No matching env file found")
+ heat = Heat(filepath=yaml_file)
+ env_parameters = pairs["eyml"].get("parameters") or {}
+ vmis = heat.get_resource_by_type("OS::ContrailV2::VirtualMachineInterface")
+ external_vmis = {rid: data for rid, data in vmis.items() if "_int_" not in rid}
+ invalid_params = []
+ for r_id, vmi in external_vmis.items():
+ aap_value = nested_dict.get(
+ vmi,
+ "properties",
+ "virtual_machine_interface_allowed_address_pairs",
+ "virtual_machine_interface_allowed_address_pairs_allowed_address_pair",
+ )
+ if not aap_value or not isinstance(aap_value, list):
+ # Skip if aap not used or is not a list.
+ continue
+ for pair_ip in aap_value:
+ if not isinstance(pair_ip, dict):
+ continue # Invalid Heat will be detected by another test
+ settings = (
+ pair_ip.get(
+ "virtual_machine_interface_allowed_address"
+ "_pairs_allowed_address_pair_ip"
+ )
+ or {}
+ )
+ if isinstance(settings, dict):
+ ip_prefix = (
+ settings.get(
+ "virtual_machine_interface_allowed_address"
+ "_pairs_allowed_address_pair_ip_ip_prefix"
+ )
+ or {}
+ )
+ ip_prefix_param = get_param(ip_prefix)
+ if ip_prefix_param and ip_prefix_param in env_parameters:
+ invalid_params.append(ip_prefix_param)
+
+ msg = (
+ "OS::ContrailV2::VirtualMachineInterface "
+ "virtual_machine_interface_allowed_address_pairs"
+ "_allowed_address_pair_ip_ip_prefix "
+ "parameters found in environment file {}: {}"
+ ).format(pairs.get("name"), ", ".join(invalid_params))
+ assert not invalid_params, msg