command/format: Fix rendering of different types

This commit is contained in:
Radek Simko 2019-01-23 13:13:48 +00:00
parent f3d1565d6f
commit 953eae7e4b
No known key found for this signature in database
GPG Key ID: 1F1C84FE689A88D7
2 changed files with 55 additions and 2 deletions

View File

@ -556,6 +556,7 @@ func (p *blockBodyDiffPrinter) writeValue(val cty.Value, action plans.Action, in
func (p *blockBodyDiffPrinter) writeValueDiff(old, new cty.Value, indent int, path cty.Path) { func (p *blockBodyDiffPrinter) writeValueDiff(old, new cty.Value, indent int, path cty.Path) {
ty := old.Type() ty := old.Type()
typesEqual := ctyTypesEqual(ty, new.Type())
// We have some specialized diff implementations for certain complex // We have some specialized diff implementations for certain complex
// values where it's useful to see a visualization of the diff of // values where it's useful to see a visualization of the diff of
@ -563,7 +564,7 @@ func (p *blockBodyDiffPrinter) writeValueDiff(old, new cty.Value, indent int, pa
// new values verbatim. // new values verbatim.
// However, these specialized implementations can apply only if both // However, these specialized implementations can apply only if both
// values are known and non-null. // values are known and non-null.
if old.IsKnown() && new.IsKnown() && !old.IsNull() && !new.IsNull() { if old.IsKnown() && new.IsKnown() && !old.IsNull() && !new.IsNull() && typesEqual {
switch { switch {
case ty == cty.String: case ty == cty.String:
// We have special behavior for both multi-line strings in general // We have special behavior for both multi-line strings in general
@ -1060,6 +1061,19 @@ func ctyEqualWithUnknown(old, new cty.Value) bool {
return old.Equals(new).True() return old.Equals(new).True()
} }
// ctyTypesEqual checks equality of two types more loosely
// by avoiding checks of object/tuple elements
// as we render differences on element-by-element basis anyway
func ctyTypesEqual(oldT, newT cty.Type) bool {
if oldT.IsObjectType() && newT.IsObjectType() {
return true
}
if oldT.IsTupleType() && newT.IsTupleType() {
return true
}
return oldT.Equals(newT)
}
func ctyEnsurePathCapacity(path cty.Path, minExtra int) cty.Path { func ctyEnsurePathCapacity(path cty.Path, minExtra int) cty.Path {
if cap(path)-len(path) >= minExtra { if cap(path)-len(path) >= minExtra {
return path return path

View File

@ -286,7 +286,7 @@ func TestResourceChange_JSON(t *testing.T) {
} }
`, `,
}, },
"in-place update": { "in-place update of object": {
Action: plans.Update, Action: plans.Update,
Mode: addrs.ManagedResourceMode, Mode: addrs.ManagedResourceMode,
Before: cty.ObjectVal(map[string]cty.Value{ Before: cty.ObjectVal(map[string]cty.Value{
@ -763,6 +763,45 @@ func TestResourceChange_JSON(t *testing.T) {
} }
) )
} }
`,
},
"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",
]
)
}
`, `,
}, },
} }