mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-26 00:41:27 -06:00
prevent an empty string from being lost
The helper/schema diff process loses empty strings, causing them to show up as unset (null) during apply. Besides failing to show as set by GetOk, the absence of the value also triggers the schema to insert a default value again during apply. It would also be be preferable if the defaults weren't re-evaluated again during ApplyResourceChange, but that would require a more invasive patch to the field readers, and ensuring the empty string is stored in the plan should block the default.
This commit is contained in:
parent
1bba574fe9
commit
4dcda04d96
@ -174,3 +174,22 @@ resource "test_resource_defaults" "foo" {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestDefaults_emptyString(t *testing.T) {
|
||||
config := `
|
||||
resource "test_resource_defaults" "test" {
|
||||
default_string = ""
|
||||
}
|
||||
`
|
||||
resource.UnitTest(t, resource.TestCase{
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: config,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("test_resource_defaults.test", "default_string", ""),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -1201,6 +1201,8 @@ func normalizeNullValues(dst, src cty.Value, apply bool) cty.Value {
|
||||
}
|
||||
}
|
||||
|
||||
// check the invariants that we need below, to ensure we are working with
|
||||
// non-null and known values.
|
||||
if src.IsNull() || !src.IsKnown() || !dst.IsKnown() {
|
||||
return dst
|
||||
}
|
||||
@ -1319,8 +1321,12 @@ func normalizeNullValues(dst, src cty.Value, apply bool) cty.Value {
|
||||
return cty.ListVal(dsts)
|
||||
}
|
||||
|
||||
case ty.IsPrimitiveType():
|
||||
if dst.IsNull() && src.IsWhollyKnown() && apply {
|
||||
case ty == cty.String:
|
||||
// The legacy SDK should not be able to remove a value during plan or
|
||||
// apply, however we are only going to overwrite this if the source was
|
||||
// an empty string, since that is what is often equated with unset and
|
||||
// lost in the diff process.
|
||||
if dst.IsNull() && src.AsString() == "" {
|
||||
return src
|
||||
}
|
||||
}
|
||||
|
@ -984,6 +984,18 @@ func TestNormalizeNullValues(t *testing.T) {
|
||||
},
|
||||
{
|
||||
// Plan primitives are kept
|
||||
Src: cty.ObjectVal(map[string]cty.Value{
|
||||
"string": cty.NumberIntVal(0),
|
||||
}),
|
||||
Dst: cty.ObjectVal(map[string]cty.Value{
|
||||
"string": cty.NullVal(cty.Number),
|
||||
}),
|
||||
Expect: cty.ObjectVal(map[string]cty.Value{
|
||||
"string": cty.NullVal(cty.Number),
|
||||
}),
|
||||
},
|
||||
{
|
||||
// Neither plan nor apply should remove empty strings
|
||||
Src: cty.ObjectVal(map[string]cty.Value{
|
||||
"string": cty.StringVal(""),
|
||||
}),
|
||||
@ -991,8 +1003,21 @@ func TestNormalizeNullValues(t *testing.T) {
|
||||
"string": cty.NullVal(cty.String),
|
||||
}),
|
||||
Expect: cty.ObjectVal(map[string]cty.Value{
|
||||
"string": cty.StringVal(""),
|
||||
}),
|
||||
},
|
||||
{
|
||||
// Neither plan nor apply should remove empty strings
|
||||
Src: cty.ObjectVal(map[string]cty.Value{
|
||||
"string": cty.StringVal(""),
|
||||
}),
|
||||
Dst: cty.ObjectVal(map[string]cty.Value{
|
||||
"string": cty.NullVal(cty.String),
|
||||
}),
|
||||
Expect: cty.ObjectVal(map[string]cty.Value{
|
||||
"string": cty.StringVal(""),
|
||||
}),
|
||||
Apply: true,
|
||||
},
|
||||
{
|
||||
// The null map is retained, because the src was unknown
|
||||
|
Loading…
Reference in New Issue
Block a user