mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
Module expander for enabled field
Signed-off-by: Diogenes Fernandes <diofeher@gmail.com>
This commit is contained in:
committed by
Diógenes Fernandes
parent
ca53b2521d
commit
732623f604
@@ -38,6 +38,7 @@ type ModuleCall struct {
|
||||
|
||||
Count hcl.Expression
|
||||
ForEach hcl.Expression
|
||||
Enabled hcl.Expression
|
||||
|
||||
Providers []PassedProviderConfig
|
||||
|
||||
|
||||
@@ -59,6 +59,12 @@ func (e *Expander) SetModuleSingle(parentAddr addrs.ModuleInstance, callAddr add
|
||||
e.setModuleExpansion(parentAddr, callAddr, expansionSingleVal)
|
||||
}
|
||||
|
||||
// SetModuleEnabled records that the given module call inside the given parent
|
||||
// module uses the "enabled" lifecycle repetition argument, with the given value.
|
||||
func (e *Expander) SetModuleEnabled(parentAddr addrs.ModuleInstance, callAddr addrs.ModuleCall, enabled bool) {
|
||||
e.setModuleExpansion(parentAddr, callAddr, expansionEnabled(enabled))
|
||||
}
|
||||
|
||||
// SetModuleCount records that the given module call inside the given parent
|
||||
// module instance uses the "count" repetition argument, with the given value.
|
||||
func (e *Expander) SetModuleCount(parentAddr addrs.ModuleInstance, callAddr addrs.ModuleCall, count int) {
|
||||
|
||||
@@ -22,6 +22,7 @@ func TestExpander(t *testing.T) {
|
||||
count2ModuleAddr := addrs.ModuleCall{Name: "count2"}
|
||||
count0ModuleAddr := addrs.ModuleCall{Name: "count0"}
|
||||
forEachModuleAddr := addrs.ModuleCall{Name: "for_each"}
|
||||
enabledModuleAddr := addrs.ModuleCall{Name: "enabled"}
|
||||
singleResourceAddr := addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "test",
|
||||
@@ -42,6 +43,11 @@ func TestExpander(t *testing.T) {
|
||||
Type: "test",
|
||||
Name: "for_each",
|
||||
}
|
||||
enabledResourceAddr := addrs.Resource{
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Type: "test",
|
||||
Name: "enabled",
|
||||
}
|
||||
eachMap := map[string]cty.Value{
|
||||
"a": cty.NumberIntVal(1),
|
||||
"b": cty.NumberIntVal(2),
|
||||
@@ -88,6 +94,7 @@ func TestExpander(t *testing.T) {
|
||||
ex.SetResourceCount(addrs.RootModuleInstance, count2ResourceAddr, 2)
|
||||
ex.SetResourceCount(addrs.RootModuleInstance, count0ResourceAddr, 0)
|
||||
ex.SetResourceForEach(addrs.RootModuleInstance, forEachResourceAddr, eachMap)
|
||||
ex.SetResourceEnabled(addrs.RootModuleInstance, enabledResourceAddr, true)
|
||||
|
||||
ex.SetModuleSingle(addrs.RootModuleInstance, singleModuleAddr)
|
||||
{
|
||||
@@ -97,6 +104,12 @@ func TestExpander(t *testing.T) {
|
||||
ex.SetResourceCount(moduleInstanceAddr, count2ResourceAddr, 2)
|
||||
}
|
||||
|
||||
ex.SetModuleEnabled(addrs.RootModuleInstance, enabledModuleAddr, true)
|
||||
{
|
||||
moduleInstanceAddr := addrs.RootModuleInstance.Child("enabled", addrs.NoKey)
|
||||
ex.SetResourceSingle(moduleInstanceAddr, singleResourceAddr)
|
||||
}
|
||||
|
||||
ex.SetModuleCount(addrs.RootModuleInstance, count2ModuleAddr, 2)
|
||||
for i1 := 0; i1 < 2; i1++ {
|
||||
moduleInstanceAddr := addrs.RootModuleInstance.Child("count2", addrs.IntKey(i1))
|
||||
@@ -146,6 +159,19 @@ func TestExpander(t *testing.T) {
|
||||
t.Errorf("wrong result\n%s", diff)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("resource enabled", func(t *testing.T) {
|
||||
got := ex.ExpandModuleResource(
|
||||
addrs.RootModule,
|
||||
enabledResourceAddr,
|
||||
)
|
||||
want := []addrs.AbsResourceInstance{
|
||||
mustAbsResourceInstanceAddr(`test.enabled`),
|
||||
}
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("wrong result\n%s", diff)
|
||||
}
|
||||
})
|
||||
t.Run("resource count2", func(t *testing.T) {
|
||||
got := ex.ExpandModuleResource(
|
||||
addrs.RootModule,
|
||||
@@ -169,6 +195,18 @@ func TestExpander(t *testing.T) {
|
||||
t.Errorf("wrong result\n%s", diff)
|
||||
}
|
||||
})
|
||||
t.Run("resource enabled", func(t *testing.T) {
|
||||
got := ex.ExpandModuleResource(
|
||||
addrs.RootModule,
|
||||
enabledResourceAddr,
|
||||
)
|
||||
want := []addrs.AbsResourceInstance{
|
||||
mustAbsResourceInstanceAddr(`test.enabled`),
|
||||
}
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("wrong result\n%s", diff)
|
||||
}
|
||||
})
|
||||
t.Run("resource for_each", func(t *testing.T) {
|
||||
got := ex.ExpandModuleResource(
|
||||
addrs.RootModule,
|
||||
@@ -191,6 +229,16 @@ func TestExpander(t *testing.T) {
|
||||
t.Errorf("wrong result\n%s", diff)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("module enabled", func(t *testing.T) {
|
||||
got := ex.ExpandModule(addrs.RootModule.Child("enabled"))
|
||||
want := []addrs.ModuleInstance{
|
||||
mustModuleInstanceAddr(`module.enabled`),
|
||||
}
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("wrong result\n%s", diff)
|
||||
}
|
||||
})
|
||||
t.Run("module single resource single", func(t *testing.T) {
|
||||
got := ex.ExpandModuleResource(
|
||||
mustModuleAddr("single"),
|
||||
|
||||
@@ -565,16 +565,23 @@ func (d *evaluationStateData) GetModule(_ context.Context, addr addrs.ModuleCall
|
||||
}
|
||||
|
||||
default:
|
||||
val, ok := moduleInstances[addrs.NoKey]
|
||||
vals, ok := moduleInstances[addrs.NoKey]
|
||||
if !ok {
|
||||
// create the object if there wasn't one known
|
||||
val = map[string]cty.Value{}
|
||||
for k := range outputConfigs {
|
||||
val[k] = cty.DynamicVal
|
||||
if callConfig.Enabled == nil {
|
||||
// create the object if there wasn't one known
|
||||
vals = map[string]cty.Value{}
|
||||
for k := range outputConfigs {
|
||||
vals[k] = cty.DynamicVal
|
||||
}
|
||||
ret = cty.ObjectVal(vals)
|
||||
} else {
|
||||
// when we're using enabled it's okay to have no
|
||||
// instance, and the entire object is null.
|
||||
ret = cty.NullVal(cty.DynamicPseudoType)
|
||||
}
|
||||
} else {
|
||||
ret = cty.ObjectVal(vals)
|
||||
}
|
||||
|
||||
ret = cty.ObjectVal(val)
|
||||
}
|
||||
|
||||
// The module won't be expanded during validation, so we need to return an
|
||||
|
||||
@@ -77,6 +77,10 @@ func (n *nodeExpandModule) References() []*addrs.Reference {
|
||||
forEachRefs, _ := lang.ReferencesInExpr(addrs.ParseRef, n.ModuleCall.ForEach)
|
||||
refs = append(refs, forEachRefs...)
|
||||
}
|
||||
if n.ModuleCall.Enabled != nil {
|
||||
enabledRefs, _ := lang.ReferencesInExpr(addrs.ParseRef, n.ModuleCall.Enabled)
|
||||
refs = append(refs, enabledRefs...)
|
||||
}
|
||||
|
||||
for _, passed := range n.ModuleCall.Providers {
|
||||
if passed.InParent.KeyExpression != nil {
|
||||
@@ -142,6 +146,23 @@ func (n *nodeExpandModule) Execute(ctx context.Context, evalCtx EvalContext, op
|
||||
}
|
||||
expander.SetModuleForEach(module, call, forEach)
|
||||
|
||||
case n.ModuleCall.Enabled != nil:
|
||||
// For enabled expressions, we need to evaluate in the parent module context
|
||||
// since the expression may reference variables defined in the parent module. e.g.
|
||||
// variable "on" { type = bool }
|
||||
// module "mod1" {
|
||||
// source = "./mod1"
|
||||
// lifecycle {
|
||||
// enabled = var.on
|
||||
// }
|
||||
// }
|
||||
parentEvalCtx := evalCtx.WithPath(module.Parent())
|
||||
enabled, enDiags := evaluateEnabledExpression(ctx, n.ModuleCall.Enabled, parentEvalCtx)
|
||||
diags = diags.Append(enDiags)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
expander.SetModuleEnabled(module, call, enabled)
|
||||
default:
|
||||
expander.SetModuleSingle(module, call)
|
||||
}
|
||||
|
||||
19
internal/tofu/testdata/apply-enabled-module/apply-enabled-module.tf
vendored
Normal file
19
internal/tofu/testdata/apply-enabled-module/apply-enabled-module.tf
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
variable "on" {
|
||||
type = bool
|
||||
}
|
||||
|
||||
module "mod1" {
|
||||
source = "./mod1"
|
||||
|
||||
lifecycle {
|
||||
enabled = var.on
|
||||
}
|
||||
}
|
||||
|
||||
output "result" {
|
||||
// This is in a 1-tuple just because OpenTofu treats a fully-null
|
||||
// root module output value as if it wasn't declared at all,
|
||||
// but we want to make sure we're actually testing the result
|
||||
// of this resource directly.
|
||||
value = [try(module.mod1.result, "")]
|
||||
}
|
||||
Reference in New Issue
Block a user