From e4f91190c9df07f70a79db9b102a40e00dec0a22 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Thu, 5 Mar 2026 13:55:15 +0100 Subject: [PATCH] add tests for dynamic module sources in terraform test --- internal/command/test.go | 75 +++-- internal/command/test_test.go | 280 ++++++++++++++++++ .../test/dynamic_source_missing_var/main.tf | 8 + .../main.tftest.hcl | 6 + .../modules/example/main.tf | 3 + .../test/dynamic_source_nested/main.tf | 9 + .../dynamic_source_nested/main.tftest.hcl | 6 + .../modules/child/main.tf | 7 + .../modules/parent/main.tf | 12 + .../test/dynamic_source_non_const_var/main.tf | 7 + .../main.tftest.hcl | 6 + .../modules/example/main.tf | 3 + .../dynamic_source_nonexistent_module/main.tf | 9 + .../main.tftest.hcl | 6 + .../modules/example/main.tf | 3 + .../test/dynamic_source_with_default/main.tf | 9 + .../main.tftest.hcl | 6 + .../modules/example/main.tf | 7 + .../dynamic_source_with_local_value/main.tf | 12 + .../main.tftest.hcl | 6 + .../modules/example/main.tf | 7 + .../dynamic_source_with_setup_module/main.tf | 14 + .../main.tftest.hcl | 21 ++ .../modules/example/main.tf | 15 + .../setup/main.tf | 13 + .../test/dynamic_source_with_var_flag/main.tf | 8 + .../main.tftest.hcl | 6 + .../modules/example/main.tf | 7 + 28 files changed, 547 insertions(+), 24 deletions(-) create mode 100644 internal/command/testdata/test/dynamic_source_missing_var/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_missing_var/main.tftest.hcl create mode 100644 internal/command/testdata/test/dynamic_source_missing_var/modules/example/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_nested/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_nested/main.tftest.hcl create mode 100644 internal/command/testdata/test/dynamic_source_nested/modules/child/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_nested/modules/parent/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_non_const_var/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_non_const_var/main.tftest.hcl create mode 100644 internal/command/testdata/test/dynamic_source_non_const_var/modules/example/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_nonexistent_module/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_nonexistent_module/main.tftest.hcl create mode 100644 internal/command/testdata/test/dynamic_source_nonexistent_module/modules/example/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_with_default/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_with_default/main.tftest.hcl create mode 100644 internal/command/testdata/test/dynamic_source_with_default/modules/example/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_with_local_value/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_with_local_value/main.tftest.hcl create mode 100644 internal/command/testdata/test/dynamic_source_with_local_value/modules/example/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_with_setup_module/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_with_setup_module/main.tftest.hcl create mode 100644 internal/command/testdata/test/dynamic_source_with_setup_module/modules/example/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_with_setup_module/setup/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_with_var_flag/main.tf create mode 100644 internal/command/testdata/test/dynamic_source_with_var_flag/main.tftest.hcl create mode 100644 internal/command/testdata/test/dynamic_source_with_var_flag/modules/example/main.tf diff --git a/internal/command/test.go b/internal/command/test.go index 404f162724..a3376cacd7 100644 --- a/internal/command/test.go +++ b/internal/command/test.go @@ -321,6 +321,57 @@ func (m *Meta) setupTestExecution(mode moduletest.CommandMode, command string, r return } + loader, err := m.initConfigLoader() + if err != nil { + diags = diags.Append(err) + view.Diagnostics(nil, nil, diags) + return + } + + registerFileSource := func(filename string, src []byte) { + loader.Parser().ForceFileSource(filename, src) + } + + // Collect variables for "terraform test" + preparation.TestVariables, moreDiags = arguments.CollectValuesForTests(preparation.Args.TestDirectory, registerFileSource) + diags = diags.Append(moreDiags) + + // Collect variable values and add them to the operation request. + // We must collect these before loading config, because + // loadConfigWithTests needs const variable values available in + // m.VariableValues to resolve dynamic module sources. + var varDiags tfdiags.Diagnostics + preparation.Variables, varDiags = preparation.Args.Vars.CollectValues(registerFileSource) + diags = diags.Append(varDiags) + if diags.HasErrors() { + view.Diagnostics(nil, nil, diags) + return + } + + // Only populate m.VariableValues with variables that are declared + // as const in the root module. loadConfigWithTests uses + // m.VariableValues to resolve dynamic module sources via + // ParseConstVariableValues, which would otherwise error on + // undeclared variables passed via -var that are intended for + // test runs rather than the root module. + // + // We do an early load of just the root module to discover which + // variables are const. We discard non-error diagnostics from this + // early load since loadConfigWithTests will re-parse and report them. + earlyMod, earlyDiags := m.loadSingleModuleWithTests(".", preparation.Args.TestDirectory) + if earlyDiags.HasErrors() { + diags = diags.Append(earlyDiags) + view.Diagnostics(nil, nil, diags) + return + } + constVars := make(map[string]arguments.UnparsedVariableValue) + for name, val := range preparation.Variables { + if decl, exists := earlyMod.Variables[name]; exists && decl.Const { + constVars[name] = val + } + } + m.VariableValues = constVars + preparation.Config, moreDiags = m.loadConfigWithTests(".", preparation.Args.TestDirectory) diags = diags.Append(moreDiags) if moreDiags.HasErrors() { @@ -377,30 +428,6 @@ func (m *Meta) setupTestExecution(mode moduletest.CommandMode, command string, r return } - loader, err := m.initConfigLoader() - if err != nil { - diags = diags.Append(err) - view.Diagnostics(nil, nil, diags) - return - } - - registerFileSource := func(filename string, src []byte) { - loader.Parser().ForceFileSource(filename, src) - } - - // Collect variables for "terraform test" - preparation.TestVariables, moreDiags = arguments.CollectValuesForTests(preparation.Args.TestDirectory, registerFileSource) - diags = diags.Append(moreDiags) - - // Collect variable value and add them to the operation request - var varDiags tfdiags.Diagnostics - preparation.Variables, varDiags = preparation.Args.Vars.CollectValues(registerFileSource) - diags = diags.Append(varDiags) - if diags.HasErrors() { - view.Diagnostics(nil, nil, diags) - return - } - opts, err := m.contextOpts() if err != nil { diags = diags.Append(err) diff --git a/internal/command/test_test.go b/internal/command/test_test.go index d10fe31a3a..10b51e2030 100644 --- a/internal/command/test_test.go +++ b/internal/command/test_test.go @@ -433,6 +433,25 @@ func TestTest_Runs(t *testing.T) { expectedOut: []string{"2 passed, 0 failed."}, code: 0, }, + "dynamic_source_with_default": { + expectedOut: []string{"1 passed, 0 failed."}, + code: 0, + }, + "dynamic_source_missing_var": { + initCode: 1, + expectedErr: []string{"No value for required variable"}, + code: 1, + }, + "dynamic_source_nonexistent_module": { + initCode: 1, + expectedErr: []string{"Unreadable module directory"}, + code: 1, + }, + "dynamic_source_non_const_var": { + initCode: 1, + expectedErr: []string{"Invalid module source"}, + code: 1, + }, } for name, tc := range tcs { t.Run(name, func(t *testing.T) { @@ -2439,6 +2458,267 @@ func TestTest_ModuleDependencies(t *testing.T) { } } +func TestTest_DynamicSourceWithVarFlag(t *testing.T) { + td := t.TempDir() + testCopyDir(t, testFixturePath(path.Join("test", "dynamic_source_with_var_flag")), td) + t.Chdir(td) + + store := &testing_command.ResourceStore{ + Data: make(map[string]cty.Value), + } + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": {"1.0.0"}, + }) + defer close() + + streams, done := terminal.StreamsForTesting(t) + view := views.NewView(streams) + ui := new(cli.MockUi) + + meta := Meta{ + testingOverrides: &testingOverrides{ + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): func() (providers.Interface, error) { + return testing_command.NewProvider(store).Provider, nil + }, + }, + }, + Ui: ui, + View: view, + Streams: streams, + ProviderSource: providerSource, + } + + init := &InitCommand{Meta: meta} + if code := init.Run([]string{"-var", "module_name=example"}); code != 0 { + output := done(t) + t.Fatalf("expected status code 0 but got %d: %s", code, output.All()) + } + + // Reset the streams for the next command. + streams, done = terminal.StreamsForTesting(t) + meta.Streams = streams + meta.View = views.NewView(streams) + + c := &TestCommand{Meta: meta} + code := c.Run([]string{"-var", "module_name=example", "-no-color"}) + output := done(t) + + if code != 0 { + t.Errorf("expected status code 0 but got %d:\n\n%s", code, output.All()) + } + + if !strings.Contains(output.Stdout(), "1 passed, 0 failed.") { + t.Errorf("output didn't contain expected string:\n\n%s", output.Stdout()) + } + + if len(store.Data) != 0 { + t.Errorf("should have deleted all resources on completion but left %d", len(store.Data)) + } +} + +func TestTest_DynamicSourceWithLocalValue(t *testing.T) { + td := t.TempDir() + testCopyDir(t, testFixturePath(path.Join("test", "dynamic_source_with_local_value")), td) + t.Chdir(td) + + store := &testing_command.ResourceStore{ + Data: make(map[string]cty.Value), + } + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": {"1.0.0"}, + }) + defer close() + + streams, done := terminal.StreamsForTesting(t) + view := views.NewView(streams) + ui := new(cli.MockUi) + + meta := Meta{ + testingOverrides: &testingOverrides{ + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): func() (providers.Interface, error) { + return testing_command.NewProvider(store).Provider, nil + }, + }, + }, + Ui: ui, + View: view, + Streams: streams, + ProviderSource: providerSource, + } + + init := &InitCommand{Meta: meta} + if code := init.Run([]string{"-var", "module_name=example"}); code != 0 { + output := done(t) + t.Fatalf("expected status code 0 but got %d: %s", code, output.All()) + } + + // Reset the streams for the next command. + streams, done = terminal.StreamsForTesting(t) + meta.Streams = streams + meta.View = views.NewView(streams) + + c := &TestCommand{Meta: meta} + code := c.Run([]string{"-var", "module_name=example", "-no-color"}) + output := done(t) + + if code != 0 { + t.Errorf("expected status code 0 but got %d:\n\n%s", code, output.All()) + } + + if !strings.Contains(output.Stdout(), "1 passed, 0 failed.") { + t.Errorf("output didn't contain expected string:\n\n%s", output.Stdout()) + } + + if len(store.Data) != 0 { + t.Errorf("should have deleted all resources on completion but left %d", len(store.Data)) + } +} + +func TestTest_DynamicSourceNested(t *testing.T) { + td := t.TempDir() + testCopyDir(t, testFixturePath(path.Join("test", "dynamic_source_nested")), td) + t.Chdir(td) + + store := &testing_command.ResourceStore{ + Data: make(map[string]cty.Value), + } + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": {"1.0.0"}, + }) + defer close() + + streams, done := terminal.StreamsForTesting(t) + view := views.NewView(streams) + ui := new(cli.MockUi) + + meta := Meta{ + testingOverrides: &testingOverrides{ + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): func() (providers.Interface, error) { + return testing_command.NewProvider(store).Provider, nil + }, + }, + }, + Ui: ui, + View: view, + Streams: streams, + ProviderSource: providerSource, + } + + init := &InitCommand{Meta: meta} + if code := init.Run([]string{"-var", "child_name=child"}); code != 0 { + output := done(t) + t.Fatalf("expected status code 0 but got %d: %s", code, output.All()) + } + + // Reset the streams for the next command. + streams, done = terminal.StreamsForTesting(t) + meta.Streams = streams + meta.View = views.NewView(streams) + + c := &TestCommand{Meta: meta} + code := c.Run([]string{"-var", "child_name=child", "-no-color"}) + output := done(t) + + if code != 0 { + t.Errorf("expected status code 0 but got %d:\n\n%s", code, output.All()) + } + + if !strings.Contains(output.Stdout(), "1 passed, 0 failed.") { + t.Errorf("output didn't contain expected string:\n\n%s", output.Stdout()) + } + + if len(store.Data) != 0 { + t.Errorf("should have deleted all resources on completion but left %d", len(store.Data)) + } +} + +func TestTest_DynamicSourceWithSetupModule(t *testing.T) { + td := t.TempDir() + testCopyDir(t, testFixturePath(path.Join("test", "dynamic_source_with_setup_module")), td) + t.Chdir(td) + + // Our two providers will share a common set of values to make things + // easier. + store := &testing_command.ResourceStore{ + Data: make(map[string]cty.Value), + } + + // We set it up so the setup provider will write into the data sources + // available to the test provider. + test := testing_command.NewProvider(store) + setup := testing_command.NewProvider(store) + + test.SetDataPrefix("data") + test.SetResourcePrefix("resource") + + // Let's make the setup provider write into the data for test provider. + setup.SetResourcePrefix("data") + + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": {"1.0.0"}, + "setup": {"1.0.0"}, + }) + defer close() + + streams, done := terminal.StreamsForTesting(t) + view := views.NewView(streams) + ui := new(cli.MockUi) + + meta := Meta{ + testingOverrides: &testingOverrides{ + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): providers.FactoryFixed(test.Provider), + addrs.NewDefaultProvider("setup"): providers.FactoryFixed(setup.Provider), + }, + }, + Ui: ui, + View: view, + Streams: streams, + ProviderSource: providerSource, + } + + init := &InitCommand{Meta: meta} + if code := init.Run(nil); code != 0 { + output := done(t) + t.Fatalf("expected status code 0 but got %d: %s", code, output.All()) + } + + // Reset the streams for the next command. + streams, done = terminal.StreamsForTesting(t) + meta.Streams = streams + meta.View = views.NewView(streams) + + c := &TestCommand{Meta: meta} + code := c.Run([]string{"-no-color"}) + output := done(t) + + printedOutput := false + + if code != 0 { + printedOutput = true + t.Errorf("expected status code 0 but got %d:\n\n%s", code, output.All()) + } + + if !strings.Contains(output.Stdout(), "2 passed, 0 failed.") { + if !printedOutput { + t.Errorf("output didn't contain expected string:\n\n%s", output.All()) + } else { + t.Errorf("output didn't contain expected string: %q", output.Stdout()) + } + } + + if test.ResourceCount() > 0 { + t.Errorf("should have deleted all resources on completion but left %s", test.ResourceString()) + } + + if setup.ResourceCount() > 0 { + t.Errorf("should have deleted all resources on completion but left %s", setup.ResourceString()) + } +} + func TestTest_CatchesErrorsBeforeDestroy(t *testing.T) { td := t.TempDir() testCopyDir(t, testFixturePath(path.Join("test", "invalid_default_state")), td) diff --git a/internal/command/testdata/test/dynamic_source_missing_var/main.tf b/internal/command/testdata/test/dynamic_source_missing_var/main.tf new file mode 100644 index 0000000000..fb85fc0265 --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_missing_var/main.tf @@ -0,0 +1,8 @@ +variable "module_name" { + type = string + const = true +} + +module "mod" { + source = "./modules/${var.module_name}" +} diff --git a/internal/command/testdata/test/dynamic_source_missing_var/main.tftest.hcl b/internal/command/testdata/test/dynamic_source_missing_var/main.tftest.hcl new file mode 100644 index 0000000000..ba8473960a --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_missing_var/main.tftest.hcl @@ -0,0 +1,6 @@ +run "should_not_reach" { + assert { + condition = true + error_message = "should not reach this point" + } +} diff --git a/internal/command/testdata/test/dynamic_source_missing_var/modules/example/main.tf b/internal/command/testdata/test/dynamic_source_missing_var/modules/example/main.tf new file mode 100644 index 0000000000..41cc84e5c4 --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_missing_var/modules/example/main.tf @@ -0,0 +1,3 @@ +resource "test_resource" "foo" { + value = "bar" +} diff --git a/internal/command/testdata/test/dynamic_source_nested/main.tf b/internal/command/testdata/test/dynamic_source_nested/main.tf new file mode 100644 index 0000000000..b0db6a9f5e --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_nested/main.tf @@ -0,0 +1,9 @@ +variable "child_name" { + type = string + const = true +} + +module "parent" { + source = "./modules/parent" + child_name = var.child_name +} diff --git a/internal/command/testdata/test/dynamic_source_nested/main.tftest.hcl b/internal/command/testdata/test/dynamic_source_nested/main.tftest.hcl new file mode 100644 index 0000000000..2ff5ea44ad --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_nested/main.tftest.hcl @@ -0,0 +1,6 @@ +run "validate_nested_dynamic_module" { + assert { + condition = module.parent.value == "from_child" + error_message = "expected from_child from nested dynamically sourced module" + } +} diff --git a/internal/command/testdata/test/dynamic_source_nested/modules/child/main.tf b/internal/command/testdata/test/dynamic_source_nested/modules/child/main.tf new file mode 100644 index 0000000000..eb337b779b --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_nested/modules/child/main.tf @@ -0,0 +1,7 @@ +resource "test_resource" "foo" { + value = "from_child" +} + +output "value" { + value = test_resource.foo.value +} diff --git a/internal/command/testdata/test/dynamic_source_nested/modules/parent/main.tf b/internal/command/testdata/test/dynamic_source_nested/modules/parent/main.tf new file mode 100644 index 0000000000..a74e631dba --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_nested/modules/parent/main.tf @@ -0,0 +1,12 @@ +variable "child_name" { + type = string + const = true +} + +module "child" { + source = "../${var.child_name}" +} + +output "value" { + value = module.child.value +} diff --git a/internal/command/testdata/test/dynamic_source_non_const_var/main.tf b/internal/command/testdata/test/dynamic_source_non_const_var/main.tf new file mode 100644 index 0000000000..17affcc60b --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_non_const_var/main.tf @@ -0,0 +1,7 @@ +variable "module_name" { + type = string +} + +module "mod" { + source = "./modules/${var.module_name}" +} diff --git a/internal/command/testdata/test/dynamic_source_non_const_var/main.tftest.hcl b/internal/command/testdata/test/dynamic_source_non_const_var/main.tftest.hcl new file mode 100644 index 0000000000..ba8473960a --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_non_const_var/main.tftest.hcl @@ -0,0 +1,6 @@ +run "should_not_reach" { + assert { + condition = true + error_message = "should not reach this point" + } +} diff --git a/internal/command/testdata/test/dynamic_source_non_const_var/modules/example/main.tf b/internal/command/testdata/test/dynamic_source_non_const_var/modules/example/main.tf new file mode 100644 index 0000000000..41cc84e5c4 --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_non_const_var/modules/example/main.tf @@ -0,0 +1,3 @@ +resource "test_resource" "foo" { + value = "bar" +} diff --git a/internal/command/testdata/test/dynamic_source_nonexistent_module/main.tf b/internal/command/testdata/test/dynamic_source_nonexistent_module/main.tf new file mode 100644 index 0000000000..ef5ee0319f --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_nonexistent_module/main.tf @@ -0,0 +1,9 @@ +variable "module_name" { + type = string + const = true + default = "nonexistent" +} + +module "mod" { + source = "./modules/${var.module_name}" +} diff --git a/internal/command/testdata/test/dynamic_source_nonexistent_module/main.tftest.hcl b/internal/command/testdata/test/dynamic_source_nonexistent_module/main.tftest.hcl new file mode 100644 index 0000000000..ba8473960a --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_nonexistent_module/main.tftest.hcl @@ -0,0 +1,6 @@ +run "should_not_reach" { + assert { + condition = true + error_message = "should not reach this point" + } +} diff --git a/internal/command/testdata/test/dynamic_source_nonexistent_module/modules/example/main.tf b/internal/command/testdata/test/dynamic_source_nonexistent_module/modules/example/main.tf new file mode 100644 index 0000000000..41cc84e5c4 --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_nonexistent_module/modules/example/main.tf @@ -0,0 +1,3 @@ +resource "test_resource" "foo" { + value = "bar" +} diff --git a/internal/command/testdata/test/dynamic_source_with_default/main.tf b/internal/command/testdata/test/dynamic_source_with_default/main.tf new file mode 100644 index 0000000000..b64283129e --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_default/main.tf @@ -0,0 +1,9 @@ +variable "module_name" { + type = string + const = true + default = "example" +} + +module "mod" { + source = "./modules/${var.module_name}" +} diff --git a/internal/command/testdata/test/dynamic_source_with_default/main.tftest.hcl b/internal/command/testdata/test/dynamic_source_with_default/main.tftest.hcl new file mode 100644 index 0000000000..4adb0d7ecd --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_default/main.tftest.hcl @@ -0,0 +1,6 @@ +run "validate_dynamic_module" { + assert { + condition = module.mod.value == "bar" + error_message = "expected bar from dynamically sourced module" + } +} diff --git a/internal/command/testdata/test/dynamic_source_with_default/modules/example/main.tf b/internal/command/testdata/test/dynamic_source_with_default/modules/example/main.tf new file mode 100644 index 0000000000..7354f944a1 --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_default/modules/example/main.tf @@ -0,0 +1,7 @@ +resource "test_resource" "foo" { + value = "bar" +} + +output "value" { + value = test_resource.foo.value +} diff --git a/internal/command/testdata/test/dynamic_source_with_local_value/main.tf b/internal/command/testdata/test/dynamic_source_with_local_value/main.tf new file mode 100644 index 0000000000..cda19b736e --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_local_value/main.tf @@ -0,0 +1,12 @@ +variable "module_name" { + type = string + const = true +} + +locals { + module_source = "./modules/${var.module_name}" +} + +module "mod" { + source = local.module_source +} diff --git a/internal/command/testdata/test/dynamic_source_with_local_value/main.tftest.hcl b/internal/command/testdata/test/dynamic_source_with_local_value/main.tftest.hcl new file mode 100644 index 0000000000..4adb0d7ecd --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_local_value/main.tftest.hcl @@ -0,0 +1,6 @@ +run "validate_dynamic_module" { + assert { + condition = module.mod.value == "bar" + error_message = "expected bar from dynamically sourced module" + } +} diff --git a/internal/command/testdata/test/dynamic_source_with_local_value/modules/example/main.tf b/internal/command/testdata/test/dynamic_source_with_local_value/modules/example/main.tf new file mode 100644 index 0000000000..7354f944a1 --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_local_value/modules/example/main.tf @@ -0,0 +1,7 @@ +resource "test_resource" "foo" { + value = "bar" +} + +output "value" { + value = test_resource.foo.value +} diff --git a/internal/command/testdata/test/dynamic_source_with_setup_module/main.tf b/internal/command/testdata/test/dynamic_source_with_setup_module/main.tf new file mode 100644 index 0000000000..26eff094a2 --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_setup_module/main.tf @@ -0,0 +1,14 @@ +variable "module_name" { + type = string + const = true + default = "example" +} + +variable "managed_id" { + type = string +} + +module "mod" { + source = "./modules/${var.module_name}" + id = var.managed_id +} diff --git a/internal/command/testdata/test/dynamic_source_with_setup_module/main.tftest.hcl b/internal/command/testdata/test/dynamic_source_with_setup_module/main.tftest.hcl new file mode 100644 index 0000000000..8789e32183 --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_setup_module/main.tftest.hcl @@ -0,0 +1,21 @@ +variables { + managed_id = "B853C121" +} + +run "setup" { + module { + source = "./setup" + } + + variables { + value = "Hello, world!" + id = "B853C121" + } +} + +run "test" { + assert { + condition = module.mod.value == "Hello, world!" + error_message = "expected value from setup module via dynamic source" + } +} diff --git a/internal/command/testdata/test/dynamic_source_with_setup_module/modules/example/main.tf b/internal/command/testdata/test/dynamic_source_with_setup_module/modules/example/main.tf new file mode 100644 index 0000000000..2416f28ddc --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_setup_module/modules/example/main.tf @@ -0,0 +1,15 @@ +variable "id" { + type = string +} + +data "test_data_source" "managed_data" { + id = var.id +} + +resource "test_resource" "foo" { + value = data.test_data_source.managed_data.value +} + +output "value" { + value = test_resource.foo.value +} diff --git a/internal/command/testdata/test/dynamic_source_with_setup_module/setup/main.tf b/internal/command/testdata/test/dynamic_source_with_setup_module/setup/main.tf new file mode 100644 index 0000000000..b4e5a75aba --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_setup_module/setup/main.tf @@ -0,0 +1,13 @@ +variable "value" { + type = string +} + +variable "id" { + type = string +} + +resource "test_resource" "managed" { + provider = setup + id = var.id + value = var.value +} diff --git a/internal/command/testdata/test/dynamic_source_with_var_flag/main.tf b/internal/command/testdata/test/dynamic_source_with_var_flag/main.tf new file mode 100644 index 0000000000..fb85fc0265 --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_var_flag/main.tf @@ -0,0 +1,8 @@ +variable "module_name" { + type = string + const = true +} + +module "mod" { + source = "./modules/${var.module_name}" +} diff --git a/internal/command/testdata/test/dynamic_source_with_var_flag/main.tftest.hcl b/internal/command/testdata/test/dynamic_source_with_var_flag/main.tftest.hcl new file mode 100644 index 0000000000..4adb0d7ecd --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_var_flag/main.tftest.hcl @@ -0,0 +1,6 @@ +run "validate_dynamic_module" { + assert { + condition = module.mod.value == "bar" + error_message = "expected bar from dynamically sourced module" + } +} diff --git a/internal/command/testdata/test/dynamic_source_with_var_flag/modules/example/main.tf b/internal/command/testdata/test/dynamic_source_with_var_flag/modules/example/main.tf new file mode 100644 index 0000000000..7354f944a1 --- /dev/null +++ b/internal/command/testdata/test/dynamic_source_with_var_flag/modules/example/main.tf @@ -0,0 +1,7 @@ +resource "test_resource" "foo" { + value = "bar" +} + +output "value" { + value = test_resource.foo.value +}