Merge pull request #24874 from hashicorp/pselle/modulecallexpansionvalidation

Add more validation to expanding modules
This commit is contained in:
Pam Selle 2020-05-06 10:12:14 -04:00 committed by GitHub
commit 3e420d5f6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 2 deletions

View File

@ -1425,7 +1425,7 @@ module "mod2" {
}
module "mod3" {
count = len(module.mod2)
count = length(module.mod2)
source = "./mod"
}
`,
@ -1472,3 +1472,67 @@ resource "aws_instance" "foo" {
t.Fatal(diags.ErrWithWarnings())
}
}
func TestContext2Validate_expandModulesInvalidCount(t *testing.T) {
m := testModuleInline(t, map[string]string{
"main.tf": `
module "mod1" {
count = -1
source = "./mod"
}
`,
"mod/main.tf": `
resource "aws_instance" "foo" {
}
`,
})
p := testProvider("aws")
p.DiffFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
},
})
diags := ctx.Validate()
if !diags.HasErrors() {
t.Fatal("succeeded; want errors")
}
if got, want := diags.Err().Error(), `Invalid count argument`; strings.Index(got, want) == -1 {
t.Fatalf("wrong error:\ngot: %s\nwant: message containing %q", got, want)
}
}
func TestContext2Validate_expandModulesInvalidForEach(t *testing.T) {
m := testModuleInline(t, map[string]string{
"main.tf": `
module "mod1" {
for_each = ["a", "b"]
source = "./mod"
}
`,
"mod/main.tf": `
resource "aws_instance" "foo" {
}
`,
})
p := testProvider("aws")
p.DiffFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
},
})
diags := ctx.Validate()
if !diags.HasErrors() {
t.Fatal("succeeded; want errors")
}
if got, want := diags.Err().Error(), `Invalid for_each argument`; strings.Index(got, want) == -1 {
t.Fatalf("wrong error:\ngot: %s\nwant: message containing %q", got, want)
}
}

View File

@ -281,8 +281,27 @@ func (n *evalValidateModule) Eval(ctx EvalContext) (interface{}, error) {
// will be a single instance, but still get our address in the expected
// manner anyway to ensure they've been registered correctly.
for _, module := range expander.ExpandModule(n.Addr.Parent()) {
ctx = ctx.WithPath(module)
// Validate our for_each and count expressions at a basic level
// We skip validation on known, because there will be unknown values before
// a full expansion, presuming these errors will be caught in later steps
switch {
case n.ModuleCall.Count != nil:
_, diags := evaluateCountExpressionValue(n.ModuleCall.Count, ctx)
if diags.HasErrors() {
return nil, diags.Err()
}
case n.ModuleCall.ForEach != nil:
_, diags := evaluateForEachExpressionValue(n.ModuleCall.ForEach, ctx)
if diags.HasErrors() {
return nil, diags.Err()
}
}
// now set our own mode to single
ctx.InstanceExpander().SetModuleSingle(module, call)
expander.SetModuleSingle(module, call)
}
return nil, nil
}