Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support PodDisruptionBudget resource #1962

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
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
248 changes: 235 additions & 13 deletions assets/schema/kubernetes-schema.graphql

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions assets/src/components/kubernetes/cluster/Cluster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
NAMESPACES_REL_PATH,
NODES_REL_PATH,
getClusterAbsPath,
PDBS_REL_PATH,
} from '../../../routes/kubernetesRoutesConsts'
import { ScrollablePage } from '../../utils/layout/ScrollablePage'
import { LinkTabWrap } from '../../utils/Tabs'
Expand All @@ -34,6 +35,7 @@ const directory = [
{ path: EVENTS_REL_PATH, label: 'Events' },
{ path: NAMESPACES_REL_PATH, label: 'Namespaces' },
{ path: HPAS_REL_PATH, label: 'Horizontal Pod Autoscalers' },
{ path: PDBS_REL_PATH, label: 'Pod Disruption Budgets' },
] as const

export default function Cluster() {
Expand Down
117 changes: 117 additions & 0 deletions assets/src/components/kubernetes/cluster/PodDisruptionBudget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { ReactElement, useMemo } from 'react'
import { Outlet, useParams } from 'react-router-dom'
import { SidecarItem, useSetBreadcrumbs } from '@pluralsh/design-system'

import ResourceDetails, { TabEntry } from '../common/ResourceDetails'
import { MetadataSidecar } from '../common/utils'
import {
PodDisruptionBudgetQueryVariables,
usePodDisruptionBudgetQuery,
} from '../../../generated/graphql-kubernetes'
import { KubernetesClient } from '../../../helpers/kubernetes.client'
import {
getResourceDetailsAbsPath,
getClusterAbsPath,
PDBS_REL_PATH,
} from '../../../routes/kubernetesRoutesConsts'
import { NAMESPACE_PARAM } from '../Navigation'
import LoadingIndicator from '../../utils/LoadingIndicator'
import { useCluster } from '../Cluster'
import { Kind } from '../common/types'

import { getBreadcrumbs } from './PodDisruptionBudgets'
import { LabelSelector } from '../common/LabelSelector.tsx'
import { isNullish } from '@apollo/client/cache/inmemory/helpers'

const directory: Array<TabEntry> = [{ path: '', label: 'Raw' }] as const

export default function PodDisruptionBudget(): ReactElement<any> {
const cluster = useCluster()
const { clusterId, name = '', namespace = '' } = useParams()
const { data, loading } = usePodDisruptionBudgetQuery({
client: KubernetesClient(clusterId ?? ''),
skip: !clusterId,
pollInterval: 30_000,
variables: { name, namespace } as PodDisruptionBudgetQueryVariables,
})

const pdb = data?.handleGetPodDisruptionBudgetDetail

useSetBreadcrumbs(
useMemo(
() => [
...getBreadcrumbs(cluster),
{
label: namespace ?? '',
url: `${getClusterAbsPath(
cluster?.id
)}/${PDBS_REL_PATH}?${NAMESPACE_PARAM}=${namespace}`,
},
{
label: name ?? '',
url: getResourceDetailsAbsPath(
clusterId,
Kind.PodDisruptionBudget,
name,
namespace
),
},
],
[cluster, clusterId, name, namespace]
)
)

if (loading) return <LoadingIndicator />

return (
<ResourceDetails
tabs={directory}
sidecar={
<MetadataSidecar resource={pdb}>
{pdb?.labelSelector && (
<SidecarItem heading="Label selector">
<LabelSelector selector={pdb?.labelSelector} />
</SidecarItem>
)}
{!isNullish(pdb?.minAvailable) && (
<SidecarItem heading="Min available">
{pdb?.minAvailable}
</SidecarItem>
)}
{!isNullish(pdb?.maxUnavailable) && (
<SidecarItem heading="Max unavailable">
{pdb?.maxUnavailable}
</SidecarItem>
)}
{pdb?.unhealthyPodEvictionPolicy && (
<SidecarItem heading="Unhealthy Pod eviction policy">
{pdb?.unhealthyPodEvictionPolicy}
</SidecarItem>
)}
{!isNullish(pdb?.currentHealthy) && (
<SidecarItem heading="Current healthy">
{pdb?.currentHealthy}
</SidecarItem>
)}
{!isNullish(pdb?.desiredHealthy) && (
<SidecarItem heading="Desired healthy">
{pdb?.desiredHealthy}
</SidecarItem>
)}
{!isNullish(pdb?.disruptionsAllowed) && (
<SidecarItem heading="Disruptions allowed">
{pdb?.disruptionsAllowed}
</SidecarItem>
)}
{!isNullish(pdb?.expectedPods) && (
<SidecarItem heading="Expected Pods">
{pdb?.expectedPods}
</SidecarItem>
)}
</MetadataSidecar>
}
>
<Outlet context={pdb} />
</ResourceDetails>
)
}
80 changes: 80 additions & 0 deletions assets/src/components/kubernetes/cluster/PodDisruptionBudgets.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { createColumnHelper } from '@tanstack/react-table'
import { useMemo } from 'react'
import { useSetBreadcrumbs } from '@pluralsh/design-system'

import {
Maybe,
Poddisruptionbudget_PodDisruptionBudgetList as PodDisruptionBudgetListT,
Poddisruptionbudget_PodDisruptionBudget as PodDisruptionBudgetT,
usePodDisruptionBudgetsQuery,
PodDisruptionBudgetsQuery,
PodDisruptionBudgetsQueryVariables,
} from '../../../generated/graphql-kubernetes'
import { useDefaultColumns } from '../common/utils'
import { ResourceList } from '../common/ResourceList'
import { KubernetesClusterFragment } from '../../../generated/graphql'
import {
getClusterAbsPath,
PDBS_REL_PATH,
} from '../../../routes/kubernetesRoutesConsts'
import { useCluster } from '../Cluster'

import { getClusterBreadcrumbs } from './Cluster.tsx'

export const getBreadcrumbs = (cluster?: Maybe<KubernetesClusterFragment>) => [
...getClusterBreadcrumbs(cluster),
{
label: 'pod disruption budgets',
url: `${getClusterAbsPath(cluster?.id)}/${PDBS_REL_PATH}`,
},
]

const columnHelper = createColumnHelper<PodDisruptionBudgetT>()

export const usePodDisruptionBudgetListColumns = () => {
const { colAction, colName, colNamespace, colLabels, colCreationTimestamp } =
useDefaultColumns(columnHelper)

return useMemo(
() => [
colName,
colNamespace,
columnHelper.accessor((pdb) => pdb.minAvailable, {
id: 'minAvailable',
header: 'Min available',
cell: ({ getValue }) => getValue(),
}),
columnHelper.accessor((pdb) => pdb.maxUnavailable, {
id: 'maxUnavailable',
header: 'Max unavailable',
cell: ({ getValue }) => getValue(),
}),
colLabels,
colCreationTimestamp,
colAction,
],
[colCreationTimestamp, colLabels, colName, colNamespace, colAction]
)
}

export default function PodDisruptionBudgets() {
const cluster = useCluster()
const columns = usePodDisruptionBudgetListColumns()

useSetBreadcrumbs(useMemo(() => getBreadcrumbs(cluster), [cluster]))

return (
<ResourceList<
PodDisruptionBudgetListT,
PodDisruptionBudgetT,
PodDisruptionBudgetsQuery,
PodDisruptionBudgetsQueryVariables
>
namespaced
columns={columns}
query={usePodDisruptionBudgetsQuery}
queryName="handleGetPodDisruptionBudgetList"
itemsKey="items"
/>
)
}
1 change: 1 addition & 0 deletions assets/src/components/kubernetes/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ enum Kind {
Event = 'event',
Namespace = 'namespace',
HorizontalPodAutoscaler = 'horizontalpodautoscaler',
PodDisruptionBudget = 'poddisruptionbudget',
// CRD
CustomResourceDefinition = 'customresourcedefinition',
None = '',
Expand Down
Loading
Loading