diff --git a/terraform/resource_provider.go b/terraform/resource_provider.go index b435142b1..d60e15109 100644 --- a/terraform/resource_provider.go +++ b/terraform/resource_provider.go @@ -46,6 +46,10 @@ type ResourceProvider interface { Diff( *ResourceState, *ResourceConfig) (*ResourceDiff, error) + + // Refresh refreshes a resource and updates all of its attributes + // with the latest information. + Refresh(*ResourceState) (*ResourceState, error) } // ResourceConfig holds the configuration given for a resource. This is diff --git a/terraform/resource_provider_mock.go b/terraform/resource_provider_mock.go index 1e4174cc3..9532b4efb 100644 --- a/terraform/resource_provider_mock.go +++ b/terraform/resource_provider_mock.go @@ -21,6 +21,11 @@ type MockResourceProvider struct { DiffFn func(*ResourceState, *ResourceConfig) (*ResourceDiff, error) DiffReturn *ResourceDiff DiffReturnError error + RefreshCalled bool + RefreshState *ResourceState + RefreshFn func(*ResourceState) (*ResourceState, error) + RefreshReturn *ResourceState + RefreshReturnError error ResourcesCalled bool ResourcesReturn []ResourceType ValidateCalled bool @@ -67,6 +72,18 @@ func (p *MockResourceProvider) Diff( return p.DiffReturn, p.DiffReturnError } +func (p *MockResourceProvider) Refresh( + s *ResourceState) (*ResourceState, error) { + p.RefreshCalled = true + p.RefreshState = s + + if p.RefreshFn != nil { + return p.RefreshFn(s) + } + + return p.RefreshReturn, p.RefreshReturnError +} + func (p *MockResourceProvider) Resources() []ResourceType { p.ResourcesCalled = true return p.ResourcesReturn diff --git a/terraform/terraform.go b/terraform/terraform.go index 669c52c43..e9546c7d2 100644 --- a/terraform/terraform.go +++ b/terraform/terraform.go @@ -173,7 +173,14 @@ func (t *Terraform) diffWalkFn( result.init() cb := func(r *Resource) (map[string]string, error) { - diff, err := r.Provider.Diff(r.State, r.Config) + // Refresh the state so we're working with the latest resource info + newState, err := r.Provider.Refresh(r.State) + if err != nil { + return nil, err + } + + // Get a diff from the newest state + diff, err := r.Provider.Diff(newState, r.Config) if err != nil { return nil, err } diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index 743736faf..fdc1b80ff 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -245,6 +245,14 @@ func TestTerraformDiff(t *testing.T) { if actual != expected { t.Fatalf("bad:\n%s", actual) } + + p := testProviderMock(testProvider(tf, "aws_instance.foo")) + if !p.RefreshCalled { + t.Fatal("refresh should be called") + } + if p.RefreshState == nil { + t.Fatal("refresh should have state") + } } func TestTerraformDiff_nil(t *testing.T) { @@ -383,10 +391,15 @@ func testProviderFunc(n string, rs []string) ResourceProviderFactory { return &diff, nil } + refreshFn := func(s *ResourceState) (*ResourceState, error) { + return s, nil + } + result := &MockResourceProvider{ Meta: n, ApplyFn: applyFn, DiffFn: diffFn, + RefreshFn: refreshFn, ResourcesReturn: resources, }