From ab289fc07c4dbbb75eecb2b526e8e8abbf23c5fd Mon Sep 17 00:00:00 2001 From: Ronny Orot Date: Mon, 24 Jun 2024 16:10:35 +0300 Subject: [PATCH] OpenTofu Specific Code Override: Add support to .tofu files (#1738) Signed-off-by: Ronny Orot --- .golangci.yml | 3 + internal/configs/parser_config_dir.go | 109 ++++++++++++++++-- internal/configs/parser_config_dir_test.go | 73 ++++++++++++ .../tofu-and-tf-files/more-resources.tf | 3 + .../tofu-and-tf-files/more-resources.tf.json | 10 ++ .../testdata/tofu-and-tf-files/resources.tf | 43 +++++++ .../tofu-and-tf-files/resources.tf.json | 14 +++ .../testdata/tofu-and-tf-files/resources.tofu | 43 +++++++ .../tofu-and-tf-files/resources.tofu.json | 14 +++ .../test/resources_test.tftest.hcl | 27 +++++ .../test/resources_test.tofutest.hcl | 27 +++++ .../test/resources_test_json.tftest.json | 29 +++++ .../test/resources_test_json.tofutest.json | 29 +++++ .../testdata/tofu-and-tf-files/variables.tf | 3 + .../tofu-and-tf-files/variables.tf.json | 7 ++ .../tofu-and-tf-files/variables_override.tf | 3 + .../variables_override.tf.json | 7 ++ .../tofu-and-tf-files/variables_override.tofu | 3 + .../variables_override.tofu.json | 7 ++ .../testdata/tofu-only-files/resources.tofu | 43 +++++++ .../tofu-only-files/resources.tofu.json | 14 +++ .../test/resources_test.tofutest.hcl | 27 +++++ .../test/resources_test_json.tofutest.json | 29 +++++ .../testdata/tofu-only-files/variables.tofu | 3 + .../tofu-only-files/variables.tofu.json | 7 ++ .../tofu-only-files/variables_override.tofu | 3 + .../variables_override.tofu.json | 7 ++ 27 files changed, 575 insertions(+), 12 deletions(-) create mode 100644 internal/configs/testdata/tofu-and-tf-files/more-resources.tf create mode 100644 internal/configs/testdata/tofu-and-tf-files/more-resources.tf.json create mode 100644 internal/configs/testdata/tofu-and-tf-files/resources.tf create mode 100644 internal/configs/testdata/tofu-and-tf-files/resources.tf.json create mode 100644 internal/configs/testdata/tofu-and-tf-files/resources.tofu create mode 100644 internal/configs/testdata/tofu-and-tf-files/resources.tofu.json create mode 100644 internal/configs/testdata/tofu-and-tf-files/test/resources_test.tftest.hcl create mode 100644 internal/configs/testdata/tofu-and-tf-files/test/resources_test.tofutest.hcl create mode 100644 internal/configs/testdata/tofu-and-tf-files/test/resources_test_json.tftest.json create mode 100644 internal/configs/testdata/tofu-and-tf-files/test/resources_test_json.tofutest.json create mode 100644 internal/configs/testdata/tofu-and-tf-files/variables.tf create mode 100644 internal/configs/testdata/tofu-and-tf-files/variables.tf.json create mode 100644 internal/configs/testdata/tofu-and-tf-files/variables_override.tf create mode 100644 internal/configs/testdata/tofu-and-tf-files/variables_override.tf.json create mode 100644 internal/configs/testdata/tofu-and-tf-files/variables_override.tofu create mode 100644 internal/configs/testdata/tofu-and-tf-files/variables_override.tofu.json create mode 100644 internal/configs/testdata/tofu-only-files/resources.tofu create mode 100644 internal/configs/testdata/tofu-only-files/resources.tofu.json create mode 100644 internal/configs/testdata/tofu-only-files/test/resources_test.tofutest.hcl create mode 100644 internal/configs/testdata/tofu-only-files/test/resources_test_json.tofutest.json create mode 100644 internal/configs/testdata/tofu-only-files/variables.tofu create mode 100644 internal/configs/testdata/tofu-only-files/variables.tofu.json create mode 100644 internal/configs/testdata/tofu-only-files/variables_override.tofu create mode 100644 internal/configs/testdata/tofu-only-files/variables_override.tofu.json diff --git a/.golangci.yml b/.golangci.yml index 2d86f7a61b..2696c0d3e5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -32,6 +32,9 @@ linters-settings: cyclop: max-complexity: 15 + gocognit: + min-complexity: 50 + issues: exclude-rules: - path: (.+)_test.go diff --git a/internal/configs/parser_config_dir.go b/internal/configs/parser_config_dir.go index a292bba383..a7c3f5472d 100644 --- a/internal/configs/parser_config_dir.go +++ b/internal/configs/parser_config_dir.go @@ -7,9 +7,11 @@ package configs import ( "fmt" + "log" "os" "path" "path/filepath" + "slices" "strings" "github.com/hashicorp/hcl/v2" @@ -19,6 +21,17 @@ const ( DefaultTestDirectory = "tests" ) +const ( + tfExt = ".tf" + tofuExt = ".tofu" + tfJSONExt = ".tf.json" + tofuJSONExt = ".tofu.json" + tfTestExt = ".tftest.hcl" + tofuTestExt = ".tofutest.hcl" + tfTestJSONExt = ".tftest.json" + tofuTestJSONExt = ".tofutest.json" +) + // LoadConfigDir reads the .tf and .tf.json files in the given directory // as config files (using LoadConfigFile) and then combines these files into // a single Module. @@ -178,7 +191,8 @@ func (p *Parser) dirFiles(dir string, testsDir string) (primary, override, tests continue } - if strings.HasSuffix(testInfo.Name(), ".tftest.hcl") || strings.HasSuffix(testInfo.Name(), ".tftest.json") { + ext := fileExt(testInfo.Name()) + if isTestFileExt(ext) { tests = append(tests, filepath.Join(testPath, testInfo.Name())) } } @@ -208,7 +222,7 @@ func (p *Parser) dirFiles(dir string, testsDir string) (primary, override, tests continue } - if ext == ".tftest.hcl" || ext == ".tftest.json" { + if isTestFileExt(ext) { if includeTests { tests = append(tests, filepath.Join(dir, name)) } @@ -226,7 +240,44 @@ func (p *Parser) dirFiles(dir string, testsDir string) (primary, override, tests } } - return + return filterTfPathsWithTofuAlternatives(primary), filterTfPathsWithTofuAlternatives(override), filterTfPathsWithTofuAlternatives(tests), diags +} + +// filterTfPathsWithTofuAlternatives filters out .tf files if they have an +// alternative .tofu file with the same name. +// For example, if there are both 'resources.tf.json' and +// 'resources.tofu.json' files, the 'resources.tf.json' file will be ignored, +// and only the 'resources.tofu.json' file will be returned as a relevant path. +func filterTfPathsWithTofuAlternatives(paths []string) []string { + var ignoredPaths []string + var relevantPaths []string + + for _, p := range paths { + ext := tfFileExt(p) + + if ext == "" { + relevantPaths = append(relevantPaths, p) + continue + } + + parallelTofuExt := strings.ReplaceAll(ext, ".tf", ".tofu") + pathWithoutExt, _ := strings.CutSuffix(p, ext) + parallelTofuPath := pathWithoutExt + parallelTofuExt + + // If the .tf file has a parallel .tofu file in the directory, + // we'll ignore the .tf file and only use the .tofu file + if slices.Contains(paths, parallelTofuPath) { + ignoredPaths = append(ignoredPaths, p) + } else { + relevantPaths = append(relevantPaths, p) + } + } + + if len(ignoredPaths) > 0 { + log.Printf("[INFO] filterTfPathsWithTofuAlternatives: Ignored the following .tf files because a .tofu file alternative exists: %q", ignoredPaths) + } + + return relevantPaths } func (p *Parser) loadTestFiles(basePath string, paths []string) (map[string]*TestFile, hcl.Diagnostics) { @@ -258,19 +309,53 @@ func (p *Parser) loadTestFiles(basePath string, paths []string) (map[string]*Tes // fileExt returns the OpenTofu configuration extension of the given // path, or a blank string if it is not a recognized extension. func fileExt(path string) string { - if strings.HasSuffix(path, ".tf") { - return ".tf" - } else if strings.HasSuffix(path, ".tf.json") { - return ".tf.json" - } else if strings.HasSuffix(path, ".tftest.hcl") { - return ".tftest.hcl" - } else if strings.HasSuffix(path, ".tftest.json") { - return ".tftest.json" - } else { + extension := tfFileExt(path) + + if extension == "" { + extension = tofuFileExt(path) + } + + return extension +} + +// tfFileExt returns the OpenTofu .tf configuration extension of the given +// path, or a blank string if it is not a recognized .tf extension. +func tfFileExt(path string) string { + switch { + case strings.HasSuffix(path, tfExt): + return tfExt + case strings.HasSuffix(path, tfJSONExt): + return tfJSONExt + case strings.HasSuffix(path, tfTestExt): + return tfTestExt + case strings.HasSuffix(path, tfTestJSONExt): + return tfTestJSONExt + default: return "" } } +// tofuFileExt returns the OpenTofu .tofu configuration extension of the given +// path, or a blank string if it is not a recognized .tofu extension. +func tofuFileExt(path string) string { + switch { + case strings.HasSuffix(path, tofuExt): + return tofuExt + case strings.HasSuffix(path, tofuJSONExt): + return tofuJSONExt + case strings.HasSuffix(path, tofuTestExt): + return tofuTestExt + case strings.HasSuffix(path, tofuTestJSONExt): + return tofuTestJSONExt + } + + return "" +} + +func isTestFileExt(ext string) bool { + return ext == tfTestExt || ext == tfTestJSONExt || ext == tofuTestExt || ext == tofuTestJSONExt +} + // IsIgnoredFile returns true if the given filename (which must not have a // directory path ahead of it) should be ignored as e.g. an editor swap file. func IsIgnoredFile(name string) bool { diff --git a/internal/configs/parser_config_dir_test.go b/internal/configs/parser_config_dir_test.go index d45499eea1..4148397d47 100644 --- a/internal/configs/parser_config_dir_test.go +++ b/internal/configs/parser_config_dir_test.go @@ -238,6 +238,79 @@ func TestParserLoadConfigDirFailure(t *testing.T) { } +func TestParserLoadConfigDirWithTests_TofuFiles(t *testing.T) { + expectedVariablesToOverride := []string{"should_override", "should_override_json"} + expectedLoadedTestFiles := []string{"test/resources_test.tofutest.hcl", "test/resources_test_json.tofutest.json"} + + tests := []struct { + name string + path string + expectedResources []string + }{ + { + name: "only .tofu files", + path: "testdata/tofu-only-files", + expectedResources: []string{"aws_security_group.firewall_tofu", "aws_instance.web_tofu", "test_object.a_tofu", "test_object.b_tofu"}, + }, + { + name: ".tofu and .tf files", + path: "testdata/tofu-and-tf-files", + expectedResources: []string{"aws_security_group.firewall_tofu", "aws_instance.web_tofu", "test_object.a_tofu", "test_object.b_tofu", "tf_resource.first", "tf_json_resource.a"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + parser := NewParser(nil) + path := tt.path + + mod, diags := parser.LoadConfigDirWithTests(path, "test") + if len(diags) != 0 { + t.Errorf("unexpected diagnostics") + for _, diag := range diags { + t.Logf("- %s", diag) + } + } + + if mod.SourceDir != path { + t.Errorf("wrong SourceDir value %q; want %s", mod.SourceDir, path) + } + + if len(tt.expectedResources) != len(mod.ManagedResources) { + t.Errorf("expected to find %d resources but instead got %d resources", len(tt.expectedResources), len(mod.ManagedResources)) + } + + for _, expectedResource := range tt.expectedResources { + if mod.ManagedResources[expectedResource] == nil { + t.Errorf("expected to load %s resource as part of configuration but it is missing", expectedResource) + } + } + + if len(expectedVariablesToOverride) != len(mod.Variables) { + t.Errorf("expected to find %d variables but instead got %d resources", len(expectedVariablesToOverride), len(mod.Variables)) + } + + for _, expectedVariable := range expectedVariablesToOverride { + variableInConfiguration := mod.Variables[expectedVariable] + if variableInConfiguration == nil { + t.Errorf("expected to load %s variable as part of configuration but it is missing", expectedVariable) + } else if variableInConfiguration.Default.AsString() != "overridden by tofu file" { + t.Errorf("expected variable default value %s to be overridden", expectedVariable) + } + } + + if len(mod.Tests) != 2 { + t.Errorf("incorrect number of test files found: %d", len(mod.Tests)) + } + + for _, expectedTest := range expectedLoadedTestFiles { + if mod.Tests[expectedTest] == nil { + t.Errorf("expected to load %s test as part of configuration but it is missing", expectedTest) + } + } + }) + } +} + func TestIsEmptyDir(t *testing.T) { val, err := IsEmptyDir(filepath.Join("testdata", "valid-files")) if err != nil { diff --git a/internal/configs/testdata/tofu-and-tf-files/more-resources.tf b/internal/configs/testdata/tofu-and-tf-files/more-resources.tf new file mode 100644 index 0000000000..6abfa801b5 --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/more-resources.tf @@ -0,0 +1,3 @@ +resource "tf_resource" "first" { + test_string = "hello" +} \ No newline at end of file diff --git a/internal/configs/testdata/tofu-and-tf-files/more-resources.tf.json b/internal/configs/testdata/tofu-and-tf-files/more-resources.tf.json new file mode 100644 index 0000000000..0a5f9809d8 --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/more-resources.tf.json @@ -0,0 +1,10 @@ +{ + "resource": { + "tf_json_resource": { + "a": { + "count": 1, + "test_string": "first" + } + } + } +} diff --git a/internal/configs/testdata/tofu-and-tf-files/resources.tf b/internal/configs/testdata/tofu-and-tf-files/resources.tf new file mode 100644 index 0000000000..349e9f6200 --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/resources.tf @@ -0,0 +1,43 @@ +resource "aws_security_group" "firewall" { + lifecycle { + create_before_destroy = true + prevent_destroy = true + ignore_changes = [ + description, + ] + } + + connection { + host = "127.0.0.1" + } + + provisioner "local-exec" { + command = "echo hello" + + connection { + host = "10.1.2.1" + } + } + + provisioner "local-exec" { + command = "echo hello" + } +} + +resource "aws_instance" "web" { + count = 2 + ami = "ami-1234" + security_groups = [ + "foo", + "bar", + ] + + network_interface { + device_index = 0 + description = "Main network interface" + } + + depends_on = [ + aws_security_group.firewall, + ] +} diff --git a/internal/configs/testdata/tofu-and-tf-files/resources.tf.json b/internal/configs/testdata/tofu-and-tf-files/resources.tf.json new file mode 100644 index 0000000000..3242755b51 --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/resources.tf.json @@ -0,0 +1,14 @@ +{ + "resource": { + "test_object": { + "a": { + "count": 1, + "test_string": "hello" + }, + "b": { + "count": 1, + "test_string": "world" + } + } + } +} diff --git a/internal/configs/testdata/tofu-and-tf-files/resources.tofu b/internal/configs/testdata/tofu-and-tf-files/resources.tofu new file mode 100644 index 0000000000..9fe059515b --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/resources.tofu @@ -0,0 +1,43 @@ +resource "aws_security_group" "firewall_tofu" { + lifecycle { + create_before_destroy = true + prevent_destroy = true + ignore_changes = [ + description, + ] + } + + connection { + host = "127.0.0.1" + } + + provisioner "local-exec" { + command = "echo hello" + + connection { + host = "10.1.2.1" + } + } + + provisioner "local-exec" { + command = "echo hello" + } +} + +resource "aws_instance" "web_tofu" { + count = 2 + ami = "ami-1234" + security_groups = [ + "foo", + "bar", + ] + + network_interface { + device_index = 0 + description = "Main network interface" + } + + depends_on = [ + aws_security_group.firewall, + ] +} diff --git a/internal/configs/testdata/tofu-and-tf-files/resources.tofu.json b/internal/configs/testdata/tofu-and-tf-files/resources.tofu.json new file mode 100644 index 0000000000..75c9045efd --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/resources.tofu.json @@ -0,0 +1,14 @@ +{ + "resource": { + "test_object": { + "a_tofu": { + "count": 1, + "test_string": "hello" + }, + "b_tofu": { + "count": 1, + "test_string": "world" + } + } + } +} diff --git a/internal/configs/testdata/tofu-and-tf-files/test/resources_test.tftest.hcl b/internal/configs/testdata/tofu-and-tf-files/test/resources_test.tftest.hcl new file mode 100644 index 0000000000..d3547ec2ac --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/test/resources_test.tftest.hcl @@ -0,0 +1,27 @@ +# test_run_one runs a partial plan +run "test_run_one" { + command = plan + + plan_options { + target = [ + test_object.b + ] + } + + assert { + condition = test_object.b.test_string == "world" + error_message = "invalid value" + } +} + +# test_run_two does a complete apply operation +run "test_run_two" { + variables { + input = "custom" + } + + assert { + condition = test_object.a.test_string == "hello" + error_message = "invalid value" + } +} diff --git a/internal/configs/testdata/tofu-and-tf-files/test/resources_test.tofutest.hcl b/internal/configs/testdata/tofu-and-tf-files/test/resources_test.tofutest.hcl new file mode 100644 index 0000000000..d3547ec2ac --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/test/resources_test.tofutest.hcl @@ -0,0 +1,27 @@ +# test_run_one runs a partial plan +run "test_run_one" { + command = plan + + plan_options { + target = [ + test_object.b + ] + } + + assert { + condition = test_object.b.test_string == "world" + error_message = "invalid value" + } +} + +# test_run_two does a complete apply operation +run "test_run_two" { + variables { + input = "custom" + } + + assert { + condition = test_object.a.test_string == "hello" + error_message = "invalid value" + } +} diff --git a/internal/configs/testdata/tofu-and-tf-files/test/resources_test_json.tftest.json b/internal/configs/testdata/tofu-and-tf-files/test/resources_test_json.tftest.json new file mode 100644 index 0000000000..7f939dc6fa --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/test/resources_test_json.tftest.json @@ -0,0 +1,29 @@ +{ + "variables": { + "input": "default" + }, + "run": { + "test_run_one": { + "command": "plan", + "plan_options": { + "target": [ + "test_object.a" + ] + }, + "assert": [ + { + "condition": "${test_object.a.test_string} == hello", + "error_message": "invalid value" + } + ] + }, + "test_run_two": { + "assert": [ + { + "condition": "${test_object.b.test_string} == world", + "error_message": "invalid value" + } + ] + } + } +} diff --git a/internal/configs/testdata/tofu-and-tf-files/test/resources_test_json.tofutest.json b/internal/configs/testdata/tofu-and-tf-files/test/resources_test_json.tofutest.json new file mode 100644 index 0000000000..7f939dc6fa --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/test/resources_test_json.tofutest.json @@ -0,0 +1,29 @@ +{ + "variables": { + "input": "default" + }, + "run": { + "test_run_one": { + "command": "plan", + "plan_options": { + "target": [ + "test_object.a" + ] + }, + "assert": [ + { + "condition": "${test_object.a.test_string} == hello", + "error_message": "invalid value" + } + ] + }, + "test_run_two": { + "assert": [ + { + "condition": "${test_object.b.test_string} == world", + "error_message": "invalid value" + } + ] + } + } +} diff --git a/internal/configs/testdata/tofu-and-tf-files/variables.tf b/internal/configs/testdata/tofu-and-tf-files/variables.tf new file mode 100644 index 0000000000..506faf6fcd --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/variables.tf @@ -0,0 +1,3 @@ +variable "should_override" { + default = "not overridden" +} diff --git a/internal/configs/testdata/tofu-and-tf-files/variables.tf.json b/internal/configs/testdata/tofu-and-tf-files/variables.tf.json new file mode 100644 index 0000000000..d7b402dd12 --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/variables.tf.json @@ -0,0 +1,7 @@ +{ + "variable": { + "should_override_json": { + "default": "not overridden" + } + } +} diff --git a/internal/configs/testdata/tofu-and-tf-files/variables_override.tf b/internal/configs/testdata/tofu-and-tf-files/variables_override.tf new file mode 100644 index 0000000000..e53315ae23 --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/variables_override.tf @@ -0,0 +1,3 @@ +variable "should_override" { + default = "overridden by tf file" +} \ No newline at end of file diff --git a/internal/configs/testdata/tofu-and-tf-files/variables_override.tf.json b/internal/configs/testdata/tofu-and-tf-files/variables_override.tf.json new file mode 100644 index 0000000000..c12ad061bf --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/variables_override.tf.json @@ -0,0 +1,7 @@ +{ + "variable": { + "should_override_json": { + "default": "overridden by tf file" + } + } +} diff --git a/internal/configs/testdata/tofu-and-tf-files/variables_override.tofu b/internal/configs/testdata/tofu-and-tf-files/variables_override.tofu new file mode 100644 index 0000000000..9a995264dd --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/variables_override.tofu @@ -0,0 +1,3 @@ +variable "should_override" { + default = "overridden by tofu file" +} \ No newline at end of file diff --git a/internal/configs/testdata/tofu-and-tf-files/variables_override.tofu.json b/internal/configs/testdata/tofu-and-tf-files/variables_override.tofu.json new file mode 100644 index 0000000000..2a73303202 --- /dev/null +++ b/internal/configs/testdata/tofu-and-tf-files/variables_override.tofu.json @@ -0,0 +1,7 @@ +{ + "variable": { + "should_override_json": { + "default": "overridden by tofu file" + } + } +} diff --git a/internal/configs/testdata/tofu-only-files/resources.tofu b/internal/configs/testdata/tofu-only-files/resources.tofu new file mode 100644 index 0000000000..9fe059515b --- /dev/null +++ b/internal/configs/testdata/tofu-only-files/resources.tofu @@ -0,0 +1,43 @@ +resource "aws_security_group" "firewall_tofu" { + lifecycle { + create_before_destroy = true + prevent_destroy = true + ignore_changes = [ + description, + ] + } + + connection { + host = "127.0.0.1" + } + + provisioner "local-exec" { + command = "echo hello" + + connection { + host = "10.1.2.1" + } + } + + provisioner "local-exec" { + command = "echo hello" + } +} + +resource "aws_instance" "web_tofu" { + count = 2 + ami = "ami-1234" + security_groups = [ + "foo", + "bar", + ] + + network_interface { + device_index = 0 + description = "Main network interface" + } + + depends_on = [ + aws_security_group.firewall, + ] +} diff --git a/internal/configs/testdata/tofu-only-files/resources.tofu.json b/internal/configs/testdata/tofu-only-files/resources.tofu.json new file mode 100644 index 0000000000..75c9045efd --- /dev/null +++ b/internal/configs/testdata/tofu-only-files/resources.tofu.json @@ -0,0 +1,14 @@ +{ + "resource": { + "test_object": { + "a_tofu": { + "count": 1, + "test_string": "hello" + }, + "b_tofu": { + "count": 1, + "test_string": "world" + } + } + } +} diff --git a/internal/configs/testdata/tofu-only-files/test/resources_test.tofutest.hcl b/internal/configs/testdata/tofu-only-files/test/resources_test.tofutest.hcl new file mode 100644 index 0000000000..d3547ec2ac --- /dev/null +++ b/internal/configs/testdata/tofu-only-files/test/resources_test.tofutest.hcl @@ -0,0 +1,27 @@ +# test_run_one runs a partial plan +run "test_run_one" { + command = plan + + plan_options { + target = [ + test_object.b + ] + } + + assert { + condition = test_object.b.test_string == "world" + error_message = "invalid value" + } +} + +# test_run_two does a complete apply operation +run "test_run_two" { + variables { + input = "custom" + } + + assert { + condition = test_object.a.test_string == "hello" + error_message = "invalid value" + } +} diff --git a/internal/configs/testdata/tofu-only-files/test/resources_test_json.tofutest.json b/internal/configs/testdata/tofu-only-files/test/resources_test_json.tofutest.json new file mode 100644 index 0000000000..7f939dc6fa --- /dev/null +++ b/internal/configs/testdata/tofu-only-files/test/resources_test_json.tofutest.json @@ -0,0 +1,29 @@ +{ + "variables": { + "input": "default" + }, + "run": { + "test_run_one": { + "command": "plan", + "plan_options": { + "target": [ + "test_object.a" + ] + }, + "assert": [ + { + "condition": "${test_object.a.test_string} == hello", + "error_message": "invalid value" + } + ] + }, + "test_run_two": { + "assert": [ + { + "condition": "${test_object.b.test_string} == world", + "error_message": "invalid value" + } + ] + } + } +} diff --git a/internal/configs/testdata/tofu-only-files/variables.tofu b/internal/configs/testdata/tofu-only-files/variables.tofu new file mode 100644 index 0000000000..e5b0f8f09e --- /dev/null +++ b/internal/configs/testdata/tofu-only-files/variables.tofu @@ -0,0 +1,3 @@ +variable "should_override" { + default = "not overridden" +} \ No newline at end of file diff --git a/internal/configs/testdata/tofu-only-files/variables.tofu.json b/internal/configs/testdata/tofu-only-files/variables.tofu.json new file mode 100644 index 0000000000..d7b402dd12 --- /dev/null +++ b/internal/configs/testdata/tofu-only-files/variables.tofu.json @@ -0,0 +1,7 @@ +{ + "variable": { + "should_override_json": { + "default": "not overridden" + } + } +} diff --git a/internal/configs/testdata/tofu-only-files/variables_override.tofu b/internal/configs/testdata/tofu-only-files/variables_override.tofu new file mode 100644 index 0000000000..9a995264dd --- /dev/null +++ b/internal/configs/testdata/tofu-only-files/variables_override.tofu @@ -0,0 +1,3 @@ +variable "should_override" { + default = "overridden by tofu file" +} \ No newline at end of file diff --git a/internal/configs/testdata/tofu-only-files/variables_override.tofu.json b/internal/configs/testdata/tofu-only-files/variables_override.tofu.json new file mode 100644 index 0000000000..2a73303202 --- /dev/null +++ b/internal/configs/testdata/tofu-only-files/variables_override.tofu.json @@ -0,0 +1,7 @@ +{ + "variable": { + "should_override_json": { + "default": "overridden by tofu file" + } + } +}