Merge pull request #26573 from hashicorp/alisdair/show-diffs-when-only-sensitivity-changes
command: Show diffs when only sensitivity changes
This commit is contained in:
commit
a275d40274
|
@ -307,12 +307,6 @@ func (p *blockBodyDiffPrinter) writeBlockBodyDiff(schema *configschema.Block, ol
|
|||
func getPlanActionAndShow(old cty.Value, new cty.Value) (plans.Action, bool) {
|
||||
var action plans.Action
|
||||
showJustNew := false
|
||||
if old.ContainsMarked() {
|
||||
old, _ = old.UnmarkDeep()
|
||||
}
|
||||
if new.ContainsMarked() {
|
||||
new, _ = new.UnmarkDeep()
|
||||
}
|
||||
switch {
|
||||
case old.IsNull():
|
||||
action = plans.Create
|
||||
|
@ -590,9 +584,6 @@ func (p *blockBodyDiffPrinter) writeNestedBlockDiffs(name string, blockS *config
|
|||
}
|
||||
|
||||
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)
|
||||
var action plans.Action
|
||||
switch {
|
||||
case old.IsNull():
|
||||
|
@ -604,7 +595,7 @@ func (p *blockBodyDiffPrinter) writeSensitiveNestedBlockDiff(name string, old, n
|
|||
// that old values must never be unknown, but we'll allow it
|
||||
// anyway to be robust.
|
||||
action = plans.Update
|
||||
case !eqV.IsKnown() || !eqV.True():
|
||||
case !ctyEqualValueAndMarks(old, new):
|
||||
action = plans.Update
|
||||
}
|
||||
|
||||
|
@ -1162,12 +1153,8 @@ func (p *blockBodyDiffPrinter) writeValueDiff(old, new cty.Value, indent int, pa
|
|||
action = plans.Delete
|
||||
}
|
||||
|
||||
// Use unmarked values for equality testing
|
||||
if old.HasIndex(kV).True() && new.HasIndex(kV).True() {
|
||||
unmarkedOld, _ := old.Index(kV).Unmark()
|
||||
unmarkedNew, _ := new.Index(kV).Unmark()
|
||||
eqV := unmarkedOld.Equals(unmarkedNew)
|
||||
if eqV.IsKnown() && eqV.True() {
|
||||
if ctyEqualValueAndMarks(old.Index(kV), new.Index(kV)) {
|
||||
action = plans.NoOp
|
||||
} else {
|
||||
action = plans.Update
|
||||
|
@ -1269,7 +1256,7 @@ func (p *blockBodyDiffPrinter) writeValueDiff(old, new cty.Value, indent int, pa
|
|||
action = plans.Create
|
||||
} else if !new.Type().HasAttribute(kV) {
|
||||
action = plans.Delete
|
||||
} else if eqV := old.GetAttr(kV).Equals(new.GetAttr(kV)); eqV.IsKnown() && eqV.True() {
|
||||
} else if ctyEqualValueAndMarks(old.GetAttr(kV), new.GetAttr(kV)) {
|
||||
action = plans.NoOp
|
||||
} else {
|
||||
action = plans.Update
|
||||
|
@ -1493,11 +1480,23 @@ func ctySequenceDiff(old, new []cty.Value) []*plans.Change {
|
|||
return ret
|
||||
}
|
||||
|
||||
// ctyEqualValueAndMarks checks equality of two possibly-marked values,
|
||||
// considering partially-unknown values and equal values with different marks
|
||||
// as inequal
|
||||
func ctyEqualWithUnknown(old, new cty.Value) bool {
|
||||
if !old.IsWhollyKnown() || !new.IsWhollyKnown() {
|
||||
return false
|
||||
}
|
||||
return old.Equals(new).True()
|
||||
return ctyEqualValueAndMarks(old, new)
|
||||
}
|
||||
|
||||
// ctyEqualValueAndMarks checks equality of two possibly-marked values,
|
||||
// considering equal values with different marks as inequal
|
||||
func ctyEqualValueAndMarks(old, new cty.Value) bool {
|
||||
oldUnmarked, oldMarks := old.UnmarkDeep()
|
||||
newUnmarked, newMarks := new.UnmarkDeep()
|
||||
sameValue := oldUnmarked.Equals(newUnmarked)
|
||||
return sameValue.IsKnown() && sameValue.True() && oldMarks.Equal(newMarks)
|
||||
}
|
||||
|
||||
// ctyTypesEqual checks equality of two types more loosely
|
||||
|
|
|
@ -4150,6 +4150,176 @@ func TestResourceChange_sensitiveVariable(t *testing.T) {
|
|||
# so its contents will not be displayed.
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
"in-place update - value unchanged, sensitivity changes": {
|
||||
Action: plans.Update,
|
||||
Mode: addrs.ManagedResourceMode,
|
||||
Before: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-BEFORE"),
|
||||
"special": cty.BoolVal(true),
|
||||
"some_number": cty.NumberIntVal(1),
|
||||
"list_field": cty.ListVal([]cty.Value{
|
||||
cty.StringVal("hello"),
|
||||
cty.StringVal("friends"),
|
||||
cty.StringVal("!"),
|
||||
}),
|
||||
"map_key": cty.MapVal(map[string]cty.Value{
|
||||
"breakfast": cty.NumberIntVal(800),
|
||||
"dinner": cty.NumberIntVal(2000), // sensitive key
|
||||
}),
|
||||
"map_whole": cty.MapVal(map[string]cty.Value{
|
||||
"breakfast": cty.StringVal("pizza"),
|
||||
"dinner": cty.StringVal("pizza"),
|
||||
}),
|
||||
"nested_block": cty.ListVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"an_attr": cty.StringVal("secretval"),
|
||||
}),
|
||||
}),
|
||||
"nested_block_set": cty.ListVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"an_attr": cty.StringVal("secretval"),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
After: cty.ObjectVal(map[string]cty.Value{
|
||||
"id": cty.StringVal("i-02ae66f368e8518a9"),
|
||||
"ami": cty.StringVal("ami-BEFORE"),
|
||||
"special": cty.BoolVal(true),
|
||||
"some_number": cty.NumberIntVal(1),
|
||||
"list_field": cty.ListVal([]cty.Value{
|
||||
cty.StringVal("hello"),
|
||||
cty.StringVal("friends"),
|
||||
cty.StringVal("!"),
|
||||
}),
|
||||
"map_key": cty.MapVal(map[string]cty.Value{
|
||||
"breakfast": cty.NumberIntVal(800),
|
||||
"dinner": cty.NumberIntVal(2000), // sensitive key
|
||||
}),
|
||||
"map_whole": cty.MapVal(map[string]cty.Value{
|
||||
"breakfast": cty.StringVal("pizza"),
|
||||
"dinner": cty.StringVal("pizza"),
|
||||
}),
|
||||
"nested_block": cty.ListVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"an_attr": cty.StringVal("secretval"),
|
||||
}),
|
||||
}),
|
||||
"nested_block_set": cty.ListVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"an_attr": cty.StringVal("secretval"),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
BeforeValMarks: []cty.PathValueMarks{
|
||||
{
|
||||
Path: cty.Path{cty.GetAttrStep{Name: "ami"}},
|
||||
Marks: cty.NewValueMarks("sensitive"),
|
||||
},
|
||||
{
|
||||
Path: cty.Path{cty.GetAttrStep{Name: "special"}},
|
||||
Marks: cty.NewValueMarks("sensitive"),
|
||||
},
|
||||
{
|
||||
Path: cty.Path{cty.GetAttrStep{Name: "some_number"}},
|
||||
Marks: cty.NewValueMarks("sensitive"),
|
||||
},
|
||||
{
|
||||
Path: cty.Path{cty.GetAttrStep{Name: "list_field"}, cty.IndexStep{Key: cty.NumberIntVal(2)}},
|
||||
Marks: cty.NewValueMarks("sensitive"),
|
||||
},
|
||||
{
|
||||
Path: cty.Path{cty.GetAttrStep{Name: "map_key"}, cty.IndexStep{Key: cty.StringVal("dinner")}},
|
||||
Marks: cty.NewValueMarks("sensitive"),
|
||||
},
|
||||
{
|
||||
Path: cty.Path{cty.GetAttrStep{Name: "map_whole"}},
|
||||
Marks: cty.NewValueMarks("sensitive"),
|
||||
},
|
||||
{
|
||||
Path: cty.Path{cty.GetAttrStep{Name: "nested_block"}},
|
||||
Marks: cty.NewValueMarks("sensitive"),
|
||||
},
|
||||
{
|
||||
Path: cty.Path{cty.GetAttrStep{Name: "nested_block_set"}},
|
||||
Marks: cty.NewValueMarks("sensitive"),
|
||||
},
|
||||
},
|
||||
RequiredReplace: cty.NewPathSet(),
|
||||
Tainted: false,
|
||||
Schema: &configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"id": {Type: cty.String, Optional: true, Computed: true},
|
||||
"ami": {Type: cty.String, Optional: true},
|
||||
"list_field": {Type: cty.List(cty.String), Optional: true},
|
||||
"special": {Type: cty.Bool, Optional: true},
|
||||
"some_number": {Type: cty.Number, Optional: true},
|
||||
"map_key": {Type: cty.Map(cty.Number), Optional: true},
|
||||
"map_whole": {Type: cty.Map(cty.String), Optional: true},
|
||||
},
|
||||
BlockTypes: map[string]*configschema.NestedBlock{
|
||||
"nested_block": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"an_attr": {Type: cty.String, Optional: true},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingList,
|
||||
},
|
||||
"nested_block_set": {
|
||||
Block: configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"an_attr": {Type: cty.String, Optional: true},
|
||||
},
|
||||
},
|
||||
Nesting: configschema.NestingSet,
|
||||
},
|
||||
},
|
||||
},
|
||||
ExpectedOutput: ` # test_instance.example will be updated in-place
|
||||
~ resource "test_instance" "example" {
|
||||
# Warning: this attribute value will no longer be marked as sensitive
|
||||
# after applying this change
|
||||
~ ami = (sensitive)
|
||||
id = "i-02ae66f368e8518a9"
|
||||
~ list_field = [
|
||||
# (1 unchanged element hidden)
|
||||
"friends",
|
||||
- (sensitive),
|
||||
+ "!",
|
||||
]
|
||||
~ map_key = {
|
||||
# Warning: this attribute value will no longer be marked as sensitive
|
||||
# after applying this change
|
||||
~ "dinner" = (sensitive)
|
||||
# (1 unchanged element hidden)
|
||||
}
|
||||
# Warning: this attribute value will no longer be marked as sensitive
|
||||
# after applying this change
|
||||
~ map_whole = (sensitive)
|
||||
# Warning: this attribute value will no longer be marked as sensitive
|
||||
# after applying this change
|
||||
~ some_number = (sensitive)
|
||||
# Warning: this attribute value will no longer be marked as sensitive
|
||||
# after applying this change
|
||||
~ special = (sensitive)
|
||||
|
||||
# Warning: this block will no longer be marked as sensitive
|
||||
# after applying this change
|
||||
~ nested_block {
|
||||
# At least one attribute in this block is (or was) sensitive,
|
||||
# so its contents will not be displayed.
|
||||
}
|
||||
|
||||
# Warning: this block will no longer be marked as sensitive
|
||||
# after applying this change
|
||||
~ nested_block_set {
|
||||
# At least one attribute in this block is (or was) sensitive,
|
||||
# so its contents will not be displayed.
|
||||
}
|
||||
}
|
||||
`,
|
||||
},
|
||||
"deletion": {
|
||||
|
|
Loading…
Reference in New Issue