diff --git a/kueue/src/components/workloads/Detail.tsx b/kueue/src/components/workloads/Detail.tsx index 95d49b4d11..ac8e556657 100644 --- a/kueue/src/components/workloads/Detail.tsx +++ b/kueue/src/components/workloads/Detail.tsx @@ -17,6 +17,7 @@ import { } from '../../resources/workload'; import { renderPodSetRequests, + renderPodSetUpdates, renderResourceList, renderStringMap, renderText, @@ -70,6 +71,7 @@ interface AdmissionCheckRow { requeueAfterSeconds: number | string; /** Retry count. */ retryCount: number | string; + podSetUpdates: string; } /** Row rendered for status.reclaimablePods. */ @@ -164,6 +166,7 @@ function getAdmissionCheckRows(admissionChecks: AdmissionCheckState[] = []): Adm message: renderText(admissionCheck.message), requeueAfterSeconds: admissionCheck.requeueAfterSeconds ?? '-', retryCount: admissionCheck.retryCount ?? '-', + podSetUpdates: renderPodSetUpdates(admissionCheck.podSetUpdates), })); } @@ -340,6 +343,10 @@ function getAdmissionChecksSection(workload: Workload) { label: 'Retry Count', getter: (row: AdmissionCheckRow) => row.retryCount, }, + { + label: 'Pod Set Updates', + getter: (row: AdmissionCheckRow) => row.podSetUpdates, + }, ]} /> diff --git a/kueue/src/resources/workload.ts b/kueue/src/resources/workload.ts index cd775d55ff..33ac176ad2 100644 --- a/kueue/src/resources/workload.ts +++ b/kueue/src/resources/workload.ts @@ -414,6 +414,20 @@ export interface PodSetRequest { resources?: ResourceList; } +/** + * Pod set modifications suggested by an AdmissionCheck for a Workload pod set. + * + * @see https://kueue.sigs.k8s.io/docs/reference/kueue.v1beta2/#podsetupdate + */ +export interface PodSetUpdate { + name: string; + labels?: Record; + annotations?: Record; + nodeSelector?: Record; + tolerations?: unknown[]; + schedulingGates?: { name: string }[]; +} + /** * Admission check state reported for a Workload. * @@ -456,6 +470,9 @@ export interface AdmissionCheckState { * @see https://kueue.sigs.k8s.io/docs/reference/kueue.v1beta2/#admissioncheckstate */ retryCount?: number; + + /** Pod set modifications suggested by this AdmissionCheck. */ + podSetUpdates?: PodSetUpdate[]; } /** diff --git a/kueue/src/resources/workloadFormatters.test.ts b/kueue/src/resources/workloadFormatters.test.ts index 5927942106..6d06f2df17 100644 --- a/kueue/src/resources/workloadFormatters.test.ts +++ b/kueue/src/resources/workloadFormatters.test.ts @@ -16,6 +16,7 @@ import { renderOwnerReferences, renderPodSetRequests, renderPodSetsSummary, + renderPodSetUpdates, renderPriority, renderPriorityClassName, renderQueueName, @@ -45,6 +46,13 @@ describe('Workload formatters', () => { expect(renderBoolean(undefined)).toBe('-'); }); + it('formats admission check pod set updates', () => { + expect(renderPodSetUpdates()).toBe('-'); + expect( + renderPodSetUpdates([{ name: 'main', labels: { role: 'worker' } }, { name: 'sidecar' }]) + ).toBe('main: labels role=worker | sidecar: -'); + }); + it('formats common Workload list values', () => { expect(renderQueueName('sample-local-queue')).toBe('sample-local-queue'); expect(renderQueueName()).toBe('-'); diff --git a/kueue/src/resources/workloadFormatters.ts b/kueue/src/resources/workloadFormatters.ts index cb6cd59bbc..cb754360fc 100644 --- a/kueue/src/resources/workloadFormatters.ts +++ b/kueue/src/resources/workloadFormatters.ts @@ -2,6 +2,7 @@ import type { KubeOwnerReference } from '@kinvolk/headlamp-plugin/lib/k8s/cluste import type { Admission, PodSet, + PodSetUpdate, ReclaimablePod, RequeueState, ResourceList, @@ -272,6 +273,29 @@ export function renderRequeueState(requeueState?: RequeueState) { return values.length > 0 ? values.join('; ') : '-'; } +/** Render the pod set modifications suggested by an AdmissionCheck. */ +export function renderPodSetUpdates(podSetUpdates: PodSetUpdate[] = []) { + if (podSetUpdates.length === 0) { + return '-'; + } + + return podSetUpdates + .map(update => { + const parts = [ + renderStringMap(update.labels) !== '-' ? `labels ${renderStringMap(update.labels)}` : '', + renderStringMap(update.annotations) !== '-' + ? `annotations ${renderStringMap(update.annotations)}` + : '', + renderStringMap(update.nodeSelector) !== '-' + ? `nodeSelector ${renderStringMap(update.nodeSelector)}` + : '', + ].filter(Boolean); + + return parts.length ? `${update.name}: ${parts.join('; ')}` : `${update.name}: -`; + }) + .join(' | '); +} + /** Render owner references without dumping raw objects. */ export function renderOwnerReferences(ownerReferences: KubeOwnerReference[] = []) { if (ownerReferences.length === 0) {