diff --git a/terraform/eval.go b/terraform/eval.go index 7a274d14cc..54cbbeba24 100644 --- a/terraform/eval.go +++ b/terraform/eval.go @@ -19,8 +19,10 @@ type EvalNode interface { // and not used at runtime. Args() ([]EvalNode, []EvalType) - // Eval evaluates this node with the given context. - Eval(EvalContext) (interface{}, error) + // Eval evaluates this node with the given context. The second parameter + // are the argument values. These will match in order and 1-1 with the + // results of the Args() return value. + Eval(EvalContext, []interface{}) (interface{}, error) // Type returns the type that will be returned by this node. Type() EvalType @@ -31,3 +33,28 @@ type EvalNode interface { type GraphNodeEvalable interface { EvalTree() EvalNode } + +// MockEvalContext is a mock version of EvalContext that can be used +// for tests. +type MockEvalContext struct { + InitProviderCalled bool + InitProviderName string + InitProviderProvider ResourceProvider + InitProviderError error + + ProviderCalled bool + ProviderName string + ProviderProvider ResourceProvider +} + +func (c *MockEvalContext) InitProvider(n string) (ResourceProvider, error) { + c.InitProviderCalled = true + c.InitProviderName = n + return c.InitProviderProvider, c.InitProviderError +} + +func (c *MockEvalContext) Provider(n string) ResourceProvider { + c.ProviderCalled = true + c.ProviderName = n + return c.ProviderProvider +} diff --git a/terraform/eval_interpolate.go b/terraform/eval_interpolate.go index ea7846b966..a0ef21cb0a 100644 --- a/terraform/eval_interpolate.go +++ b/terraform/eval_interpolate.go @@ -14,7 +14,8 @@ func (n *EvalInterpolate) Args() ([]EvalNode, []EvalType) { return nil, nil } -func (n *EvalInterpolate) Eval(ctx EvalContext) (interface{}, error) { +func (n *EvalInterpolate) Eval( + ctx EvalContext, args []interface{}) (interface{}, error) { return nil, nil } diff --git a/terraform/eval_literal.go b/terraform/eval_literal.go new file mode 100644 index 0000000000..2159298721 --- /dev/null +++ b/terraform/eval_literal.go @@ -0,0 +1,20 @@ +package terraform + +// EvalLiteral is an EvalNode implementation that returns a literal +// value. This is very useful for testing as well as in practice. +type EvalLiteral struct { + Value interface{} + ValueType EvalType +} + +func (n *EvalLiteral) Args() ([]EvalNode, []EvalType) { + return nil, nil +} + +func (n *EvalLiteral) Eval(EvalContext, []interface{}) (interface{}, error) { + return n.Value, nil +} + +func (n *EvalLiteral) Type() EvalType { + return n.ValueType +} diff --git a/terraform/eval_literal_test.go b/terraform/eval_literal_test.go new file mode 100644 index 0000000000..f82a5613d1 --- /dev/null +++ b/terraform/eval_literal_test.go @@ -0,0 +1,27 @@ +package terraform + +import ( + "testing" +) + +func TestEvalLiteral_impl(t *testing.T) { + var _ EvalNode = new(EvalLiteral) +} + +func TestEvalLiteralEval(t *testing.T) { + n := &EvalLiteral{Value: 42} + actual, err := n.Eval(nil, nil) + if err != nil { + t.Fatalf("err: %s", err) + } + if actual != 42 { + t.Fatalf("bad: %#v", actual) + } +} + +func TestEvalLiteralType(t *testing.T) { + n := &EvalLiteral{Value: 42, ValueType: EvalTypeConfig} + if actual := n.Type(); actual != EvalTypeConfig { + t.Fatalf("bad: %#v", actual) + } +} diff --git a/terraform/eval_provider.go b/terraform/eval_provider.go index f2c9115bf9..032515da68 100644 --- a/terraform/eval_provider.go +++ b/terraform/eval_provider.go @@ -16,7 +16,8 @@ func (n *EvalConfigProvider) Args() ([]EvalNode, []EvalType) { []EvalType{EvalTypeResourceProvider, EvalTypeConfig} } -func (n *EvalConfigProvider) Eval(ctx EvalContext) (interface{}, error) { +func (n *EvalConfigProvider) Eval( + ctx EvalContext, args []interface{}) (interface{}, error) { return nil, nil } @@ -35,7 +36,8 @@ func (n *EvalInitProvider) Args() ([]EvalNode, []EvalType) { return nil, nil } -func (n *EvalInitProvider) Eval(ctx EvalContext) (interface{}, error) { +func (n *EvalInitProvider) Eval( + ctx EvalContext, args []interface{}) (interface{}, error) { return ctx.InitProvider(n.Name) } @@ -53,7 +55,8 @@ func (n *EvalGetProvider) Args() ([]EvalNode, []EvalType) { return nil, nil } -func (n *EvalGetProvider) Eval(ctx EvalContext) (interface{}, error) { +func (n *EvalGetProvider) Eval( + ctx EvalContext, args []interface{}) (interface{}, error) { result := ctx.Provider(n.Name) if result == nil { return nil, fmt.Errorf("provider %s not initialized", n.Name) diff --git a/terraform/eval_provider_test.go b/terraform/eval_provider_test.go new file mode 100644 index 0000000000..ba56dc22db --- /dev/null +++ b/terraform/eval_provider_test.go @@ -0,0 +1,49 @@ +package terraform + +import ( + "testing" +) + +func TestEvalInitProvider_impl(t *testing.T) { + var _ EvalNode = new(EvalInitProvider) +} + +func TestEvalInitProvider(t *testing.T) { + n := &EvalInitProvider{Name: "foo"} + provider := &MockResourceProvider{} + ctx := &MockEvalContext{InitProviderProvider: provider} + if actual, err := n.Eval(ctx, nil); err != nil { + t.Fatalf("err: %s", err) + } else if actual != provider { + t.Fatalf("bad: %#v", actual) + } + + if !ctx.InitProviderCalled { + t.Fatal("should be called") + } + if ctx.InitProviderName != "foo" { + t.Fatalf("bad: %#v", ctx.InitProviderName) + } +} + +func TestEvalGetProvider_impl(t *testing.T) { + var _ EvalNode = new(EvalGetProvider) +} + +func TestEvalGetProvider(t *testing.T) { + n := &EvalGetProvider{Name: "foo"} + provider := &MockResourceProvider{} + ctx := &MockEvalContext{ProviderProvider: provider} + if actual, err := n.Eval(ctx, nil); err != nil { + t.Fatalf("err: %s", err) + } else if actual != provider { + t.Fatalf("bad: %#v", actual) + } + + if !ctx.ProviderCalled { + t.Fatal("should be called") + } + if ctx.ProviderName != "foo" { + t.Fatalf("bad: %#v", ctx.ProviderName) + } +} diff --git a/terraform/eval_test.go b/terraform/eval_test.go new file mode 100644 index 0000000000..e89f2641bf --- /dev/null +++ b/terraform/eval_test.go @@ -0,0 +1,9 @@ +package terraform + +import ( + "testing" +) + +func TestMockEvalContext_impl(t *testing.T) { + var _ EvalContext = new(MockEvalContext) +}