Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

### Bug Fixes

* Fixed `lifecycle { ignore_changes }` not working for `Optional+Computed` fields whose API returns empty values. The shared `StructToData` gate in `common/reflect_resource.go` was silently dropping empty/nil values for all `Optional` fields, including `Computed` ones, causing perpetual `(known after apply)` diffs and preventing `ignore_changes` from preserving externally-set values.
* Fix `databricks_metastore` so that updating `external_access_enabled` from `true` to `false` is sent in the PATCH request. Previously the field was silently dropped from the request body, so the change never reached the API.
||||||| parent of 7a333420 ([Fix] StructToData gate: allow empty values through for Optional+Computed fields)

### Documentation

Expand Down
2 changes: 1 addition & 1 deletion common/reflect_resource.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions common/reflect_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -973,3 +973,45 @@ func TestStructToData_IndirectString(t *testing.T) {
}, scm, d)
assert.NoError(t, err)
}

func TestStructToData_OptionalComputedEmptyMapWrittenToState(t *testing.T) {
type Resource struct {
Name string `json:"name"`
Tags map[string]string `json:"tags,omitempty"`
}
s := StructToSchema(Resource{}, func(s map[string]*schema.Schema) map[string]*schema.Schema {
s["tags"].Optional = true
s["tags"].Computed = true
return s
})
d := schema.TestResourceDataRaw(t, s, map[string]any{"name": "test"})
d.SetId("existing-resource")
err := StructToData(Resource{Name: "test", Tags: map[string]string{}}, s, d)
assert.NoError(t, err)
// Optional+Computed empty maps must reach state so ignore_changes and drift
// detection work correctly; without the !fieldSchema.Computed guard they
// were silently dropped, causing a perpetual "(known after apply)" diff.
tags := d.Get("tags")
assert.NotNil(t, tags)
tagsMap, ok := tags.(map[string]interface{})
assert.True(t, ok)
assert.Empty(t, tagsMap)
}

func TestStructToData_OptionalOnlyEmptyMapNotWrittenToState(t *testing.T) {
type Resource struct {
Name string `json:"name"`
Tags map[string]string `json:"tags,omitempty"`
}
s := StructToSchema(Resource{}, nil)
d := schema.TestResourceDataRaw(t, s, map[string]any{"name": "test"})
d.SetId("existing-resource")
err := StructToData(Resource{Name: "test", Tags: map[string]string{}}, s, d)
assert.NoError(t, err)
// Optional-only (non-Computed) empty maps are still filtered to avoid
// writing server defaults into state for unconfigured fields.
tags := d.Get("tags")
tagsMap, ok := tags.(map[string]interface{})
assert.True(t, ok)
assert.Empty(t, tagsMap)
}