From de3d9fb9d9446b05bd2010931d5c4be8331971e2 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 5 Feb 2015 20:09:57 -0500 Subject: [PATCH] terraform: evaluation interpolater connect --- terraform/context.go | 17 +++++++++-- terraform/context_test.go | 1 - terraform/eval_context.go | 9 ++++-- terraform/eval_context_builtin.go | 51 ++++++++++--------------------- terraform/eval_interpolate.go | 5 +-- 5 files changed, 40 insertions(+), 43 deletions(-) diff --git a/terraform/context.go b/terraform/context.go index 7bbedb59a..11beacd7e 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -30,6 +30,8 @@ type Context2 struct { module *module.Tree providers map[string]ResourceProviderFactory state *State + stateLock sync.RWMutex + variables map[string]string } // NewContext creates a new Context structure. @@ -42,6 +44,7 @@ func NewContext2(opts *ContextOpts) *Context2 { module: opts.Module, providers: opts.Providers, state: opts.State, + variables: opts.Variables, } } @@ -71,8 +74,7 @@ func (c *Context2) Validate() ([]string, []error) { errs = append(errs, err) } - evalCtx := c.evalContext() - evalCtx.ComputeMissing = true + evalCtx := c.evalContext(walkValidate) // Build the graph graph, err := c.GraphBuilder().Build(RootModulePath) @@ -114,8 +116,17 @@ func (c *Context2) Validate() ([]string, []error) { return warns, errs } -func (c *Context2) evalContext() *BuiltinEvalContext { +func (c *Context2) evalContext(op walkOperation) *BuiltinEvalContext { return &BuiltinEvalContext{ + Path: RootModulePath, Providers: c.providers, + + Interpolater: &Interpolater{ + Operation: op, + Module: c.module, + State: c.state, + StateLock: &c.stateLock, + Variables: nil, + }, } } diff --git a/terraform/context_test.go b/terraform/context_test.go index 1663bf44f..aca3d623f 100644 --- a/terraform/context_test.go +++ b/terraform/context_test.go @@ -162,7 +162,6 @@ func TestContext2Validate_requiredVar(t *testing.T) { if len(w) > 0 { t.Fatalf("bad: %#v", w) } - // TODO: fail if len(e) == 0 { t.Fatalf("bad: %s", e) } diff --git a/terraform/eval_context.go b/terraform/eval_context.go index a41941eea..7ae383f0a 100644 --- a/terraform/eval_context.go +++ b/terraform/eval_context.go @@ -18,7 +18,10 @@ type EvalContext interface { // Interpolate takes the given raw configuration and completes // the interpolations, returning the processed ResourceConfig. - Interpolate(*config.RawConfig) (*ResourceConfig, error) + // + // The resource argument is optional. If given, it is the resource + // that is currently being acted upon. + Interpolate(*config.RawConfig, *Resource) (*ResourceConfig, error) } // MockEvalContext is a mock version of EvalContext that can be used @@ -35,6 +38,7 @@ type MockEvalContext struct { InterpolateCalled bool InterpolateConfig *config.RawConfig + InterpolateResource *Resource InterpolateConfigResult *ResourceConfig InterpolateError error } @@ -52,8 +56,9 @@ func (c *MockEvalContext) Provider(n string) ResourceProvider { } func (c *MockEvalContext) Interpolate( - config *config.RawConfig) (*ResourceConfig, error) { + config *config.RawConfig, resource *Resource) (*ResourceConfig, error) { c.InterpolateCalled = true c.InterpolateConfig = config + c.InterpolateResource = resource return c.InterpolateConfigResult, c.InterpolateError } diff --git a/terraform/eval_context_builtin.go b/terraform/eval_context_builtin.go index cffc67908..2a1a298c6 100644 --- a/terraform/eval_context_builtin.go +++ b/terraform/eval_context_builtin.go @@ -5,14 +5,14 @@ import ( "sync" "github.com/hashicorp/terraform/config" - "github.com/hashicorp/terraform/config/lang/ast" ) // BuiltinEvalContext is an EvalContext implementation that is used by // Terraform by default. type BuiltinEvalContext struct { - Providers map[string]ResourceProviderFactory - ComputeMissing bool + Path []string + Interpolater *Interpolater + Providers map[string]ResourceProviderFactory providers map[string]ResourceProvider once sync.Once @@ -45,42 +45,23 @@ func (ctx *BuiltinEvalContext) Provider(n string) ResourceProvider { } func (ctx *BuiltinEvalContext) Interpolate( - cfg *config.RawConfig) (*ResourceConfig, error) { - vs := make(map[string]ast.Variable) + cfg *config.RawConfig, r *Resource) (*ResourceConfig, error) { + if cfg != nil { + scope := &InterpolationScope{ + Path: ctx.Path, + Resource: r, + } + vs, err := ctx.Interpolater.Values(scope, cfg.Variables) + if err != nil { + return nil, err + } - // If we don't have a config, use the blank config - if cfg == nil { - goto INTERPOLATE_RESULT - } - - for n, rawV := range cfg.Variables { - switch rawV.(type) { - case *config.ModuleVariable: - if ctx.ComputeMissing { - vs[n] = ast.Variable{ - Value: config.UnknownVariableValue, - Type: ast.TypeString, - } - } - case *config.ResourceVariable: - if ctx.ComputeMissing { - vs[n] = ast.Variable{ - Value: config.UnknownVariableValue, - Type: ast.TypeString, - } - } - default: - return nil, fmt.Errorf( - "unknown interpolation type: %#v", rawV) + // Do the interpolation + if err := cfg.Interpolate(vs); err != nil { + return nil, err } } - // Do the interpolation - if err := cfg.Interpolate(vs); err != nil { - return nil, err - } - -INTERPOLATE_RESULT: result := NewResourceConfig(cfg) result.interpolateForce() return result, nil diff --git a/terraform/eval_interpolate.go b/terraform/eval_interpolate.go index 1313610ae..654359c0d 100644 --- a/terraform/eval_interpolate.go +++ b/terraform/eval_interpolate.go @@ -7,7 +7,8 @@ import ( // EvalInterpolate is an EvalNode implementation that takes a raw // configuration and interpolates it. type EvalInterpolate struct { - Config *config.RawConfig + Config *config.RawConfig + Resource *Resource } func (n *EvalInterpolate) Args() ([]EvalNode, []EvalType) { @@ -16,7 +17,7 @@ func (n *EvalInterpolate) Args() ([]EvalNode, []EvalType) { func (n *EvalInterpolate) Eval( ctx EvalContext, args []interface{}) (interface{}, error) { - return ctx.Interpolate(n.Config) + return ctx.Interpolate(n.Config, n.Resource) } func (n *EvalInterpolate) Type() EvalType {