2017-05-27 07:47:42 +02:00
|
|
|
package schema
|
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
2018-02-28 13:55:14 +01:00
|
|
|
"sort"
|
2017-05-27 07:47:42 +02:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
|
|
"github.com/hashicorp/terraform/terraform"
|
|
|
|
)
|
|
|
|
|
|
|
|
// testSetFunc is a very simple function we use to test a foo/bar complex set.
|
|
|
|
// Both "foo" and "bar" are int values.
|
|
|
|
//
|
|
|
|
// This is not foolproof as since it performs sums, you can run into
|
|
|
|
// collisions. Spec tests accordingly. :P
|
|
|
|
func testSetFunc(v interface{}) int {
|
|
|
|
m := v.(map[string]interface{})
|
|
|
|
return m["foo"].(int) + m["bar"].(int)
|
|
|
|
}
|
|
|
|
|
2017-05-28 03:17:41 +02:00
|
|
|
// resourceDiffTestCase provides a test case struct for SetNew and SetDiff.
|
|
|
|
type resourceDiffTestCase struct {
|
|
|
|
Name string
|
|
|
|
Schema map[string]*Schema
|
|
|
|
State *terraform.InstanceState
|
|
|
|
Config *terraform.ResourceConfig
|
|
|
|
Diff *terraform.InstanceDiff
|
|
|
|
Key string
|
|
|
|
OldValue interface{}
|
|
|
|
NewValue interface{}
|
|
|
|
Expected *terraform.InstanceDiff
|
2018-02-28 13:55:14 +01:00
|
|
|
ExpectedKeys []string
|
2017-05-28 03:17:41 +02:00
|
|
|
ExpectedError bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// testDiffCases produces a list of test cases for use with SetNew and SetDiff.
|
|
|
|
func testDiffCases(t *testing.T, oldPrefix string, oldOffset int, computed bool) []resourceDiffTestCase {
|
|
|
|
return []resourceDiffTestCase{
|
|
|
|
resourceDiffTestCase{
|
2017-05-27 07:47:42 +02:00
|
|
|
Name: "basic primitive diff",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
NewValue: "qux",
|
|
|
|
Expected: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
2017-05-31 17:03:29 +02:00
|
|
|
Old: "bar",
|
2017-05-28 03:17:41 +02:00
|
|
|
New: func() string {
|
|
|
|
if computed {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return "qux"
|
|
|
|
}(),
|
|
|
|
NewComputed: computed,
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
resourceDiffTestCase{
|
2017-05-27 07:47:42 +02:00
|
|
|
Name: "basic set diff",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeSet,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
Elem: &Schema{Type: TypeString},
|
|
|
|
Set: HashString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo.#": "1",
|
|
|
|
"foo.1996459178": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": []interface{}{"baz"},
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo.1996459178": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "",
|
|
|
|
NewRemoved: true,
|
|
|
|
},
|
|
|
|
"foo.2015626392": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
NewValue: []interface{}{"qux"},
|
|
|
|
Expected: &terraform.InstanceDiff{
|
2017-05-28 03:17:41 +02:00
|
|
|
Attributes: func() map[string]*terraform.ResourceAttrDiff {
|
|
|
|
result := map[string]*terraform.ResourceAttrDiff{}
|
|
|
|
if computed {
|
|
|
|
result["foo.#"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "1",
|
|
|
|
New: "",
|
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result["foo.2800005064"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "qux",
|
|
|
|
}
|
2017-05-31 17:03:29 +02:00
|
|
|
result["foo.1996459178"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
2017-05-28 03:17:41 +02:00
|
|
|
New: "",
|
|
|
|
NewRemoved: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}(),
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
resourceDiffTestCase{
|
2017-05-27 07:47:42 +02:00
|
|
|
Name: "basic list diff",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeList,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
Elem: &Schema{Type: TypeString},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo.#": "1",
|
|
|
|
"foo.0": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": []interface{}{"baz"},
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo.0": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
NewValue: []interface{}{"qux"},
|
|
|
|
Expected: &terraform.InstanceDiff{
|
2017-05-28 03:17:41 +02:00
|
|
|
Attributes: func() map[string]*terraform.ResourceAttrDiff {
|
|
|
|
result := make(map[string]*terraform.ResourceAttrDiff)
|
|
|
|
if computed {
|
|
|
|
result["foo.#"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "1",
|
|
|
|
New: "",
|
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result["foo.0"] = &terraform.ResourceAttrDiff{
|
2017-05-31 17:03:29 +02:00
|
|
|
Old: "bar",
|
2017-05-28 03:17:41 +02:00
|
|
|
New: "qux",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}(),
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
resourceDiffTestCase{
|
2017-05-27 07:47:42 +02:00
|
|
|
Name: "basic map diff",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeMap,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo.%": "1",
|
|
|
|
"foo.bar": "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": map[string]interface{}{"bar": "qux"},
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo.bar": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "baz",
|
|
|
|
New: "qux",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
NewValue: map[string]interface{}{"bar": "quux"},
|
|
|
|
Expected: &terraform.InstanceDiff{
|
2017-05-28 03:17:41 +02:00
|
|
|
Attributes: func() map[string]*terraform.ResourceAttrDiff {
|
|
|
|
result := make(map[string]*terraform.ResourceAttrDiff)
|
|
|
|
if computed {
|
|
|
|
result["foo.%"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "",
|
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
result["foo.bar"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "baz",
|
|
|
|
New: "",
|
|
|
|
NewRemoved: true,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result["foo.bar"] = &terraform.ResourceAttrDiff{
|
2017-05-31 17:03:29 +02:00
|
|
|
Old: "baz",
|
2017-05-28 03:17:41 +02:00
|
|
|
New: "quux",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}(),
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
resourceDiffTestCase{
|
2017-05-27 07:47:42 +02:00
|
|
|
Name: "additional diff with primitive",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"one": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
"one": "two",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "one",
|
|
|
|
NewValue: "four",
|
|
|
|
Expected: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
"one": &terraform.ResourceAttrDiff{
|
2017-05-31 17:03:29 +02:00
|
|
|
Old: "two",
|
2017-05-28 03:17:41 +02:00
|
|
|
New: func() string {
|
|
|
|
if computed {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return "four"
|
|
|
|
}(),
|
|
|
|
NewComputed: computed,
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
resourceDiffTestCase{
|
2017-05-27 07:47:42 +02:00
|
|
|
Name: "additional diff with primitive computed only",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"one": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
"one": "two",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "one",
|
|
|
|
NewValue: "three",
|
|
|
|
Expected: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
"one": &terraform.ResourceAttrDiff{
|
2017-05-31 17:03:29 +02:00
|
|
|
Old: "two",
|
2017-05-28 03:17:41 +02:00
|
|
|
New: func() string {
|
|
|
|
if computed {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return "three"
|
|
|
|
}(),
|
|
|
|
NewComputed: computed,
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
resourceDiffTestCase{
|
2017-05-27 07:47:42 +02:00
|
|
|
Name: "complex-ish set diff",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"top": &Schema{
|
|
|
|
Type: TypeSet,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
Elem: &Resource{
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeInt,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"bar": &Schema{
|
|
|
|
Type: TypeInt,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Set: testSetFunc,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"top.#": "2",
|
|
|
|
"top.3.foo": "1",
|
|
|
|
"top.3.bar": "2",
|
|
|
|
"top.23.foo": "11",
|
|
|
|
"top.23.bar": "12",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"top": []interface{}{
|
|
|
|
map[string]interface{}{
|
|
|
|
"foo": 1,
|
|
|
|
"bar": 3,
|
|
|
|
},
|
|
|
|
map[string]interface{}{
|
|
|
|
"foo": 12,
|
|
|
|
"bar": 12,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"top.4.foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "1",
|
|
|
|
},
|
|
|
|
"top.4.bar": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "3",
|
|
|
|
},
|
|
|
|
"top.24.foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "12",
|
|
|
|
},
|
|
|
|
"top.24.bar": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "12",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "top",
|
2017-05-31 18:52:10 +02:00
|
|
|
NewValue: NewSet(testSetFunc, []interface{}{
|
|
|
|
map[string]interface{}{
|
|
|
|
"foo": 1,
|
|
|
|
"bar": 4,
|
|
|
|
},
|
|
|
|
map[string]interface{}{
|
|
|
|
"foo": 13,
|
|
|
|
"bar": 12,
|
|
|
|
},
|
|
|
|
map[string]interface{}{
|
|
|
|
"foo": 21,
|
|
|
|
"bar": 22,
|
|
|
|
},
|
|
|
|
}),
|
2017-05-28 03:17:41 +02:00
|
|
|
Expected: &terraform.InstanceDiff{
|
|
|
|
Attributes: func() map[string]*terraform.ResourceAttrDiff {
|
|
|
|
result := make(map[string]*terraform.ResourceAttrDiff)
|
|
|
|
if computed {
|
|
|
|
result["top.#"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "2",
|
|
|
|
New: "",
|
|
|
|
NewComputed: true,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
result["top.#"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "2",
|
|
|
|
New: "3",
|
|
|
|
}
|
|
|
|
result["top.5.foo"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "1",
|
|
|
|
}
|
|
|
|
result["top.5.bar"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "4",
|
|
|
|
}
|
|
|
|
result["top.25.foo"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "13",
|
|
|
|
}
|
|
|
|
result["top.25.bar"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "12",
|
|
|
|
}
|
|
|
|
result["top.43.foo"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "21",
|
|
|
|
}
|
|
|
|
result["top.43.bar"] = &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "22",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}(),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "primitive, no diff, no refresh",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{}),
|
|
|
|
Diff: &terraform.InstanceDiff{Attributes: map[string]*terraform.ResourceAttrDiff{}},
|
|
|
|
Key: "foo",
|
|
|
|
NewValue: "baz",
|
2017-05-27 07:47:42 +02:00
|
|
|
Expected: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
2017-05-28 03:17:41 +02:00
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
2017-05-31 17:03:29 +02:00
|
|
|
Old: "bar",
|
2017-05-28 03:17:41 +02:00
|
|
|
New: func() string {
|
|
|
|
if computed {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return "baz"
|
|
|
|
}(),
|
|
|
|
NewComputed: computed,
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "non-computed key, should error",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
NewValue: "qux",
|
|
|
|
ExpectedError: true,
|
|
|
|
},
|
2017-06-01 18:19:03 +02:00
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "bad key, should error",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "bad",
|
|
|
|
NewValue: "qux",
|
|
|
|
ExpectedError: true,
|
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetNew(t *testing.T) {
|
|
|
|
testCases := testDiffCases(t, "", 0, false)
|
|
|
|
for _, tc := range testCases {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
m := schemaMap(tc.Schema)
|
2017-05-28 06:18:21 +02:00
|
|
|
d := newResourceDiff(tc.Schema, tc.Config, tc.State, tc.Diff)
|
2017-05-28 03:17:41 +02:00
|
|
|
err := d.SetNew(tc.Key, tc.NewValue)
|
|
|
|
switch {
|
|
|
|
case err != nil && !tc.ExpectedError:
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
case err == nil && tc.ExpectedError:
|
|
|
|
t.Fatalf("Expected error, got none")
|
|
|
|
case err != nil && tc.ExpectedError:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, k := range d.UpdatedKeys() {
|
|
|
|
if err := m.diff(k, m[k], tc.Diff, d, false); err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(tc.Expected, tc.Diff) {
|
|
|
|
t.Fatalf("Expected %s, got %s", spew.Sdump(tc.Expected), spew.Sdump(tc.Diff))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetNewComputed(t *testing.T) {
|
|
|
|
testCases := testDiffCases(t, "", 0, true)
|
|
|
|
for _, tc := range testCases {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
m := schemaMap(tc.Schema)
|
2017-05-28 06:18:21 +02:00
|
|
|
d := newResourceDiff(tc.Schema, tc.Config, tc.State, tc.Diff)
|
2017-05-28 03:17:41 +02:00
|
|
|
err := d.SetNewComputed(tc.Key)
|
|
|
|
switch {
|
|
|
|
case err != nil && !tc.ExpectedError:
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
case err == nil && tc.ExpectedError:
|
|
|
|
t.Fatalf("Expected error, got none")
|
|
|
|
case err != nil && tc.ExpectedError:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, k := range d.UpdatedKeys() {
|
|
|
|
if err := m.diff(k, m[k], tc.Diff, d, false); err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(tc.Expected, tc.Diff) {
|
|
|
|
t.Fatalf("Expected %s, got %s", spew.Sdump(tc.Expected), spew.Sdump(tc.Diff))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestForceNew(t *testing.T) {
|
|
|
|
cases := []resourceDiffTestCase{
|
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "basic primitive diff",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
Expected: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
RequiresNew: true,
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "no change, should error",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "bar",
|
|
|
|
}),
|
|
|
|
ExpectedError: true,
|
|
|
|
},
|
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "basic primitive, non-computed key",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
2017-05-28 03:17:41 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
Expected: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
RequiresNew: true,
|
2017-05-27 07:47:42 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2018-02-28 13:55:14 +01:00
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "nested field",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeList,
|
|
|
|
Required: true,
|
|
|
|
MaxItems: 1,
|
|
|
|
Elem: &Resource{
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"bar": {
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"baz": {
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo.#": "1",
|
|
|
|
"foo.0.bar": "abc",
|
|
|
|
"foo.0.baz": "xyz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": []map[string]interface{}{
|
|
|
|
map[string]interface{}{
|
|
|
|
"bar": "abcdefg",
|
|
|
|
"baz": "changed",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo.0.bar": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "abc",
|
|
|
|
New: "abcdefg",
|
|
|
|
},
|
|
|
|
"foo.0.baz": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "xyz",
|
|
|
|
New: "changed",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo.0.baz",
|
|
|
|
Expected: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo.0.bar": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "abc",
|
|
|
|
New: "abcdefg",
|
|
|
|
},
|
|
|
|
"foo.0.baz": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "xyz",
|
|
|
|
New: "changed",
|
|
|
|
RequiresNew: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2017-05-27 07:47:42 +02:00
|
|
|
}
|
2017-05-28 03:17:41 +02:00
|
|
|
for _, tc := range cases {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
m := schemaMap(tc.Schema)
|
2017-05-28 06:18:21 +02:00
|
|
|
d := newResourceDiff(m, tc.Config, tc.State, tc.Diff)
|
2017-05-28 03:17:41 +02:00
|
|
|
err := d.ForceNew(tc.Key)
|
|
|
|
switch {
|
|
|
|
case err != nil && !tc.ExpectedError:
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
case err == nil && tc.ExpectedError:
|
|
|
|
t.Fatalf("Expected error, got none")
|
|
|
|
case err != nil && tc.ExpectedError:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, k := range d.UpdatedKeys() {
|
|
|
|
if err := m.diff(k, m[k], tc.Diff, d, false); err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(tc.Expected, tc.Diff) {
|
|
|
|
t.Fatalf("Expected %s, got %s", spew.Sdump(tc.Expected), spew.Sdump(tc.Diff))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2017-05-27 07:47:42 +02:00
|
|
|
|
2017-05-28 03:17:41 +02:00
|
|
|
func TestClear(t *testing.T) {
|
|
|
|
cases := []resourceDiffTestCase{
|
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "basic primitive diff",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
Expected: &terraform.InstanceDiff{Attributes: map[string]*terraform.ResourceAttrDiff{}},
|
|
|
|
},
|
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "non-computed key, should error",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
ExpectedError: true,
|
|
|
|
},
|
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "multi-value, one removed",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"one": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
"one": "two",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
"one": "three",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
"one": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "two",
|
|
|
|
New: "three",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "one",
|
|
|
|
Expected: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
2017-05-27 07:47:42 +02:00
|
|
|
m := schemaMap(tc.Schema)
|
2017-05-28 06:18:21 +02:00
|
|
|
d := newResourceDiff(m, tc.Config, tc.State, tc.Diff)
|
2017-05-28 03:17:41 +02:00
|
|
|
err := d.Clear(tc.Key)
|
|
|
|
switch {
|
|
|
|
case err != nil && !tc.ExpectedError:
|
2017-05-27 07:47:42 +02:00
|
|
|
t.Fatalf("bad: %s", err)
|
2017-05-28 03:17:41 +02:00
|
|
|
case err == nil && tc.ExpectedError:
|
|
|
|
t.Fatalf("Expected error, got none")
|
|
|
|
case err != nil && tc.ExpectedError:
|
|
|
|
return
|
2017-05-27 07:47:42 +02:00
|
|
|
}
|
|
|
|
for _, k := range d.UpdatedKeys() {
|
|
|
|
if err := m.diff(k, m[k], tc.Diff, d, false); err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(tc.Expected, tc.Diff) {
|
|
|
|
t.Fatalf("Expected %s, got %s", spew.Sdump(tc.Expected), spew.Sdump(tc.Diff))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2018-02-28 13:55:14 +01:00
|
|
|
|
|
|
|
func TestGetChangedKeysPrefix(t *testing.T) {
|
|
|
|
cases := []resourceDiffTestCase{
|
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "basic primitive diff",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"foo": "baz",
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "bar",
|
|
|
|
New: "baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
ExpectedKeys: []string{
|
|
|
|
"foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
resourceDiffTestCase{
|
|
|
|
Name: "nested field filtering",
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"testfield": &Schema{
|
|
|
|
Type: TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"foo": &Schema{
|
|
|
|
Type: TypeList,
|
|
|
|
Required: true,
|
|
|
|
MaxItems: 1,
|
|
|
|
Elem: &Resource{
|
|
|
|
Schema: map[string]*Schema{
|
|
|
|
"bar": {
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"baz": {
|
|
|
|
Type: TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
State: &terraform.InstanceState{
|
|
|
|
Attributes: map[string]string{
|
|
|
|
"testfield": "blablah",
|
|
|
|
"foo.#": "1",
|
|
|
|
"foo.0.bar": "abc",
|
|
|
|
"foo.0.baz": "xyz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Config: testConfig(t, map[string]interface{}{
|
|
|
|
"testfield": "modified",
|
|
|
|
"foo": []map[string]interface{}{
|
|
|
|
map[string]interface{}{
|
|
|
|
"bar": "abcdefg",
|
|
|
|
"baz": "changed",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}),
|
|
|
|
Diff: &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"testfield": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "blablah",
|
|
|
|
New: "modified",
|
|
|
|
},
|
|
|
|
"foo.0.bar": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "abc",
|
|
|
|
New: "abcdefg",
|
|
|
|
},
|
|
|
|
"foo.0.baz": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "xyz",
|
|
|
|
New: "changed",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Key: "foo",
|
|
|
|
ExpectedKeys: []string{
|
|
|
|
"foo.0.bar",
|
|
|
|
"foo.0.baz",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
m := schemaMap(tc.Schema)
|
|
|
|
d := newResourceDiff(m, tc.Config, tc.State, tc.Diff)
|
|
|
|
keys := d.GetChangedKeysPrefix(tc.Key)
|
|
|
|
|
|
|
|
for _, k := range d.UpdatedKeys() {
|
|
|
|
if err := m.diff(k, m[k], tc.Diff, d, false); err != nil {
|
|
|
|
t.Fatalf("bad: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sort.Strings(keys)
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(tc.ExpectedKeys, keys) {
|
|
|
|
t.Fatalf("Expected %s, got %s", spew.Sdump(tc.ExpectedKeys), spew.Sdump(keys))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|