feat: adopt duplicate module creates and guard all-None matcher lookups - #201
Open
leoparente wants to merge 5 commits into
Open
feat: adopt duplicate module creates and guard all-None matcher lookups#201leoparente wants to merge 5 commits into
leoparente wants to merge 5 commits into
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Skip .lower() on None values in the case-insensitive fingerprint branch; previously any None in an insensitive ref field crashed fingerprinting with AttributeError. - Move the expressions all-None skip before _prepare_data and reuse the cached _get_refs() ref set, mirroring the fields-path guard so both read identical raw inputs. - Pin the all-vs-any semantics of the fingerprint all-None guard with a regression test on the dcim.macaddress isnull-variant matcher, and a regression test for the None-safe case-insensitive fix. Also drop an unused Location import from the test module. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
☂️ Code Coverage
Overall Coverage
New Files
Modified Files
|
Contributor
Author
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
leoparente
marked this pull request as ready for review
August 13, 2026 13:23
leoparente
requested review from
MicahParks,
davidlanouette,
jajeffries,
ltucker and
mfiedorowicz
as code owners
August 13, 2026 13:23
jajeffries
approved these changes
Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes MON-305.
Problem
Two related defects around NULL handling in object matching:
module=ref plans a seconddcim.moduleCREATE for a bay whose module was created by an earlier changeset in the same run. Since v1.12.0 the failed INSERT is recovered by adopting the existing module, but the recovery is lossy (the second CREATE's divergent fields are silently discarded for that round) and noisy (a failed INSERT plus a swallowed Postgres error per duplicate). Agents work around it by dropping the sub-bay'smodule=parent link, losing UI nesting.asset_tag: nulladopts and physically relocates an unrelated module,master: nullbinds an arbitrary masterless VirtualChassis of any name,rd: nullbinds an unrelated rd-null VRF. A sibling defect fuses two different-identity entities that share only a None-keyed fingerprint (e.g. two null-asset_tag modules), failing the plan with a merge-conflict 400. Explicitly-cleared generic refs (assigned_object,scope) crashcontent_type_id(None)and 500 the plan.Fix
All-None matcher guard (
ObjectMatchCriteria), landed first: a matcher is skipped (queryset and fingerprint) only when every referenced lookup value is None. Partial-null lookups keep today's behavior byte-identically (Django renders=NoneasIS NULL, which live clear-FK dedupe depends on — e.g. racklocation: null). Includes None-safe ContentType preparation (cleared generic refs no longer 500) and a None-safe case-insensitive fingerprint path (a null in an insensitive ref no longer crashes). Consequence worth knowing: thelogical_mac_address_within_parentisnull-variant's queryset path is functional for the first time — explicit-null MAC assignments now match by MAC + assigned-object-isnull (its path previously crashed before querying; absent-key payloads are unaffected).dcim.modulejoins_REQUIRES_PRE_SAVE_MATCH: the applier's find-first pass converts the plan-ahead duplicate CREATE into a partial update of the bay's module via the DB-backedunique_module_baymatcher — payload applied instead of discarded, sub-bay nesting restored, idempotent, no failed-INSERT noise.Behavior changes
module_type(previously the incoming payload was silently discarded for that round). A type swap retains the old type's auto-created children and does not instantiate the new type's templates — parity with today's plan-time UPDATE semantics.apply-change-setclients as well, not only the diode pipeline.asset_tagmatch may physically move a module at apply time (plan-time already had move semantics).Tests
asset_tag/master); partial-null multi-field dedupe preserved (rack); macaddress isnull-variant matches without crashing; condition-scoped null matchers unaffected; cleared-GFK payloads no longer raise; None-fingerprint fusion removed; partial-null fingerprints preserved (mutation-tested:all→anyfails).v4.4.x/v4.5.x/v4.6.xtrees; green on v4.6.0, v4.5.5, v4.4.10 plus existing matcher/apply/update suites.module=parent link + installed transceiver lands with correct nesting, and a second identical ingest converges with no changes.Follow-up
Agent-side (tracked in MON-305): with nesting proven end-to-end, discovery agents can drop the strip-the-parent-link workaround for transceiver sub-bays.
🤖 Generated with Claude Code