diff --git a/tests/conftest.py b/tests/conftest.py index b36e04a64..0b23ed084 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -162,7 +162,7 @@ def basedir(): def generic_plan_summary(request): 'Returns a function to generate a PlanSummary' - def inner(module_path, basedir=None, tf_var_files=None, **tf_vars): + def inner(module_path, tf_var_files=None, basedir=None, **tf_vars): '''Run a Terraform plan on the module located at `module_path`.\ - module_path: terraform root module to run. Can be an absolute @@ -210,8 +210,8 @@ def generic_plan_summary(request): # if we're copying the module, we might as well remove any # files and directories from the test directory that are # automatically read by terraform. Useful to avoid surprises - # with (e.g. if you have an active fast deployment with links - # to configs) + # surprises if, for example, you have an active fast + # deployment with links to configs) autopaths = itertools.chain( test_path.glob("*.auto.tfvars"), test_path.glob("*.auto.tfvars.json"), @@ -265,65 +265,71 @@ def generic_plan_summary(request): def generic_plan_validator(generic_plan_summary, request): 'Return a function that builds a PlanSummary and compares it to an yaml inventory' - def inner(inventory_path, module_path, basedir=None, tf_var_files=None, + def inner(module_path, inventory_paths, tf_var_files=None, basedir=None, **tf_vars): if basedir is None: basedir = Path(request.fspath).parent - # allow tfvars and inventory to be relative to the caller - inventory_path = basedir / inventory_path - inventory = yaml.safe_load(inventory_path.read_text()) - assert inventory is not None, f'Inventory {inventory_path} is empty' + summary = generic_plan_summary(module_path=module_path, + tf_var_files=tf_var_files, basedir=basedir, + **tf_vars) - summary = generic_plan_summary(module_path, tf_var_files=tf_var_files, - basedir=basedir) + # allow single single string for inventory_paths + if not isinstance(inventory_paths, list): + inventory_paths = [inventory_paths] - # If you add additional asserts to this function: - # - put the values coming from the plan on the left side of - # any comparison operators - # - put the values coming from user's inventory the right - # side of any comparison operators. - # - include a descriptive error message to the assert + for path in inventory_paths: + # allow tfvars and inventory to be relative to the caller + path = basedir / path + inventory = yaml.safe_load(path.read_text()) + assert inventory is not None, f'Inventory {path} is empty' - # for values: - # - verify each address in the user's inventory exists in the plan - # - for those address that exist on both the user's inventory and - # the plan output, ensure the set of keys on the inventory are a - # subset of the keys in the plan, and compare their values by - # equality - if 'values' in inventory: - expected_values = inventory['values'] - for address, expected_value in expected_values.items(): - assert address in summary.values, \ - f'{address} is not a valid address in the plan' - for k, v in expected_value.items(): - assert k in summary.values[address], \ - f'{k} not found at {address}' - plan_value = summary.values[address][k] - assert plan_value == v, \ - f'{k} at {address} failed. Got `{plan_value}`, expected `{v}`' + # If you add additional asserts to this function: + # - put the values coming from the plan on the left side of + # any comparison operators + # - put the values coming from user's inventory the right + # side of any comparison operators. + # - include a descriptive error message to the assert - if 'counts' in inventory: - expected_counts = inventory['counts'] - for type_, expected_count in expected_counts.items(): - assert type_ in summary.counts, \ - f'module does not create any resources of type `{type_}`' - plan_count = summary.counts[type_] - assert plan_count == expected_count, \ - f'count of {type_} resources failed. Got {plan_count}, expected {expected_count}' + # for values: + # - verify each address in the user's inventory exists in the plan + # - for those address that exist on both the user's inventory and + # the plan output, ensure the set of keys on the inventory are a + # subset of the keys in the plan, and compare their values by + # equality + if 'values' in inventory: + expected_values = inventory['values'] + for address, expected_value in expected_values.items(): + assert address in summary.values, \ + f'{address} is not a valid address in the plan' + for k, v in expected_value.items(): + assert k in summary.values[address], \ + f'{k} not found at {address}' + plan_value = summary.values[address][k] + assert plan_value == v, \ + f'{k} at {address} failed. Got `{plan_value}`, expected `{v}`' - if 'outputs' in inventory: - expected_outputs = inventory['outputs'] - for output_name, expected_output in expected_outputs.items(): - assert output_name in summary.outputs, \ - f'module does not output `{output_name}`' - output = summary.outputs[output_name] - # assert 'value' in output, \ - # f'output `{output_name}` does not have a value (is it sensitive or dynamic?)' - plan_output = output.get('value', '__missing__') - assert plan_output == expected_output, \ - f'output {output_name} failed. Got `{plan_output}`, expected `{expected_output}`' + if 'counts' in inventory: + expected_counts = inventory['counts'] + for type_, expected_count in expected_counts.items(): + assert type_ in summary.counts, \ + f'module does not create any resources of type `{type_}`' + plan_count = summary.counts[type_] + assert plan_count == expected_count, \ + f'count of {type_} resources failed. Got {plan_count}, expected {expected_count}' + + if 'outputs' in inventory: + expected_outputs = inventory['outputs'] + for output_name, expected_output in expected_outputs.items(): + assert output_name in summary.outputs, \ + f'module does not output `{output_name}`' + output = summary.outputs[output_name] + # assert 'value' in output, \ + # f'output `{output_name}` does not have a value (is it sensitive or dynamic?)' + plan_output = output.get('value', '__missing__') + assert plan_output == expected_output, \ + f'output {output_name} failed. Got `{plan_output}`, expected `{expected_output}`' return summary diff --git a/tests/fast/stages/s00_bootstrap/test_plan.py b/tests/fast/stages/s00_bootstrap/test_plan.py index d2c0d533f..206b394a5 100644 --- a/tests/fast/stages/s00_bootstrap/test_plan.py +++ b/tests/fast/stages/s00_bootstrap/test_plan.py @@ -14,8 +14,5 @@ def test_simple(generic_plan_validator): - generic_plan_validator( - inventory_path='simple.yaml', - module_path="fast/stages/00-bootstrap", - tf_var_files=['simple.tfvars'], - ) + generic_plan_validator("fast/stages/00-bootstrap", 'simple.yaml', + ['simple.tfvars']) diff --git a/tests/modules/net_vpc/test_plan.py b/tests/modules/net_vpc/test_plan.py index e50c81979..5deec3004 100644 --- a/tests/modules/net_vpc/test_plan.py +++ b/tests/modules/net_vpc/test_plan.py @@ -37,38 +37,25 @@ _VAR_ROUTES_NEXT_HOPS = { def test_simple(generic_plan_validator): - generic_plan_validator( - inventory_path='simple.yaml', - module_path='modules/net-vpc', - tf_var_files=['common.tfvars'], - ) + generic_plan_validator('modules/net-vpc', 'simple.yaml', ['common.tfvars']) def test_vpc_shared(generic_plan_validator): - generic_plan_validator( - inventory_path='shared_vpc.yaml', - module_path='modules/net-vpc', - tf_var_files=['common.tfvars', 'shared_vpc.tfvars'], - ) + generic_plan_validator('modules/net-vpc', 'shared_vpc.yaml', + ['common.tfvars', 'shared_vpc.tfvars']) def test_vpc_peering(generic_plan_validator): - generic_plan_validator( - inventory_path='peering.yaml', - module_path='modules/net-vpc', - tf_var_files=['common.tfvars', 'peering.tfvars'], - ) + generic_plan_validator('modules/net-vpc', 'peering.yaml', + ['common.tfvars', 'peering.tfvars']) def test_vpc_routes(generic_plan_summary): 'Test vpc routes.' for next_hop_type, next_hop in _VAR_ROUTES_NEXT_HOPS.items(): var_routes = _VAR_ROUTES_TEMPLATE % (next_hop_type, next_hop) - summary = generic_plan_summary( - module_path='modules/net-vpc', - tf_var_files=['common.tfvars'], - routes=var_routes, - ) + summary = generic_plan_summary('modules/net-vpc', ['common.tfvars'], + routes=var_routes) assert len(summary.values) == 3 route = summary.values[f'google_compute_route.{next_hop_type}["next-hop"]'] assert route[f'next_hop_{next_hop_type}'] == next_hop diff --git a/tests/modules/net_vpc/test_plan_psa.py b/tests/modules/net_vpc/test_plan_psa.py index 9ae7cdb4d..ad26e559e 100644 --- a/tests/modules/net_vpc/test_plan_psa.py +++ b/tests/modules/net_vpc/test_plan_psa.py @@ -16,25 +16,20 @@ import yaml def test_simple(generic_plan_validator): - generic_plan_validator(inventory_path='psa_simple.yaml', - module_path="modules/net-vpc", - tf_var_files=['common.tfvars', 'psa_simple.tfvars']) + generic_plan_validator("modules/net-vpc", 'psa_simple.yaml', + ['common.tfvars', 'psa_simple.tfvars']) def test_routes_export(generic_plan_validator): - generic_plan_validator( - inventory_path='psa_routes_export.yaml', module_path="modules/net-vpc", - tf_var_files=['common.tfvars', 'psa_routes_export.tfvars']) + generic_plan_validator("modules/net-vpc", 'psa_routes_export.yaml', + ['common.tfvars', 'psa_routes_export.tfvars']) def test_routes_import(generic_plan_validator): - generic_plan_validator( - inventory_path='psa_routes_import.yaml', module_path="modules/net-vpc", - tf_var_files=['common.tfvars', 'psa_routes_import.tfvars']) + generic_plan_validator("modules/net-vpc", 'psa_routes_import.yaml', + ['common.tfvars', 'psa_routes_import.tfvars']) def test_routes_import_export(generic_plan_validator): - generic_plan_validator( - inventory_path='psa_routes_import_export.yaml', - module_path="modules/net-vpc", - tf_var_files=['common.tfvars', 'psa_routes_import_export.tfvars']) + generic_plan_validator("modules/net-vpc", 'psa_routes_import_export.yaml', + ['common.tfvars', 'psa_routes_import_export.tfvars']) diff --git a/tests/modules/net_vpc/test_plan_subnets.py b/tests/modules/net_vpc/test_plan_subnets.py index ef155c7c8..f9af768f3 100644 --- a/tests/modules/net_vpc/test_plan_subnets.py +++ b/tests/modules/net_vpc/test_plan_subnets.py @@ -31,8 +31,5 @@ def test_subnet_factory(plan_runner): def test_subnets(generic_plan_validator): - generic_plan_validator( - inventory_path='subnets.yaml', - module_path="modules/net-vpc", - tf_var_files=['common.tfvars', 'subnets.tfvars'], - ) + generic_plan_validator("modules/net-vpc", 'subnets.yaml', + ['common.tfvars', 'subnets.tfvars'])