diff --git a/helper/schema/provider.go b/helper/schema/provider.go index f418aab09992..1ac6b77fe906 100644 --- a/helper/schema/provider.go +++ b/helper/schema/provider.go @@ -237,6 +237,19 @@ func (p *Provider) ReadData( return r.ReadData(c, p.meta) } +// ReadDataDiff implementation of terraform.ResourceProvider interface. +func (p *Provider) ReadDataDiff( + info *terraform.InstanceInfo, + c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { + + r, ok := p.DataSourcesMap[info.Type] + if !ok { + return nil, fmt.Errorf("unknown data source: %s", info.Type) + } + + return r.Diff(nil, c) +} + // DataSources implementation of terraform.ResourceProvider interface. func (p *Provider) DataSources() []terraform.DataSource { keys := make([]string, 0, len(p.DataSourcesMap)) diff --git a/plugin/resource_provider.go b/plugin/resource_provider.go index 0c6ce009c1ef..5d82fdf16ebf 100644 --- a/plugin/resource_provider.go +++ b/plugin/resource_provider.go @@ -232,6 +232,26 @@ func (p *ResourceProvider) ReadData( return resp.State, err } +func (p *ResourceProvider) ReadDataDiff( + info *terraform.InstanceInfo, + c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { + var resp ResourceProviderReadDataDiffResponse + args := &ResourceProviderReadDataDiffArgs{ + Info: info, + Config: c, + } + + err := p.Client.Call("Plugin.ReadDataDiff", args, &resp) + if err != nil { + return nil, err + } + if resp.Error != nil { + err = resp.Error + } + + return resp.Diff, err +} + func (p *ResourceProvider) DataSources() []terraform.DataSource { var result []terraform.DataSource @@ -311,6 +331,16 @@ type ResourceProviderReadDataResponse struct { Error *plugin.BasicError } +type ResourceProviderReadDataDiffArgs struct { + Info *terraform.InstanceInfo + Config *terraform.ResourceConfig +} + +type ResourceProviderReadDataDiffResponse struct { + Diff *terraform.InstanceDiff + Error *plugin.BasicError +} + type ResourceProviderValidateArgs struct { Config *terraform.ResourceConfig } @@ -460,6 +490,17 @@ func (s *ResourceProviderServer) ReadData( return nil } +func (s *ResourceProviderServer) ReadDataDiff( + args *ResourceProviderReadDataDiffArgs, + result *ResourceProviderReadDataDiffResponse) error { + diff, err := s.Provider.ReadDataDiff(args.Info, args.Config) + *result = ResourceProviderReadDataDiffResponse{ + Diff: diff, + Error: plugin.NewBasicError(err), + } + return nil +} + func (s *ResourceProviderServer) DataSources( nothing interface{}, result *[]terraform.DataSource) error { diff --git a/terraform/resource_provider.go b/terraform/resource_provider.go index ab44b9f9b98c..54598944ba87 100644 --- a/terraform/resource_provider.go +++ b/terraform/resource_provider.go @@ -89,6 +89,14 @@ type ResourceProvider interface { // ReadData initializes a data instance, which will be of one of the // types returned by DataSources. ReadData(*InstanceInfo, *ResourceConfig) (*InstanceState, error) + + // ReadDataDiff produces a diff that describes the result of a future + // ReadData as if it were the creation of the data resource. + // This is called when ReadData itself cannot yet be called due to + // computed interpolations within the configuration, and tells Terraform + // which attributes will become available once the data source is read, + // thus allowing dependent resources to be verified. + ReadDataDiff(*InstanceInfo, *ResourceConfig) (*InstanceDiff, error) } // ResourceProviderCloser is an interface that providers that can close diff --git a/terraform/resource_provider_mock.go b/terraform/resource_provider_mock.go index f282fd4d29ce..390de0dbcca9 100644 --- a/terraform/resource_provider_mock.go +++ b/terraform/resource_provider_mock.go @@ -50,6 +50,12 @@ type MockResourceProvider struct { ReadDataFn func(*InstanceInfo, *ResourceConfig) (*InstanceState, error) ReadDataReturn *InstanceState ReadDataReturnError error + ReadDataDiffCalled bool + ReadDataDiffInfo *InstanceInfo + ReadDataDiffDesired *ResourceConfig + ReadDataDiffFn func(*InstanceInfo, *ResourceConfig) (*InstanceDiff, error) + ReadDataDiffReturn *InstanceDiff + ReadDataDiffReturnError error DataSourcesCalled bool DataSourcesReturn []DataSource ValidateCalled bool @@ -222,6 +228,22 @@ func (p *MockResourceProvider) ReadData( return p.ReadDataReturn, p.ReadDataReturnError } +func (p *MockResourceProvider) ReadDataDiff( + info *InstanceInfo, + desired *ResourceConfig) (*InstanceDiff, error) { + p.Lock() + defer p.Unlock() + + p.ReadDataDiffCalled = true + p.ReadDataDiffInfo = info + p.ReadDataDiffDesired = desired + if p.ReadDataDiffFn != nil { + return p.ReadDataDiffFn(info, desired) + } + + return p.ReadDataDiffReturn, p.ReadDataDiffReturnError +} + func (p *MockResourceProvider) DataSources() []DataSource { p.Lock() defer p.Unlock()