The class status controller, the admission webhooks and the API
server's budget check all need the same answers: which units of a
class are free on a node, which classes clash on a resource name,
how a budget key is spelled, and whether a namespace is entitled to
vGPU. Kept in one package of pure functions, each rule has a single
implementation that every component calls, tested without a cluster.
Free units come from Node allocatable and pod requests alone, so no
inventory kind or node agent is needed. A node counts only while it
is Ready, not cordoned and carries no NoSchedule or NoExecute taint
the class does not tolerate, except the three taints Kubernetes sets
for a cordon or a node that is not Ready, which the first two rules
already decide.
Budget keys follow DRA's class-scoped form, so a key never collides
with a resource name a device plugin advertises, the key without a
class prefix needs no reserved class name, and any key in the domain
is recognised as a budget even when it is malformed.
When two classes share a resource name, the older one keeps it and
the newer one is in conflict, so a mistyped new class cannot take an
offer tenants already run on out of service.
Assisted-by: LLM
Signed-off-by: Aleksei Sviridkin <f@lex.la>