mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add Runtime Classes views (#6294)
* Show runtimeClassName in pods view Signed-off-by: Piotr Roszatycki <piotr.roszatycki@gmail.com> * Runtime Classes view Signed-off-by: Piotr Roszatycki <piotr.roszatycki@gmail.com> * Reverted formatting Signed-off-by: Piotr Roszatycki <piotr.roszatycki@gmail.com> Signed-off-by: Piotr Roszatycki <piotr.roszatycki@gmail.com>
This commit is contained in:
parent
6dc2a5c4e8
commit
79efe1be29
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import runtimeClassesRouteInjectable from "./runtime-classes-route.injectable";
|
||||||
|
import { navigateToRouteInjectionToken } from "../../../../navigate-to-route-injection-token";
|
||||||
|
|
||||||
|
const navigateToRuntimeClassesInjectable = getInjectable({
|
||||||
|
id: "navigate-to-runtime-classes",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const navigateToRoute = di.inject(navigateToRouteInjectionToken);
|
||||||
|
const route = di.inject(runtimeClassesRouteInjectable);
|
||||||
|
|
||||||
|
return () => navigateToRoute(route);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default navigateToRuntimeClassesInjectable;
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import isAllowedResourceInjectable from "../../../../../utils/is-allowed-resource.injectable";
|
||||||
|
import { frontEndRouteInjectionToken } from "../../../../front-end-route-injection-token";
|
||||||
|
|
||||||
|
const runtimeClassesRouteInjectable = getInjectable({
|
||||||
|
id: "runtime-classes-route",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const isAllowedResource = di.inject(isAllowedResourceInjectable, "runtimeclasses");
|
||||||
|
|
||||||
|
return {
|
||||||
|
path: "/runtimeclasses",
|
||||||
|
clusterFrame: true,
|
||||||
|
isEnabled: isAllowedResource,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
injectionToken: frontEndRouteInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default runtimeClassesRouteInjectable;
|
||||||
@ -34,6 +34,7 @@ export * from "./replica-set.api";
|
|||||||
export * from "./resource-quota.api";
|
export * from "./resource-quota.api";
|
||||||
export * from "./role.api";
|
export * from "./role.api";
|
||||||
export * from "./role-binding.api";
|
export * from "./role-binding.api";
|
||||||
|
export * from "./runtime-class.api";
|
||||||
export * from "./secret.api";
|
export * from "./secret.api";
|
||||||
export * from "./self-subject-rules-reviews.api";
|
export * from "./self-subject-rules-reviews.api";
|
||||||
export * from "./service.api";
|
export * from "./service.api";
|
||||||
|
|||||||
@ -677,6 +677,10 @@ export class Pod extends KubeObject<
|
|||||||
return this.spec?.priorityClassName || "";
|
return this.spec?.priorityClassName || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getRuntimeClassName() {
|
||||||
|
return this.spec?.runtimeClassName || "";
|
||||||
|
}
|
||||||
|
|
||||||
getServiceAccountName() {
|
getServiceAccountName() {
|
||||||
return this.spec?.serviceAccountName || "";
|
return this.spec?.serviceAccountName || "";
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/common/k8s-api/endpoints/runtime-class.api.injectable.ts
Normal file
22
src/common/k8s-api/endpoints/runtime-class.api.injectable.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import assert from "assert";
|
||||||
|
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||||
|
import { RuntimeClassApi } from "./runtime-class.api";
|
||||||
|
import { kubeApiInjectionToken } from "../kube-api/kube-api-injection-token";
|
||||||
|
|
||||||
|
const runtimeClassApiInjectable = getInjectable({
|
||||||
|
id: "runtime-class-api",
|
||||||
|
instantiate: (di) => {
|
||||||
|
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "RuntimeClassApi is only available in certain environments");
|
||||||
|
|
||||||
|
return new RuntimeClassApi();
|
||||||
|
},
|
||||||
|
|
||||||
|
injectionToken: kubeApiInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default runtimeClassApiInjectable;
|
||||||
72
src/common/k8s-api/endpoints/runtime-class.api.ts
Normal file
72
src/common/k8s-api/endpoints/runtime-class.api.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { DerivedKubeApiOptions } from "../kube-api";
|
||||||
|
import { KubeApi } from "../kube-api";
|
||||||
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import type { ClusterScopedMetadata, KubeObjectMetadata, KubeObjectScope, Toleration } from "../kube-object";
|
||||||
|
import { KubeObject } from "../kube-object";
|
||||||
|
|
||||||
|
export interface RuntimeClassData extends KubeJsonApiData<KubeObjectMetadata<KubeObjectScope.Cluster>, void, void> {
|
||||||
|
handler: string;
|
||||||
|
overhead?: RuntimeClassOverhead;
|
||||||
|
scheduling?: RuntimeClassScheduling;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RuntimeClassOverhead {
|
||||||
|
podFixed?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RuntimeClassScheduling {
|
||||||
|
nodeSelector?: Partial<Record<string, string>>;
|
||||||
|
tolerations?: Toleration[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RuntimeClass extends KubeObject<
|
||||||
|
ClusterScopedMetadata,
|
||||||
|
void,
|
||||||
|
void
|
||||||
|
> {
|
||||||
|
static readonly kind = "RuntimeClass";
|
||||||
|
static readonly namespaced = false;
|
||||||
|
static readonly apiBase = "/apis/node.k8s.io/v1/runtimeclasses";
|
||||||
|
|
||||||
|
handler: string;
|
||||||
|
overhead?: RuntimeClassOverhead;
|
||||||
|
scheduling?: RuntimeClassScheduling;
|
||||||
|
|
||||||
|
constructor({ handler, overhead, scheduling, ...rest }: RuntimeClassData) {
|
||||||
|
super(rest);
|
||||||
|
this.handler = handler;
|
||||||
|
this.overhead = overhead;
|
||||||
|
this.scheduling = scheduling;
|
||||||
|
}
|
||||||
|
|
||||||
|
getHandler() {
|
||||||
|
return this.handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPodFixed() {
|
||||||
|
return this.overhead?.podFixed ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
getNodeSelectors(): string[] {
|
||||||
|
return Object.entries(this.scheduling?.nodeSelector ?? {})
|
||||||
|
.map(values => values.join(": "));
|
||||||
|
}
|
||||||
|
|
||||||
|
getTolerations() {
|
||||||
|
return this.scheduling?.tolerations ?? [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RuntimeClassApi extends KubeApi<RuntimeClass, RuntimeClassData> {
|
||||||
|
constructor(opts: DerivedKubeApiOptions = {}) {
|
||||||
|
super({
|
||||||
|
objectConstructor: RuntimeClass,
|
||||||
|
...opts,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,7 +7,8 @@ export type KubeResource =
|
|||||||
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" |
|
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" |
|
||||||
"secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumeclaims" | "persistentvolumes" | "storageclasses" |
|
"secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumeclaims" | "persistentvolumes" | "storageclasses" |
|
||||||
"pods" | "daemonsets" | "deployments" | "statefulsets" | "replicasets" | "jobs" | "cronjobs" |
|
"pods" | "daemonsets" | "deployments" | "statefulsets" | "replicasets" | "jobs" | "cronjobs" |
|
||||||
"endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "podsecuritypolicies" | "poddisruptionbudgets" | "priorityclasses" |
|
"endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "podsecuritypolicies" | "poddisruptionbudgets" |
|
||||||
|
"priorityclasses" | "runtimeclasses" |
|
||||||
"roles" | "clusterroles" | "rolebindings" | "clusterrolebindings" | "serviceaccounts";
|
"roles" | "clusterroles" | "rolebindings" | "clusterrolebindings" | "serviceaccounts";
|
||||||
|
|
||||||
export interface KubeApiResource extends KubeApiResourceData {
|
export interface KubeApiResource extends KubeApiResourceData {
|
||||||
@ -42,6 +43,7 @@ export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
|
|||||||
"poddisruptionbudgets": { kind: "PodDisruptionBudget", group: "policy" },
|
"poddisruptionbudgets": { kind: "PodDisruptionBudget", group: "policy" },
|
||||||
"podsecuritypolicies": { kind: "PodSecurityPolicy", group: "policy" },
|
"podsecuritypolicies": { kind: "PodSecurityPolicy", group: "policy" },
|
||||||
"priorityclasses": { kind: "PriorityClass", group: "scheduling.k8s.io" },
|
"priorityclasses": { kind: "PriorityClass", group: "scheduling.k8s.io" },
|
||||||
|
"runtimeclasses": { kind: "RuntimeClass", group: "node.k8s.io" },
|
||||||
"resourcequotas": { kind: "ResourceQuota" },
|
"resourcequotas": { kind: "ResourceQuota" },
|
||||||
"replicasets": { kind: "ReplicaSet", group: "apps" },
|
"replicasets": { kind: "ReplicaSet", group: "apps" },
|
||||||
"roles": { kind: "Role", group: "rbac.authorization.k8s.io" },
|
"roles": { kind: "Role", group: "rbac.authorization.k8s.io" },
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const priorityClassesSidebarItemsInjectable = getInjectable({
|
|||||||
onClick: navigateToPriorityClasses,
|
onClick: navigateToPriorityClasses,
|
||||||
isActive: routeIsActive,
|
isActive: routeIsActive,
|
||||||
isVisible: route.isEnabled,
|
isVisible: route.isEnabled,
|
||||||
orderNumber: 60,
|
orderNumber: 70,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { PriorityClasses } from "./priority-classes";
|
|||||||
import priorityClassesRouteInjectable from "../../../common/front-end-routing/routes/cluster/config/priority-classes/priority-classes-route.injectable";
|
import priorityClassesRouteInjectable from "../../../common/front-end-routing/routes/cluster/config/priority-classes/priority-classes-route.injectable";
|
||||||
import { routeSpecificComponentInjectionToken } from "../../routes/route-specific-component-injection-token";
|
import { routeSpecificComponentInjectionToken } from "../../routes/route-specific-component-injection-token";
|
||||||
|
|
||||||
const podDisruptionBudgetsRouteComponentInjectable = getInjectable({
|
const priorityClassesRouteComponentInjectable = getInjectable({
|
||||||
id: "priority-classes-route-component",
|
id: "priority-classes-route-component",
|
||||||
|
|
||||||
instantiate: (di) => ({
|
instantiate: (di) => ({
|
||||||
@ -18,4 +18,4 @@ const podDisruptionBudgetsRouteComponentInjectable = getInjectable({
|
|||||||
injectionToken: routeSpecificComponentInjectionToken,
|
injectionToken: routeSpecificComponentInjectionToken,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default podDisruptionBudgetsRouteComponentInjectable;
|
export default priorityClassesRouteComponentInjectable;
|
||||||
|
|||||||
7
src/renderer/components/+config-runtime-classes/index.ts
Normal file
7
src/renderer/components/+config-runtime-classes/index.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from "./runtime-classes";
|
||||||
|
export * from "./runtime-classes-details";
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.RuntimeClassDetailsTolerations {
|
||||||
|
grid-template-columns: auto;
|
||||||
|
|
||||||
|
.RuntimeClassTolerations {
|
||||||
|
margin-top: var(--margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expanding value cell to cover 2 columns (whole Drawer width)
|
||||||
|
|
||||||
|
>.name {
|
||||||
|
grid-row-start: 1;
|
||||||
|
grid-column-start: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
>.value {
|
||||||
|
grid-row-start: 1;
|
||||||
|
grid-column-start: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DrawerParamToggler>.params {
|
||||||
|
margin-left: var(--drawer-item-title-width);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "./runtime-classes-details-tolerations.scss";
|
||||||
|
import React from "react";
|
||||||
|
import { DrawerParamToggler, DrawerItem } from "../drawer";
|
||||||
|
import type { Toleration, KubeObject } from "../../../common/k8s-api/kube-object";
|
||||||
|
import { RuntimeClassTolerations } from "./runtime-classes-tolerations";
|
||||||
|
|
||||||
|
export interface KubeObjectWithTolerations extends KubeObject {
|
||||||
|
getTolerations(): Toleration[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RuntimeClassDetailsTolerationsProps {
|
||||||
|
runtimeClass: KubeObjectWithTolerations;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RuntimeClassDetailsTolerations({ runtimeClass: runtimeClass }: RuntimeClassDetailsTolerationsProps) {
|
||||||
|
const tolerations = runtimeClass.getTolerations();
|
||||||
|
|
||||||
|
if (!tolerations.length) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DrawerItem name="Tolerations" className="RuntimeClassDetailsTolerations">
|
||||||
|
<DrawerParamToggler label={tolerations.length}>
|
||||||
|
<RuntimeClassTolerations tolerations={tolerations} />
|
||||||
|
</DrawerParamToggler>
|
||||||
|
</DrawerItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.RuntimeClassesDetails {}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "./runtime-classes.scss";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { DrawerItem } from "../drawer";
|
||||||
|
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||||
|
import type { RuntimeClass } from "../../../common/k8s-api/endpoints";
|
||||||
|
import { KubeObjectMeta } from "../kube-object-meta";
|
||||||
|
import { Badge } from "../badge";
|
||||||
|
import { RuntimeClassDetailsTolerations } from "./runtime-classes-details-tolerations";
|
||||||
|
|
||||||
|
export interface RuntimeClassesDetailsProps extends KubeObjectDetailsProps<RuntimeClass> {
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export class RuntimeClassesDetails extends React.Component<RuntimeClassesDetailsProps> {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { object: rc } = this.props;
|
||||||
|
const nodeSelector = rc.getNodeSelectors();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="RuntimeClassesDetails">
|
||||||
|
<KubeObjectMeta object={rc} />
|
||||||
|
|
||||||
|
<DrawerItem name="Handler">
|
||||||
|
{rc.getHandler()}
|
||||||
|
</DrawerItem>
|
||||||
|
|
||||||
|
<DrawerItem name="Pod Fixed" hidden={rc.getPodFixed() === ""}>
|
||||||
|
{rc.getPodFixed()}
|
||||||
|
</DrawerItem>
|
||||||
|
|
||||||
|
<DrawerItem name="Node Selector" hidden={nodeSelector.length === 0}>
|
||||||
|
{nodeSelector.map(label => <Badge key={label} label={label} />)}
|
||||||
|
</DrawerItem>
|
||||||
|
|
||||||
|
<RuntimeClassDetailsTolerations runtimeClass={rc} />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import { computed } from "mobx";
|
||||||
|
|
||||||
|
import runtimeClassesRouteInjectable from "../../../common/front-end-routing/routes/cluster/config/runtime-classes/runtime-classes-route.injectable";
|
||||||
|
import { configSidebarItemId } from "../+config/config-sidebar-items.injectable";
|
||||||
|
import { sidebarItemsInjectionToken } from "../layout/sidebar-items.injectable";
|
||||||
|
import routeIsActiveInjectable from "../../routes/route-is-active.injectable";
|
||||||
|
import navigateToRuntimeClassesInjectable from "../../../common/front-end-routing/routes/cluster/config/runtime-classes/navigate-to-runtime-classes.injectable";
|
||||||
|
|
||||||
|
const runtimeClassesSidebarItemsInjectable = getInjectable({
|
||||||
|
id: "runtime-classes-sidebar-items",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const route = di.inject(runtimeClassesRouteInjectable);
|
||||||
|
const navigateToRuntimeClasses = di.inject(navigateToRuntimeClassesInjectable);
|
||||||
|
const routeIsActive = di.inject(routeIsActiveInjectable, route);
|
||||||
|
|
||||||
|
return computed(() => [
|
||||||
|
{
|
||||||
|
id: "runtime-classes",
|
||||||
|
parentId: configSidebarItemId,
|
||||||
|
title: "Runtime Classes",
|
||||||
|
onClick: navigateToRuntimeClasses,
|
||||||
|
isActive: routeIsActive,
|
||||||
|
isVisible: route.isEnabled,
|
||||||
|
orderNumber: 70,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
|
||||||
|
injectionToken: sidebarItemsInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default runtimeClassesSidebarItemsInjectable;
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import { RuntimeClasses } from "./runtime-classes";
|
||||||
|
import runtimeClassesRouteInjectable from "../../../common/front-end-routing/routes/cluster/config/runtime-classes/runtime-classes-route.injectable";
|
||||||
|
import { routeSpecificComponentInjectionToken } from "../../routes/route-specific-component-injection-token";
|
||||||
|
|
||||||
|
const runtimeClassesRouteComponentInjectable = getInjectable({
|
||||||
|
id: "runtime-classes-route-component",
|
||||||
|
|
||||||
|
instantiate: (di) => ({
|
||||||
|
route: di.inject(runtimeClassesRouteInjectable),
|
||||||
|
Component: RuntimeClasses,
|
||||||
|
}),
|
||||||
|
|
||||||
|
injectionToken: routeSpecificComponentInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default runtimeClassesRouteComponentInjectable;
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.RuntimeClassTolerations {
|
||||||
|
.TableHead {
|
||||||
|
background-color: var(--drawerSubtitleBackground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.TableCell {
|
||||||
|
white-space: normal;
|
||||||
|
word-break: normal;
|
||||||
|
|
||||||
|
&.key {
|
||||||
|
flex-grow: 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "./runtime-classes-tolerations.scss";
|
||||||
|
import React from "react";
|
||||||
|
import uniqueId from "lodash/uniqueId";
|
||||||
|
|
||||||
|
import type { Toleration } from "../../../common/k8s-api/kube-object";
|
||||||
|
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||||
|
|
||||||
|
export interface RuntimeClassTolerationsProps {
|
||||||
|
tolerations: Toleration[];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum sortBy {
|
||||||
|
Key = "key",
|
||||||
|
Operator = "operator",
|
||||||
|
Effect = "effect",
|
||||||
|
Seconds = "seconds",
|
||||||
|
Value = "value",
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTableRow = (toleration: Toleration) => {
|
||||||
|
const { key, operator, effect, tolerationSeconds, value } = toleration;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow
|
||||||
|
key={uniqueId("toleration-")}
|
||||||
|
sortItem={toleration}
|
||||||
|
nowrap
|
||||||
|
>
|
||||||
|
<TableCell className="key">{key}</TableCell>
|
||||||
|
<TableCell className="operator">{operator}</TableCell>
|
||||||
|
<TableCell className="value">{value}</TableCell>
|
||||||
|
<TableCell className="effect">{effect}</TableCell>
|
||||||
|
<TableCell className="seconds">{tolerationSeconds}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function RuntimeClassTolerations({ tolerations }: RuntimeClassTolerationsProps) {
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
tableId="workloads_pod_tolerations"
|
||||||
|
selectable
|
||||||
|
items={tolerations}
|
||||||
|
scrollable={false}
|
||||||
|
sortable={{
|
||||||
|
[sortBy.Key]: toleration => toleration.key,
|
||||||
|
[sortBy.Operator]: toleration => toleration.operator,
|
||||||
|
[sortBy.Effect]: toleration => toleration.effect,
|
||||||
|
[sortBy.Seconds]: toleration => toleration.tolerationSeconds,
|
||||||
|
}}
|
||||||
|
sortSyncWithUrl={false}
|
||||||
|
className="RuntimeClassTolerations"
|
||||||
|
renderRow={getTableRow}
|
||||||
|
>
|
||||||
|
<TableHead sticky={false}>
|
||||||
|
<TableCell className="key" sortBy={sortBy.Key}>Key</TableCell>
|
||||||
|
<TableCell className="operator" sortBy={sortBy.Operator}>Operator</TableCell>
|
||||||
|
<TableCell className="value" sortBy={sortBy.Value}>Value</TableCell>
|
||||||
|
<TableCell className="effect" sortBy={sortBy.Effect}>Effect</TableCell>
|
||||||
|
<TableCell className="seconds" sortBy={sortBy.Seconds}>Seconds</TableCell>
|
||||||
|
</TableHead>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.RuntimeClasses {
|
||||||
|
.TableCell {
|
||||||
|
&.name {
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
@include table-cell-warning;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.keys {
|
||||||
|
flex: 2.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.age {
|
||||||
|
flex: .5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "./runtime-classes.scss";
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import type { RuntimeClass } from "../../../common/k8s-api/endpoints/runtime-class.api";
|
||||||
|
import { KubeObjectStatusIcon } from "../kube-object-status-icon";
|
||||||
|
import type { KubeObjectDetailsProps } from "../kube-object-details";
|
||||||
|
import { KubeObjectListLayout } from "../kube-object-list-layout";
|
||||||
|
import { SiblingsInTabLayout } from "../layout/siblings-in-tab-layout";
|
||||||
|
import { KubeObjectAge } from "../kube-object/age";
|
||||||
|
import { autoBind } from "../../../common/utils";
|
||||||
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
|
import runtimeClassStoreInjectable from "./store.injectable";
|
||||||
|
import type { RuntimeClassStore } from "./store";
|
||||||
|
|
||||||
|
enum columnId {
|
||||||
|
name = "name",
|
||||||
|
handler = "handler",
|
||||||
|
age = "age",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RuntimeClassesProps extends KubeObjectDetailsProps<RuntimeClass> {
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Dependencies {
|
||||||
|
runtimeClassStore: RuntimeClassStore;
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
class NonInjectedRuntimeClasses extends React.Component<RuntimeClassesProps & Dependencies> {
|
||||||
|
constructor(props: RuntimeClassesProps & Dependencies) {
|
||||||
|
super(props);
|
||||||
|
autoBind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { runtimeClassStore } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SiblingsInTabLayout>
|
||||||
|
<KubeObjectListLayout
|
||||||
|
isConfigurable
|
||||||
|
tableId="configuration_runtime_classes"
|
||||||
|
className="RuntimeClasses"
|
||||||
|
store={runtimeClassStore}
|
||||||
|
sortingCallbacks={{
|
||||||
|
[columnId.name]: rc => rc.getName(),
|
||||||
|
[columnId.handler]: rc => rc.getHandler(),
|
||||||
|
[columnId.age]: rc => -rc.getCreationTimestamp(),
|
||||||
|
}}
|
||||||
|
searchFilters={[
|
||||||
|
rc => rc.getSearchFields(),
|
||||||
|
]}
|
||||||
|
renderHeaderTitle="Runtime Classes"
|
||||||
|
renderTableHeader={[
|
||||||
|
{ title: "Name", className: "name", sortBy: columnId.name, id: columnId.name },
|
||||||
|
{ className: "warning", showWithColumn: columnId.name },
|
||||||
|
{ title: "Handler", className: "handler", sortBy: columnId.handler, id: columnId.handler },
|
||||||
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
|
]}
|
||||||
|
renderTableContents={rc => [
|
||||||
|
rc.getName(),
|
||||||
|
<KubeObjectStatusIcon key="icon" object={rc} />,
|
||||||
|
rc.getHandler(),
|
||||||
|
<KubeObjectAge key="age" object={rc} />,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</SiblingsInTabLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RuntimeClasses = withInjectables<Dependencies, RuntimeClassesProps>(NonInjectedRuntimeClasses, {
|
||||||
|
getProps: (di, props) => ({
|
||||||
|
...props,
|
||||||
|
runtimeClassStore: di.inject(runtimeClassStoreInjectable),
|
||||||
|
}),
|
||||||
|
});
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import assert from "assert";
|
||||||
|
import { kubeObjectStoreInjectionToken } from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||||
|
import runtimeClassApiInjectable from "../../../common/k8s-api/endpoints/runtime-class.api.injectable";
|
||||||
|
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||||
|
import { RuntimeClassStore } from "./store";
|
||||||
|
|
||||||
|
const runtimeClassStoreInjectable = getInjectable({
|
||||||
|
id: "runtime-class-store",
|
||||||
|
instantiate: (di) => {
|
||||||
|
assert(di.inject(storesAndApisCanBeCreatedInjectable), "runtimeClassStore is only available in certain environments");
|
||||||
|
|
||||||
|
const api = di.inject(runtimeClassApiInjectable);
|
||||||
|
|
||||||
|
return new RuntimeClassStore(api);
|
||||||
|
},
|
||||||
|
injectionToken: kubeObjectStoreInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default runtimeClassStoreInjectable;
|
||||||
10
src/renderer/components/+config-runtime-classes/store.ts
Normal file
10
src/renderer/components/+config-runtime-classes/store.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
|
||||||
|
import type { RuntimeClass, RuntimeClassApi } from "../../../common/k8s-api/endpoints/runtime-class.api";
|
||||||
|
|
||||||
|
export class RuntimeClassStore extends KubeObjectStore<RuntimeClass, RuntimeClassApi> {
|
||||||
|
}
|
||||||
@ -132,12 +132,15 @@ class NonInjectedPodDetails extends React.Component<PodDetailsProps & Dependenci
|
|||||||
<DrawerItem name="Service Account">
|
<DrawerItem name="Service Account">
|
||||||
{pod.getServiceAccountName()}
|
{pod.getServiceAccountName()}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
<DrawerItem name="Priority Class">
|
<DrawerItem name="Priority Class" hidden={pod.getPriorityClassName() === ""}>
|
||||||
{pod.getPriorityClassName()}
|
{pod.getPriorityClassName()}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
<DrawerItem name="QoS Class">
|
<DrawerItem name="QoS Class">
|
||||||
{pod.getQosClass()}
|
{pod.getQosClass()}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
<DrawerItem name="Runtime Class" hidden={pod.getRuntimeClassName() === ""}>
|
||||||
|
{pod.getRuntimeClassName()}
|
||||||
|
</DrawerItem>
|
||||||
|
|
||||||
<DrawerItem
|
<DrawerItem
|
||||||
name="Conditions"
|
name="Conditions"
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import { kubeObjectDetailItemInjectionToken } from "../kube-object-detail-item-injection-token";
|
||||||
|
import { computed } from "mobx";
|
||||||
|
import { RuntimeClassesDetails } from "../../../+config-runtime-classes";
|
||||||
|
import { kubeObjectMatchesToKindAndApiVersion } from "../kube-object-matches-to-kind-and-api-version";
|
||||||
|
import currentKubeObjectInDetailsInjectable from "../../current-kube-object-in-details.injectable";
|
||||||
|
|
||||||
|
const runtimeClassDetailItemInjectable = getInjectable({
|
||||||
|
id: "runtime-class-detail-item",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const kubeObject = di.inject(currentKubeObjectInDetailsInjectable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
Component: RuntimeClassesDetails,
|
||||||
|
enabled: computed(() => isRuntimeClass(kubeObject.get())),
|
||||||
|
orderNumber: 10,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
injectionToken: kubeObjectDetailItemInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
const isRuntimeClass = kubeObjectMatchesToKindAndApiVersion(
|
||||||
|
"RuntimeClass",
|
||||||
|
["node.k8s.io/v1"],
|
||||||
|
);
|
||||||
|
|
||||||
|
export default runtimeClassDetailItemInjectable;
|
||||||
@ -32,6 +32,7 @@ export const ResourceNames: Record<KubeResource, string> = {
|
|||||||
"podsecuritypolicies": "Pod Security Policies",
|
"podsecuritypolicies": "Pod Security Policies",
|
||||||
"poddisruptionbudgets": "Pod Disruption Budgets",
|
"poddisruptionbudgets": "Pod Disruption Budgets",
|
||||||
"priorityclasses": "Priority Classes",
|
"priorityclasses": "Priority Classes",
|
||||||
|
"runtimeclasses": "Runtime Classes",
|
||||||
"limitranges": "Limit Ranges",
|
"limitranges": "Limit Ranges",
|
||||||
"roles": "Roles",
|
"roles": "Roles",
|
||||||
"rolebindings": "Role Bindings",
|
"rolebindings": "Role Bindings",
|
||||||
|
|||||||
12
templates/create-resource/RuntimeClass.yaml
Normal file
12
templates/create-resource/RuntimeClass.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: node.k8s.io/v1
|
||||||
|
kind: RuntimeClass
|
||||||
|
metadata:
|
||||||
|
name: spot
|
||||||
|
handler: runc
|
||||||
|
scheduling:
|
||||||
|
nodeSelector:
|
||||||
|
eks.amazonaws.com/capacityType: "SPOT"
|
||||||
|
tolerations:
|
||||||
|
- key: eks.amazonaws.com/capacityType
|
||||||
|
value: SPOT
|
||||||
|
effect: NoSchedule
|
||||||
Loading…
Reference in New Issue
Block a user