From 02a3603a9a14ba42c167179d3826c5e5cd1e989a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 6 Jun 2014 00:48:32 -0700 Subject: [PATCH] rpc: Diff implementation --- rpc/resource_provider.go | 52 +++++++++++++++--- rpc/resource_provider_test.go | 85 +++++++++++++++++++++++------ terraform/resource_provider.go | 2 +- terraform/resource_provider_mock.go | 6 +- terraform/terraform_test.go | 4 +- 5 files changed, 119 insertions(+), 30 deletions(-) diff --git a/rpc/resource_provider.go b/rpc/resource_provider.go index 8e277cd85..ffa1d3e1b 100644 --- a/rpc/resource_provider.go +++ b/rpc/resource_provider.go @@ -13,9 +13,28 @@ type ResourceProvider struct { Name string } -func (p *ResourceProvider) Configure(c map[string]interface{}) ([]string, error) { +func (p *ResourceProvider) Configure(c map[string]interface{}) error { var resp ResourceProviderConfigureResponse err := p.Client.Call(p.Name+".Configure", c, &resp) + if err != nil { + return err + } + if resp.Error != nil { + err = resp.Error + } + + return err +} + +func (p *ResourceProvider) Diff( + s *terraform.ResourceState, + c map[string]interface{}) (*terraform.ResourceDiff, error) { + var resp ResourceProviderDiffResponse + args := &ResourceProviderDiffArgs{ + State: s, + Config: c, + } + err := p.Client.Call(p.Name+".Diff", args, &resp) if err != nil { return nil, err } @@ -23,7 +42,7 @@ func (p *ResourceProvider) Configure(c map[string]interface{}) ([]string, error) err = resp.Error } - return resp.Warnings, err + return resp.Diff, err } func (p *ResourceProvider) Resources() []terraform.ResourceType { @@ -45,17 +64,36 @@ type ResourceProviderServer struct { } type ResourceProviderConfigureResponse struct { - Warnings []string - Error *BasicError + Error *BasicError +} + +type ResourceProviderDiffArgs struct { + State *terraform.ResourceState + Config map[string]interface{} +} + +type ResourceProviderDiffResponse struct { + Diff *terraform.ResourceDiff + Error *BasicError } func (s *ResourceProviderServer) Configure( config map[string]interface{}, reply *ResourceProviderConfigureResponse) error { - warnings, err := s.Provider.Configure(config) + err := s.Provider.Configure(config) *reply = ResourceProviderConfigureResponse{ - Warnings: warnings, - Error: NewBasicError(err), + Error: NewBasicError(err), + } + return nil +} + +func (s *ResourceProviderServer) Diff( + args *ResourceProviderDiffArgs, + result *ResourceProviderDiffResponse) error { + diff, err := s.Provider.Diff(args.State, args.Config) + *result = ResourceProviderDiffResponse{ + Diff: diff, + Error: NewBasicError(err), } return nil } diff --git a/rpc/resource_provider_test.go b/rpc/resource_provider_test.go index 645eb1e7d..7f86b7601 100644 --- a/rpc/resource_provider_test.go +++ b/rpc/resource_provider_test.go @@ -19,16 +19,13 @@ func TestResourceProvider_configure(t *testing.T) { // Configure config := map[string]interface{}{"foo": "bar"} - w, e := provider.Configure(config) + e := provider.Configure(config) if !p.ConfigureCalled { t.Fatal("configure should be called") } if !reflect.DeepEqual(p.ConfigureConfig, config) { t.Fatalf("bad: %#v", p.ConfigureConfig) } - if w != nil { - t.Fatalf("bad: %#v", w) - } if e != nil { t.Fatalf("bad: %#v", e) } @@ -47,16 +44,13 @@ func TestResourceProvider_configure_errors(t *testing.T) { // Configure config := map[string]interface{}{"foo": "bar"} - w, e := provider.Configure(config) + e := provider.Configure(config) if !p.ConfigureCalled { t.Fatal("configure should be called") } if !reflect.DeepEqual(p.ConfigureConfig, config) { t.Fatalf("bad: %#v", p.ConfigureConfig) } - if w != nil { - t.Fatalf("bad: %#v", w) - } if e == nil { t.Fatal("should have error") } @@ -74,28 +68,85 @@ func TestResourceProvider_configure_warnings(t *testing.T) { } provider := &ResourceProvider{Client: client, Name: name} - p.ConfigureReturnWarnings = []string{"foo", "bar"} - // Configure config := map[string]interface{}{"foo": "bar"} - w, e := provider.Configure(config) + e := provider.Configure(config) if !p.ConfigureCalled { t.Fatal("configure should be called") } if !reflect.DeepEqual(p.ConfigureConfig, config) { t.Fatalf("bad: %#v", p.ConfigureConfig) } - if w == nil { - t.Fatal("should have warnings") - } - if !reflect.DeepEqual(w, []string{"foo", "bar"}) { - t.Fatalf("bad: %#v", w) - } if e != nil { t.Fatalf("bad: %#v", e) } } +func TestResourceProvider_diff(t *testing.T) { + p := new(terraform.MockResourceProvider) + client, server := testClientServer(t) + name, err := Register(server, p) + if err != nil { + t.Fatalf("err: %s", err) + } + provider := &ResourceProvider{Client: client, Name: name} + + p.DiffReturn = &terraform.ResourceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "foo": &terraform.ResourceAttrDiff{ + Old: "", + New: "bar", + }, + }, + } + + // Diff + state := &terraform.ResourceState{} + config := map[string]interface{}{"foo": "bar"} + diff, err := provider.Diff(state, config) + if !p.DiffCalled { + t.Fatal("diff should be called") + } + if !reflect.DeepEqual(p.DiffDesired, config) { + t.Fatalf("bad: %#v", p.DiffDesired) + } + if err != nil { + t.Fatalf("bad: %#v", err) + } + if !reflect.DeepEqual(p.DiffReturn, diff) { + t.Fatalf("bad: %#v", diff) + } +} + +func TestResourceProvider_diff_error(t *testing.T) { + p := new(terraform.MockResourceProvider) + client, server := testClientServer(t) + name, err := Register(server, p) + if err != nil { + t.Fatalf("err: %s", err) + } + provider := &ResourceProvider{Client: client, Name: name} + + p.DiffReturnError = errors.New("foo") + + // Diff + state := &terraform.ResourceState{} + config := map[string]interface{}{"foo": "bar"} + diff, err := provider.Diff(state, config) + if !p.DiffCalled { + t.Fatal("diff should be called") + } + if !reflect.DeepEqual(p.DiffDesired, config) { + t.Fatalf("bad: %#v", p.DiffDesired) + } + if err == nil { + t.Fatal("should have error") + } + if diff != nil { + t.Fatal("should not have diff") + } +} + func TestResourceProvider_resources(t *testing.T) { p := new(terraform.MockResourceProvider) client, server := testClientServer(t) diff --git a/terraform/resource_provider.go b/terraform/resource_provider.go index 424315021..613bb749b 100644 --- a/terraform/resource_provider.go +++ b/terraform/resource_provider.go @@ -30,7 +30,7 @@ type ResourceProvider interface { // a diff. Diff( *ResourceState, - map[string]interface{}) (ResourceDiff, error) + map[string]interface{}) (*ResourceDiff, error) } // ResourceType is a type of resource that a resource provider can manage. diff --git a/terraform/resource_provider_mock.go b/terraform/resource_provider_mock.go index 0c0adc83e..1c83da9cb 100644 --- a/terraform/resource_provider_mock.go +++ b/terraform/resource_provider_mock.go @@ -12,8 +12,8 @@ type MockResourceProvider struct { DiffCalled bool DiffState *ResourceState DiffDesired map[string]interface{} - DiffFn func(*ResourceState, map[string]interface{}) (ResourceDiff, error) - DiffReturn ResourceDiff + DiffFn func(*ResourceState, map[string]interface{}) (*ResourceDiff, error) + DiffReturn *ResourceDiff DiffReturnError error ResourcesCalled bool ResourcesReturn []ResourceType @@ -27,7 +27,7 @@ func (p *MockResourceProvider) Configure(c map[string]interface{}) error { func (p *MockResourceProvider) Diff( state *ResourceState, - desired map[string]interface{}) (ResourceDiff, error) { + desired map[string]interface{}) (*ResourceDiff, error) { p.DiffCalled = true p.DiffState = state p.DiffDesired = desired diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index c429292e9..3c90f5939 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -261,7 +261,7 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory { return func() (ResourceProvider, error) { diffFn := func( _ *ResourceState, - c map[string]interface{}) (ResourceDiff, error) { + c map[string]interface{}) (*ResourceDiff, error) { var diff ResourceDiff diff.Attributes = make(map[string]*ResourceAttrDiff) for k, v := range c { @@ -290,7 +290,7 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory { diff.Attributes[k] = attrDiff } - return diff, nil + return &diff, nil } result := &MockResourceProvider{