diff --git a/internal/command/cliconfig/cliconfig.go b/internal/command/cliconfig/cliconfig.go index d43839680a..ba86c4027d 100644 --- a/internal/command/cliconfig/cliconfig.go +++ b/internal/command/cliconfig/cliconfig.go @@ -9,7 +9,9 @@ package cliconfig import ( + "errors" "fmt" + "io/fs" "io/ioutil" "log" "os" @@ -102,12 +104,14 @@ func LoadConfig() (*Config, tfdiags.Diagnostics) { configVal := BuiltinConfig // copy config := &configVal - if mainFilename, err := cliConfigFile(); err == nil { + if mainFilename, mainFileDiags := cliConfigFile(); len(mainFileDiags) == 0 { if _, err := os.Stat(mainFilename); err == nil { mainConfig, mainDiags := loadConfigFile(mainFilename) diags = diags.Append(mainDiags) config = config.Merge(mainConfig) } + } else { + diags = diags.Append(mainFileDiags) } // Unless the user has specifically overridden the configuration file @@ -407,7 +411,8 @@ func (c *Config) Merge(c2 *Config) *Config { return &result } -func cliConfigFile() (string, error) { +func cliConfigFile() (string, tfdiags.Diagnostics) { + var diags tfdiags.Diagnostics mustExist := true configFilePath := cliConfigFileOverride() @@ -427,15 +432,19 @@ func cliConfigFile() (string, error) { f, err := os.Open(configFilePath) if err == nil { f.Close() - return configFilePath, nil + return configFilePath, diags } - if mustExist || !os.IsNotExist(err) { - return "", err + if mustExist || !errors.Is(err, fs.ErrNotExist) { + diags = append(diags, tfdiags.Sourceless( + tfdiags.Warning, + "Unable to open CLI configuration file", + fmt.Sprintf("The CLI configuration file at %q does not exist.", configFilePath), + )) } log.Println("[DEBUG] File doesn't exist, but doesn't need to. Ignoring.") - return "", nil + return "", diags } func cliConfigFileOverride() string { diff --git a/internal/command/cliconfig/cliconfig_test.go b/internal/command/cliconfig/cliconfig_test.go index efc6d358d7..c94dae86f2 100644 --- a/internal/command/cliconfig/cliconfig_test.go +++ b/internal/command/cliconfig/cliconfig_test.go @@ -8,6 +8,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/google/go-cmp/cmp" + "github.com/hashicorp/terraform/internal/tfdiags" ) // This is the directory where our test fixtures are. @@ -55,6 +56,31 @@ func TestLoadConfig_envSubst(t *testing.T) { } } +func TestLoadConfig_non_existing_file(t *testing.T) { + tmpDir := os.TempDir() + cliTmpFile := filepath.Join(tmpDir, "dev.tfrc") + + os.Setenv("TF_CLI_CONFIG_FILE", cliTmpFile) + defer os.Unsetenv("TF_CLI_CONFIG_FILE") + + c, errs := LoadConfig() + if errs.HasErrors() || c.Validate().HasErrors() { + t.Fatalf("err: %s", errs) + } + + hasOpenFileWarn := false + for _, err := range errs { + if err.Severity() == tfdiags.Warning && err.Description().Summary == "Unable to open CLI configuration file" { + hasOpenFileWarn = true + break + } + } + + if !hasOpenFileWarn { + t.Fatal("expecting a warning message because of nonexisting CLI configuration file") + } +} + func TestEnvConfig(t *testing.T) { tests := map[string]struct { env map[string]string