Merge pull request #24575 from hashicorp/pselle/mod-expansion-keywords

Enable count.index and each.key/value in module expansion
This commit is contained in:
Pam Selle 2020-04-07 10:03:13 -04:00 committed by GitHub
commit d109f79678
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 18 deletions

View File

@ -34,7 +34,7 @@ type BuiltinEvalContext struct {
// pathSet indicates that this context was explicitly created for a
// specific path, and can be safely used for evaluation. This lets us
// differentiate between Pathvalue being unset, and the zero value which is
// differentiate between PathValue being unset, and the zero value which is
// equivalent to RootModuleInstance. Path and Evaluation methods will
// panic if this is not set.
pathSet bool

View File

@ -37,9 +37,10 @@ func (n *EvalSetModuleCallArguments) Eval(ctx EvalContext) (interface{}, error)
// EvalContext.SetModuleCallArguments, which expects a map to merge in with
// any existing arguments.
type EvalModuleCallArgument struct {
Addr addrs.InputVariable
Config *configs.Variable
Expr hcl.Expression
Addr addrs.InputVariable
Config *configs.Variable
Expr hcl.Expression
ModuleInstance addrs.ModuleInstance
// If this flag is set, any diagnostics are discarded and this operation
// will always succeed, though may produce an unknown value in the
@ -68,9 +69,13 @@ func (n *EvalModuleCallArgument) Eval(ctx EvalContext) (interface{}, error) {
return nil, nil
}
val, diags := ctx.EvaluateExpr(expr, cty.DynamicPseudoType, nil)
// Get the repetition data for this module instance,
// so we can create the appropriate scope for evaluating our expression
moduleInstanceRepetitionData := ctx.InstanceExpander().GetModuleInstanceRepetitionData(n.ModuleInstance)
scope := ctx.EvaluationScope(nil, moduleInstanceRepetitionData)
val, diags := scope.EvalExpr(expr, cty.DynamicPseudoType)
// We intentionally passed DynamicPseudoType to EvaluateExpr above because
// We intentionally passed DynamicPseudoType to EvalExpr above because
// now we can do our own local type conversion and produce an error message
// with better context if it fails.
var convErr error

View File

@ -144,7 +144,7 @@ func (d *evaluationStateData) GetCountAttr(addr addrs.CountAttr, rng tfdiags.Sou
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: `Reference to "count" in non-counted context`,
Detail: fmt.Sprintf(`The "count" object can be used only in "resource" and "data" blocks, and only when the "count" argument is set.`),
Detail: fmt.Sprintf(`The "count" object can only be used in "module", "resource", and "data" blocks, and only when the "count" argument is set.`),
Subject: rng.ToHCL().Ptr(),
})
return cty.UnknownVal(cty.Number), diags
@ -195,7 +195,7 @@ func (d *evaluationStateData) GetForEachAttr(addr addrs.ForEachAttr, rng tfdiags
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: `Reference to "each" in context without for_each`,
Detail: fmt.Sprintf(`The "each" object can be used only in "resource" blocks, and only when the "for_each" argument is set.`),
Detail: fmt.Sprintf(`The "each" object can be used only in "module" or "resource" blocks, and only when the "for_each" argument is set.`),
Subject: rng.ToHCL().Ptr(),
})
return cty.UnknownVal(cty.DynamicPseudoType), diags

View File

@ -38,9 +38,10 @@ func (n *NodePlannableModuleVariable) DynamicExpand(ctx EvalContext) (*Graph, er
expander := ctx.InstanceExpander()
for _, module := range expander.ExpandModule(n.Module) {
o := &NodeApplyableModuleVariable{
Addr: n.Addr.Absolute(module),
Config: n.Config,
Expr: n.Expr,
Addr: n.Addr.Absolute(module),
Config: n.Config,
Expr: n.Expr,
ModuleInstance: module,
}
g.Add(o)
}
@ -114,6 +115,9 @@ type NodeApplyableModuleVariable struct {
Addr addrs.AbsInputVariableInstance
Config *configs.Variable // Config is the var in the config
Expr hcl.Expression // Expr is the value expression given in the call
// ModuleInstance in order to create the appropriate context for evaluating
// ModuleCallArguments, ex. so count.index and each.key can resolve
ModuleInstance addrs.ModuleInstance
}
// Ensure that we are implementing all of the interfaces we think we are
@ -222,10 +226,11 @@ func (n *NodeApplyableModuleVariable) EvalTree() EvalNode {
Ops: []walkOperation{walkRefresh, walkPlan, walkApply,
walkDestroy, walkValidate},
Node: &EvalModuleCallArgument{
Addr: n.Addr.Variable,
Config: n.Config,
Expr: n.Expr,
Values: vals,
Addr: n.Addr.Variable,
Config: n.Config,
Expr: n.Expr,
ModuleInstance: n.ModuleInstance,
Values: vals,
IgnoreDiagnostics: false,
},

View File

@ -10,10 +10,9 @@ variable "myvar" {
default = "baz"
}
module "count_child" {
count = local.val
foo = 2
foo = count.index
bar = var.myvar
source = "./child"
}
@ -21,7 +20,7 @@ module "count_child" {
module "for_each_child" {
for_each = aws_instance.foo
foo = 2
bar = var.myvar
bar = each.key
source = "./child"
}