Skip to content

Commit 1e77a20

Browse files
feat: adding endpoints for workload and multikueuecluster
1 parent def1433 commit 1e77a20

8 files changed

Lines changed: 276 additions & 95 deletions

File tree

‎locales/en/plugin__pipelines-console-plugin.json‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@
307307
"Missing workspaces": "Missing workspaces",
308308
"More info": "More info",
309309
"Multicluster Pipeline Run": "Multicluster Pipeline Run",
310+
"MultiKueueCluster": "MultiKueueCluster",
311+
"MultiKueueClusters": "MultiKueueClusters",
310312
"Must define at least one task.": "Must define at least one task.",
311313
"Name": "Name",
312314
"Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.": "Name must consist of lower-case letters, numbers and hyphens. It must start with a letter and end with a letter or number.",
@@ -667,6 +669,8 @@
667669
"When expression was met": "When expression was met",
668670
"When expression was not met": "When expression was not met",
669671
"When expressions": "When expressions",
672+
"Workload": "Workload",
673+
"Workloads": "Workloads",
670674
"Workspace name has changed; reselect.": "Workspace name has changed; reselect.",
671675
"Workspace Resources": "Workspace Resources",
672676
"Workspaces": "Workspaces",

‎src/components/hooks/useMultiClusterProxyService.ts‎

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,41 @@ import { TektonConfigModel } from '../../models';
22
import { TektonConfig } from '../../types';
33
import { useK8sGet } from './use-k8sGet-hook';
44

5-
import { KUEUE_LABEL_PREFIX, PIPELINE_RUN_MANAGED_BY_KUEUE_LABEL } from "../../consts";
5+
import {
6+
KUEUE_LABEL_PREFIX,
7+
PIPELINE_RUN_MANAGED_BY_KUEUE_LABEL,
8+
} from '../../consts';
69

710
export type UseMultiClusterProxyOptions = {
8-
managedBy?: string,
9-
labels?: {[key: string]: string}
10-
}
11+
managedBy?: string;
12+
labels?: { [key: string]: string };
13+
};
1114

1215
/**
1316
* Hook to detect if the current cluster is a hub cluster and if the resource had executed in a Spoke Cluster
1417
* A hub cluster has TektonConfig.spec.scheduler.['multi-cluster-disabled'] === false and TektonConfig.spec.scheduler.['multi-cluster-role'] === 'hub'. (this config is propagating from operator/pkg/reconciler/shared/tektonconfig/scheduler/scheduler.go)
1518
* A resource executed on Spoke cluster has managedBy === 'kueue.x-k8s.io/multikueue' (for PLRs) or lables with prefix 'kueue.x-k8s.io' (for TRs)
1619
*
17-
* @returns { isResourceManagedByKueue } - isResourceManagedByKueue indicates if the resource had executed on a Spoke Cluster
20+
* @returns { isHub, isResourceManagedByKueue } - isHub indicates hub role; isResourceManagedByKueue indicates the resource executed on a Spoke Cluster
1821
*/
19-
export const useMultiClusterProxyService = (options: UseMultiClusterProxyOptions): {isResourceManagedByKueue: boolean} => {
22+
export const useMultiClusterProxyService = (
23+
options: UseMultiClusterProxyOptions,
24+
): { isHub: boolean; isResourceManagedByKueue: boolean } => {
2025
const [tektonConfig, loaded] = useK8sGet<TektonConfig>(
2126
TektonConfigModel,
2227
'config',
2328
);
24-
const isHub = loaded && !tektonConfig?.spec?.scheduler?.['multi-cluster-disabled'] && tektonConfig?.spec?.scheduler?.['multi-cluster-role']?.toLowerCase() === 'hub';
25-
26-
const isResourceManagedByKueue = isHub && (options?.managedBy === PIPELINE_RUN_MANAGED_BY_KUEUE_LABEL || (options?.labels && Object.keys(options?.labels).some(key => key.startsWith(KUEUE_LABEL_PREFIX))));
27-
return { isResourceManagedByKueue }
28-
};
29+
const isHub =
30+
loaded &&
31+
!tektonConfig?.spec?.kueue?.['multi-cluster-disabled'] &&
32+
tektonConfig?.spec?.kueue?.['multi-cluster-role']?.toLowerCase() === 'hub';
33+
34+
const isResourceManagedByKueue =
35+
isHub &&
36+
(options?.managedBy === PIPELINE_RUN_MANAGED_BY_KUEUE_LABEL ||
37+
(options?.labels &&
38+
Object.keys(options?.labels).some((key) =>
39+
key.startsWith(KUEUE_LABEL_PREFIX),
40+
)));
41+
return { isHub, isResourceManagedByKueue };
42+
};
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk';
2+
import { useMemo } from 'react';
3+
import { MultiKueueClusterModel, WorkloadModel } from '../../models';
4+
import { MultiKueueClusterKind, WorkloadKind } from '../../types';
5+
import { useMultiClusterProxyService } from './useMultiClusterProxyService';
6+
7+
/**
8+
* Watch MultiKueueClusters (cluster-scoped). Gated to hub clusters via TektonConfig.
9+
*/
10+
export const useMultiKueueClusters = (): [
11+
MultiKueueClusterKind[],
12+
boolean,
13+
unknown,
14+
] => {
15+
const { isHub } = useMultiClusterProxyService({});
16+
17+
const watchOptions = useMemo(
18+
() =>
19+
isHub
20+
? {
21+
isList: true,
22+
groupVersionKind: {
23+
group: MultiKueueClusterModel.apiGroup,
24+
kind: MultiKueueClusterModel.kind,
25+
version: MultiKueueClusterModel.apiVersion,
26+
},
27+
}
28+
: null,
29+
[isHub],
30+
);
31+
32+
return useK8sWatchResource<MultiKueueClusterKind[]>(watchOptions);
33+
};
34+
35+
/**
36+
* Watch Workloads in a namespace. Gated to hub clusters via TektonConfig.
37+
*/
38+
export const useWorkloads = (
39+
namespace: string,
40+
): [WorkloadKind[], boolean, unknown] => {
41+
const { isHub } = useMultiClusterProxyService({});
42+
43+
const watchOptions = useMemo(
44+
() =>
45+
isHub && namespace && namespace !== '-'
46+
? {
47+
isList: true,
48+
groupVersionKind: {
49+
group: WorkloadModel.apiGroup,
50+
kind: WorkloadModel.kind,
51+
version: WorkloadModel.apiVersion,
52+
},
53+
namespace,
54+
namespaced: true,
55+
}
56+
: null,
57+
[isHub, namespace],
58+
);
59+
60+
return useK8sWatchResource<WorkloadKind[]>(watchOptions);
61+
};

‎src/models.ts‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,3 +501,39 @@ export const GroupModel: K8sKind = {
501501
crd: true,
502502
color,
503503
};
504+
505+
export const MultiKueueClusterModel: K8sKind = {
506+
apiGroup: 'kueue.x-k8s.io',
507+
apiVersion: 'v1beta2',
508+
label: 'MultiKueueCluster',
509+
// t('plugin__pipelines-console-plugin~MultiKueueCluster')
510+
labelKey: 'MultiKueueCluster',
511+
// t('plugin__pipelines-console-plugin~MultiKueueClusters')
512+
labelPluralKey: 'MultiKueueClusters',
513+
plural: 'multikueueclusters',
514+
abbr: 'MKC',
515+
namespaced: false,
516+
kind: 'MultiKueueCluster',
517+
id: 'multikueuecluster',
518+
labelPlural: 'MultiKueueClusters',
519+
crd: true,
520+
color,
521+
};
522+
523+
export const WorkloadModel: K8sKind = {
524+
apiGroup: 'kueue.x-k8s.io',
525+
apiVersion: 'v1beta2',
526+
label: 'Workload',
527+
// t('plugin__pipelines-console-plugin~Workload')
528+
labelKey: 'Workload',
529+
// t('plugin__pipelines-console-plugin~Workloads')
530+
labelPluralKey: 'Workloads',
531+
plural: 'workloads',
532+
abbr: 'WL',
533+
namespaced: true,
534+
kind: 'Workload',
535+
id: 'workload',
536+
labelPlural: 'Workloads',
537+
crd: true,
538+
color,
539+
};

‎src/types/coreTekton.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ export interface Spec {
137137
pipeline: Pipeline;
138138
profile: string;
139139
pruner: Pruner;
140-
scheduler?: Scheduler;
140+
kueue?: Kueue;
141141
targetNamespace: string;
142142
trigger: Trigger;
143143
}
@@ -157,7 +157,7 @@ export type TektonConfig = K8sResourceCommon & {
157157
status: Status;
158158
};
159159

160-
export interface Scheduler {
160+
export interface Kueue {
161161
'multi-cluster-disabled': boolean;
162162
'multi-cluster-role': string;
163163
}

‎src/types/index.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export * from './artifacthub';
1919
export * from './backendAPI';
2020
export * from './common';
2121
export * from './coreTekton';
22+
export * from './kueue';
2223
export * from './openshift';
2324
export * from './pipeline';
2425
export * from './pipelineResource';

‎src/types/kueue.ts‎

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk';
2+
import { Condition } from './pipelineRun';
3+
4+
export type MultiKueueClusterKind = K8sResourceCommon & {
5+
spec?: {
6+
clusterSource?: {
7+
kubeConfig?: {
8+
location?: string;
9+
locationType?: string;
10+
};
11+
};
12+
};
13+
status?: {
14+
conditions?: (Condition & { observedGeneration?: number })[];
15+
};
16+
};
17+
18+
export type WorkloadPodSet = {
19+
count?: number;
20+
name?: string;
21+
template?: {
22+
metadata?: { [key: string]: unknown };
23+
spec?: {
24+
containers?: {
25+
image?: string;
26+
name?: string;
27+
resources?: {
28+
requests?: { [key: string]: string };
29+
};
30+
}[];
31+
};
32+
};
33+
};
34+
35+
export type WorkloadAdmissionCheck = {
36+
lastTransitionTime?: string;
37+
message?: string;
38+
name?: string;
39+
state?: string;
40+
};
41+
42+
export type WorkloadPodSetAssignment = {
43+
count?: number;
44+
flavors?: { [key: string]: string };
45+
name?: string;
46+
resourceUsage?: { [key: string]: string };
47+
};
48+
49+
export type WorkloadKind = K8sResourceCommon & {
50+
spec?: {
51+
active?: boolean;
52+
podSets?: WorkloadPodSet[];
53+
priority?: number;
54+
queueName?: string;
55+
};
56+
status?: {
57+
admission?: {
58+
clusterQueue?: string;
59+
podSetAssignments?: WorkloadPodSetAssignment[];
60+
};
61+
admissionChecks?: WorkloadAdmissionCheck[];
62+
clusterName?: string;
63+
conditions?: (Condition & { observedGeneration?: number })[];
64+
};
65+
};

0 commit comments

Comments
 (0)