Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Diff with set going to 0 elements removes it from state #986

Merged
merged 1 commit into from
Feb 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions helper/schema/field_reader_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,12 @@ func (r *DiffFieldReader) readPrimitive(

func (r *DiffFieldReader) readSet(
address []string, schema *Schema) (FieldReadResult, error) {
prefix := strings.Join(address, ".") + "."

// Create the set that will be our result
set := &Set{F: schema.Set}

// Go through the map and find all the set items
prefix := strings.Join(address, ".") + "."
for k, _ := range r.Diff.Attributes {
if !strings.HasPrefix(k, prefix) {
continue
Expand All @@ -174,8 +175,21 @@ func (r *DiffFieldReader) readSet(
set.Add(raw.Value)
}

// Determine if the set "exists". It exists if there are items or if
// the diff explicitly wanted it empty.
exists := set.Len() > 0
if !exists {
// We could check if the diff value is "0" here but I think the
// existence of "#" on its own is enough to show it existed. This
// protects us in the future from the zero value changing from
// "0" to "" breaking us (if that were to happen).
if _, ok := r.Diff.Attributes[prefix+"#"]; ok {
exists = true
}
}

return FieldReadResult{
Value: set,
Exists: set.Len() > 0,
Exists: exists,
}, nil
}
42 changes: 42 additions & 0 deletions helper/schema/field_reader_diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,28 @@ func TestDiffFieldReader_extra(t *testing.T) {
return m["index"].(int)
},
},

"setEmpty": &Schema{
Type: TypeSet,
Optional: true,
Elem: &Resource{
Schema: map[string]*Schema{
"index": &Schema{
Type: TypeInt,
Required: true,
},

"value": &Schema{
Type: TypeString,
Required: true,
},
},
},
Set: func(a interface{}) int {
m := a.(map[string]interface{})
return m["index"].(int)
},
},
}

r := &DiffFieldReader{
Expand All @@ -114,6 +136,11 @@ func TestDiffFieldReader_extra(t *testing.T) {
Old: "50",
New: "80",
},

"setEmpty.#": &terraform.ResourceAttrDiff{
Old: "2",
New: "0",
},
},
},

Expand All @@ -131,6 +158,12 @@ func TestDiffFieldReader_extra(t *testing.T) {
"setChange.#": "1",
"setChange.10.index": "10",
"setChange.10.value": "50",

"setEmpty.#": "2",
"setEmpty.10.index": "10",
"setEmpty.10.value": "50",
"setEmpty.20.index": "20",
"setEmpty.20.value": "50",
}),
},
}
Expand Down Expand Up @@ -191,6 +224,15 @@ func TestDiffFieldReader_extra(t *testing.T) {
},
false,
},

"setEmpty": {
[]string{"setEmpty"},
FieldReadResult{
Value: []interface{}{},
Exists: true,
},
false,
},
}

for name, tc := range cases {
Expand Down
36 changes: 36 additions & 0 deletions helper/schema/getsource_string.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// generated by stringer -type=getSource resource_data_get_source.go; DO NOT EDIT

package schema

import "fmt"

const (
_getSource_name_0 = "getSourceStategetSourceConfig"
_getSource_name_1 = "getSourceDiff"
_getSource_name_2 = "getSourceSet"
_getSource_name_3 = "getSourceLevelMaskgetSourceExact"
)

var (
_getSource_index_0 = [...]uint8{0, 14, 29}
_getSource_index_1 = [...]uint8{0, 13}
_getSource_index_2 = [...]uint8{0, 12}
_getSource_index_3 = [...]uint8{0, 18, 32}
)

func (i getSource) String() string {
switch {
case 1 <= i && i <= 2:
i -= 1
return _getSource_name_0[_getSource_index_0[i]:_getSource_index_0[i+1]]
case i == 4:
return _getSource_name_1
case i == 8:
return _getSource_name_2
case 15 <= i && i <= 16:
i -= 15
return _getSource_name_3[_getSource_index_3[i]:_getSource_index_3[i+1]]
default:
return fmt.Sprintf("getSource(%d)", i)
}
}
14 changes: 0 additions & 14 deletions helper/schema/resource_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,6 @@ type ResourceData struct {
once sync.Once
}

// getSource represents the level we want to get for a value (internally).
// Any source less than or equal to the level will be loaded (whichever
// has a value first).
type getSource byte

const (
getSourceState getSource = 1 << iota
getSourceConfig
getSourceDiff
getSourceSet
getSourceExact // Only get from the _exact_ level
getSourceLevelMask getSource = getSourceState | getSourceConfig | getSourceDiff | getSourceSet
)

// getResult is the internal structure that is generated when a Get
// is called that contains some extra data that might be used.
type getResult struct {
Expand Down
17 changes: 17 additions & 0 deletions helper/schema/resource_data_get_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package schema

//go:generate stringer -type=getSource resource_data_get_source.go

// getSource represents the level we want to get for a value (internally).
// Any source less than or equal to the level will be loaded (whichever
// has a value first).
type getSource byte

const (
getSourceState getSource = 1 << iota
getSourceConfig
getSourceDiff
getSourceSet
getSourceExact // Only get from the _exact_ level
getSourceLevelMask getSource = getSourceState | getSourceConfig | getSourceDiff | getSourceSet
)
47 changes: 41 additions & 6 deletions helper/schema/resource_data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -648,11 +648,10 @@ func TestResourceDataGet(t *testing.T) {

State: &terraform.InstanceState{
Attributes: map[string]string{
"ratio": "0.5",
"ratio": "0.5",
},
},


Diff: nil,

Key: "ratio",
Expand All @@ -672,11 +671,10 @@ func TestResourceDataGet(t *testing.T) {

State: &terraform.InstanceState{
Attributes: map[string]string{
"ratio": "-0.5",
"ratio": "-0.5",
},
},


Diff: &terraform.InstanceDiff{
Attributes: map[string]*terraform.ResourceAttrDiff{
"ratio": &terraform.ResourceAttrDiff{
Expand All @@ -686,7 +684,6 @@ func TestResourceDataGet(t *testing.T) {
},
},


Key: "ratio",

Value: 33.0,
Expand Down Expand Up @@ -1533,7 +1530,6 @@ func TestResourceDataSet(t *testing.T) {
GetKey: "ratios",
GetValue: []interface{}{1.0, 2.2, 5.5},
},

}

for i, tc := range cases {
Expand Down Expand Up @@ -2500,6 +2496,45 @@ func TestResourceDataState(t *testing.T) {
},
},
},

// #24
{
Schema: map[string]*Schema{
"ports": &Schema{
Type: TypeSet,
Optional: true,
Computed: true,
Elem: &Schema{Type: TypeInt},
Set: func(a interface{}) int {
return a.(int)
},
},
},

State: &terraform.InstanceState{
Attributes: map[string]string{
"ports.#": "3",
"ports.100": "100",
"ports.80": "80",
"ports.81": "81",
},
},

Diff: &terraform.InstanceDiff{
Attributes: map[string]*terraform.ResourceAttrDiff{
"ports.#": &terraform.ResourceAttrDiff{
Old: "3",
New: "0",
},
},
},

Result: &terraform.InstanceState{
Attributes: map[string]string{
"ports.#": "0",
},
},
},
}

for i, tc := range cases {
Expand Down