diff --git a/lang/eval.go b/lang/eval.go index db5a15a24..381ec4288 100644 --- a/lang/eval.go +++ b/lang/eval.go @@ -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