Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/v1.13/BUG FIXES-20250529-163449.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: BUG FIXES
body: 'Added a missing warning diagnostic that alerts users when child module contains an ignored `cloud` block.'
time: 2025-05-29T16:34:49.041168+01:00
custom:
Issue: "37180"
11 changes: 10 additions & 1 deletion internal/configs/config_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,20 @@ func loadModule(root *Config, req *ModuleRequest, walker ModuleWalker) (*Config,
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagWarning,
Summary: "Backend configuration ignored",
Detail: "Any selected backend applies to the entire configuration, so Terraform expects provider configurations only in the root module.\n\nThis is a warning rather than an error because it's sometimes convenient to temporarily call a root module as a child module for testing purposes, but this backend configuration block will have no effect.",
Detail: "Any selected backend applies to the entire configuration, so Terraform expects backend configurations only in the root module.\n\nThis is a warning rather than an error because it's sometimes convenient to temporarily call a root module as a child module for testing purposes, but this backend configuration block will have no effect.",
Subject: mod.Backend.DeclRange.Ptr(),
})
}

if mod.CloudConfig != nil {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagWarning,
Summary: "Cloud configuration ignored",
Detail: "A cloud configuration block applies to the entire configuration, so Terraform expects 'cloud' blocks to only be in the root module.\n\nThis is a warning rather than an error because it's sometimes convenient to temporarily call a root module as a child module for testing purposes, but this cloud configuration block will have no effect.",
Subject: mod.CloudConfig.DeclRange.Ptr(),
})
}

if len(mod.Import) > 0 {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Expand Down
45 changes: 44 additions & 1 deletion internal/configs/config_build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func TestBuildConfigDiags(t *testing.T) {
}
}

func TestBuildConfigChildModuleBackend(t *testing.T) {
func TestBuildConfigChildModule_Backend(t *testing.T) {
parser := NewParser(nil)
mod, diags := parser.LoadConfigDir("testdata/nested-backend-warning")
assertNoDiagnostics(t, diags)
Expand Down Expand Up @@ -170,6 +170,49 @@ func TestBuildConfigChildModuleBackend(t *testing.T) {
}
}

func TestBuildConfigChildModule_CloudBlock(t *testing.T) {
parser := NewParser(nil)
mod, diags := parser.LoadConfigDir("testdata/nested-cloud-warning")
assertNoDiagnostics(t, diags)
if mod == nil {
t.Fatal("got nil root module; want non-nil")
}

cfg, diags := BuildConfig(mod, ModuleWalkerFunc(
func(req *ModuleRequest) (*Module, *version.Version, hcl.Diagnostics) {
// For the sake of this test we're going to just treat our
// SourceAddr as a path relative to our fixture directory.
// A "real" implementation of ModuleWalker should accept the
// various different source address syntaxes Terraform supports.
sourcePath := filepath.Join("testdata/nested-cloud-warning", req.SourceAddr.String())

mod, diags := parser.LoadConfigDir(sourcePath)
version, _ := version.NewVersion("1.0.0")
return mod, version, diags
}),
MockDataLoaderFunc(func(provider *Provider) (*MockData, hcl.Diagnostics) {
return nil, nil
}),
)

assertDiagnosticSummary(t, diags, "Cloud configuration ignored")

// we should still have module structure loaded
var got []string
cfg.DeepEach(func(c *Config) {
got = append(got, fmt.Sprintf("%s %s", strings.Join(c.Path, "."), c.Version))
})
sort.Strings(got)
want := []string{
" <nil>",
"child 1.0.0",
}

if !reflect.DeepEqual(got, want) {
t.Fatalf("wrong result\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(want))
}
}

func TestBuildConfigInvalidModules(t *testing.T) {
testDir := "testdata/config-diagnostics"
dirs, err := ioutil.ReadDir(testDir)
Expand Down