docs(netbox_ip_address): clarify state=present identity semantics + query_params escape hatch (#1030)#1572
Draft
ldrozdz93 wants to merge 1 commit into
Draft
docs(netbox_ip_address): clarify state=present identity semantics + query_params escape hatch (#1030)#1572ldrozdz93 wants to merge 1 commit into
ldrozdz93 wants to merge 1 commit into
Conversation
…uery_params escape hatch (#1030) By default an existing IP is matched on its assignment as well as its address, so the same address with a different assignment creates a new (duplicate) IP rather than updating the existing one. This is intentional (NetBox permits duplicate addresses for anycast/VRRP), but it was undocumented, so users repeatedly hit it as a surprise on #1030. Document the semantics explicitly in the module docs, describe the query_params: ['address'] escape hatch for update-in-place with a worked example, and add integration coverage proving the update-in-place path and a clean idempotent re-run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR clarifies the netbox_ip_address module’s state: present identity/lookup semantics (especially around assignment-aware matching and intentional duplicate-address behavior in NetBox) and adds integration coverage demonstrating the documented query_params “update-in-place” pattern.
Changes:
- Document how
state: presentdetermines whether an IP “already exists”, and how to force address-only matching viaquery_params. - Add a new module example showing the address-only
query_paramsapproach to move an IP to a different interface. - Add v4.4 and v4.5 integration tasks asserting update-in-place (same object id), idempotency, and cleanup.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
plugins/modules/netbox_ip_address.py |
Expands module docs for state: present identity semantics and adds an example using query_params. |
tests/integration/targets/v4.4/tasks/netbox_ip_address.yml |
Adds integration tasks validating “move in place” via query_params: [address] and idempotency. |
tests/integration/targets/v4.5/tasks/netbox_ip_address.yml |
Same as v4.4, using the v4.5 token fixture pattern. |
changelogs/fragments/1030-ip-address-identity-semantics.yml |
Adds a minor changelog entry describing the documentation update and escape hatch. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+159
to
+168
| - | | ||
| Identity for C(present) - an existing IP is matched on its assignment as | ||
| well as its address. The lookup keys are C(address), C(vrf), C(device), | ||
| C(interface) and C(assigned_object). The same C(address) with a | ||
| different assignment therefore does not match the existing record, and a | ||
| new (duplicate) IP is created. This is intentional, because NetBox | ||
| permits duplicate addresses (for example anycast or VRRP). To update an | ||
| existing address in place regardless of its assignment, narrow the match | ||
| to the address alone with C(query_params=['address']) on the task (see | ||
| the I(query_params) option and the examples below). |
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.
What this does
Makes the identity rules for
netbox_ip_addresswithstate: presentexplicit, and documents how to update an address in place.When you run
netbox_ip_addresswithstate: present, the module decides whether an IP "already exists" by matching on its assignment as well as its address — the lookup keys areaddress,vrf,device,interfaceandassigned_object. So if you give the sameaddressbut a different assignment (for example moving an IP from one interface or VM to another), the module does not find the existing record and creates a second, duplicate IP instead of updating the one you meant.This is intentional — NetBox itself permits duplicate addresses (anycast, VRRP), so "the address already exists" can't be treated as automatically meaning "update it". But the behaviour was undocumented, which is why it keeps surprising people (issue #1030 has a long thread of users expecting an update and getting a duplicate).
This change keeps the existing default behaviour unchanged and instead documents it clearly, and documents the supported way to get update-in-place.
Changes
netbox_ip_address) — thestatedescription now spells out that an existing IP is matched on its assignment as well as its address, why that is (duplicate addresses are legitimate in NetBox), and that you can narrow the match to the address alone withquery_params: ['address']to update an existing address regardless of its assignment.query_params: ['address']update-in-place pattern.query_params: ['address']update it onto a different interface (same record id, no duplicate), and prove a clean re-run reports no change.Identity semantics — decision
Three options were on the table for resolving #1030: (a) keep today's default and document it plus the
query_paramsescape hatch; (b) change the default so identity is address-only; (c) add a new option/state for update-in-place. This PR takes (a).Option (b) is deliberately avoided because it would be a breaking change: playbooks that today rely on assignment-aware identity to create intentional duplicates (anycast/VRRP) would silently start updating an existing record instead. Documenting the existing, already-supported
query_params: ['address']hatch resolves the confusion without changing behaviour for anyone.Out of scope
The thread on #1030 also mentions
primary_ip4/oob_ipbeing silently ignored onnetbox_device. That is a separate module and a separate behaviour; it is not addressed here.Testing
black,yamllint,ansible-lint(production profile),antsibull-changelog lint, andvalidate-modulessanity on the module: all passing.netbox-deploy.pyfixtures (test100/GigabitEthernet1/GigabitEthernet2) but were not executed here; the new tasks only ever reference a single address (198.51.100.50/24) and update it in place, so they never create a true duplicate and do not depend on NetBox's duplicate-address enforcement setting.Fixes #1030.