Description
kueueApiVersions registers two API versions, and kueueApi.test.ts asserts that
this is deliberate:
export const kueueApiVersions = [`${kueueApiGroup}/v1beta2`, `${kueueApiGroup}/v1beta1`];
Headlamp honours that fallback. KubeObject.apiEndpoint maps the array into
per-version factory arguments, and multipleApiFactory documents its behaviour as
"It first tries the first endpoint, then the second, and so on until it gets a
successful response." So on a cluster where only kueue.x-k8s.io/v1beta1 is
served, the plugin lists ClusterQueues successfully via v1beta1.
The ClusterQueueSpec type, however, was written from the v1beta2 reference alone
— every @see link points at kueue.v1beta2 — so two fields that Kueue renamed
or restructured between the versions are never read.
Kueue's own conversion code names both:
func Convert_v1beta1_ClusterQueueSpec_To_v1beta2_ClusterQueueSpec(...) {
out.CohortName = v1beta2.CohortReference(in.Cohort)
...
out.AdmissionChecksStrategy = &v1beta2.AdmissionChecksStrategy{...}
| Field |
v1beta1 |
v1beta2 |
| Cohort |
spec.cohort |
spec.cohortName |
| Admission checks |
spec.admissionChecks: string[] |
spec.admissionChecksStrategy.admissionChecks[].name |
get cohortName() reads only spec.cohortName, and admissionChecksDisplay
passes only spec.admissionChecksStrategy to renderAdmissionChecks.
Steps to reproduce
-
Connect Headlamp to a cluster running a Kueue release that serves only
kueue.x-k8s.io/v1beta1.
-
Apply a ClusterQueue with a cohort and an admission check:
apiVersion: kueue.x-k8s.io/v1beta1
kind: ClusterQueue
metadata:
name: team-a
spec:
cohort: research
admissionChecks:
- prov-request
namespaceSelector: {}
-
Open Kueue > ClusterQueues, and the detail page for team-a.
Actual
The Cohort column in the list and the Cohort row on the detail page both read -.
The Admission Checks row reads -. Measured against the current getters:
{ "cohort": "-", "admissionChecks": "-" }
Expected
{ "cohort": "research", "admissionChecks": "prov-request (all flavors)" }
Cohorts are the mechanism by which ClusterQueues borrow unused quota from each
other, so this hides a relationship rather than an optional detail. Admission
checks gate whether a workload can be admitted at all.
Proposed fix
Resolve both shapes before rendering. The v1beta1 admission check form carries no
per-flavor scoping, so those entries render as applying to all flavors.
I have this working with tests. The plugin's resource classes can't be unit tested
under Vitest because they import KubeObject, a build-time virtual module, which
is why the existing tests only exercise the pure *Formatters modules. So the
resolvers belong in a pure module the class delegates to, matching that structure.
Happy to open a PR.
Note
There is a third v1beta1/v1beta2 difference I have not treated as a bug:
flavorFungibility.whenCanBorrow and whenCanPreempt used Borrow and Preempt
in v1beta1, which v1beta2 renamed to MayStopSearch. The plugin's TypeScript union
lists only the v1beta2 values, but the renderer prints whatever string the API
returned, so the display stays correct. That is a type-completeness gap.
Kueue also ships conversion files for LocalQueue, Workload and MultiKueue, so the
same class of gap may exist there. Those files are currently touched by open PRs
(#1068, #1046), so I have left them alone.
Environment
- kueue plugin,
main @ (current)
- @kinvolk/headlamp-plugin 0.14.0
Description
kueueApiVersionsregisters two API versions, andkueueApi.test.tsasserts thatthis is deliberate:
Headlamp honours that fallback.
KubeObject.apiEndpointmaps the array intoper-version factory arguments, and
multipleApiFactorydocuments its behaviour as"It first tries the first endpoint, then the second, and so on until it gets a
successful response." So on a cluster where only
kueue.x-k8s.io/v1beta1isserved, the plugin lists ClusterQueues successfully via v1beta1.
The
ClusterQueueSpectype, however, was written from the v1beta2 reference alone— every
@seelink points atkueue.v1beta2— so two fields that Kueue renamedor restructured between the versions are never read.
Kueue's own conversion code names both:
spec.cohortspec.cohortNamespec.admissionChecks: string[]spec.admissionChecksStrategy.admissionChecks[].nameget cohortName()reads onlyspec.cohortName, andadmissionChecksDisplaypasses only
spec.admissionChecksStrategytorenderAdmissionChecks.Steps to reproduce
Connect Headlamp to a cluster running a Kueue release that serves only
kueue.x-k8s.io/v1beta1.Apply a ClusterQueue with a cohort and an admission check:
Open Kueue > ClusterQueues, and the detail page for
team-a.Actual
The Cohort column in the list and the Cohort row on the detail page both read
-.The Admission Checks row reads
-. Measured against the current getters:Expected
Cohorts are the mechanism by which ClusterQueues borrow unused quota from each
other, so this hides a relationship rather than an optional detail. Admission
checks gate whether a workload can be admitted at all.
Proposed fix
Resolve both shapes before rendering. The v1beta1 admission check form carries no
per-flavor scoping, so those entries render as applying to all flavors.
I have this working with tests. The plugin's resource classes can't be unit tested
under Vitest because they import
KubeObject, a build-time virtual module, whichis why the existing tests only exercise the pure
*Formattersmodules. So theresolvers belong in a pure module the class delegates to, matching that structure.
Happy to open a PR.
Note
There is a third v1beta1/v1beta2 difference I have not treated as a bug:
flavorFungibility.whenCanBorrowandwhenCanPreemptusedBorrowandPreemptin v1beta1, which v1beta2 renamed to
MayStopSearch. The plugin's TypeScript unionlists only the v1beta2 values, but the renderer prints whatever string the API
returned, so the display stays correct. That is a type-completeness gap.
Kueue also ships conversion files for LocalQueue, Workload and MultiKueue, so the
same class of gap may exist there. Those files are currently touched by open PRs
(#1068, #1046), so I have left them alone.
Environment
main@ (current)