Background
We are integrating milo-os/ipam into datum-cloud/network-services-operator as the IPAM backend for a cloud networking platform. During design, we identified that IPAddress/IPAddressClaim and IPPrefix/IPPrefixClaim are mathematically the same concept — a single host address is just a prefix with prefixLength: 128 (IPv6) or prefixLength: 32 (IPv4).
The IPAM service's own database schema reflects this: both resource types write to ipam_prefix_allocations, with only the is_child_pool flag distinguishing them. The core allocation algorithm FindFirstAvailableBlock in internal/allocation/cidr.go is identical for both cases.
Proposal
Remove IPAddress and IPAddressClaim as distinct resource types. Treat a single host address as an IPPrefixClaim with prefixLength: 128. The childPrefixTemplate and capacity tracking on IPPrefix simply become irrelevant at /128 — no enforcement needed.
This gives a natural continuum across a single resource type:
IPPrefixClaim { prefixLength: 48 } → network pool
IPPrefixClaim { prefixLength: 56 } → regional delegation
IPPrefixClaim { prefixLength: 64 } → subnet
IPPrefixClaim { prefixLength: 128 } → single host address
Benefits
- Reduces the API surface from four resource types to two (
IPPrefix, IPPrefixClaim)
- Consumers only need one claim type regardless of whether they want a single IP or a subnet — controlled by
prefixLength
- Eliminates a conceptual split that doesn't exist at the storage or algorithm layer
- Simplifies client code that currently needs to branch between
IPAddressClaim and IPPrefixClaim depending on allocation size
Impact on Consumers
In datum-cloud/network-services-operator, NetworkInterface resources need to allocate either a single address (/128) or an entire subnet (e.g., /64) depending on the interface type. With consolidation, this becomes a single ipPrefixClaimTemplate field with a prefixLength parameter rather than two separate mutually exclusive template fields (ipAddressClaimTemplate vs ipPrefixClaimTemplate).
The integration also spans datum-cloud/compute, which creates NetworkInterfaceClaim resources that flow down through NSO to IPAM for address allocation.
Things to Verify Before Implementing
References
Background
We are integrating
milo-os/ipamintodatum-cloud/network-services-operatoras the IPAM backend for a cloud networking platform. During design, we identified thatIPAddress/IPAddressClaimandIPPrefix/IPPrefixClaimare mathematically the same concept — a single host address is just a prefix withprefixLength: 128(IPv6) orprefixLength: 32(IPv4).The IPAM service's own database schema reflects this: both resource types write to
ipam_prefix_allocations, with only theis_child_poolflag distinguishing them. The core allocation algorithmFindFirstAvailableBlockininternal/allocation/cidr.gois identical for both cases.Proposal
Remove
IPAddressandIPAddressClaimas distinct resource types. Treat a single host address as anIPPrefixClaimwithprefixLength: 128. ThechildPrefixTemplateand capacity tracking onIPPrefixsimply become irrelevant at/128— no enforcement needed.This gives a natural continuum across a single resource type:
Benefits
IPPrefix,IPPrefixClaim)prefixLengthIPAddressClaimandIPPrefixClaimdepending on allocation sizeImpact on Consumers
In
datum-cloud/network-services-operator,NetworkInterfaceresources need to allocate either a single address (/128) or an entire subnet (e.g.,/64) depending on the interface type. With consolidation, this becomes a singleipPrefixClaimTemplatefield with aprefixLengthparameter rather than two separate mutually exclusive template fields (ipAddressClaimTemplatevsipPrefixClaimTemplate).The integration also spans
datum-cloud/compute, which createsNetworkInterfaceClaimresources that flow down through NSO to IPAM for address allocation.Things to Verify Before Implementing
FindFirstAvailableBlockhandles/128claims against a/64parent pool correctly (expected: yes, since it operates on prefix lengths generically)IPPrefixhandles the case whereprefixLength == 128without breaking utilization metricschildPrefixTemplateis simply a no-op / not applicable whenprefixLength == 128IPAddressClaimReferences
internal/allocation/cidr.go—FindFirstAvailableBlockinternal/allocator/prefix.go—AllocatePrefixmigrations/001_initial_schema.sql—ipam_prefix_allocationstable (note: bothIPAddressandIPPrefixallocations already share this table)pkg/apis/ipam/v1alpha1/types.go— current type definitionsdatum-cloud/network-services-operator— primary consumer driving this requestdatum-cloud/compute— upstream compute operator