terraform: evaluation interpolater connect

This commit is contained in:
Mitchell Hashimoto 2015-02-05 20:09:57 -05:00
parent 3908b6319a
commit de3d9fb9d9
5 changed files with 40 additions and 43 deletions

View File

@ -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,
},
}
}

View File

@ -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)
}

View File

@ -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
}

View File

@ -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

View File

@ -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 {