Skip to content

kueue: ClusterQueue Cohort and Admission Checks show "-" on clusters serving only v1beta1 #1150

Description

@Shashank200345

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

  1. Connect Headlamp to a cluster running a Kueue release that serves only
    kueue.x-k8s.io/v1beta1.

  2. 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: {}
    
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions