command: Fix missing force new for sensitive blocks

If an entire block is marked sensitive (possibly because it is of type
NestedSet) and results in replacement of the resource, we should render
the standard "forces replacement" text after the opening line of the
block.
This commit is contained in:
Alisdair McDiarmid 2020-10-07 10:50:54 -04:00
parent 79a3e33c4d
commit 62e6f56a50
2 changed files with 44 additions and 7 deletions

View File

@ -381,7 +381,7 @@ func (p *blockBodyDiffPrinter) writeNestedBlockDiffs(name string, blockS *config
// Display a special diff because it is irrelevant
// to list all obfuscated attributes as (sensitive)
if old.IsMarked() || new.IsMarked() {
p.writeSensitiveNestedBlockDiff(name, old, new, indent, blankBefore)
p.writeSensitiveNestedBlockDiff(name, old, new, indent, blankBefore, path)
return 0
}
@ -589,7 +589,7 @@ func (p *blockBodyDiffPrinter) writeNestedBlockDiffs(name string, blockS *config
return skippedBlocks
}
func (p *blockBodyDiffPrinter) writeSensitiveNestedBlockDiff(name string, old, new cty.Value, indent int, blankBefore bool) {
func (p *blockBodyDiffPrinter) writeSensitiveNestedBlockDiff(name string, old, new cty.Value, indent int, blankBefore bool, path cty.Path) {
unmarkedOld, _ := old.Unmark()
unmarkedNew, _ := new.Unmark()
eqV := unmarkedNew.Equals(unmarkedOld)
@ -618,6 +618,9 @@ func (p *blockBodyDiffPrinter) writeSensitiveNestedBlockDiff(name string, old, n
p.buf.WriteString(strings.Repeat(" ", indent))
p.writeActionSymbol(action)
fmt.Fprintf(p.buf, "%s {", name)
if action != plans.NoOp && p.pathForcesNewResource(path) {
p.buf.WriteString(p.color.Color(forcesNewResourceCaption))
}
p.buf.WriteRune('\n')
p.buf.WriteString(strings.Repeat(" ", indent+4))
p.buf.WriteString("# At least one attribute in this block is (or was) sensitive,\n")

View File

@ -4259,20 +4259,38 @@ func TestResourceChange_sensitiveVariable(t *testing.T) {
Before: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("i-02ae66f368e8518a9"),
"ami": cty.StringVal("ami-BEFORE"),
"nested_block_set": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"an_attr": cty.StringVal("secret"),
}),
}),
}),
After: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("i-02ae66f368e8518a9"),
"ami": cty.StringVal("ami-AFTER"),
"nested_block_set": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"an_attr": cty.StringVal("changed"),
}),
}),
}),
BeforeValMarks: []cty.PathValueMarks{
{
Path: cty.Path{cty.GetAttrStep{Name: "ami"}},
Path: cty.GetAttrPath("ami"),
Marks: cty.NewValueMarks("sensitive"),
},
{
Path: cty.GetAttrPath("nested_block_set"),
Marks: cty.NewValueMarks("sensitive"),
},
},
AfterValMarks: []cty.PathValueMarks{
{
Path: cty.Path{cty.GetAttrStep{Name: "ami"}},
Path: cty.GetAttrPath("ami"),
Marks: cty.NewValueMarks("sensitive"),
},
{
Path: cty.GetAttrPath("nested_block_set"),
Marks: cty.NewValueMarks("sensitive"),
},
},
@ -4281,15 +4299,31 @@ func TestResourceChange_sensitiveVariable(t *testing.T) {
"id": {Type: cty.String, Optional: true, Computed: true},
"ami": {Type: cty.String, Optional: true},
},
BlockTypes: map[string]*configschema.NestedBlock{
"nested_block_set": {
Block: configschema.Block{
Attributes: map[string]*configschema.Attribute{
"an_attr": {Type: cty.String, Required: true},
},
RequiredReplace: cty.NewPathSet(cty.Path{
cty.GetAttrStep{Name: "ami"},
}),
},
Nesting: configschema.NestingSet,
},
},
},
RequiredReplace: cty.NewPathSet(
cty.GetAttrPath("ami"),
cty.GetAttrPath("nested_block_set"),
),
Tainted: false,
ExpectedOutput: ` # test_instance.example must be replaced
-/+ resource "test_instance" "example" {
~ ami = (sensitive) # forces replacement
id = "i-02ae66f368e8518a9"
~ nested_block_set { # forces replacement
# At least one attribute in this block is (or was) sensitive,
# so its contents will not be displayed.
}
}
`,
},