diff --git a/helper/schema/schema.go b/helper/schema/schema.go index ed8b0ac94..94ba865a5 100644 --- a/helper/schema/schema.go +++ b/helper/schema/schema.go @@ -17,7 +17,6 @@ import ( "reflect" "sort" "strconv" - "strings" "github.com/hashicorp/terraform/terraform" "github.com/mitchellh/mapstructure" @@ -812,12 +811,18 @@ func (m schemaMap) diffSet( } for _, code := range ns.listCode() { + // If the code is negative (first character is -) then + // replace it with "~" for our computed set stuff. + codeStr := strconv.Itoa(code) + if codeStr[0] == '-' { + codeStr = string('~') + codeStr[1:] + } + switch t := schema.Elem.(type) { case *Resource: // This is a complex resource for k2, schema := range t.Schema { - subK := fmt.Sprintf("%s.%d.%s", k, code, k2) - subK = strings.Replace(subK, "-", "~", -1) + subK := fmt.Sprintf("%s.%s.%s", k, codeStr, k2) err := m.diff(subK, schema, diff, d, true) if err != nil { return err @@ -831,8 +836,7 @@ func (m schemaMap) diffSet( // This is just a primitive element, so go through each and // just diff each. - subK := fmt.Sprintf("%s.%d", k, code) - subK = strings.Replace(subK, "-", "~", -1) + subK := fmt.Sprintf("%s.%s", k, codeStr) err := m.diff(subK, &t2, diff, d, true) if err != nil { return err diff --git a/helper/schema/schema_test.go b/helper/schema/schema_test.go index 52980ad80..7ec4e5dbb 100644 --- a/helper/schema/schema_test.go +++ b/helper/schema/schema_test.go @@ -2224,6 +2224,63 @@ func TestSchemaMap_Diff(t *testing.T) { Err: false, }, + + // #58 Set with hyphen keys + { + Schema: map[string]*Schema{ + "route": &Schema{ + Type: TypeSet, + Optional: true, + Elem: &Resource{ + Schema: map[string]*Schema{ + "index": &Schema{ + Type: TypeInt, + Required: true, + }, + + "gateway-name": &Schema{ + Type: TypeString, + Optional: true, + }, + }, + }, + Set: func(v interface{}) int { + m := v.(map[string]interface{}) + return m["index"].(int) + }, + }, + }, + + State: nil, + + Config: map[string]interface{}{ + "route": []map[string]interface{}{ + map[string]interface{}{ + "index": "1", + "gateway-name": "hello", + }, + }, + }, + + Diff: &terraform.InstanceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "route.#": &terraform.ResourceAttrDiff{ + Old: "0", + New: "1", + }, + "route.1.index": &terraform.ResourceAttrDiff{ + Old: "", + New: "1", + }, + "route.1.gateway-name": &terraform.ResourceAttrDiff{ + Old: "", + New: "hello", + }, + }, + }, + + Err: false, + }, } for i, tc := range cases { diff --git a/helper/schema/set.go b/helper/schema/set.go index 965ad6f8b..a10c2b8d9 100644 --- a/helper/schema/set.go +++ b/helper/schema/set.go @@ -123,6 +123,9 @@ func (s *Set) add(item interface{}) int { s.once.Do(s.init) code := s.F(item) + if code < 0 { + code *= -1 + } if _, ok := s.m[code]; !ok { s.m[code] = item } diff --git a/helper/schema/set_test.go b/helper/schema/set_test.go index 8ae4be479..9688c5f71 100644 --- a/helper/schema/set_test.go +++ b/helper/schema/set_test.go @@ -18,6 +18,20 @@ func TestSetAdd(t *testing.T) { } } +func TestSetAdd_negative(t *testing.T) { + // Since we don't allow negative hashes, this should just hash to the + // same thing... + s := &Set{F: testSetInt} + s.Add(-1) + s.Add(1) + + expected := []interface{}{-1} + actual := s.List() + if !reflect.DeepEqual(actual, expected) { + t.Fatalf("bad: %#v", actual) + } +} + func TestSetContains(t *testing.T) { s := &Set{F: testSetInt} s.Add(5)