Merge pull request #9613 from hashicorp/b-accurate-forcenew

helper/schema: only mark "ForceNew" on resources that cause the ForceNew
This commit is contained in:
Mitchell Hashimoto 2016-11-08 15:56:31 -08:00 committed by GitHub
commit 95871adca9
2 changed files with 89 additions and 21 deletions

View File

@ -288,9 +288,21 @@ func (s *Schema) finalizeDiff(
d.New = normalizeBoolString(d.New)
}
if s.Computed && !d.NewRemoved && d.New == "" {
// Computed attribute without a new value set
d.NewComputed = true
}
if s.ForceNew {
// Force new, set it to true in the diff
d.RequiresNew = true
// ForceNew, mark that this field is requiring new under the
// following conditions, explained below:
//
// * Old != New - There is a change in value. This field
// is therefore causing a new resource.
//
// * NewComputed - This field is being computed, hence a
// potential change in value, mark as causing a new resource.
d.RequiresNew = d.Old != d.New || d.NewComputed
}
if d.NewRemoved {

View File

@ -2341,9 +2341,8 @@ func TestSchemaMap_Diff(t *testing.T) {
RequiresNew: true,
},
"instances.3": &terraform.ResourceAttrDiff{
Old: "333",
New: "333",
RequiresNew: true,
Old: "333",
New: "333",
},
"instances.4": &terraform.ResourceAttrDiff{
Old: "",
@ -2426,6 +2425,61 @@ func TestSchemaMap_Diff(t *testing.T) {
Err: false,
},
"Set ForceNew only marks the changing element as ForceNew": {
Schema: map[string]*Schema{
"ports": &Schema{
Type: TypeSet,
Required: true,
ForceNew: true,
Elem: &Schema{Type: TypeInt},
Set: func(a interface{}) int {
return a.(int)
},
},
},
State: &terraform.InstanceState{
Attributes: map[string]string{
"ports.#": "3",
"ports.1": "1",
"ports.2": "2",
"ports.4": "4",
},
},
Config: map[string]interface{}{
"ports": []interface{}{5, 2, 1},
},
Diff: &terraform.InstanceDiff{
Attributes: map[string]*terraform.ResourceAttrDiff{
"ports.#": &terraform.ResourceAttrDiff{
Old: "3",
New: "3",
},
"ports.1": &terraform.ResourceAttrDiff{
Old: "1",
New: "1",
},
"ports.2": &terraform.ResourceAttrDiff{
Old: "2",
New: "2",
},
"ports.5": &terraform.ResourceAttrDiff{
Old: "",
New: "5",
RequiresNew: true,
},
"ports.4": &terraform.ResourceAttrDiff{
Old: "4",
New: "0",
NewRemoved: true,
RequiresNew: true,
},
},
},
},
"removed optional items should trigger ForceNew": {
Schema: map[string]*Schema{
"description": &Schema{
@ -2495,26 +2549,28 @@ func TestSchemaMap_Diff(t *testing.T) {
}
for tn, tc := range cases {
c, err := config.NewRawConfig(tc.Config)
if err != nil {
t.Fatalf("#%q err: %s", tn, err)
}
if len(tc.ConfigVariables) > 0 {
if err := c.Interpolate(tc.ConfigVariables); err != nil {
t.Run(tn, func(t *testing.T) {
c, err := config.NewRawConfig(tc.Config)
if err != nil {
t.Fatalf("#%q err: %s", tn, err)
}
}
d, err := schemaMap(tc.Schema).Diff(
tc.State, terraform.NewResourceConfig(c))
if err != nil != tc.Err {
t.Fatalf("#%q err: %s", tn, err)
}
if len(tc.ConfigVariables) > 0 {
if err := c.Interpolate(tc.ConfigVariables); err != nil {
t.Fatalf("#%q err: %s", tn, err)
}
}
if !reflect.DeepEqual(tc.Diff, d) {
t.Fatalf("#%q:\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Diff, d)
}
d, err := schemaMap(tc.Schema).Diff(
tc.State, terraform.NewResourceConfig(c))
if err != nil != tc.Err {
t.Fatalf("#%q err: %s", tn, err)
}
if !reflect.DeepEqual(tc.Diff, d) {
t.Fatalf("#%q:\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Diff, d)
}
})
}
}