From d4cfe8536137b26080c2ba218a170405fdd9c064 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Tue, 1 May 2018 13:40:52 -0700 Subject: [PATCH] core: pass InstanceKey to EvaluateBlock This gives us the value we need to evaluate a "count.index" reference, and later also the equivalent for the "for_each" argument once implemented. --- terraform/eval_apply.go | 4 ++-- terraform/eval_context.go | 8 +++++++- terraform/eval_context_builtin.go | 6 +++--- terraform/eval_context_mock.go | 4 +++- terraform/eval_diff.go | 2 +- terraform/eval_lang.go | 2 +- terraform/eval_provider.go | 2 +- terraform/eval_read_data.go | 2 +- terraform/eval_validate.go | 10 +++++----- 9 files changed, 24 insertions(+), 16 deletions(-) diff --git a/terraform/eval_apply.go b/terraform/eval_apply.go index 613f6efcc..d3b95e22f 100644 --- a/terraform/eval_apply.go +++ b/terraform/eval_apply.go @@ -302,10 +302,10 @@ func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*configs.Provisio schema := ctx.ProvisionerSchema(prov.Type) // Evaluate the main provisioner configuration. - config, _, configDiags := ctx.EvaluateBlock(prov.Config, schema, instanceAddr) + config, _, configDiags := ctx.EvaluateBlock(prov.Config, schema, instanceAddr, instanceAddr.Key) diags = diags.Append(configDiags) - connInfo, _, connInfoDiags := ctx.EvaluateBlock(prov.Config, connectionBlockSupersetSchema, instanceAddr) + connInfo, _, connInfoDiags := ctx.EvaluateBlock(prov.Config, connectionBlockSupersetSchema, instanceAddr, instanceAddr.Key) diags = diags.Append(connInfoDiags) if configDiags.HasErrors() || connInfoDiags.HasErrors() { diff --git a/terraform/eval_context.go b/terraform/eval_context.go index e5838119b..48e178dcd 100644 --- a/terraform/eval_context.go +++ b/terraform/eval_context.go @@ -89,11 +89,17 @@ type EvalContext interface { // address that the name "self" should behave as an alias for when // evaluating. Set this to nil if the "self" object should not be available. // + // The "key" argument is also optional. If given, it is the instance key + // of the current object within the multi-instance container it belongs + // to. For example, on a resource block with "count" set this should be + // set to a different addrs.IntKey for each instance created from that + // block. Set this to addrs.NoKey if not appropriate. + // // The returned body is an expanded version of the given body, with any // "dynamic" blocks replaced with zero or more static blocks. This can be // used to extract correct source location information about attributes of // the returned object value. - EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable) (cty.Value, hcl.Body, tfdiags.Diagnostics) + EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, key addrs.InstanceKey) (cty.Value, hcl.Body, tfdiags.Diagnostics) // EvaluateExpr takes the given HCL expression and evaluates it to produce // a value. diff --git a/terraform/eval_context_builtin.go b/terraform/eval_context_builtin.go index b43f5d5bf..4b1ce9b18 100644 --- a/terraform/eval_context_builtin.go +++ b/terraform/eval_context_builtin.go @@ -292,9 +292,9 @@ func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error { return nil } -func (ctx *BuiltinEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable) (cty.Value, hcl.Body, tfdiags.Diagnostics) { +func (ctx *BuiltinEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, key addrs.InstanceKey) (cty.Value, hcl.Body, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics - scope := ctx.Evaluator.Scope(ctx.PathValue, self) + scope := ctx.Evaluator.Scope(ctx.PathValue, self, key) body, evalDiags := scope.ExpandBlock(body, schema) diags = diags.Append(evalDiags) val, evalDiags := scope.EvalBlock(body, schema) @@ -303,7 +303,7 @@ func (ctx *BuiltinEvalContext) EvaluateBlock(body hcl.Body, schema *configschema } func (ctx *BuiltinEvalContext) EvaluateExpr(expr hcl.Expression, wantType cty.Type, self addrs.Referenceable) (cty.Value, tfdiags.Diagnostics) { - scope := ctx.Evaluator.Scope(ctx.PathValue, self) + scope := ctx.Evaluator.Scope(ctx.PathValue, self, addrs.NoKey) return scope.EvalExpr(expr, wantType) } diff --git a/terraform/eval_context_mock.go b/terraform/eval_context_mock.go index b7f964e88..4df1801b8 100644 --- a/terraform/eval_context_mock.go +++ b/terraform/eval_context_mock.go @@ -78,6 +78,7 @@ type MockEvalContext struct { EvaluateBlockBody hcl.Body EvaluateBlockSchema *configschema.Block EvaluateBlockSelf addrs.Referenceable + EvaluateBlockKey addrs.InstanceKey EvaluateBlockResult cty.Value EvaluateBlockExpandedBody hcl.Body EvaluateBlockDiags tfdiags.Diagnostics @@ -209,11 +210,12 @@ func (c *MockEvalContext) CloseProvisioner(n string) error { return nil } -func (c *MockEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable) (cty.Value, hcl.Body, tfdiags.Diagnostics) { +func (c *MockEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, key addrs.InstanceKey) (cty.Value, hcl.Body, tfdiags.Diagnostics) { c.EvaluateBlockCalled = true c.EvaluateBlockBody = body c.EvaluateBlockSchema = schema c.EvaluateBlockSelf = self + c.EvaluateBlockKey = key return c.EvaluateBlockResult, c.EvaluateBlockExpandedBody, c.EvaluateBlockDiags } diff --git a/terraform/eval_diff.go b/terraform/eval_diff.go index cd3a6db62..5d742d7d9 100644 --- a/terraform/eval_diff.go +++ b/terraform/eval_diff.go @@ -129,7 +129,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) { // Should be caught during validation, so we don't bother with a pretty error here return nil, fmt.Errorf("provider does not support resource type %q", n.Addr.Resource.Type) } - configVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, nil) + configVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, nil, n.Addr.Key) diags = diags.Append(configDiags) if configDiags.HasErrors() { return nil, diags.Err() diff --git a/terraform/eval_lang.go b/terraform/eval_lang.go index 5263a9c7a..d309622ed 100644 --- a/terraform/eval_lang.go +++ b/terraform/eval_lang.go @@ -26,7 +26,7 @@ type EvalConfigBlock struct { } func (n *EvalConfigBlock) Eval(ctx EvalContext) (interface{}, error) { - val, body, diags := ctx.EvaluateBlock(*n.Config, n.Schema, n.SelfAddr) + val, body, diags := ctx.EvaluateBlock(*n.Config, n.Schema, n.SelfAddr, addrs.NoKey) if diags.HasErrors() && n.ContinueOnErr { log.Printf("[WARN] Block evaluation failed: %s", diags.Err()) return nil, EvalEarlyExitError{} diff --git a/terraform/eval_provider.go b/terraform/eval_provider.go index 411960f21..b0d46ea4f 100644 --- a/terraform/eval_provider.go +++ b/terraform/eval_provider.go @@ -55,7 +55,7 @@ func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) { configSchema := schema.Provider configBody := buildProviderConfig(ctx, n.Addr, config.Config) - configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil) + configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, addrs.NoKey) diags = diags.Append(evalDiags) if evalDiags.HasErrors() { return nil, diags.NonFatalErr() diff --git a/terraform/eval_read_data.go b/terraform/eval_read_data.go index 53521746c..f9241017f 100644 --- a/terraform/eval_read_data.go +++ b/terraform/eval_read_data.go @@ -60,7 +60,7 @@ func (n *EvalReadDataDiff) Eval(ctx EvalContext) (interface{}, error) { } var configDiags tfdiags.Diagnostics - configVal, _, configDiags = ctx.EvaluateBlock(config.Config, schema, nil) + configVal, _, configDiags = ctx.EvaluateBlock(config.Config, schema, nil, n.Addr.Key) diags = diags.Append(configDiags) if configDiags.HasErrors() { return nil, diags.Err() diff --git a/terraform/eval_validate.go b/terraform/eval_validate.go index 4c453980f..7a35c23f4 100644 --- a/terraform/eval_validate.go +++ b/terraform/eval_validate.go @@ -86,7 +86,7 @@ func (n *EvalValidateProvider) Eval(ctx EvalContext) (interface{}, error) { configSchema := schema.Provider configBody := buildProviderConfig(ctx, n.Addr, config.Config) - configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil) + configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, addrs.NoKey) diags = diags.Append(evalDiags) if evalDiags.HasErrors() { return nil, diags.NonFatalErr() @@ -136,7 +136,7 @@ func (n *EvalValidateProvisioner) Eval(ctx EvalContext) (interface{}, error) { { // Validate the provisioner's own config first - configVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, n.ResourceAddr) + configVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, n.ResourceAddr, n.ResourceAddr.Key) diags = diags.Append(configDiags) if configDiags.HasErrors() { return nil, diags.Err() @@ -184,7 +184,7 @@ func (n *EvalValidateProvisioner) validateConnConfig(ctx EvalContext, config *co // We evaluate here just by evaluating the block and returning any // diagnostics we get, since evaluation alone is enough to check for // extraneous arguments and incorrectly-typed arguments. - _, _, configDiags := ctx.EvaluateBlock(config.Config, connectionBlockSupersetSchema, self) + _, _, configDiags := ctx.EvaluateBlock(config.Config, connectionBlockSupersetSchema, self, n.ResourceAddr.Key) diags = diags.Append(configDiags) return diags @@ -339,7 +339,7 @@ func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) { return nil, diags.Err() } - configVal, _, valDiags := ctx.EvaluateBlock(cfg.Config, schema, nil) + configVal, _, valDiags := ctx.EvaluateBlock(cfg.Config, schema, nil, n.Addr.Key) diags = diags.Append(valDiags) if valDiags.HasErrors() { return nil, diags.Err() @@ -366,7 +366,7 @@ func (n *EvalValidateResource) Eval(ctx EvalContext) (interface{}, error) { return nil, diags.Err() } - configVal, _, valDiags := ctx.EvaluateBlock(cfg.Config, schema, nil) + configVal, _, valDiags := ctx.EvaluateBlock(cfg.Config, schema, nil, n.Addr.Key) diags = diags.Append(valDiags) if valDiags.HasErrors() { return nil, diags.Err()