def is_incremental_module(yaml_file, yaml_files): """ Returns true if the file is not a base module, volume module, or nested module. """ base_template = get_base_template_from_yaml_files(yaml_files) nested_templates = get_nested_files(yaml_files) is_volume_module = os.path.splitext(yaml_file)[0].endswith("_volume") return (yaml_file != base_template and yaml_file not in nested_templates and not is_volume_module)
def list_template_dir( metafunc, extensions, exclude_nested=True, template_type="", sub_dirs=None ): """ returns the filenames excluding the nested files for a template_dir, either as its passed in on CLI or, during --self-test, the directory whos name matches the current tests module name """ sub_dirs = [] if sub_dirs is None else sub_dirs filenames = [] nested_files = [] filenames = list_filenames_in_template_dir( metafunc, extensions, template_type, sub_dirs ) if exclude_nested: nested_files = get_nested_files(filenames) return list(set(filenames) - set(nested_files))
def test_filename_is_vmtype_dot_yaml(yaml_files): vm_types = [] invalid_files = [] nested_files = [] nested_files.extend( os.path.splitext(os.path.basename(filename))[0] for filename in get_nested_files(yaml_files) ) vm_types = get_all_vm_types(yaml_files) invalid_files.extend(vm_type for vm_type in vm_types if vm_type in nested_files) assert ( not invalid_files ), "Nested filenames must not be in format vm_type.yaml: {}".format(invalid_files)
def test_neutron_port_internal_fixed_ips_subnet_in_base(yaml_files): base_path = get_base_template_from_yaml_files(yaml_files) if not base_path: pytest.skip("No base module detected") base_heat = load_yaml(base_path) base_outputs = base_heat.get("outputs") or {} nested_template_paths = get_nested_files(yaml_files) errors = [] for yaml_file in yaml_files: if yaml_file == base_path or yaml_file in nested_template_paths: continue # Only applies to incremental modules heat = Heat(filepath=yaml_file) internal_ports = { r_id: p for r_id, p in heat.neutron_port_resources.items() if get_network_type_from_port(p) == "internal" } for r_id, port in internal_ports.items(): props = port.get("properties") or {} fip_list = props.get("fixed_ips") or [] if not isinstance(fip_list, list): continue for ip in fip_list: subnet = ip.get("subnet") if not subnet: continue if "get_param" not in subnet: continue param = subnet.get("get_param") if param not in base_outputs: errors.append(( "Internal fixed_ips/subnet parameter {} is attached to " "port {}, but the subnet parameter " "is not defined as an output in the base module ({})." ).format(param, r_id, base_path)) assert not errors, " ".join(errors)
def test_internal_network_parameters(yaml_files): base_path = get_base_template_from_yaml_files(yaml_files) if not base_path: pytest.skip("No base module found") base_heat = Heat(filepath=base_path) nested_paths = get_nested_files(yaml_files) incremental_modules = [ f for f in yaml_files if is_incremental_module(f, base_path, nested_paths) ] errors = [] for module in incremental_modules: heat = Heat(filepath=module) for rid, port in heat.neutron_port_resources.items(): rid_match = INTERNAL_PORT.match(rid) if not rid_match: continue network = (port.get("properties") or {}).get("network") or {} if isinstance(network, dict) and ("get_resource" in network or "get_attr" in network): continue param = get_param(network) if not param: errors.append( ("The internal port ({}) must either connect to a network " "in the base module using get_param or to a network " "created in this module ({})").format( rid, os.path.split(module)[1])) continue param_match = INTERNAL_UUID_PATTERN.match( param) or INTERNAL_NAME_PATTERN.match(param) if not param_match: errors.append(( "The internal port ({}) network parameter ({}) does not " "match one of the required naming conventions of " "int_{{network-role}}_net_id or " "int_{{network-role}}_net_name " "for connecting to an internal network. " "If this is not an internal port, then change the resource " "ID to adhere to the external port naming convention." ).format(rid, param)) continue if param not in base_heat.yml.get("outputs", {}): base_module = os.path.split(base_path)[1] errors.append(( "The internal network parameter ({}) attached to port ({}) " "must be defined in the output section of the base module ({})." ).format(param, rid, base_module)) continue param_network_role = param_match.groupdict().get("network_role") rid_network_role = rid_match.groupdict().get("network_role") if param_network_role.lower() != rid_network_role.lower(): errors.append(( "The network role ({}) extracted from the resource ID ({}) " "does not match network role ({}) extracted from the " "network parameter ({})").format(rid_network_role, rid, param_network_role, param)) resources = base_heat.get_all_resources( os.path.split(base_path)[0]) networks = { rid: resource for rid, resource in resources.items() if resource.get("type") in {"OS::Neutron::Net", "OS::ContrailV2::VirtualNetwork"} } matches = (INTERNAL_NETWORK_PATTERN.match(n) for n in networks) roles = { m.groupdict()["network_role"].lower() for m in matches if m } if param_network_role.lower() not in roles: errors.append( ("No internal network with a network role of {} was " "found in the base modules networks: {}").format( param_network_role, ", ".join(networks))) assert not errors, ". ".join(errors)
def non_nested_files(filenames): nested_files = get_nested_files(filenames) return set(filenames).difference(set(nested_files))