direct: Fix state serialization for zero-value fields on deeply-embedded SDK specs#5782
direct: Fix state serialization for zero-value fields on deeply-embedded SDK specs#5782pietern wants to merge 2 commits into
Conversation
The dyn->typed ForceSendFields routing only handled one level of struct embedding. When a field declared in an SDK spec embedded two levels deep (e.g. PostgresProject -> PostgresProjectConfig -> ProjectSpec) was set to its zero value, its name was recorded in the wrong struct's ForceSendFields. The direct engine then failed to serialize the plan state with "field X cannot be found in struct Y". Route each field's ForceSendFields entry to the struct that actually declares it, at any embedding depth. This affected postgres_projects (enable_pg_native_login: false), postgres_branches, and postgres_endpoints (replace_existing: false). Terraform was unaffected (it serializes via dyn, not the SDK marshaler). Add a unit regression test for the deep-embedding case and a systemic guard that round-trips every registered resource type's zero-value fields, so any future resource using the embedded-spec wrapper pattern is covered automatically. Co-authored-by: Isaac
Approval status: pending
|
Integration test reportCommit: 29cab63
25 interesting tests: 13 SKIP, 7 KNOWN, 4 flaky, 1 RECOVERED
Top 5 slowest tests (at least 2 minutes):
|
| ForceEmpty: make(map[string]bool), | ||
| GolangNames: make(map[string]string), | ||
| ForceSendFieldsStructKey: make(map[string]int), | ||
| ForceSendFieldsStructKey: make(map[string]string), |
There was a problem hiding this comment.
why can't we keep precalculated index? the structs are static, so it should always resolve to the same index, right?
There was a problem hiding this comment.
Very good point, fixed on latest.
| my_project: | ||
| project_id: test-pg-proj-$UNIQUE_NAME | ||
| display_name: "Test Postgres Project" | ||
| enable_pg_native_login: false |
There was a problem hiding this comment.
can we also add this to invariant tests?
There was a problem hiding this comment.
Included this in the project resource config for the invariant tests.
… at runtime Store the full reflect index path to each field's governing ForceSendFields slice, keyed by JSON name, instead of a single struct index. The previous map[string]int could only address a ForceSendFields one embed level down, so the deep-embedding fix walked the value at conversion time to relocate them. The location is static per type, so resolve it once in buildStructInfo and FieldByIndex into it from both consumers. Co-authored-by: Isaac
The dyn→typed
ForceSendFieldsrouting only handled one level of struct embedding. When a field declared in an SDK spec embedded two levels deep (e.g.PostgresProject→PostgresProjectConfig→ProjectSpec) was set to its zero value, its name was recorded in the wrong struct'sForceSendFields. The direct engine then failed to serialize the plan state withfield X cannot be found in struct Y.Fix routes each field's
ForceSendFieldsentry to the struct that actually declares it, at any embedding depth. This affectedpostgres_projects(enable_pg_native_login: false),postgres_branches, andpostgres_endpoints(replace_existing: false). Terraform was unaffected (it serializes via dyn, not the SDK marshaler).Adds a unit regression test for the deep-embedding case and a systemic guard that round-trips every registered resource type's zero-value fields, so any future resource using the embedded-spec wrapper pattern is covered automatically.
This pull request and its description were written by Isaac.