command/format: Render empty object as {}

This commit is contained in:
Radek Simko 2019-01-14 16:07:04 +00:00
parent 5f14b7a7f2
commit 13896d72c5
No known key found for this signature in database
GPG Key ID: 1F1C84FE689A88D7
2 changed files with 70 additions and 14 deletions

View File

@ -100,7 +100,7 @@ func ResourceChange(
buf.WriteString(addr.String())
}
buf.WriteString(" {\n")
buf.WriteString(" {")
p := blockBodyDiffPrinter{
buf: &buf,
@ -122,9 +122,12 @@ func ResourceChange(
panic(fmt.Sprintf("failed to decode plan for %s while rendering diff: %s", addr, err))
}
p.writeBlockBodyDiff(schema, changeV.Before, changeV.After, 6, path)
buf.WriteString(" }\n")
bodyWritten := p.writeBlockBodyDiff(schema, changeV.Before, changeV.After, 6, path)
if bodyWritten {
buf.WriteString("\n")
buf.WriteString(strings.Repeat(" ", 4))
}
buf.WriteString("}\n")
return buf.String()
}
@ -143,9 +146,12 @@ type blockBodyDiffPrinter struct {
const forcesNewResourceCaption = " [red]# forces replacement[reset]"
func (p *blockBodyDiffPrinter) writeBlockBodyDiff(schema *configschema.Block, old, new cty.Value, indent int, path cty.Path) {
// writeBlockBodyDiff writes attribute or block differences
// and returns true if any differences were found and written
func (p *blockBodyDiffPrinter) writeBlockBodyDiff(schema *configschema.Block, old, new cty.Value, indent int, path cty.Path) bool {
path = ctyEnsurePathCapacity(path, 1)
bodyWritten := false
blankBeforeBlocks := false
{
attrNames := make([]string, 0, len(schema.Attributes))
@ -176,6 +182,7 @@ func (p *blockBodyDiffPrinter) writeBlockBodyDiff(schema *configschema.Block, ol
oldVal := ctyGetAttrMaybeNull(old, name)
newVal := ctyGetAttrMaybeNull(new, name)
bodyWritten = true
p.writeAttrDiff(name, attrS, oldVal, newVal, attrNameLen, indent, path)
}
}
@ -192,16 +199,20 @@ func (p *blockBodyDiffPrinter) writeBlockBodyDiff(schema *configschema.Block, ol
oldVal := ctyGetAttrMaybeNull(old, name)
newVal := ctyGetAttrMaybeNull(new, name)
bodyWritten = true
p.writeNestedBlockDiffs(name, blockS, oldVal, newVal, blankBeforeBlocks, indent, path)
// Always include a blank for any subsequent block types.
blankBeforeBlocks = true
}
}
return bodyWritten
}
func (p *blockBodyDiffPrinter) writeAttrDiff(name string, attrS *configschema.Attribute, old, new cty.Value, nameLen, indent int, path cty.Path) {
path = append(path, cty.GetAttrStep{Name: name})
p.buf.WriteString("\n")
p.buf.WriteString(strings.Repeat(" ", indent))
showJustNew := false
var action plans.Action
@ -239,9 +250,6 @@ func (p *blockBodyDiffPrinter) writeAttrDiff(name string, attrS *configschema.At
p.writeValueDiff(old, new, indent+2, path)
}
}
p.buf.WriteString("\n")
}
func (p *blockBodyDiffPrinter) writeNestedBlockDiffs(name string, blockS *configschema.NestedBlock, old, new cty.Value, blankBefore bool, indent int, path cty.Path) {
@ -393,6 +401,7 @@ func (p *blockBodyDiffPrinter) writeNestedBlockDiffs(name string, blockS *config
}
func (p *blockBodyDiffPrinter) writeNestedBlockDiff(name string, label *string, blockS *configschema.Block, action plans.Action, old, new cty.Value, indent int, path cty.Path) {
p.buf.WriteString("\n")
p.buf.WriteString(strings.Repeat(" ", indent))
p.writeActionSymbol(action)
@ -406,12 +415,12 @@ func (p *blockBodyDiffPrinter) writeNestedBlockDiff(name string, label *string,
p.buf.WriteString(p.color.Color(forcesNewResourceCaption))
}
p.buf.WriteString("\n")
p.writeBlockBodyDiff(blockS, old, new, indent+4, path)
p.buf.WriteString(strings.Repeat(" ", indent+2))
p.buf.WriteString("}\n")
bodyWritten := p.writeBlockBodyDiff(blockS, old, new, indent+4, path)
if bodyWritten {
p.buf.WriteString("\n")
p.buf.WriteString(strings.Repeat(" ", indent+2))
}
p.buf.WriteString("}")
}
func (p *blockBodyDiffPrinter) writeValue(val cty.Value, action plans.Action, indent int) {

View File

@ -1282,6 +1282,53 @@ func TestResourceChange_nestedList(t *testing.T) {
`,
},
"in-place update - creation": {
Action: plans.Update,
Mode: addrs.ManagedResourceMode,
Before: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("i-02ae66f368e8518a9"),
"ami": cty.StringVal("ami-BEFORE"),
"root_block_device": cty.ListValEmpty(cty.EmptyObject),
}),
After: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("i-02ae66f368e8518a9"),
"ami": cty.StringVal("ami-AFTER"),
"root_block_device": cty.ListVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"volume_type": cty.NullVal(cty.String),
}),
}),
}),
RequiredReplace: cty.NewPathSet(),
Schema: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"id": {Type: cty.String, Optional: true, Computed: true},
"ami": {Type: cty.String, Optional: true},
},
BlockTypes: map[string]*configschema.NestedBlock{
"root_block_device": {
Block: configschema.Block{
Attributes: map[string]*configschema.Attribute{
"volume_type": {
Type: cty.String,
Optional: true,
Computed: true,
},
},
},
Nesting: configschema.NestingList,
},
},
},
ExpectedOutput: ` # test_instance.example will be updated in-place
~ resource "test_instance" "example" {
~ ami = "ami-BEFORE" -> "ami-AFTER"
id = "i-02ae66f368e8518a9"
+ root_block_device {}
}
`,
},
"in-place update - first insertion": {
Action: plans.Update,
Mode: addrs.ManagedResourceMode,
Before: cty.ObjectVal(map[string]cty.Value{