helper/schema: generate a full diff in destroy/create cycle
This commit is contained in:
parent
84fda6a5ad
commit
c9a541d95b
|
@ -91,6 +91,7 @@ func resourceAwsInstance() *schema.Resource {
|
|||
"security_groups": &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Set: func(v interface{}) int {
|
||||
return hashcode.String(v.(string))
|
||||
|
|
|
@ -82,11 +82,8 @@ func (r *Resource) Apply(
|
|||
return data.State(), err
|
||||
}
|
||||
|
||||
// Reset the data to be empty
|
||||
data, err = schemaMap(r.Schema).Data(nil, d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Make sure the ID is gone.
|
||||
data.SetId("")
|
||||
}
|
||||
|
||||
// If we're only destroying, and not creating, then return
|
||||
|
@ -97,7 +94,7 @@ func (r *Resource) Apply(
|
|||
}
|
||||
|
||||
err = nil
|
||||
if s.ID == "" {
|
||||
if data.Id() == "" {
|
||||
// We're creating, it is a new resource.
|
||||
err = r.Create(data, meta)
|
||||
} else {
|
||||
|
|
|
@ -177,6 +177,64 @@ func (m schemaMap) Diff(
|
|||
}
|
||||
}
|
||||
|
||||
// If the diff requires a new resource, then we recompute the diff
|
||||
// so we have the complete new resource diff, and preserve the
|
||||
// RequiresNew fields where necessary so the user knows exactly what
|
||||
// caused that.
|
||||
if result.RequiresNew() {
|
||||
// Create the new diff
|
||||
result2 := new(terraform.ResourceDiff)
|
||||
result2.Attributes = make(map[string]*terraform.ResourceAttrDiff)
|
||||
|
||||
// Reset the data to not contain state
|
||||
d.state = nil
|
||||
|
||||
// Perform the diff again
|
||||
for k, schema := range m {
|
||||
err := m.diff(k, schema, result2, d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Force all the fields to not force a new since we know what we
|
||||
// want to force new.
|
||||
for k, attr := range result2.Attributes {
|
||||
if attr == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if attr.RequiresNew {
|
||||
attr.RequiresNew = false
|
||||
}
|
||||
|
||||
if s != nil {
|
||||
attr.Old = s.Attributes[k]
|
||||
}
|
||||
}
|
||||
|
||||
// Now copy in all the requires new diffs...
|
||||
for k, attr := range result.Attributes {
|
||||
if attr == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
newAttr, ok := result2.Attributes[k]
|
||||
if !ok {
|
||||
newAttr = attr
|
||||
}
|
||||
|
||||
if attr.RequiresNew {
|
||||
newAttr.RequiresNew = true
|
||||
}
|
||||
|
||||
result2.Attributes[k] = newAttr
|
||||
}
|
||||
|
||||
// And set the diff!
|
||||
result = result2
|
||||
}
|
||||
|
||||
// Remove any nil diffs just to keep things clean
|
||||
for k, v := range result.Attributes {
|
||||
if v == nil {
|
||||
|
|
|
@ -764,6 +764,104 @@ func TestSchemaMap_Diff(t *testing.T) {
|
|||
|
||||
Err: false,
|
||||
},
|
||||
|
||||
/*
|
||||
* ForceNews
|
||||
*/
|
||||
|
||||
{
|
||||
Schema: map[string]*Schema{
|
||||
"availability_zone": &Schema{
|
||||
Type: TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"address": &Schema{
|
||||
Type: TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
|
||||
State: &terraform.ResourceState{
|
||||
Attributes: map[string]string{
|
||||
"availability_zone": "bar",
|
||||
"address": "foo",
|
||||
},
|
||||
},
|
||||
|
||||
Config: map[string]interface{}{
|
||||
"availability_zone": "foo",
|
||||
},
|
||||
|
||||
Diff: &terraform.ResourceDiff{
|
||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||
"availability_zone": &terraform.ResourceAttrDiff{
|
||||
Old: "bar",
|
||||
New: "foo",
|
||||
RequiresNew: true,
|
||||
},
|
||||
|
||||
"address": &terraform.ResourceAttrDiff{
|
||||
Old: "foo",
|
||||
New: "",
|
||||
NewComputed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Err: false,
|
||||
},
|
||||
|
||||
// Set
|
||||
{
|
||||
Schema: map[string]*Schema{
|
||||
"availability_zone": &Schema{
|
||||
Type: TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"ports": &Schema{
|
||||
Type: TypeSet,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Elem: &Schema{Type: TypeInt},
|
||||
Set: func(v interface{}) int { return v.(int) },
|
||||
},
|
||||
},
|
||||
|
||||
State: &terraform.ResourceState{
|
||||
Attributes: map[string]string{
|
||||
"availability_zone": "bar",
|
||||
"ports.#": "1",
|
||||
"ports.0": "80",
|
||||
},
|
||||
},
|
||||
|
||||
Config: map[string]interface{}{
|
||||
"availability_zone": "foo",
|
||||
},
|
||||
|
||||
Diff: &terraform.ResourceDiff{
|
||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||
"availability_zone": &terraform.ResourceAttrDiff{
|
||||
Old: "bar",
|
||||
New: "foo",
|
||||
RequiresNew: true,
|
||||
},
|
||||
|
||||
"ports.#": &terraform.ResourceAttrDiff{
|
||||
Old: "1",
|
||||
New: "",
|
||||
NewComputed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Err: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range cases {
|
||||
|
|
Loading…
Reference in New Issue