From ce24a6b9614c433e2b32cffc8544250e2173b193 Mon Sep 17 00:00:00 2001 From: Christian Mesh Date: Fri, 2 Aug 2024 07:29:40 -0400 Subject: [PATCH] Better var file type detection (#1881) Signed-off-by: Christian Mesh --- internal/command/command.go | 5 +- internal/command/meta_vars.go | 10 +++- internal/command/meta_vars_test.go | 78 ++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 internal/command/meta_vars_test.go diff --git a/internal/command/command.go b/internal/command/command.go index 927fd42a1d..42dda99e39 100644 --- a/internal/command/command.go +++ b/internal/command/command.go @@ -32,8 +32,11 @@ const DefaultPluginVendorDir = "terraform.d/plugins/" + pluginMachineName // DefaultStateFilename is the default filename used for the state file. const DefaultStateFilename = "terraform.tfstate" +// DefaultVarsExtension is the default file extension used for vars +const DefaultVarsExtension = ".tfvars" + // DefaultVarsFilename is the default filename used for vars -const DefaultVarsFilename = "terraform.tfvars" +const DefaultVarsFilename = "terraform" + DefaultVarsExtension // DefaultBackupExtension is added to the state file to form the path const DefaultBackupExtension = ".backup" diff --git a/internal/command/meta_vars.go b/internal/command/meta_vars.go index 9811855419..0b2a98a475 100644 --- a/internal/command/meta_vars.go +++ b/internal/command/meta_vars.go @@ -182,7 +182,15 @@ func (m *Meta) addVarsFromFile(filename string, sourceType tofu.ValueSourceType, loader.Parser().ForceFileSource(filename, src) var f *hcl.File - if strings.HasSuffix(filename, ".json") { + + extJSON := strings.HasSuffix(filename, ".json") + extTfvars := strings.HasSuffix(filename, DefaultVarsExtension) + + // Only try json detection if ambiguous + // Ex: -var-file=<(./scripts/vars.sh) + detectJSON := !extJSON && !extTfvars && strings.HasPrefix(strings.TrimSpace(string(src)), "{") + + if extJSON || detectJSON { var hclDiags hcl.Diagnostics f, hclDiags = hcljson.Parse(src, filename) diags = diags.Append(hclDiags) diff --git a/internal/command/meta_vars_test.go b/internal/command/meta_vars_test.go new file mode 100644 index 0000000000..2e5b9656cb --- /dev/null +++ b/internal/command/meta_vars_test.go @@ -0,0 +1,78 @@ +// Copyright (c) The OpenTofu Authors +// SPDX-License-Identifier: MPL-2.0 +// Copyright (c) 2023 HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package command + +import ( + "os" + "path/filepath" + "testing" + + "github.com/opentofu/opentofu/internal/backend" + "github.com/opentofu/opentofu/internal/tofu" +) + +func TestMeta_addVarsFromFile(t *testing.T) { + d := t.TempDir() + defer testChdir(t, d)() + + hclData := `foo = "bar"` + jsonData := `{"foo": "bar"}` + + cases := []struct { + filename string + contents string + errors bool + }{ + { + filename: "input.tfvars", + contents: hclData, + errors: false, + }, + { + filename: "input.json", + contents: jsonData, + errors: false, + }, + { + filename: "input_a.unknown", + contents: hclData, + errors: false, + }, + { + filename: "input_b.unknown", + contents: jsonData, + errors: false, + }, + { + filename: "mismatch.tfvars", + contents: jsonData, + errors: true, + }, + { + filename: "mismatch.json", + contents: hclData, + errors: true, + }, + } + + for _, tc := range cases { + t.Run(tc.filename, func(t *testing.T) { + target := filepath.Join(d, tc.filename) + err := os.WriteFile(target, []byte(tc.contents), 0600) + if err != nil { + t.Fatalf("err: %s", err) + } + + m := new(Meta) + to := make(map[string]backend.UnparsedVariableValue) + diags := m.addVarsFromFile(target, tofu.ValueFromAutoFile, to) + if tc.errors != diags.HasErrors() { + t.Log(diags.Err()) + t.Errorf("Expected: %v, got %v", tc.errors, diags.HasErrors()) + } + }) + } +}