From 953ada1cf80a70bf4a7d30b6c60f3b5522525f23 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Mon, 17 Feb 2020 16:07:38 -0500 Subject: [PATCH] destroy provisioner cannot re-evaluate for_each During destroy, the for expression may be unknown and evaluation will fail. Destroy provisioners however can only reference the key value, which is known in the address. --- terraform/eval_apply.go | 11 +++++++++-- terraform/evaluate.go | 26 +++++++++++--------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/terraform/eval_apply.go b/terraform/eval_apply.go index dbb3667ef..5be883197 100644 --- a/terraform/eval_apply.go +++ b/terraform/eval_apply.go @@ -561,8 +561,15 @@ func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*configs.Provisio provisioner := ctx.Provisioner(prov.Type) schema := ctx.ProvisionerSchema(prov.Type) - forEach, forEachDiags := evaluateResourceForEachExpression(n.ResourceConfig.ForEach, ctx) - diags = diags.Append(forEachDiags) + var forEach map[string]cty.Value + + // We can't evaluate the for_each expression during a destroy + if n.When != configs.ProvisionerWhenDestroy { + m, forEachDiags := evaluateResourceForEachExpression(n.ResourceConfig.ForEach, ctx) + diags = diags.Append(forEachDiags) + forEach = m + } + keyData := EvalDataForInstanceKey(instanceAddr.Key, forEach) // Evaluate the main provisioner configuration. diff --git a/terraform/evaluate.go b/terraform/evaluate.go index 65a7172eb..1ce77a64f 100644 --- a/terraform/evaluate.go +++ b/terraform/evaluate.go @@ -105,24 +105,20 @@ type InstanceKeyEvalData = instances.RepetitionData // EvalDataForInstanceKey constructs a suitable InstanceKeyEvalData for // evaluating in a context that has the given instance key. func EvalDataForInstanceKey(key addrs.InstanceKey, forEachMap map[string]cty.Value) InstanceKeyEvalData { - var countIdx cty.Value - var eachKey cty.Value - var eachVal cty.Value - - if intKey, ok := key.(addrs.IntKey); ok { - countIdx = cty.NumberIntVal(int64(intKey)) + var evalData InstanceKeyEvalData + if key == nil { + return evalData } - if stringKey, ok := key.(addrs.StringKey); ok { - eachKey = cty.StringVal(string(stringKey)) - eachVal = forEachMap[string(stringKey)] - } - - return InstanceKeyEvalData{ - CountIndex: countIdx, - EachKey: eachKey, - EachValue: eachVal, + keyValue := key.Value() + switch keyValue.Type() { + case cty.String: + evalData.EachKey = keyValue + evalData.EachValue = forEachMap[keyValue.AsString()] + case cty.Number: + evalData.CountIndex = keyValue } + return evalData } // EvalDataForNoInstanceKey is a value of InstanceKeyData that sets no instance