lang.Scope.EvalSelfBlock

In order to properly evaluate a destroy provisioner, we cannot rely on
the usual evaluation context, because the resource has already been
removed from the state.

EvalSelfBlock evaluates an hcl.Body in the limited scope of a single
object as "self", with the added values of "count.index" and "each.key".
This commit is contained in:
James Bardin 2020-10-02 11:25:21 -04:00
parent 43c0525277
commit 64c3a8f550
1 changed files with 30 additions and 0 deletions

View File

@ -8,6 +8,7 @@ import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/instances"
"github.com/hashicorp/terraform/lang/blocktoattr"
"github.com/hashicorp/terraform/tfdiags"
"github.com/zclconf/go-cty/cty"
@ -69,6 +70,35 @@ func (s *Scope) EvalBlock(body hcl.Body, schema *configschema.Block) (cty.Value,
return val, diags
}
// EvalSelfBlock evaluates the given body only within the scope of the provided
// object and instance key data. References to the object must use self, and the
// key data will only contain count.index or each.key.
func (s *Scope) EvalSelfBlock(body hcl.Body, self cty.Value, schema *configschema.Block, keyData instances.RepetitionData) (cty.Value, tfdiags.Diagnostics) {
vals := make(map[string]cty.Value)
vals["self"] = self
if !keyData.CountIndex.IsNull() {
vals["count"] = cty.ObjectVal(map[string]cty.Value{
"index": keyData.CountIndex,
})
}
if !keyData.EachKey.IsNull() {
vals["each"] = cty.ObjectVal(map[string]cty.Value{
"key": keyData.EachKey,
})
}
ctx := &hcl.EvalContext{
Variables: vals,
Functions: s.Functions(),
}
var diags tfdiags.Diagnostics
val, decDiags := hcldec.Decode(body, schema.DecoderSpec(), ctx)
diags = diags.Append(decDiags)
return val, diags
}
// EvalExpr evaluates a single expression in the receiving context and returns
// the resulting value. The value will be converted to the given type before
// it is returned if possible, or else an error diagnostic will be produced