rpc: Diff implementation

This commit is contained in:
Mitchell Hashimoto 2014-06-06 00:48:32 -07:00
parent 0561edc2fd
commit 02a3603a9a
5 changed files with 119 additions and 30 deletions

View File

@ -13,9 +13,28 @@ type ResourceProvider struct {
Name string Name string
} }
func (p *ResourceProvider) Configure(c map[string]interface{}) ([]string, error) { func (p *ResourceProvider) Configure(c map[string]interface{}) error {
var resp ResourceProviderConfigureResponse var resp ResourceProviderConfigureResponse
err := p.Client.Call(p.Name+".Configure", c, &resp) 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 { if err != nil {
return nil, err return nil, err
} }
@ -23,7 +42,7 @@ func (p *ResourceProvider) Configure(c map[string]interface{}) ([]string, error)
err = resp.Error err = resp.Error
} }
return resp.Warnings, err return resp.Diff, err
} }
func (p *ResourceProvider) Resources() []terraform.ResourceType { func (p *ResourceProvider) Resources() []terraform.ResourceType {
@ -45,17 +64,36 @@ type ResourceProviderServer struct {
} }
type ResourceProviderConfigureResponse 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( func (s *ResourceProviderServer) Configure(
config map[string]interface{}, config map[string]interface{},
reply *ResourceProviderConfigureResponse) error { reply *ResourceProviderConfigureResponse) error {
warnings, err := s.Provider.Configure(config) err := s.Provider.Configure(config)
*reply = ResourceProviderConfigureResponse{ *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 return nil
} }

View File

@ -19,16 +19,13 @@ func TestResourceProvider_configure(t *testing.T) {
// Configure // Configure
config := map[string]interface{}{"foo": "bar"} config := map[string]interface{}{"foo": "bar"}
w, e := provider.Configure(config) e := provider.Configure(config)
if !p.ConfigureCalled { if !p.ConfigureCalled {
t.Fatal("configure should be called") t.Fatal("configure should be called")
} }
if !reflect.DeepEqual(p.ConfigureConfig, config) { if !reflect.DeepEqual(p.ConfigureConfig, config) {
t.Fatalf("bad: %#v", p.ConfigureConfig) t.Fatalf("bad: %#v", p.ConfigureConfig)
} }
if w != nil {
t.Fatalf("bad: %#v", w)
}
if e != nil { if e != nil {
t.Fatalf("bad: %#v", e) t.Fatalf("bad: %#v", e)
} }
@ -47,16 +44,13 @@ func TestResourceProvider_configure_errors(t *testing.T) {
// Configure // Configure
config := map[string]interface{}{"foo": "bar"} config := map[string]interface{}{"foo": "bar"}
w, e := provider.Configure(config) e := provider.Configure(config)
if !p.ConfigureCalled { if !p.ConfigureCalled {
t.Fatal("configure should be called") t.Fatal("configure should be called")
} }
if !reflect.DeepEqual(p.ConfigureConfig, config) { if !reflect.DeepEqual(p.ConfigureConfig, config) {
t.Fatalf("bad: %#v", p.ConfigureConfig) t.Fatalf("bad: %#v", p.ConfigureConfig)
} }
if w != nil {
t.Fatalf("bad: %#v", w)
}
if e == nil { if e == nil {
t.Fatal("should have error") t.Fatal("should have error")
} }
@ -74,28 +68,85 @@ func TestResourceProvider_configure_warnings(t *testing.T) {
} }
provider := &ResourceProvider{Client: client, Name: name} provider := &ResourceProvider{Client: client, Name: name}
p.ConfigureReturnWarnings = []string{"foo", "bar"}
// Configure // Configure
config := map[string]interface{}{"foo": "bar"} config := map[string]interface{}{"foo": "bar"}
w, e := provider.Configure(config) e := provider.Configure(config)
if !p.ConfigureCalled { if !p.ConfigureCalled {
t.Fatal("configure should be called") t.Fatal("configure should be called")
} }
if !reflect.DeepEqual(p.ConfigureConfig, config) { if !reflect.DeepEqual(p.ConfigureConfig, config) {
t.Fatalf("bad: %#v", p.ConfigureConfig) 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 { if e != nil {
t.Fatalf("bad: %#v", e) 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) { func TestResourceProvider_resources(t *testing.T) {
p := new(terraform.MockResourceProvider) p := new(terraform.MockResourceProvider)
client, server := testClientServer(t) client, server := testClientServer(t)

View File

@ -30,7 +30,7 @@ type ResourceProvider interface {
// a diff. // a diff.
Diff( Diff(
*ResourceState, *ResourceState,
map[string]interface{}) (ResourceDiff, error) map[string]interface{}) (*ResourceDiff, error)
} }
// ResourceType is a type of resource that a resource provider can manage. // ResourceType is a type of resource that a resource provider can manage.

View File

@ -12,8 +12,8 @@ type MockResourceProvider struct {
DiffCalled bool DiffCalled bool
DiffState *ResourceState DiffState *ResourceState
DiffDesired map[string]interface{} DiffDesired map[string]interface{}
DiffFn func(*ResourceState, map[string]interface{}) (ResourceDiff, error) DiffFn func(*ResourceState, map[string]interface{}) (*ResourceDiff, error)
DiffReturn ResourceDiff DiffReturn *ResourceDiff
DiffReturnError error DiffReturnError error
ResourcesCalled bool ResourcesCalled bool
ResourcesReturn []ResourceType ResourcesReturn []ResourceType
@ -27,7 +27,7 @@ func (p *MockResourceProvider) Configure(c map[string]interface{}) error {
func (p *MockResourceProvider) Diff( func (p *MockResourceProvider) Diff(
state *ResourceState, state *ResourceState,
desired map[string]interface{}) (ResourceDiff, error) { desired map[string]interface{}) (*ResourceDiff, error) {
p.DiffCalled = true p.DiffCalled = true
p.DiffState = state p.DiffState = state
p.DiffDesired = desired p.DiffDesired = desired

View File

@ -261,7 +261,7 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
return func() (ResourceProvider, error) { return func() (ResourceProvider, error) {
diffFn := func( diffFn := func(
_ *ResourceState, _ *ResourceState,
c map[string]interface{}) (ResourceDiff, error) { c map[string]interface{}) (*ResourceDiff, error) {
var diff ResourceDiff var diff ResourceDiff
diff.Attributes = make(map[string]*ResourceAttrDiff) diff.Attributes = make(map[string]*ResourceAttrDiff)
for k, v := range c { for k, v := range c {
@ -290,7 +290,7 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory {
diff.Attributes[k] = attrDiff diff.Attributes[k] = attrDiff
} }
return diff, nil return &diff, nil
} }
result := &MockResourceProvider{ result := &MockResourceProvider{