Make config errors more important during init operations (#33628)

* make config errors more important during init operations

* address comments
This commit is contained in:
Liam Cervante 2023-08-09 11:19:00 +02:00 committed by GitHub
parent e26d07dda4
commit f8b1fe47dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 27 deletions

View File

@ -262,24 +262,25 @@ func (c *InitCommand) Run(args []string) int {
return 1
}
// If we pass the core version check, we want to show any errors from initializing the backend next,
// which will include syntax errors from loading the configuration. However, there's a special case
// where we are unable to load the backend from configuration or state _and_ the configuration has
// errors. In that case, we want to show a slightly friendlier error message for newcomers.
showBackendDiags := back != nil || rootModEarly.Backend != nil || rootModEarly.CloudConfig != nil
if showBackendDiags {
diags = diags.Append(backDiags)
if backDiags.HasErrors() {
c.showDiagnostics(diags)
return 1
}
} else {
diags = diags.Append(earlyConfDiags)
if earlyConfDiags.HasErrors() {
c.Ui.Error(strings.TrimSpace(errInitConfigError))
c.showDiagnostics(diags)
return 1
}
// We've passed the core version check, now we can show errors from the
// configuration and backend initialisation.
// Now, we can check the diagnostics from the early configuration and the
// backend.
diags = diags.Append(earlyConfDiags)
diags = diags.Append(backDiags)
if earlyConfDiags.HasErrors() {
c.Ui.Error(strings.TrimSpace(errInitConfigError))
c.showDiagnostics(diags)
return 1
}
// Now, we can show any errors from initializing the backend, but we won't
// show the errInitConfigError preamble as we didn't detect problems with
// the early configuration.
if backDiags.HasErrors() {
c.showDiagnostics(diags)
return 1
}
// If everything is ok with the core version check and backend initialization,
@ -1187,7 +1188,8 @@ func (c *InitCommand) Synopsis() string {
}
const errInitConfigError = `
[reset]There are some problems with the configuration, described below.
[reset]Terraform encountered problems during initialisation, including problems
with the configuration, described below.
The Terraform configuration must be valid before initialization so that
Terraform can determine which modules and providers need to be installed.

View File

@ -2642,7 +2642,7 @@ func TestInit_invalidSyntaxNoBackend(t *testing.T) {
}
errStr := ui.ErrorWriter.String()
if subStr := "There are some problems with the configuration, described below"; !strings.Contains(errStr, subStr) {
if subStr := "Terraform encountered problems during initialisation, including problems\nwith the configuration, described below."; !strings.Contains(errStr, subStr) {
t.Errorf("Error output should include preamble\nwant substr: %s\ngot:\n%s", subStr, errStr)
}
if subStr := "Error: Unsupported block type"; !strings.Contains(errStr, subStr) {
@ -2671,7 +2671,7 @@ func TestInit_invalidSyntaxWithBackend(t *testing.T) {
}
errStr := ui.ErrorWriter.String()
if subStr := "There are some problems with the configuration, described below"; !strings.Contains(errStr, subStr) {
if subStr := "Terraform encountered problems during initialisation, including problems\nwith the configuration, described below."; !strings.Contains(errStr, subStr) {
t.Errorf("Error output should include preamble\nwant substr: %s\ngot:\n%s", subStr, errStr)
}
if subStr := "Error: Unsupported block type"; !strings.Contains(errStr, subStr) {
@ -2700,17 +2700,49 @@ func TestInit_invalidSyntaxInvalidBackend(t *testing.T) {
}
errStr := ui.ErrorWriter.String()
if subStr := "There are some problems with the configuration, described below"; strings.Contains(errStr, subStr) {
t.Errorf("Error output should not include preamble\nwant substr: %s\ngot:\n%s", subStr, errStr)
if subStr := "Terraform encountered problems during initialisation, including problems\nwith the configuration, described below."; !strings.Contains(errStr, subStr) {
t.Errorf("Error output should include preamble\nwant substr: %s\ngot:\n%s", subStr, errStr)
}
if subStr := "Error: Unsupported block type"; strings.Contains(errStr, subStr) {
t.Errorf("Error output should not mention syntax errors\nwant substr: %s\ngot:\n%s", subStr, errStr)
if subStr := "Error: Unsupported block type"; !strings.Contains(errStr, subStr) {
t.Errorf("Error output should mention syntax errors\nwant substr: %s\ngot:\n%s", subStr, errStr)
}
if subStr := "Error: Unsupported backend type"; !strings.Contains(errStr, subStr) {
t.Errorf("Error output should mention the invalid backend\nwant substr: %s\ngot:\n%s", subStr, errStr)
}
}
func TestInit_invalidSyntaxBackendAttribute(t *testing.T) {
td := t.TempDir()
testCopyDir(t, testFixturePath("init-syntax-invalid-backend-attribute-invalid"), td)
defer testChdir(t, td)()
ui := cli.NewMockUi()
view, _ := testView(t)
m := Meta{
Ui: ui,
View: view,
}
c := &InitCommand{
Meta: m,
}
if code := c.Run(nil); code == 0 {
t.Fatalf("succeeded, but was expecting error\nstdout:\n%s\nstderr:\n%s", ui.OutputWriter, ui.ErrorWriter)
}
errStr := ui.ErrorWriter.String()
if subStr := "Terraform encountered problems during initialisation, including problems\nwith the configuration, described below."; !strings.Contains(errStr, subStr) {
t.Errorf("Error output should include preamble\nwant substr: %s\ngot:\n%s", subStr, errStr)
}
if subStr := "Error: Invalid character"; !strings.Contains(errStr, subStr) {
t.Errorf("Error output should mention the invalid character\nwant substr: %s\ngot:\n%s", subStr, errStr)
}
if subStr := "Error: Invalid expression"; !strings.Contains(errStr, subStr) {
t.Errorf("Error output should mention the invalid expression\nwant substr: %s\ngot:\n%s", subStr, errStr)
}
}
func TestInit_tests(t *testing.T) {
// Create a temporary working directory that is empty
td := t.TempDir()

View File

@ -19,6 +19,9 @@ import (
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
ctyjson "github.com/zclconf/go-cty/cty/json"
"github.com/hashicorp/terraform/internal/backend"
"github.com/hashicorp/terraform/internal/cloud"
"github.com/hashicorp/terraform/internal/command/arguments"
@ -29,8 +32,6 @@ import (
"github.com/hashicorp/terraform/internal/states/statemgr"
"github.com/hashicorp/terraform/internal/terraform"
"github.com/hashicorp/terraform/internal/tfdiags"
"github.com/zclconf/go-cty/cty"
ctyjson "github.com/zclconf/go-cty/cty/json"
backendInit "github.com/hashicorp/terraform/internal/backend/init"
backendLocal "github.com/hashicorp/terraform/internal/backend/local"
@ -1398,6 +1399,14 @@ func (m *Meta) backendInitFromConfig(c *configs.Backend) (backend.Backend, cty.V
return nil, cty.NilVal, diags
}
if !configVal.IsWhollyKnown() {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Unknown values within backend definition",
"The `terraform` configuration block should contain only concrete and static values. Another diagnostic should contain more information about which part of the configuration is problematic."))
return nil, cty.NilVal, diags
}
// TODO: test
if m.Input() {
var err error

View File

@ -0,0 +1,10 @@
terraform {
backend "local" {
path = $invalid
}
}
variable "input" {
type = string
}