Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions kueue/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,26 @@ See the [Kueue getting started guide](https://kueue.sigs.k8s.io/docs/getting-sta

## Current Scope

This plugin currently reads Kueue `ClusterQueue`, `LocalQueue`, `ResourceFlavor`, and `Workload` resources from the Kubernetes API and displays them in basic list and detail pages. It registers a Kueue sidebar section with entries for these resources.
This plugin currently reads Kueue `Cohort`, `ClusterQueue`, `LocalQueue`, `ResourceFlavor`, and `Workload` resources from the Kubernetes API and displays them in basic list and detail pages. It registers a Kueue sidebar section with entries for these resources.

The views are read-only. Cohort pages show parent and child Cohort relationships, member ClusterQueues, ResourceFlavor references, resource groups, and fair-sharing values.

Additional queueing views will be added in later PRs.

## Prerequisites

Kueue CRDs must be installed in the cluster before the plugin can list resources. See the [Kueue installation guide](https://kueue.sigs.k8s.io/docs/getting-started/installation/) for installation instructions.

You can check for the `ClusterQueue`, `LocalQueue`, `ResourceFlavor`, and `Workload` CRDs and resources with:
You can check for the `Cohort`, `ClusterQueue`, `LocalQueue`, `ResourceFlavor`, and `Workload` CRDs and resources with:

```bash
kubectl get crd cohorts.kueue.x-k8s.io
kubectl get crd clusterqueues.kueue.x-k8s.io
kubectl get crd localqueues.kueue.x-k8s.io
kubectl get crd resourceflavors.kueue.x-k8s.io
kubectl get crd workloads.kueue.x-k8s.io
kubectl get cohorts
kubectl get cohort default -o yaml
kubectl get clusterqueues
kubectl get localqueues -A
kubectl get localqueue <name> -n <namespace> -o yaml
Expand All @@ -31,21 +36,23 @@ kubectl get workload <name> -n <namespace> -o yaml

## Test Files

Sample `ClusterQueue`, `LocalQueue`, `ResourceFlavor`, and Job manifests are available in `test-files/deploy/`. The sample Job uses the `team-a-queue` LocalQueue so Kueue can create a real `Workload` for local UI testing.
Sample `Cohort`, `ClusterQueue`, `LocalQueue`, `ResourceFlavor`, and Job manifests are available in `test-files/deploy/`. The sample ClusterQueue belongs to the `default` Cohort, and the sample Job uses the `team-a-queue` LocalQueue so Kueue can create a real `Workload` for local UI testing.

Apply them to a cluster with Kueue installed:

```bash
kubectl apply -f test-files/deploy/resourceflavor-default.yaml
kubectl apply -f test-files/deploy/resourceflavor-spot.yaml
kubectl apply -f test-files/deploy/resourceflavor-topology.yaml
kubectl apply -f test-files/deploy/cohort-default.yaml
kubectl apply -f test-files/deploy/clusterqueue-team-a.yaml
kubectl apply -f test-files/deploy/localqueue-team-a.yaml
kubectl apply -f test-files/deploy/job-sample-workload.yaml
kubectl get cohorts
kubectl get workloads -A
```

After applying the examples, open `Kueue` > `ClusterQueues`, `Kueue` > `LocalQueues`, `Kueue` > `ResourceFlavors`, or `Kueue` > `Workloads` in Headlamp.
After applying the examples, open `Kueue` > `Cohorts`, `Kueue` > `ClusterQueues`, `Kueue` > `LocalQueues`, `Kueue` > `ResourceFlavors`, or `Kueue` > `Workloads` in Headlamp.

## Development

Expand Down
90 changes: 7 additions & 83 deletions kueue/src/components/clusterqueues/Detail.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,14 @@
import {
ConditionsSection,
DetailsGrid,
Link,
SectionBox,
SimpleTable,
} from '@kinvolk/headlamp-plugin/lib/components/common';
import { useParams } from 'react-router-dom';
import {
ClusterQueue,
FlavorUsage,
ResourceGroup,
ResourceQuota,
} from '../../resources/clusterQueue';
import { kueueRouteNames } from '../../utils/kueueRoutes';
import { ClusterQueue, FlavorUsage } from '../../resources/clusterQueue';
import { getResourceGroupRows, ResourceGroupRow } from '../../resources/clusterQueueFormatters';
import KueueAdminResourceAccess from '../common/KueueAdminResourceAccess';

/** Flattened row rendered in the ClusterQueue resource groups table. */
interface ResourceGroupRow {
/** Display label for the resource group index from spec.resourceGroups. */
group: string;
/** Comma-separated resources covered by this group, such as cpu and memory. */
coveredResources: string;
/** ResourceFlavor name associated with this resource quota row. */
flavor: string;
/** Resource name within the flavor quota, for example cpu or memory. */
resource: string;
/** Guaranteed quota configured for the resource and flavor pair. */
nominalQuota: string | number;
/** Optional quota this ClusterQueue can borrow from the cohort. */
borrowingLimit?: string | number;
/** Optional quota this ClusterQueue can lend to the cohort. */
lendingLimit?: string | number;
}
import { renderCohortLink, renderResourceFlavorLink } from '../common/KueueResourceLinks';

/** Flattened row rendered for status flavor reservations or flavor usage. */
interface FlavorUsageRow {
Expand All @@ -53,59 +30,6 @@ interface AdmissionCheckRow {
flavors: string[];
}

/** Render a ResourceFlavor name as a Headlamp link to its detail page. */
function renderFlavorLink(flavorName: string) {
return (
<Link routeName={kueueRouteNames.resourceFlavorDetail} params={{ name: flavorName }}>
{flavorName}
</Link>
);
}

/** Convert nested ClusterQueue resource groups into table rows. */
function getResourceGroupRows(resourceGroups: ResourceGroup[]): ResourceGroupRow[] {
return resourceGroups.flatMap((group, groupIndex): ResourceGroupRow[] => {
const groupLabel = `Group ${groupIndex + 1}`;
const coveredResources = group.coveredResources?.join(', ') || '-';

if (!group.flavors?.length) {
return [
{
group: groupLabel,
coveredResources,
flavor: '-',
resource: '-',
nominalQuota: '-',
},
];
}

return group.flavors.flatMap((flavor): ResourceGroupRow[] => {
if (!flavor.resources?.length) {
return [
{
group: groupLabel,
coveredResources,
flavor: flavor.name,
resource: '-',
nominalQuota: '-',
},
];
}

return flavor.resources.map((resource: ResourceQuota) => ({
group: groupLabel,
coveredResources,
flavor: flavor.name,
resource: resource.name,
nominalQuota: resource.nominalQuota,
borrowingLimit: resource.borrowingLimit,
lendingLimit: resource.lendingLimit,
}));
});
});
}

/** Convert status flavor usage or reservation entries into table rows. */
function getFlavorUsageRows(flavorUsage: FlavorUsage[] = []): FlavorUsageRow[] {
return flavorUsage.flatMap(flavor => {
Expand Down Expand Up @@ -163,7 +87,7 @@ function getResourceGroupsSection(clusterQueue: ClusterQueue) {
{
label: 'ResourceFlavor',
getter: (row: ResourceGroupRow) =>
row.flavor === '-' ? '-' : renderFlavorLink(row.flavor),
row.flavor === '-' ? '-' : renderResourceFlavorLink(row.flavor),
},
{
label: 'Resource',
Expand Down Expand Up @@ -206,7 +130,7 @@ function getFlavorUsageSection(title: string, id: string, flavorUsage?: FlavorUs
{
label: 'ResourceFlavor',
getter: (row: FlavorUsageRow) =>
row.flavor === '-' ? '-' : renderFlavorLink(row.flavor),
row.flavor === '-' ? '-' : renderResourceFlavorLink(row.flavor),
},
{
label: 'Resource',
Expand Down Expand Up @@ -254,7 +178,7 @@ function getAdmissionChecksSection(clusterQueue: ClusterQueue) {
{row.flavors.map((flavor, index) => (
<span key={flavor}>
{index > 0 ? ', ' : ''}
{renderFlavorLink(flavor)}
{renderResourceFlavorLink(flavor)}
</span>
))}
</>
Expand Down Expand Up @@ -296,7 +220,7 @@ export default function ClusterQueueDetail() {
? [
{
name: 'Cohort',
value: clusterQueue.cohortName,
value: renderCohortLink(clusterQueue.spec.cohortName),
},
{
name: 'Queueing Strategy',
Expand Down
2 changes: 2 additions & 0 deletions kueue/src/components/clusterqueues/List.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ResourceListView } from '@kinvolk/headlamp-plugin/lib/CommonComponents';
import { ClusterQueue } from '../../resources/clusterQueue';
import KueueAdminResourceAccess from '../common/KueueAdminResourceAccess';
import { renderCohortLink } from '../common/KueueResourceLinks';

export default function ClusterQueueList() {
return (
Expand All @@ -18,6 +19,7 @@ export default function ClusterQueueList() {
id: 'cohort',
label: 'Cohort',
getValue: (clusterQueue: ClusterQueue) => clusterQueue.cohortName,
render: (clusterQueue: ClusterQueue) => renderCohortLink(clusterQueue.spec.cohortName),
},
{
id: 'queueingStrategy',
Expand Down
Loading
Loading