helper/diff: calculate removed keys

This commit is contained in:
Mitchell Hashimoto 2014-07-09 09:47:21 -07:00
parent fdfed5000f
commit 2d97738636
2 changed files with 103 additions and 34 deletions

View File

@ -55,45 +55,70 @@ func (b *ResourceBuilder) Diff(
flatRaw := flatmap.Flatten(c.Raw) flatRaw := flatmap.Flatten(c.Raw)
flatConfig := flatmap.Flatten(c.Config) flatConfig := flatmap.Flatten(c.Config)
for k, v := range flatRaw { for ak, at := range b.Attrs {
// Make sure this is an attribute that actually affects // Keep track of all the keys we saw in the raw structure
// the diff in some way. // so that we can prune our attributes later.
var attr AttrType seenKeys := make([]string, 0)
for ak, at := range b.Attrs {
if strings.HasPrefix(k, ak) { // Go through and find the added/changed keys in flatRaw
attr = at for k, v := range flatRaw {
break // Find only the attributes that match our prefix
if !strings.HasPrefix(k, ak) {
continue
}
// Track that we saw this key
seenKeys = append(seenKeys, k)
// If this key is in the cleaned config, then use that value
// because it'll have its variables properly interpolated
if cleanV, ok := flatConfig[k]; ok {
v = cleanV
}
oldV, ok := s.Attributes[k]
// If there is an old value and they're the same, no change
if ok && oldV == v {
continue
}
// Record the change
attrs[k] = &terraform.ResourceAttrDiff{
Old: oldV,
New: v,
Type: terraform.DiffAttrInput,
}
// If this requires a new resource, record that and flag our
// boolean.
if at == AttrTypeCreate {
attrs[k].RequiresNew = true
requiresNew = true
} }
} }
if attr == AttrTypeUnknown {
continue // Go through our attribues and find the deleted keys
matchingKeys := make(map[string]struct{})
for k, _ := range s.Attributes {
// Find only the attributes that match our prefix
if !strings.HasPrefix(k, ak) {
continue
}
matchingKeys[k] = struct{}{}
} }
// If this key is in the cleaned config, then use that value // Delete the keys we saw to find the deleted keys
// because it'll have its variables properly interpolated for _, k := range seenKeys {
if cleanV, ok := flatConfig[k]; ok { delete(matchingKeys, k)
v = cleanV
} }
for k, _ := range matchingKeys {
oldV, ok := s.Attributes[k] attrs[k] = &terraform.ResourceAttrDiff{
Old: s.Attributes[k],
// If there is an old value and they're the same, no change New: "",
if ok && oldV == v { Type: terraform.DiffAttrInput,
continue }
}
// Record the change
attrs[k] = &terraform.ResourceAttrDiff{
Old: oldV,
New: v,
Type: terraform.DiffAttrInput,
}
// If this requires a new resource, record that and flag our
// boolean.
if attr == AttrTypeCreate {
attrs[k].RequiresNew = true
requiresNew = true
} }
} }

View File

@ -46,6 +46,45 @@ func TestResourceBuilder_complex(t *testing.T) {
} }
} }
func TestResourceBuilder_complexReplace(t *testing.T) {
rb := &ResourceBuilder{
Attrs: map[string]AttrType{
"listener": AttrTypeUpdate,
},
}
state := &terraform.ResourceState{
ID: "foo",
Attributes: map[string]string{
"ignore": "1",
"listener.#": "1",
"listener.0.port": "80",
},
}
c := testConfig(t, map[string]interface{}{
"listener": []interface{}{
map[interface{}]interface{}{
"value": "50",
},
},
}, nil)
diff, err := rb.Diff(state, c)
if err != nil {
t.Fatalf("err: %s", err)
}
if diff == nil {
t.Fatal("should not be nil")
}
actual := testResourceDiffStr(diff)
expected := testRBComplexReplaceDiff
if actual != expected {
t.Fatalf("bad: %s", actual)
}
}
func TestResourceBuilder_new(t *testing.T) { func TestResourceBuilder_new(t *testing.T) {
rb := &ResourceBuilder{ rb := &ResourceBuilder{
Attrs: map[string]AttrType{ Attrs: map[string]AttrType{
@ -200,6 +239,11 @@ const testRBComplexDiff = `UPDATE
IN listener.0.port: "80" => "3000" IN listener.0.port: "80" => "3000"
` `
const testRBComplexReplaceDiff = `UPDATE
IN listener.0.port: "80" => ""
IN listener.0.value: "" => "50"
`
const testRBNewDiff = `UPDATE const testRBNewDiff = `UPDATE
IN foo: "" => "bar" IN foo: "" => "bar"
OUT private_ip: "" => "<computed>" OUT private_ip: "" => "<computed>"