From 3b04b41250ee8b1f4e93ecbe15bb6b04c5b8f2b5 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 25 Jan 2019 18:29:28 -0500 Subject: [PATCH] fix RequiresNew in diff With the new diff.Apply we can keep the diff mostly intact, but we need turn off all RequiresNew flags so that the prior state is not removed from the apply. --- builtin/providers/test/resource_list_test.go | 21 +++++++++++++++++ helper/plugin/grpc_provider.go | 24 ++++++++++++++------ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/builtin/providers/test/resource_list_test.go b/builtin/providers/test/resource_list_test.go index 4d78f3547..76c82f15a 100644 --- a/builtin/providers/test/resource_list_test.go +++ b/builtin/providers/test/resource_list_test.go @@ -15,6 +15,27 @@ func TestResourceList_changed(t *testing.T) { Steps: []resource.TestStep{ resource.TestStep{ Config: strings.TrimSpace(` +resource "test_resource_list" "foo" { + list_block { + string = "a" + int = 1 + } +} + `), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "test_resource_list.foo", "list_block.#", "1", + ), + resource.TestCheckResourceAttr( + "test_resource_list.foo", "list_block.0.string", "a", + ), + resource.TestCheckResourceAttr( + "test_resource_list.foo", "list_block.0.int", "1", + ), + ), + }, + resource.TestStep{ + Config: strings.TrimSpace(` resource "test_resource_list" "foo" { list_block { string = "a" diff --git a/helper/plugin/grpc_provider.go b/helper/plugin/grpc_provider.go index 2f85c0fd8..b3b5d1af5 100644 --- a/helper/plugin/grpc_provider.go +++ b/helper/plugin/grpc_provider.go @@ -713,17 +713,27 @@ func (s *GRPCProviderServer) ApplyResourceChange(_ context.Context, req *proto.A } } - // strip out non-diffs - for k, v := range diff.Attributes { - if v.New == v.Old && !v.NewComputed && v.NewExtra == "" { - delete(diff.Attributes, k) - } - } - if private != nil { diff.Meta = private } + // We need to turn off any RequiresNew. There could be attributes + // without changes in here inserted by helper/schema, but if they have + // RequiresNew then the state will will be dropped from the ResourceData. + for k := range diff.Attributes { + diff.Attributes[k].RequiresNew = false + } + + // check that any "removed" attributes actually exist in the prior state, or + // helper/schema will confuse itself + for k, d := range diff.Attributes { + if d.NewRemoved { + if _, ok := priorState.Attributes[k]; !ok { + delete(diff.Attributes, k) + } + } + } + newInstanceState, err := s.provider.Apply(info, priorState, diff) if err != nil { resp.Diagnostics = convert.AppendProtoDiag(resp.Diagnostics, err)