You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
IPClaim should not carry spec.ipFamily; the class owns the family #128
IPClaim.spec.ipFamily duplicates a fact the class already owns, and the duplication is doing damage in both directions.
When spec.className is set, the field is silently ignored.ResolveClass returns LoadClass(className) without looking at the family, and everything downstream — the prefix request, the IPAllocation — reads class.Spec.IPFamily. A claim saying className: datum-vpc-ipv6, ipFamily: IPv4 allocates IPv6 and reports no error.
When it is absent, it corrupts validation.validateIPClaim sizes the prefix-length bound off the claim's own family:
A claim that names an IPv6 class, omits ipFamily, and asks for prefixLength: 64 is rejected with "must be between 1 and 32". The class knows it is IPv6; validation cannot ask, because strategy validation runs before class resolution and cannot read the database.
The data already agrees with the design: of 478 IPClasses in production, 474 have an empty spec.ipFamily. Those are the per-project references; only the 4 platform classes declare a family, resolved through spec.source.
Proposed change
Make spec.className required and remove spec.ipFamily from IPClaim.
Move the prefix-length range check out of strategy validation into Create, where the class is already resolved and spec.allowedPrefixLengths is checked. Validation then uses the authoritative family.
LoadDefaultClass and IsDefaultClassAnnotation go with it.
Subsumes the idea of adding status.classRef: if every claim names its class, there is nothing resolved to report.
Open question
Six claims in production currently use the family-only path, all created this week (*-0-eth0-f-ipv6). NSO sets ClassName: request.className when it builds claims, so either that value is empty on the endpoint path or a different producer is responsible. Tracing this is a prerequisite: if the producer genuinely cannot know class names, the answer may be a named default class per project rather than removing the selector outright.
That field carries +kubebuilder:default={IPv6}, so every NetworkInterfaceClaim requests an address by family unless someone explicitly adds spec.addresses[].class — and that path is for extra addresses, flagged external: true. The six production claims are not stragglers; they are the currently-live interfaces. Their names confirm it: familyDiscriminator renders f-ipv6, classDiscriminator renders c-<class>, and all six end in -f-ipv6.
Revised proposal
Removing spec.ipFamily would break the primary address path for every workload on the platform. Withdrawing that part.
The two defects are real and fixable without touching the contract:
className and ipFamily are not mutually exclusive. A claim setting both has one silently ignored. Reject it at validation instead, so the field cannot contradict the class.
Prefix-length validation reads the wrong family. Move the range check out of strategy validation into Create, where the class is resolved, so the bound comes from the class rather than defaulting to IPv4 when the claim says nothing.
And status.classRef is now clearly worth adding rather than optional: the family-only path is the default path, so the resolved class is unrecorded on the majority of claims, not a handful.
Retitling would be fair — this is no longer about removing the field.
Implemented in #129, as the three fixes above minus the removal: spec.className is defaulted from the resolved class at create (PVC/StorageClass shape), a family that disagrees with the class is refused rather than ignored, and the IPv4-assuming prefix-length bound is gone. spec.ipFamily stays as the selector the defaulting needs, and status.classRef is no longer needed — the answer lands in spec.
Superseded in direction by #130: the per-family default selector has never selected anything (zero IPv4 classes, claims or pools in either environment), so the follow-on is one default class per project and no spec.ipFamily on IPClaim at all. #129 still stands on its own — defaulting spec.className and the prefix-length bound are correct under either model, and refusing a mismatched family is the right guard until #130 lands.
Activity
scotwells commentedon Sep 23, 2026
Producer traced: this is the default path, not a stray caller
The family-only claims come from NSO's
networkinterfaceclaim_controller.go, and deliberately:request.classNameis empty for every request built fromNetworkInterfaceClaim.spec.ipFamilies:That field carries
+kubebuilder:default={IPv6}, so every NetworkInterfaceClaim requests an address by family unless someone explicitly addsspec.addresses[].class— and that path is for extra addresses, flaggedexternal: true. The six production claims are not stragglers; they are the currently-live interfaces. Their names confirm it:familyDiscriminatorrendersf-ipv6,classDiscriminatorrendersc-<class>, and all six end in-f-ipv6.Revised proposal
Removing
spec.ipFamilywould break the primary address path for every workload on the platform. Withdrawing that part.The two defects are real and fixable without touching the contract:
classNameandipFamilyare not mutually exclusive. A claim setting both has one silently ignored. Reject it at validation instead, so the field cannot contradict the class.Create, where the class is resolved, so the bound comes from the class rather than defaulting to IPv4 when the claim says nothing.And
status.classRefis now clearly worth adding rather than optional: the family-only path is the default path, so the resolved class is unrecorded on the majority of claims, not a handful.Retitling would be fair — this is no longer about removing the field.
scotwells commentedon Sep 23, 2026
Implemented in #129, as the three fixes above minus the removal:
spec.classNameis defaulted from the resolved class at create (PVC/StorageClass shape), a family that disagrees with the class is refused rather than ignored, and the IPv4-assuming prefix-length bound is gone.spec.ipFamilystays as the selector the defaulting needs, andstatus.classRefis no longer needed — the answer lands in spec.scotwells commentedon Sep 23, 2026
Superseded in direction by #130: the per-family default selector has never selected anything (zero IPv4 classes, claims or pools in either environment), so the follow-on is one default class per project and no
spec.ipFamilyon IPClaim at all. #129 still stands on its own — defaultingspec.classNameand the prefix-length bound are correct under either model, and refusing a mismatched family is the right guard until #130 lands.