From 9ab5577beb6b44f73346635b1d54ec6a75618428 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 20 Aug 2014 21:02:42 -0700 Subject: [PATCH] helper/schema: set diff tests --- helper/schema/resource_data.go | 23 +++++++--- helper/schema/schema.go | 18 ++++++-- helper/schema/schema_test.go | 82 ++++++++++++++++++++++++++++++++++ helper/schema/set.go | 15 +++++++ helper/schema/set_test.go | 12 +++++ 5 files changed, 141 insertions(+), 9 deletions(-) diff --git a/helper/schema/resource_data.go b/helper/schema/resource_data.go index 4b9217305..ccb1183f9 100644 --- a/helper/schema/resource_data.go +++ b/helper/schema/resource_data.go @@ -153,13 +153,14 @@ func (d *ResourceData) getChange( key string, oldLevel getSource, newLevel getSource) (interface{}, interface{}) { - var parts []string + var parts, parts2 []string if key != "" { parts = strings.Split(key, ".") + parts2 = strings.Split(key, ".") } o := d.getObject("", parts, d.schema, oldLevel) - n := d.getObject("", parts, d.schema, newLevel) + n := d.getObject("", parts2, d.schema, newLevel) return o, n } @@ -191,14 +192,23 @@ func (d *ResourceData) getSet( parts []string, schema *Schema, source getSource) interface{} { + s := &Set{F: schema.Set} raw := d.getList(k, nil, schema, source) if raw == nil { - return nil + if len(parts) > 0 { + return d.getList(k, parts, schema, source) + } + + return s } list := raw.([]interface{}) if len(list) == 0 { - return nil + if len(parts) > 0 { + return d.getList(k, parts, schema, source) + } + + return s } // This is a reverse map of hash code => index in config used to @@ -219,7 +229,6 @@ func (d *ResourceData) getSet( } // Build the set from all the items using the given hash code - s := &Set{F: schema.Set} for i, v := range list { code := s.add(v) if indexMap != nil { @@ -413,11 +422,13 @@ func (d *ResourceData) getPrimitive( if err := mapstructure.WeakDecode(v, &result); err != nil { panic(err) } + + resultSet = true } else { result = "" + resultSet = false } - resultSet = true } if d.diff != nil && source >= getSourceDiff { diff --git a/helper/schema/schema.go b/helper/schema/schema.go index cff662164..69c12759c 100644 --- a/helper/schema/schema.go +++ b/helper/schema/schema.go @@ -238,6 +238,12 @@ func (m schemaMap) diffList( diff *terraform.ResourceDiff, d *ResourceData) error { o, n, _ := d.diffChange(k) + if s, ok := o.(*Set); ok { + o = s.List() + } + if s, ok := n.(*Set); ok { + n = s.List() + } os := o.([]interface{}) vs := n.([]interface{}) @@ -355,7 +361,7 @@ func (m schemaMap) diffSet( schema *Schema, diff *terraform.ResourceDiff, d *ResourceData) error { - return nil + return m.diffList(k, schema, diff, d) } func (m schemaMap) diffString( @@ -380,9 +386,15 @@ func (m schemaMap) diffString( } } + removed := false + if o != nil && n == nil { + removed = true + } + diff.Attributes[k] = schema.finalizeDiff(&terraform.ResourceAttrDiff{ - Old: os, - New: ns, + Old: os, + New: ns, + NewRemoved: removed, }) return nil diff --git a/helper/schema/schema_test.go b/helper/schema/schema_test.go index 70ef1ddb4..36ca3bb54 100644 --- a/helper/schema/schema_test.go +++ b/helper/schema/schema_test.go @@ -365,6 +365,88 @@ func TestSchemaMap_Diff(t *testing.T) { Err: false, }, + { + Schema: map[string]*Schema{ + "ports": &Schema{ + Type: TypeSet, + Required: true, + Elem: &Schema{Type: TypeInt}, + Set: func(a interface{}) int { + return a.(int) + }, + }, + }, + + State: &terraform.ResourceState{ + Attributes: map[string]string{ + "ports.#": "2", + "ports.0": "2", + "ports.1": "1", + }, + }, + + Config: map[string]interface{}{ + "ports": []interface{}{5, 2, 1}, + }, + + Diff: &terraform.ResourceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "ports.#": &terraform.ResourceAttrDiff{ + Old: "2", + New: "3", + }, + "ports.2": &terraform.ResourceAttrDiff{ + Old: "", + New: "5", + }, + }, + }, + + Err: false, + }, + + { + Schema: map[string]*Schema{ + "ports": &Schema{ + Type: TypeSet, + Required: true, + Elem: &Schema{Type: TypeInt}, + Set: func(a interface{}) int { + return a.(int) + }, + }, + }, + + State: &terraform.ResourceState{ + Attributes: map[string]string{ + "ports.#": "2", + "ports.0": "2", + "ports.1": "1", + }, + }, + + Config: map[string]interface{}{}, + + Diff: &terraform.ResourceDiff{ + Attributes: map[string]*terraform.ResourceAttrDiff{ + "ports.#": &terraform.ResourceAttrDiff{ + Old: "2", + New: "0", + }, + "ports.0": &terraform.ResourceAttrDiff{ + Old: "1", + NewRemoved: true, + }, + "ports.1": &terraform.ResourceAttrDiff{ + Old: "2", + NewRemoved: true, + }, + }, + }, + + Err: false, + }, + /* * List of structure decode */ diff --git a/helper/schema/set.go b/helper/schema/set.go index 73b6da8a3..21e329f22 100644 --- a/helper/schema/set.go +++ b/helper/schema/set.go @@ -19,6 +19,17 @@ func (s *Set) Add(item interface{}) { s.add(item) } +// Contains checks if the set has the given item. +func (s *Set) Contains(item interface{}) bool { + _, ok := s.m[s.F(item)] + return ok +} + +// Len returns the amount of items in the set. +func (s *Set) Len() int { + return len(s.m) +} + // List returns the elements of this set in slice format. // // The order of the returned elements is deterministic. Given the same @@ -93,6 +104,10 @@ func (s *Set) add(item interface{}) int { return code } +func (s *Set) index(item interface{}) int { + return sort.SearchInts(s.listCode(), s.F(item)) +} + func (s *Set) listCode() []int { // Sort the hash codes so the order of the list is deterministic keys := make([]int, 0, len(s.m)) diff --git a/helper/schema/set_test.go b/helper/schema/set_test.go index 88b1ebbfe..7a5778af4 100644 --- a/helper/schema/set_test.go +++ b/helper/schema/set_test.go @@ -18,6 +18,18 @@ func TestSetAdd(t *testing.T) { } } +func TestSetContains(t *testing.T) { + s := &Set{F: testSetInt} + s.Add(5) + + if s.Contains(2) { + t.Fatal("should not contain") + } + if !s.Contains(5) { + t.Fatal("should contain") + } +} + func TestSetDifference(t *testing.T) { s1 := &Set{F: testSetInt} s2:= &Set{F: testSetInt}