feat(node): number pool attach/detach, provenance and declared ranges
Merged
AJ
4d ago+1219+1219+0123456789012345678901234567890123456789-92-92-01234567890123456789
Why
Infrahub 1.12 adds number-pool features that SDK users cannot use today:
- Detaching a number from its pool, by sending
from_pool: nullon an update (IFC-3333). The SDK has no way to send it. Attaching a number the user already holds (valueandfrom_pooltogether) has the same problem: on create, the SDK sends onlyfrom_pool, so the pool allocates a new number instead of attaching the given one. - Reading whether the pool allocated each number or a user provided it, from the
provenancefield ofInfrahubResourcePoolAllocated(IFC-3367).get_pool_allocated_resources()returns only the nodes and drops every row field. - Creating a number pool with its ranges in one call (IFC-3369). The pool mutations take
rangesasNumberPoolRangeInput(start,end,allocation_weight), but the SDK sends every relationship peer as a reference, soranges=[{"start": 1, "end": 10}]reaches Infrahub as[{}]: one range with no start and no end.
Closes IFC-3333, IFC-3367, IFC-3369
What changed
Attach and detach a number (IFC-3333)
- Number attributes have
attach_to_pool(pool)anddetach_from_pool(). Both are sent on the next save.attach_to_pool()sends the number the attribute holds withfrom_pool, so the pool tracks it as provided. It raisesValueErrorwhen the attribute holds no number, or when it is given a node that is not a resource pool or has not been saved.detach_from_pool()sendsfrom_pool: null. The attribute keeps its number. On a node that is not saved yet, the number is sent with the detach so the node is created with it.
- An attribute built with both
valueandfrom_poolnow sends both, so the pool attaches the given number instead of allocating a new one. - A
from_poolrequest is sent once. A private pending flag is cleared after a successful mutation, so the next update does not send it again._from_poolstays set, sois_from_pool_attribute()still returnsTrueafter a save. - The
IntegerandIntegerOptionalprotocols declare the two methods for typed code.
List a pool's allocations with their provenance (IFC-3367)
- Resource pool nodes have
get_pool_allocations(resource), async and sync. It returnsPoolAllocationentries (node ID, kind, branch, display label, identifier, provenance) without fetching the nodes. provenanceisPoolAllocationProvenance.ALLOCATED,PoolAllocationProvenance.PROVIDED, orNonefor IP pools.get_pool_allocated_resources()is unchanged. It shares the paging loop but does not requestprovenance, so it keeps working against servers older than 1.12.
Create a number pool with its ranges (IFC-3369)
- A relationship whose peer kind is
CoreNumberPoolRangesends the peer's fields instead of a reference, matching how Infrahub picksNumberPoolRangeInputfor that peer kind. The rule lives in one place:INLINE_INPUT_PEER_KINDSandRelatedNodeBase. client.create(kind="CoreNumberPool", ..., ranges=[{"start": 100, "end": 199, "allocation_weight": 10}])creates the pool and its ranges in one mutation.save(allow_upsert=True)sets an existing pool's ranges to the declared list.- Single ranges of an existing pool are added, changed or deleted through
CoreNumberPoolRangenodes, which already worked. Infrahub refuses edits made through the pool'srangesrelationship (Field 'id' is not defined by type 'NumberPoolRangeInput').
What stayed the same
- No schema or protocol generation changes.
- Every relationship other than one whose peer kind is
CoreNumberPoolRangeis serialized as before.
How to review
Suggested order, one commit per ticket:
1d55171battach and detach:node/attribute.pyand the twonode.pyhunks (clearing the pending flag in_process_mutation_result, and keepingvaluenext tofrom_poolin_strip_unmodified_dict).ef09423fprovenance:PoolAllocation, the shared query builder and paging loop innode.py.3204d16cranges:node/related_node.pyandnode/constants.py. It also removes a secondself._relationship_metadata = NoneinRelatedNodeBase.__init__, which the constructor already sets just above.2ed22456integration test.
docs/docs/python-sdk/sdk_ref/ is generated.
Impact & rollout
- Backward compatibility:
- A save no longer resends
from_poolafter it succeeded. Before, the next update sent{"from_pool": ...}again, which Infrahub ignored. rangesdicts on aCoreNumberPoolare now sent as range definitions instead of empty objects.
- A save no longer resends
- Deployment notes: the new features need Infrahub 1.12 or later.
Checklist
- Tests added/updated
- Changelog entry added
- External docs updated (resource manager guide, generated SDK reference)
- Internal .md docs updated (none needed)
- reviewed LLM-generated code
š¤ Generated with Claude Code
Summary by cubic
Adds SDK support for the Infrahub 1.12 number-pool features: attaching or detaching a number from a pool, reading how each allocation came to be held, and declaring a pool's ranges on create or upsert.
- Number attributes get
attach_to_pool()anddetach_from_pool(), both sent on the next save. Creating an attribute with bothvalueandfrom_poolnow sends both, so the pool tracks the given number instead of allocating a new one. - Resource pool nodes get
get_pool_allocations(), returningPoolAllocationentries withprovenanceofALLOCATEDorPROVIDED(Nonefor IP pools).get_pool_allocated_resources()still requests noprovenance, so it keeps working against Infrahub before 1.12. - A
CoreNumberPoolcan be created withrangesas dicts ofstart,endandallocation_weight; before, each range reached Infrahub as an empty object.
Behavior changes
- A
from_poolrequest is sent once instead of being resent on every update. - Saving with
allow_upsert=Truesets an existing pool's ranges to the declared list. - The new features require Infrahub 1.12 or later.