mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Add support for PodDisruptionBudgets (#452)
Signed-off-by: Dan Slinky <dan-slinky@cookpad.jp>
This commit is contained in:
parent
5163ede4f1
commit
81a0c432c6
@ -4,7 +4,7 @@ export type KubeResource =
|
|||||||
"namespaces" | "nodes" | "events" | "resourcequotas" |
|
"namespaces" | "nodes" | "events" | "resourcequotas" |
|
||||||
"services" | "secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumes" | "storageclasses" |
|
"services" | "secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumes" | "storageclasses" |
|
||||||
"pods" | "daemonsets" | "deployments" | "statefulsets" | "replicasets" | "jobs" | "cronjobs" |
|
"pods" | "daemonsets" | "deployments" | "statefulsets" | "replicasets" | "jobs" | "cronjobs" |
|
||||||
"endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "podsecuritypolicies"
|
"endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "podsecuritypolicies" | "poddisruptionbudgets"
|
||||||
|
|
||||||
export interface KubeApiResource {
|
export interface KubeApiResource {
|
||||||
resource: KubeResource; // valid resource name
|
resource: KubeResource; // valid resource name
|
||||||
@ -28,6 +28,7 @@ export const apiResources: KubeApiResource[] = [
|
|||||||
{ resource: "nodes" },
|
{ resource: "nodes" },
|
||||||
{ resource: "persistentvolumes" },
|
{ resource: "persistentvolumes" },
|
||||||
{ resource: "pods" },
|
{ resource: "pods" },
|
||||||
|
{ resource: "poddisruptionbudgets" },
|
||||||
{ resource: "podsecuritypolicies" },
|
{ resource: "podsecuritypolicies" },
|
||||||
{ resource: "resourcequotas" },
|
{ resource: "resourcequotas" },
|
||||||
{ resource: "secrets" },
|
{ resource: "secrets" },
|
||||||
|
|||||||
@ -28,3 +28,4 @@ export * from "./storage-class.api"
|
|||||||
export * from "./pod-metrics.api"
|
export * from "./pod-metrics.api"
|
||||||
export * from "./podsecuritypolicy.api"
|
export * from "./podsecuritypolicy.api"
|
||||||
export * from "./selfsubjectrulesreviews.api"
|
export * from "./selfsubjectrulesreviews.api"
|
||||||
|
export * from "./poddisruptionbudget.api"
|
||||||
|
|||||||
49
src/renderer/api/endpoints/poddisruptionbudget.api.ts
Normal file
49
src/renderer/api/endpoints/poddisruptionbudget.api.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { autobind } from "../../utils";
|
||||||
|
import { KubeObject } from "../kube-object";
|
||||||
|
import { KubeApi } from "../kube-api";
|
||||||
|
|
||||||
|
@autobind()
|
||||||
|
export class PodDisruptionBudget extends KubeObject {
|
||||||
|
static kind = "PodDisruptionBudget";
|
||||||
|
|
||||||
|
spec: {
|
||||||
|
minAvailable: string;
|
||||||
|
maxUnavailable: string;
|
||||||
|
selector: { matchLabels: { [app: string]: string } };
|
||||||
|
}
|
||||||
|
status: {
|
||||||
|
currentHealthy: number
|
||||||
|
desiredHealthy: number
|
||||||
|
disruptionsAllowed: number
|
||||||
|
expectedPods: number
|
||||||
|
}
|
||||||
|
|
||||||
|
getSelectors() {
|
||||||
|
const selector = this.spec.selector;
|
||||||
|
return KubeObject.stringifyLabels(selector ? selector.matchLabels : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
getMinAvailable() {
|
||||||
|
return this.spec.minAvailable || "N/A";
|
||||||
|
}
|
||||||
|
|
||||||
|
getMaxUnavailable() {
|
||||||
|
return this.spec.maxUnavailable || "N/A";
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentHealthy() {
|
||||||
|
return this.status.currentHealthy;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDesiredHealthy() {
|
||||||
|
return this.status.desiredHealthy;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pdbApi = new KubeApi({
|
||||||
|
kind: PodDisruptionBudget.kind,
|
||||||
|
apiBase: "/apis/policy/v1beta1/poddisruptionbudgets",
|
||||||
|
isNamespaced: true,
|
||||||
|
objectConstructor: PodDisruptionBudget,
|
||||||
|
});
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
export * from "./pod-disruption-budgets.route"
|
||||||
|
export * from "./pod-disruption-budgets"
|
||||||
|
export * from "./pod-disruption-budgets-details"
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
.PodDisruptionBudgetDetails {
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
import "./pod-disruption-budgets-details.scss";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { Trans } from "@lingui/macro";
|
||||||
|
import { DrawerItem, DrawerTitle } from "../drawer";
|
||||||
|
import { Badge } from "../badge";
|
||||||
|
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||||
|
import { KubeObjectDetailsProps } from "../kube-object";
|
||||||
|
import { PodDisruptionBudget, pdbApi } from "../../api/endpoints";
|
||||||
|
import { apiManager } from "../../api/api-manager";
|
||||||
|
import { KubeObjectStore } from "../../kube-object.store";
|
||||||
|
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
|
||||||
|
|
||||||
|
interface Props extends KubeObjectDetailsProps<PodDisruptionBudget> {
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export class PodDisruptionBudgetDetails extends React.Component<Props> {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { object: pdb } = this.props;
|
||||||
|
if (!pdb) return null
|
||||||
|
const { status, spec } = pdb
|
||||||
|
const selectors = pdb.getSelectors();
|
||||||
|
return (
|
||||||
|
<div className="PdbDetails">
|
||||||
|
<KubeObjectMeta object={pdb}/>
|
||||||
|
|
||||||
|
{selectors.length > 0 &&
|
||||||
|
<DrawerItem name={<Trans>Selector</Trans>} labelsOnly>
|
||||||
|
{
|
||||||
|
selectors.map(label => <Badge key={label} label={label}/>)
|
||||||
|
}
|
||||||
|
</DrawerItem>
|
||||||
|
}
|
||||||
|
|
||||||
|
<DrawerItem name={<Trans>Min Available</Trans>}>
|
||||||
|
{pdb.getMinAvailable()}
|
||||||
|
</DrawerItem>
|
||||||
|
|
||||||
|
<DrawerItem name={<Trans>Max Unavailable</Trans>}>
|
||||||
|
{pdb.getMaxUnavailable()}
|
||||||
|
</DrawerItem>
|
||||||
|
|
||||||
|
<DrawerItem name={<Trans>Current Healthy</Trans>}>
|
||||||
|
{pdb.getCurrentHealthy()}
|
||||||
|
</DrawerItem>
|
||||||
|
|
||||||
|
<DrawerItem name={<Trans>Desired Healthy</Trans>}>
|
||||||
|
{pdb.getDesiredHealthy()}
|
||||||
|
</DrawerItem>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apiManager.registerViews(pdbApi, {
|
||||||
|
Details: PodDisruptionBudgetDetails,
|
||||||
|
});
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { RouteProps } from "react-router";
|
||||||
|
import { buildURL } from "../../navigation";
|
||||||
|
|
||||||
|
export const pdbRoute: RouteProps = {
|
||||||
|
path: "/poddisruptionbudgets"
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPodDisruptionBudgetsRouteParams {
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pdbURL = buildURL<IPodDisruptionBudgetsRouteParams>(pdbRoute.path)
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
.PodDisruptionBudgets {
|
||||||
|
.TableCell {
|
||||||
|
&.name {
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.keys {
|
||||||
|
flex: 2.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.age {
|
||||||
|
flex: .5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import { KubeObjectStore } from "../../kube-object.store";
|
||||||
|
import { autobind } from "../../utils";
|
||||||
|
import { PodDisruptionBudget, pdbApi } from "../../api/endpoints/poddisruptionbudget.api";
|
||||||
|
import { apiManager } from "../../api/api-manager";
|
||||||
|
|
||||||
|
@autobind()
|
||||||
|
export class PodDisruptionBudgetsStore extends KubeObjectStore<PodDisruptionBudget> {
|
||||||
|
api = pdbApi
|
||||||
|
}
|
||||||
|
|
||||||
|
export const podDisruptionBudgetsStore = new PodDisruptionBudgetsStore();
|
||||||
|
apiManager.registerStore(pdbApi, podDisruptionBudgetsStore);
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
import "./pod-disruption-budgets.scss"
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
import { Trans } from "@lingui/macro";
|
||||||
|
import { RouteComponentProps } from "react-router";
|
||||||
|
import { podDisruptionBudgetsStore } from "./pod-disruption-budgets.store";
|
||||||
|
import { PodDisruptionBudget, pdbApi } from "../../api/endpoints/poddisruptionbudget.api";
|
||||||
|
import { KubeObjectMenu, KubeObjectMenuProps } from "../kube-object/kube-object-menu";
|
||||||
|
import { KubeObjectDetailsProps, KubeObjectListLayout } from "../kube-object";
|
||||||
|
import { IPodDisruptionBudgetsRouteParams } from "./pod-disruption-budgets.route";
|
||||||
|
import { apiManager } from "../../api/api-manager";
|
||||||
|
|
||||||
|
enum sortBy {
|
||||||
|
name = "name",
|
||||||
|
namespace = "namespace",
|
||||||
|
minAvailable = "min-available",
|
||||||
|
maxUnavailable = "max-unavailable",
|
||||||
|
currentHealthy = "current-healthy",
|
||||||
|
desiredHealthy = "desired-healthy",
|
||||||
|
age = "age",
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Props extends KubeObjectDetailsProps<PodDisruptionBudget> {
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export class PodDisruptionBudgets extends React.Component<Props> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<KubeObjectListLayout
|
||||||
|
className="PodDisruptionBudgets"
|
||||||
|
store={podDisruptionBudgetsStore}
|
||||||
|
sortingCallbacks={{
|
||||||
|
[sortBy.name]: (pdb: PodDisruptionBudget) => pdb.getName(),
|
||||||
|
[sortBy.namespace]: (pdb: PodDisruptionBudget) => pdb.getNs(),
|
||||||
|
[sortBy.minAvailable]: (pdb: PodDisruptionBudget) => pdb.getMinAvailable(),
|
||||||
|
[sortBy.maxUnavailable]: (pdb: PodDisruptionBudget) => pdb.getMaxUnavailable(),
|
||||||
|
[sortBy.currentHealthy]: (pdb: PodDisruptionBudget) => pdb.getCurrentHealthy(),
|
||||||
|
[sortBy.desiredHealthy]: (pdb: PodDisruptionBudget) => pdb.getDesiredHealthy(),
|
||||||
|
[sortBy.age]: (pdb: PodDisruptionBudget) => pdb.getAge(),
|
||||||
|
}}
|
||||||
|
searchFilters={[
|
||||||
|
(pdb: PodDisruptionBudget) => pdb.getSearchFields(),
|
||||||
|
]}
|
||||||
|
renderHeaderTitle={<Trans>Pod Disruption Budgets</Trans>}
|
||||||
|
renderTableHeader={[
|
||||||
|
{ title: <Trans>Name</Trans>, className: "name", sortBy: sortBy.name },
|
||||||
|
{ title: <Trans>Namespace</Trans>, className: "namespace", sortBy: sortBy.namespace },
|
||||||
|
{ title: <Trans>Min Available</Trans>, className: "min-available", sortBy: sortBy.minAvailable },
|
||||||
|
{ title: <Trans>Max Unavailable</Trans>, className: "max-unavailable", sortBy: sortBy.maxUnavailable },
|
||||||
|
{ title: <Trans>Current Healthy</Trans>, className: "current-healthy", sortBy: sortBy.currentHealthy },
|
||||||
|
{ title: <Trans>Desired Healthy</Trans>, className: "desired-healthy", sortBy: sortBy.desiredHealthy },
|
||||||
|
{ title: <Trans>Age</Trans>, className: "age", sortBy: sortBy.age },
|
||||||
|
]}
|
||||||
|
renderTableContents={(pdb: PodDisruptionBudget) => {
|
||||||
|
return [
|
||||||
|
pdb.getName(),
|
||||||
|
pdb.getNs(),
|
||||||
|
pdb.getMinAvailable(),
|
||||||
|
pdb.getMaxUnavailable(),
|
||||||
|
pdb.getCurrentHealthy(),
|
||||||
|
pdb.getDesiredHealthy(),
|
||||||
|
pdb.getAge(),
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
renderItemMenu={(pdb: PodDisruptionBudget) => {
|
||||||
|
return <PodDisruptionBudgetsMenu object={pdb}/>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PodDisruptionBudgetsMenu(props: KubeObjectMenuProps<PodDisruptionBudget>) {
|
||||||
|
return (
|
||||||
|
<KubeObjectMenu {...props}/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
apiManager.registerViews(pdbApi, {
|
||||||
|
Menu: PodDisruptionBudgetsMenu,
|
||||||
|
})
|
||||||
@ -7,6 +7,7 @@ import { ConfigMaps, configMapsRoute, configMapsURL } from "../+config-maps";
|
|||||||
import { Secrets, secretsRoute, secretsURL } from "../+config-secrets";
|
import { Secrets, secretsRoute, secretsURL } from "../+config-secrets";
|
||||||
import { namespaceStore } from "../+namespaces/namespace.store";
|
import { namespaceStore } from "../+namespaces/namespace.store";
|
||||||
import { resourceQuotaRoute, ResourceQuotas, resourceQuotaURL } from "../+config-resource-quotas";
|
import { resourceQuotaRoute, ResourceQuotas, resourceQuotaURL } from "../+config-resource-quotas";
|
||||||
|
import { PodDisruptionBudgets, pdbRoute, pdbURL } from "../+config-pod-disruption-budgets";
|
||||||
import { configURL } from "./config.route";
|
import { configURL } from "./config.route";
|
||||||
import { HorizontalPodAutoscalers, hpaRoute, hpaURL } from "../+config-autoscalers";
|
import { HorizontalPodAutoscalers, hpaRoute, hpaURL } from "../+config-autoscalers";
|
||||||
import { buildURL } from "../../navigation";
|
import { buildURL } from "../../navigation";
|
||||||
@ -53,6 +54,14 @@ export class Config extends React.Component {
|
|||||||
path: hpaRoute.path,
|
path: hpaRoute.path,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if (isAllowedResource("poddisruptionbudgets")) {
|
||||||
|
routes.push({
|
||||||
|
title: <Trans>Pod Disruption Budgets</Trans>,
|
||||||
|
component: PodDisruptionBudgets,
|
||||||
|
url: pdbURL({ query }),
|
||||||
|
path: pdbRoute.path,
|
||||||
|
})
|
||||||
|
}
|
||||||
return routes;
|
return routes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user