diff --git a/rpc/resource_provider.go b/rpc/resource_provider.go index c7e19237c..dcd51eb85 100644 --- a/rpc/resource_provider.go +++ b/rpc/resource_provider.go @@ -13,6 +13,24 @@ type ResourceProvider struct { Name string } +func (p *ResourceProvider) Validate(c *terraform.ResourceConfig) ([]string, []error) { + var resp ResourceProviderValidateResponse + err := p.Client.Call(p.Name+".Validate", c, &resp) + if err != nil { + return nil, []error{err} + } + + var errs []error + if len(resp.Errors) > 0 { + errs = make([]error, len(resp.Errors)) + for i, err := range resp.Errors { + errs[i] = err + } + } + + return resp.Warnings, errs +} + func (p *ResourceProvider) Configure(c *terraform.ResourceConfig) error { var resp ResourceProviderConfigureResponse err := p.Client.Call(p.Name+".Configure", c, &resp) @@ -77,6 +95,26 @@ type ResourceProviderDiffResponse struct { Error *BasicError } +type ResourceProviderValidateResponse struct { + Warnings []string + Errors []*BasicError +} + +func (s *ResourceProviderServer) Validate( + config *terraform.ResourceConfig, + reply *ResourceProviderValidateResponse) error { + warns, errs := s.Provider.Validate(config) + berrs := make([]*BasicError, len(errs)) + for i, err := range errs { + berrs[i] = NewBasicError(err) + } + *reply = ResourceProviderValidateResponse{ + Warnings: warns, + Errors: berrs, + } + return nil +} + func (s *ResourceProviderServer) Configure( config *terraform.ResourceConfig, reply *ResourceProviderConfigureResponse) error { diff --git a/rpc/resource_provider_test.go b/rpc/resource_provider_test.go index 7d25ac807..8866efe30 100644 --- a/rpc/resource_provider_test.go +++ b/rpc/resource_provider_test.go @@ -8,6 +8,10 @@ import ( "github.com/hashicorp/terraform/terraform" ) +func TestResourceProvider_impl(t *testing.T) { + var _ terraform.ResourceProvider = new(ResourceProvider) +} + func TestResourceProvider_configure(t *testing.T) { p := new(terraform.MockResourceProvider) client, server := testClientServer(t) @@ -182,3 +186,97 @@ func TestResourceProvider_resources(t *testing.T) { t.Fatalf("bad: %#v", result) } } + +func TestResourceProvider_validate(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} + + // Configure + config := &terraform.ResourceConfig{ + Raw: map[string]interface{}{"foo": "bar"}, + } + w, e := provider.Validate(config) + if !p.ValidateCalled { + t.Fatal("configure should be called") + } + if !reflect.DeepEqual(p.ValidateConfig, config) { + t.Fatalf("bad: %#v", p.ValidateConfig) + } + if w != nil { + t.Fatalf("bad: %#v", w) + } + if e != nil { + t.Fatalf("bad: %#v", e) + } +} + +func TestResourceProvider_validate_errors(t *testing.T) { + p := new(terraform.MockResourceProvider) + p.ValidateReturnErrors = []error{errors.New("foo")} + + client, server := testClientServer(t) + name, err := Register(server, p) + if err != nil { + t.Fatalf("err: %s", err) + } + provider := &ResourceProvider{Client: client, Name: name} + + // Configure + config := &terraform.ResourceConfig{ + Raw: map[string]interface{}{"foo": "bar"}, + } + w, e := provider.Validate(config) + if !p.ValidateCalled { + t.Fatal("configure should be called") + } + if !reflect.DeepEqual(p.ValidateConfig, config) { + t.Fatalf("bad: %#v", p.ValidateConfig) + } + if w != nil { + t.Fatalf("bad: %#v", w) + } + + if len(e) != 1 { + t.Fatalf("bad: %#v", e) + } + if e[0].Error() != "foo" { + t.Fatalf("bad: %#v", e) + } +} + +func TestResourceProvider_validate_warns(t *testing.T) { + p := new(terraform.MockResourceProvider) + p.ValidateReturnWarns = []string{"foo"} + + client, server := testClientServer(t) + name, err := Register(server, p) + if err != nil { + t.Fatalf("err: %s", err) + } + provider := &ResourceProvider{Client: client, Name: name} + + // Configure + config := &terraform.ResourceConfig{ + Raw: map[string]interface{}{"foo": "bar"}, + } + w, e := provider.Validate(config) + if !p.ValidateCalled { + t.Fatal("configure should be called") + } + if !reflect.DeepEqual(p.ValidateConfig, config) { + t.Fatalf("bad: %#v", p.ValidateConfig) + } + if e != nil { + t.Fatalf("bad: %#v", e) + } + + expected := []string{"foo"} + if !reflect.DeepEqual(w, expected) { + t.Fatalf("bad: %#v", w) + } +}