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{
|
"security_groups": &schema.Schema{
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Computed: true,
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
Set: func(v interface{}) int {
|
Set: func(v interface{}) int {
|
||||||
return hashcode.String(v.(string))
|
return hashcode.String(v.(string))
|
||||||
|
|
|
@ -82,11 +82,8 @@ func (r *Resource) Apply(
|
||||||
return data.State(), err
|
return data.State(), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the data to be empty
|
// Make sure the ID is gone.
|
||||||
data, err = schemaMap(r.Schema).Data(nil, d)
|
data.SetId("")
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're only destroying, and not creating, then return
|
// If we're only destroying, and not creating, then return
|
||||||
|
@ -97,7 +94,7 @@ func (r *Resource) Apply(
|
||||||
}
|
}
|
||||||
|
|
||||||
err = nil
|
err = nil
|
||||||
if s.ID == "" {
|
if data.Id() == "" {
|
||||||
// We're creating, it is a new resource.
|
// We're creating, it is a new resource.
|
||||||
err = r.Create(data, meta)
|
err = r.Create(data, meta)
|
||||||
} else {
|
} 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
|
// Remove any nil diffs just to keep things clean
|
||||||
for k, v := range result.Attributes {
|
for k, v := range result.Attributes {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
|
|
|
@ -764,6 +764,104 @@ func TestSchemaMap_Diff(t *testing.T) {
|
||||||
|
|
||||||
Err: false,
|
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 {
|
for i, tc := range cases {
|
||||||
|
|
Loading…
Reference in New Issue