From 47604c36c8e3a31dac7c3e7756e7834b0ce49ec5 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 27 Feb 2019 12:19:25 -0500 Subject: [PATCH] remove the partially-known ~ set sigil in diffs The NewExtra values are stored outside the diff from plan, and the original keys may not contain the ~ prefix. Adding the NewExtra back into the diff with the mismatched key was causing an entire new set element to be populated. Since this symbol isn't used to apply the diff in helper/schema, we can simply strip them out. --- .../providers/test/resource_computed_set.go | 40 +++++++++++++++++++ .../test/resource_computed_set_test.go | 19 +++++++++ helper/plugin/grpc_provider.go | 11 +++++ 3 files changed, 70 insertions(+) diff --git a/builtin/providers/test/resource_computed_set.go b/builtin/providers/test/resource_computed_set.go index 5adf1bd99..09b49d420 100644 --- a/builtin/providers/test/resource_computed_set.go +++ b/builtin/providers/test/resource_computed_set.go @@ -1,9 +1,12 @@ package test import ( + "bytes" "fmt" "math/rand" + "strings" + "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" ) @@ -39,10 +42,47 @@ func testResourceComputedSet() *schema.Resource { }, Set: schema.HashString, }, + + "rule": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "ip_protocol": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + + "cidr": { + Type: schema.TypeString, + Optional: true, + ForceNew: false, + StateFunc: func(v interface{}) string { + return strings.ToLower(v.(string)) + }, + }, + }, + }, + }, }, } } +func computeSecGroupV2RuleHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["ip_protocol"].(string))) + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["cidr"].(string)))) + + return hashcode.String(buf.String()) +} + func testResourceComputedSetCreate(d *schema.ResourceData, meta interface{}) error { d.SetId(fmt.Sprintf("%x", rand.Int63())) return testResourceComputedSetRead(d, meta) diff --git a/builtin/providers/test/resource_computed_set_test.go b/builtin/providers/test/resource_computed_set_test.go index 806795c1d..06e608235 100644 --- a/builtin/providers/test/resource_computed_set_test.go +++ b/builtin/providers/test/resource_computed_set_test.go @@ -50,3 +50,22 @@ resource "test_resource_computed_set" "foo" { }, }) } + +func TestResourceComputedSet_ruleTest(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckResourceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: strings.TrimSpace(` +resource "test_resource_computed_set" "foo" { + rule { + ip_protocol = "udp" + cidr = "0.0.0.0/0" + } +} + `), + }, + }, + }) +} diff --git a/helper/plugin/grpc_provider.go b/helper/plugin/grpc_provider.go index b1b4b5d3d..21069080d 100644 --- a/helper/plugin/grpc_provider.go +++ b/helper/plugin/grpc_provider.go @@ -747,6 +747,17 @@ func (s *GRPCProviderServer) ApplyResourceChange(_ context.Context, req *proto.A } } + // We need to fix any sets that may be using the "~" index prefix to + // indicate partially computed. The special sigil isn't really used except + // as a clue to visually indicate that the set isn't wholly known. + for k, d := range diff.Attributes { + if strings.Contains(k, ".~") { + delete(diff.Attributes, k) + k = strings.Replace(k, ".~", ".", -1) + diff.Attributes[k] = d + } + } + // add NewExtra Fields that may have been stored in the private data if newExtra := private[newExtraKey]; newExtra != nil { for k, v := range newExtra.(map[string]interface{}) {