diff --git a/command/format/diff.go b/command/format/diff.go index a7635e862..b697b1726 100644 --- a/command/format/diff.go +++ b/command/format/diff.go @@ -855,13 +855,33 @@ func (p *blockBodyDiffPrinter) pathForcesNewResource(path cty.Path) bool { return p.requiredReplace.Has(path) } +func ctyEmptyString(value cty.Value) bool { + if !value.IsNull() && value.IsKnown() { + valueType := value.Type() + if valueType == cty.String && value.AsString() == "" { + return true + } + } + return false +} + func ctyGetAttrMaybeNull(val cty.Value, name string) cty.Value { + attrType := val.Type().AttributeType(name) + if val.IsNull() { - ty := val.Type().AttributeType(name) - return cty.NullVal(ty) + return cty.NullVal(attrType) } - return val.GetAttr(name) + // We treat "" as null here + // as existing SDK doesn't support null yet. + // This allows us to avoid spurious diffs + // until we introduce null to the SDK. + attrValue := val.GetAttr(name) + if ctyEmptyString(attrValue) { + return cty.NullVal(attrType) + } + + return attrValue } func ctyCollectionValues(val cty.Value) []cty.Value { diff --git a/command/format/diff_test.go b/command/format/diff_test.go index c5c666048..314173fb8 100644 --- a/command/format/diff_test.go +++ b/command/format/diff_test.go @@ -48,6 +48,27 @@ func TestResourceChange_primitiveTypes(t *testing.T) { - resource "test_instance" "example" { - id = "i-02ae66f368e8518a9" -> null } +`, + }, + "deletion (empty string)": { + Action: plans.Delete, + Mode: addrs.ManagedResourceMode, + Before: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("i-02ae66f368e8518a9"), + "intentionally_long": cty.StringVal(""), + }), + After: cty.NullVal(cty.EmptyObject), + Schema: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "id": {Type: cty.String, Computed: true}, + "intentionally_long": {Type: cty.String, Optional: true}, + }, + }, + RequiredReplace: cty.NewPathSet(), + ExpectedOutput: ` # test_instance.example will be destroyed + - resource "test_instance" "example" { + - id = "i-02ae66f368e8518a9" -> null + } `, }, "string in-place update": {