|
|
|
|
@ -286,7 +286,7 @@ func TestResourceChange_JSON(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"in-place update": {
|
|
|
|
|
"in-place update of object": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
@ -309,13 +309,108 @@ func TestResourceChange_JSON(t *testing.T) {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ {
|
|
|
|
|
- aaa = "value"
|
|
|
|
|
} -> {
|
|
|
|
|
+ aaa = "value"
|
|
|
|
|
aaa = "value"
|
|
|
|
|
+ bbb = "new_value"
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"in-place update (from empty tuple)": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`{"aaa": []}`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`{"aaa": ["value"]}`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ {
|
|
|
|
|
~ aaa = [
|
|
|
|
|
+ "value",
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"in-place update (to empty tuple)": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`{"aaa": ["value"]}`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`{"aaa": []}`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ {
|
|
|
|
|
~ aaa = [
|
|
|
|
|
- "value",
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"in-place update (tuple of different types)": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`{"aaa": [42, {"foo":"bar"}, "value"]}`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`{"aaa": [42, {"foo":"baz"}, "value"]}`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ {
|
|
|
|
|
~ aaa = [
|
|
|
|
|
42,
|
|
|
|
|
~ {
|
|
|
|
|
~ foo = "bar" -> "baz"
|
|
|
|
|
},
|
|
|
|
|
"value",
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"force-new update": {
|
|
|
|
|
@ -343,9 +438,7 @@ func TestResourceChange_JSON(t *testing.T) {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ {
|
|
|
|
|
- aaa = "value"
|
|
|
|
|
} -> {
|
|
|
|
|
+ aaa = "value"
|
|
|
|
|
aaa = "value"
|
|
|
|
|
+ bbb = "new_value"
|
|
|
|
|
} # forces replacement
|
|
|
|
|
)
|
|
|
|
|
@ -436,6 +529,279 @@ func TestResourceChange_JSON(t *testing.T) {
|
|
|
|
|
+ id = (known after apply)
|
|
|
|
|
+ json_field = jsonencode({})
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"JSON list item removal": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`["first","second","third"]`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`["first","second"]`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ [
|
|
|
|
|
"first",
|
|
|
|
|
"second",
|
|
|
|
|
- "third",
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"JSON list item addition": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`["first","second"]`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`["first","second","third"]`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ [
|
|
|
|
|
"first",
|
|
|
|
|
"second",
|
|
|
|
|
+ "third",
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"JSON list object addition": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`{"first":"111"}`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`{"first":"111","second":"222"}`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ {
|
|
|
|
|
first = "111"
|
|
|
|
|
+ second = "222"
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"JSON object with nested list": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`{
|
|
|
|
|
"Statement": ["first"]
|
|
|
|
|
}`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`{
|
|
|
|
|
"Statement": ["first", "second"]
|
|
|
|
|
}`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ {
|
|
|
|
|
~ Statement = [
|
|
|
|
|
"first",
|
|
|
|
|
+ "second",
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"JSON list of objects": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`[{"one": "111"}]`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`[{"one": "111"}, {"two": "222"}]`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ [
|
|
|
|
|
{
|
|
|
|
|
one = "111"
|
|
|
|
|
},
|
|
|
|
|
+ {
|
|
|
|
|
+ two = "222"
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"JSON object with list of objects": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`{"parent":[{"one": "111"}]}`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`{"parent":[{"one": "111"}, {"two": "222"}]}`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ {
|
|
|
|
|
~ parent = [
|
|
|
|
|
{
|
|
|
|
|
one = "111"
|
|
|
|
|
},
|
|
|
|
|
+ {
|
|
|
|
|
+ two = "222"
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"JSON object double nested lists": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`{"parent":[{"another_list": ["111"]}]}`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`{"parent":[{"another_list": ["111", "222"]}]}`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ {
|
|
|
|
|
~ parent = [
|
|
|
|
|
~ {
|
|
|
|
|
~ another_list = [
|
|
|
|
|
"111",
|
|
|
|
|
+ "222",
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
"in-place update from object to tuple": {
|
|
|
|
|
Action: plans.Update,
|
|
|
|
|
Mode: addrs.ManagedResourceMode,
|
|
|
|
|
Before: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
|
|
|
|
"json_field": cty.StringVal(`{"aaa": [42, {"foo":"bar"}, "value"]}`),
|
|
|
|
|
}),
|
|
|
|
|
After: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"id": cty.UnknownVal(cty.String),
|
|
|
|
|
"json_field": cty.StringVal(`["aaa", 42, "something"]`),
|
|
|
|
|
}),
|
|
|
|
|
Schema: &configschema.Block{
|
|
|
|
|
Attributes: map[string]*configschema.Attribute{
|
|
|
|
|
"id": {Type: cty.String, Optional: true, Computed: true},
|
|
|
|
|
"json_field": {Type: cty.String, Optional: true},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
RequiredReplace: cty.NewPathSet(),
|
|
|
|
|
ExpectedOutput: ` # test_instance.example will be updated in-place
|
|
|
|
|
~ resource "test_instance" "example" {
|
|
|
|
|
~ id = "i-02ae66f368e8518a9" -> (known after apply)
|
|
|
|
|
~ json_field = jsonencode(
|
|
|
|
|
~ {
|
|
|
|
|
- aaa = [
|
|
|
|
|
- 42,
|
|
|
|
|
- {
|
|
|
|
|
- foo = "bar"
|
|
|
|
|
},
|
|
|
|
|
- "value",
|
|
|
|
|
]
|
|
|
|
|
} -> [
|
|
|
|
|
+ "aaa",
|
|
|
|
|
+ 42,
|
|
|
|
|
+ "something",
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
`,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|