fix: Send full nested object on update - #141
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adjusts JSON diffing for msgraph_resource PATCH updates to avoid Microsoft Graph resetting omitted sub-fields inside complex (nested) types by sending the full nested object whenever it changes.
Changes:
- Update
DiffObjectto return full nested objects for changed object-valued properties (while keeping top-level minimal PATCH behavior). - Centralize “redacted string” detection and extend unit tests to cover complex-type patching and redacted/casing no-op diffs.
- Add an acceptance test covering updates to
federatedIdentityCredentials.claimsMatchingExpressionand document the fix in the changelog.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| internal/utils/json.go | Changes DiffObject to emit full nested objects on change; factors out redacted-string detection helper. |
| internal/utils/json_test.go | Updates/extends tests to validate full-object patching for nested complex types and no-op diffs for redacted/casing-only differences. |
| internal/services/msgraph_resource_test.go | Adds acceptance coverage for updating claimsMatchingExpression without resetting sibling fields. |
| CHANGELOG.md | Documents the bug fix and links to issue #137. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (2)
internal/utils/json.go:242
- DiffObject now sends the full nested object by assigning res[key] = newVal when any child differs. This bypasses the leaf-level IgnoreMissingProperty/redaction handling (e.g., "****" / "" / ""), so a nested object that changed in one field can still write back redacted placeholder values in other fields, contradicting isRedactedString's contract.
if oldVal, ok := oldValue[key]; ok {
if d := DiffObject(oldVal, newVal, option); d != nil {
res[key] = newVal
}
internal/utils/json_test.go:357
- TestDiffObject covers the case where a complex type differs only by a redacted leaf (expecting nil), but it does not cover the more problematic case where a complex type changes in a real field while also containing a redacted placeholder sibling. With the new "send full object" behavior, that scenario can regress into sending the placeholder back unless explicitly tested.
{
name: "complex type differing only by redacted leaf -> no change",
old: map[string]interface{}{
"credentials": map[string]interface{}{"displayName": "cred", "secretText": "s3cret"},
},
Gerry Tan (gerrytan)
left a comment
There was a problem hiding this comment.
Thx Lucia (@QixiaLu) , the PR looks good. Just small check: can you please check if the acctest failure TestAcc_ResourceMoveState_DirectoryRoleMember is related to this changes at all? This is passing in main (maybe a flake).
…into fix_update_nested_objects
…into fix_update_nested_objects
|
Thanks Gerry Tan (@gerrytan) for reviewing! I have merged Main into this branch, and fix an issue in the new test (seems like an Azure API validation change....). The final test result (https://dev.azure.com/azclitools/internal/_build/results?buildId=335481&view=logs&j=ca395085-040a-526b-2ce8-bdc85f692774&t=e722f262-b132-5c61-9453-a20c0496ffb3) is consistent with what in the main. Could I get another review when you get a chance? Thank you! |
Gerry Tan (gerrytan)
left a comment
There was a problem hiding this comment.
Thx Lucia (@QixiaLu) , approved, the PR looks good now.
Problem
DiffObjectwas computing a minimal diff at every level, so changing one sub-field produced a partial object. UpdatingclaimsMatchingExpression.valueon a federated identity credential sent onlyvalue, and Graph resetlanguageVersionto its default.Fix
DiffObjectnow emits the entire object whenever a nested object changes. Minimal-diff semantics are kept at the top level for scalars and arrays, which do follow JSON Merge PATCH.Change detection routes through
DiffObjectrather than a rawreflect.DeepEqual, soIgnoreCasingandIgnoreMissingPropertyare honoured — an object whose only difference is a recased string or a"****"placeholder read back from Graph is not re-sent.fix issue #137
Test
acctest result: https://dev.azure.com/azclitools/internal/_build/results?buildId=334251&view=logs&j=ca395085-040a-526b-2ce8-bdc85f692774&t=e722f262-b132-5c61-9453-a20c0496ffb3