diff --git a/assets/src/components/kubernetes/Navigation.tsx b/assets/src/components/kubernetes/Navigation.tsx
index 6685d6b8fb..f7d4636a55 100644
--- a/assets/src/components/kubernetes/Navigation.tsx
+++ b/assets/src/components/kubernetes/Navigation.tsx
@@ -18,6 +18,7 @@ import {
STORAGE_REL_PATH,
WORKLOADS_REL_PATH,
getKubernetesAbsPath,
+ AUDIT_REL_PATH,
} from '../../routes/kubernetesRoutesConsts'
import { ResponsiveLayoutPage } from '../utils/layout/ResponsiveLayoutPage'
import { ResponsiveLayoutSidenavContainer } from '../utils/layout/ResponsiveLayoutSidenavContainer'
@@ -44,6 +45,7 @@ const directory: Directory = [
{ path: RBAC_REL_PATH, label: 'RBAC' },
{ path: CLUSTER_REL_PATH, label: 'Cluster' },
{ path: CUSTOM_RESOURCES_REL_PATH, label: 'Custom resources' },
+ { path: AUDIT_REL_PATH, label: 'Audit logs' },
] as const
export default function Navigation() {
@@ -64,6 +66,8 @@ export default function Navigation() {
const pageHeaderContext = useMemo(() => ({ setHeaderContent }), [])
useLayoutEffect(() => {
+ dataSelect.setEnabled(true)
+
if (clusterId) sessionStorage.setItem(LAST_SELECTED_CLUSTER_KEY, clusterId)
const newParams = new URLSearchParams()
@@ -125,7 +129,7 @@ export default function Navigation() {
}}
>
{headerContent}
-
+ {dataSelect.enabled && }
diff --git a/assets/src/components/kubernetes/audit/Audit.tsx b/assets/src/components/kubernetes/audit/Audit.tsx
new file mode 100644
index 0000000000..92869e7b7e
--- /dev/null
+++ b/assets/src/components/kubernetes/audit/Audit.tsx
@@ -0,0 +1,95 @@
+import { Table } from '@pluralsh/design-system'
+import { CellContext, createColumnHelper } from '@tanstack/react-table'
+import { useEffect, useMemo } from 'react'
+import {
+ ClusterAuditLog,
+ useKubernetesClusterAuditLogsQuery,
+} from '../../../generated/graphql.ts'
+import { GqlError } from '../../utils/Alert.tsx'
+import { ScrollablePage } from '../../utils/layout/ScrollablePage.tsx'
+import { DateTimeCol } from '../../utils/table/DateTimeCol.tsx'
+import { useFetchPaginatedData } from '../../utils/table/useFetchPaginatedData.tsx'
+import UserInfo from '../../utils/UserInfo.tsx'
+import { useCluster } from '../Cluster.tsx'
+import { useDataSelect } from '../common/DataSelect.tsx'
+
+const columnHelper = createColumnHelper()
+
+const RawColumn = ({ getValue }: CellContext): string => getValue()
+
+const pathColumn = columnHelper.accessor((log) => log?.path, {
+ id: 'path',
+ header: 'Path',
+ enableSorting: true,
+ cell: RawColumn,
+})
+
+const methodColumn = columnHelper.accessor((log) => log?.method, {
+ id: 'method',
+ header: 'Method',
+ enableSorting: true,
+ cell: RawColumn,
+})
+
+const insertedAtColumn = columnHelper.accessor((log) => log?.insertedAt, {
+ id: 'timestamp',
+ header: 'Timestamp',
+ enableSorting: true,
+ cell: ({ getValue }) => ,
+})
+
+const userColumn = columnHelper.accessor((log) => log?.actor, {
+ id: 'user',
+ header: 'User',
+ enableSorting: true,
+ cell: ({ getValue }) => ,
+})
+
+const columns = [methodColumn, pathColumn, userColumn, insertedAtColumn]
+
+export default function Audit() {
+ const cluster = useCluster()
+ const { setEnabled } = useDataSelect()
+
+ const { data, loading, error, pageInfo, fetchNextPage, setVirtualSlice } =
+ useFetchPaginatedData(
+ {
+ skip: !cluster?.id,
+ queryHook: useKubernetesClusterAuditLogsQuery,
+ keyPath: ['auditLogs'],
+ pollInterval: 30_000,
+ },
+ {
+ clusterId: cluster?.id,
+ }
+ )
+
+ useEffect(() => {
+ // Disable data select on audit page
+ setEnabled(false)
+ })
+
+ const auditLogs = useMemo(
+ () => data?.cluster?.auditLogs?.edges?.map((edge) => edge?.node),
+ [data]
+ )
+
+ return (
+
+ {error && }
+
+
+ )
+}
diff --git a/assets/src/components/kubernetes/common/DataSelect.tsx b/assets/src/components/kubernetes/common/DataSelect.tsx
index 5dd327737d..6c45d743bd 100644
--- a/assets/src/components/kubernetes/common/DataSelect.tsx
+++ b/assets/src/components/kubernetes/common/DataSelect.tsx
@@ -24,6 +24,8 @@ export type DataSelectT = {
}
export type DataSelectContextT = {
+ enabled: boolean
+ setEnabled: Dispatch>
namespaced: boolean
setNamespaced: Dispatch>
namespace: string
@@ -41,10 +43,13 @@ export function useDataSelect(defaults?: DataSelectT) {
const [namespaced, setNamespaced] = useState(false)
const [namespace, setNamespace] = useState(defaults?.namespace ?? '')
const [filter, setFilter] = useState(defaults?.filter ?? '')
+ const [enabled, setEnabled] = useState(true)
return useMemo(
() =>
context ?? {
+ enabled,
+ setEnabled,
namespaced,
setNamespaced,
namespace,
@@ -53,6 +58,8 @@ export function useDataSelect(defaults?: DataSelectT) {
setFilter,
},
[
+ enabled,
+ setEnabled,
context,
namespaced,
setNamespaced,
diff --git a/assets/src/generated/graphql.ts b/assets/src/generated/graphql.ts
index 6ce13a4558..02b27ee5e5 100644
--- a/assets/src/generated/graphql.ts
+++ b/assets/src/generated/graphql.ts
@@ -11120,6 +11120,17 @@ export type KubernetesClustersQueryVariables = Exact<{
export type KubernetesClustersQuery = { __typename?: 'RootQueryType', clusters?: { __typename?: 'ClusterConnection', edges?: Array<{ __typename?: 'ClusterEdge', node?: { __typename?: 'Cluster', self?: boolean | null, virtual?: boolean | null, id: string, name: string, handle?: string | null, distro?: ClusterDistro | null, project?: { __typename?: 'Project', id: string, name: string, default?: boolean | null, description?: string | null } | null, pinnedCustomResources?: Array<{ __typename?: 'PinnedCustomResource', id: string, name: string, kind: string, version: string, group: string, displayName: string, namespaced?: boolean | null, cluster?: { __typename?: 'Cluster', self?: boolean | null, virtual?: boolean | null, id: string, name: string, handle?: string | null, distro?: ClusterDistro | null, upgradePlan?: { __typename?: 'ClusterUpgradePlan', compatibilities?: boolean | null, deprecations?: boolean | null, incompatibilities?: boolean | null } | null, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null } | null> | null, upgradePlan?: { __typename?: 'ClusterUpgradePlan', compatibilities?: boolean | null, deprecations?: boolean | null, incompatibilities?: boolean | null } | null, provider?: { __typename?: 'ClusterProvider', name: string, cloud: string } | null } | null } | null> | null } | null };
+export type KubernetesClusterAuditLogsQueryVariables = Exact<{
+ clusterId?: InputMaybe;
+ first?: InputMaybe;
+ after?: InputMaybe;
+ before?: InputMaybe;
+ last?: InputMaybe;
+}>;
+
+
+export type KubernetesClusterAuditLogsQuery = { __typename?: 'RootQueryType', cluster?: { __typename?: 'Cluster', auditLogs?: { __typename?: 'ClusterAuditLogConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean, endCursor?: string | null, hasPreviousPage: boolean, startCursor?: string | null }, edges?: Array<{ __typename?: 'ClusterAuditLogEdge', node?: { __typename?: 'ClusterAuditLog', id: string, insertedAt?: string | null, method: string, path: string, actor?: { __typename?: 'User', name: string, email: string } | null } | null } | null> | null } | null } | null };
+
export type PinCustomResourceMutationVariables = Exact<{
attributes: PinnedCustomResourceAttributes;
}>;
@@ -22260,6 +22271,66 @@ export type KubernetesClustersQueryHookResult = ReturnType;
export type KubernetesClustersSuspenseQueryHookResult = ReturnType;
export type KubernetesClustersQueryResult = Apollo.QueryResult;
+export const KubernetesClusterAuditLogsDocument = gql`
+ query KubernetesClusterAuditLogs($clusterId: ID, $first: Int, $after: String, $before: String, $last: Int) {
+ cluster(id: $clusterId) {
+ auditLogs(first: $first, last: $last, after: $after, before: $before) {
+ pageInfo {
+ ...PageInfo
+ }
+ edges {
+ node {
+ id
+ insertedAt
+ method
+ path
+ actor {
+ name
+ email
+ }
+ }
+ }
+ }
+ }
+}
+ ${PageInfoFragmentDoc}`;
+
+/**
+ * __useKubernetesClusterAuditLogsQuery__
+ *
+ * To run a query within a React component, call `useKubernetesClusterAuditLogsQuery` and pass it any options that fit your needs.
+ * When your component renders, `useKubernetesClusterAuditLogsQuery` returns an object from Apollo Client that contains loading, error, and data properties
+ * you can use to render your UI.
+ *
+ * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
+ *
+ * @example
+ * const { data, loading, error } = useKubernetesClusterAuditLogsQuery({
+ * variables: {
+ * clusterId: // value for 'clusterId'
+ * first: // value for 'first'
+ * after: // value for 'after'
+ * before: // value for 'before'
+ * last: // value for 'last'
+ * },
+ * });
+ */
+export function useKubernetesClusterAuditLogsQuery(baseOptions?: Apollo.QueryHookOptions) {
+ const options = {...defaultOptions, ...baseOptions}
+ return Apollo.useQuery(KubernetesClusterAuditLogsDocument, options);
+ }
+export function useKubernetesClusterAuditLogsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) {
+ const options = {...defaultOptions, ...baseOptions}
+ return Apollo.useLazyQuery(KubernetesClusterAuditLogsDocument, options);
+ }
+export function useKubernetesClusterAuditLogsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) {
+ const options = {...defaultOptions, ...baseOptions}
+ return Apollo.useSuspenseQuery(KubernetesClusterAuditLogsDocument, options);
+ }
+export type KubernetesClusterAuditLogsQueryHookResult = ReturnType;
+export type KubernetesClusterAuditLogsLazyQueryHookResult = ReturnType;
+export type KubernetesClusterAuditLogsSuspenseQueryHookResult = ReturnType;
+export type KubernetesClusterAuditLogsQueryResult = Apollo.QueryResult;
export const PinCustomResourceDocument = gql`
mutation PinCustomResource($attributes: PinnedCustomResourceAttributes!) {
createPinnedCustomResource(attributes: $attributes) {
@@ -26146,6 +26217,7 @@ export const namedOperations = {
GroupMembers: 'GroupMembers',
UpgradeStatistics: 'UpgradeStatistics',
KubernetesClusters: 'KubernetesClusters',
+ KubernetesClusterAuditLogs: 'KubernetesClusterAuditLogs',
ArgoRollout: 'ArgoRollout',
Canary: 'Canary',
Certificate: 'Certificate',
diff --git a/assets/src/graph/kubernetes.graphql b/assets/src/graph/kubernetes.graphql
index 92faeccd8c..a5c8569f9a 100644
--- a/assets/src/graph/kubernetes.graphql
+++ b/assets/src/graph/kubernetes.graphql
@@ -31,6 +31,34 @@ query KubernetesClusters($projectId: ID) {
}
}
+query KubernetesClusterAuditLogs(
+ $clusterId: ID
+ $first: Int
+ $after: String
+ $before: String
+ $last: Int
+) {
+ cluster(id: $clusterId) {
+ auditLogs(first: $first, last: $last, after: $after, before: $before) {
+ pageInfo {
+ ...PageInfo
+ }
+ edges {
+ node {
+ id
+ insertedAt
+ method
+ path
+ actor {
+ name
+ email
+ }
+ }
+ }
+ }
+ }
+}
+
mutation PinCustomResource($attributes: PinnedCustomResourceAttributes!) {
createPinnedCustomResource(attributes: $attributes) {
...PinnedCustomResource
diff --git a/assets/src/routes/kubernetesRoute.tsx b/assets/src/routes/kubernetesRoute.tsx
index c7423657c4..92880f5677 100644
--- a/assets/src/routes/kubernetesRoute.tsx
+++ b/assets/src/routes/kubernetesRoute.tsx
@@ -1,4 +1,8 @@
-import { Navigate, Route } from 'react-router-dom'
+import Secret, { SecretData } from 'components/kubernetes/configuration/Secret'
+import CustomResourceDefinition, {
+ CustomResourceDefinitionConditions,
+ CustomResourceDefinitionObjects,
+} from 'components/kubernetes/customresources/CustomResourceDefinition'
import Service, {
ServiceEvents,
@@ -6,54 +10,29 @@ import Service, {
ServiceIngresses,
ServicePods,
} from 'components/kubernetes/network/Service'
-import PersistentVolume, {
- PersistentVolumeInfo,
-} from 'components/kubernetes/storage/PersistentVolume'
-import Secret, { SecretData } from 'components/kubernetes/configuration/Secret'
-import RoleBinding, {
- RoleBindingSubjects,
-} from 'components/kubernetes/rbac/RoleBinding'
-import Role, { RolePolicyRules } from 'components/kubernetes/rbac/Role'
import ClusterRole from 'components/kubernetes/rbac/ClusterRole'
import ClusterRoleBinding, {
ClusterRoleBindingSubjects,
} from 'components/kubernetes/rbac/ClusterRoleBinding'
-import CustomResourceDefinition, {
- CustomResourceDefinitionObjects,
- CustomResourceDefinitionConditions,
-} from 'components/kubernetes/customresources/CustomResourceDefinition'
+import Role, { RolePolicyRules } from 'components/kubernetes/rbac/Role'
+import RoleBinding, {
+ RoleBindingSubjects,
+} from 'components/kubernetes/rbac/RoleBinding'
+import PersistentVolume, {
+ PersistentVolumeInfo,
+} from 'components/kubernetes/storage/PersistentVolume'
+import { Navigate, Route } from 'react-router-dom'
+import Audit from '../components/kubernetes/audit/Audit.tsx'
-import {
- Pod,
- PodContainers,
- PodEvents,
- PodExec,
- PodInfo,
- PodLogs,
-} from '../components/kubernetes/workloads/Pod'
-import Navigation from '../components/kubernetes/Navigation'
-import Workloads from '../components/kubernetes/workloads/Workloads'
-import Network from '../components/kubernetes/network/Network'
-import Services from '../components/kubernetes/network/Services'
-import Ingresses from '../components/kubernetes/network/Ingresses'
-import IngressClasses from '../components/kubernetes/network/IngressClasses'
-import Storage from '../components/kubernetes/storage/Storage'
-import Configuration from '../components/kubernetes/configuration/Configuration'
-import Deployments from '../components/kubernetes/workloads/Deployments'
-import Pods from '../components/kubernetes/workloads/Pods'
-import ReplicaSets from '../components/kubernetes/workloads/ReplicaSets'
-import StatefulSets from '../components/kubernetes/workloads/StatefulSets'
-import DaemonSets from '../components/kubernetes/workloads/DaemonSets'
-import Jobs from '../components/kubernetes/workloads/Jobs'
-import CronJobs from '../components/kubernetes/workloads/CronJobs'
-import ReplicationControllers from '../components/kubernetes/workloads/ReplicationControllers'
-import PersistentVolumeClaims from '../components/kubernetes/storage/PersistentVolumeClaims'
-import PersistentVolumes from '../components/kubernetes/storage/PersistentVolumes'
-import StorageClasses from '../components/kubernetes/storage/StorageClasses'
-import ConfigMaps from '../components/kubernetes/configuration/ConfigMaps'
-import Secrets from '../components/kubernetes/configuration/Secrets'
+import Root from '../components/kubernetes/Cluster'
import Cluster from '../components/kubernetes/cluster/Cluster'
-import Nodes from '../components/kubernetes/cluster/Nodes'
+import Events from '../components/kubernetes/cluster/Events'
+
+import HorizontalPodAutoscalers from '../components/kubernetes/cluster/HorizontalPodAutoscalers'
+import Namespace, {
+ NamespaceEvents,
+} from '../components/kubernetes/cluster/Namespace'
+import Namespaces from '../components/kubernetes/cluster/Namespaces'
import Node, {
NodeConditions,
NodeContainerImages,
@@ -61,96 +40,119 @@ import Node, {
NodeInfo,
NodePods,
} from '../components/kubernetes/cluster/Node'
-import Events from '../components/kubernetes/cluster/Events'
-import Namespaces from '../components/kubernetes/cluster/Namespaces'
+import Nodes from '../components/kubernetes/cluster/Nodes'
+
+import Raw from '../components/kubernetes/common/Raw'
+import ConfigMap, {
+ ConfigMapData,
+} from '../components/kubernetes/configuration/ConfigMap'
+import ConfigMaps from '../components/kubernetes/configuration/ConfigMaps'
+import Configuration from '../components/kubernetes/configuration/Configuration'
+import Secrets from '../components/kubernetes/configuration/Secrets'
+
+import CustomResource, {
+ CustomResourceEvents,
+} from '../components/kubernetes/customresources/CustomResource'
import CustomResourceDefinitions from '../components/kubernetes/customresources/CustomResourceDefinitions'
+import Navigation from '../components/kubernetes/Navigation'
+import Ingress, {
+ IngressEvents,
+ IngressInfo,
+} from '../components/kubernetes/network/Ingress'
+import IngressClass from '../components/kubernetes/network/IngressClass'
+import IngressClasses from '../components/kubernetes/network/IngressClasses'
+import Ingresses from '../components/kubernetes/network/Ingresses'
+import Network from '../components/kubernetes/network/Network'
import NetworkPolicies from '../components/kubernetes/network/NetworkPolicies'
+import NetworkPolicy, {
+ NetworkPolicyInfo,
+} from '../components/kubernetes/network/NetworkPolicy'
+import Services from '../components/kubernetes/network/Services'
import ClusterRoleBindings from '../components/kubernetes/rbac/ClusterRoleBindings'
import ClusterRoles from '../components/kubernetes/rbac/ClusterRoles'
+import Rbac from '../components/kubernetes/rbac/Rbac'
import RoleBindings from '../components/kubernetes/rbac/RoleBindings'
import Roles from '../components/kubernetes/rbac/Roles'
-import Rbac from '../components/kubernetes/rbac/Rbac'
+
+import ServiceAccount from '../components/kubernetes/rbac/ServiceAccount'
+
+import ServiceAccounts from '../components/kubernetes/rbac/ServiceAccounts'
+import PersistentVolumeClaim from '../components/kubernetes/storage/PersistentVolumeClaim'
+import PersistentVolumeClaims from '../components/kubernetes/storage/PersistentVolumeClaims'
+import PersistentVolumes from '../components/kubernetes/storage/PersistentVolumes'
+import Storage from '../components/kubernetes/storage/Storage'
+import StorageClass, {
+ StorageClassPersistentVolumes,
+} from '../components/kubernetes/storage/StorageClass'
+import StorageClasses from '../components/kubernetes/storage/StorageClasses'
+import CronJob, {
+ CronJobEvents,
+ CronJobJobs,
+} from '../components/kubernetes/workloads/CronJob'
+import CronJobs from '../components/kubernetes/workloads/CronJobs'
+import DaemonSet, {
+ DaemonSetEvents,
+ DaemonSetPods,
+ DaemonSetServices,
+} from '../components/kubernetes/workloads/DaemonSet'
+import DaemonSets from '../components/kubernetes/workloads/DaemonSets'
import Deployment, {
DeploymentEvents,
DeploymentHorizontalPodAutoscalers,
DeploymentReplicaSets,
} from '../components/kubernetes/workloads/Deployment'
+import Deployments from '../components/kubernetes/workloads/Deployments'
+import Job, {
+ JobConditions,
+ JobEvents,
+ JobPods,
+} from '../components/kubernetes/workloads/Job'
+import Jobs from '../components/kubernetes/workloads/Jobs'
+
+import {
+ Pod,
+ PodContainers,
+ PodEvents,
+ PodExec,
+ PodInfo,
+ PodLogs,
+} from '../components/kubernetes/workloads/Pod'
+import Pods from '../components/kubernetes/workloads/Pods'
import ReplicaSet, {
ReplicaSetEvents,
ReplicaSetInfo,
ReplicaSetPods,
ReplicaSetServices,
} from '../components/kubernetes/workloads/ReplicaSet'
-import StatefulSet, {
- StatefulSetEvents,
- StatefulSetPods,
-} from '../components/kubernetes/workloads/StatefulSet'
-import DaemonSet, {
- DaemonSetEvents,
- DaemonSetPods,
- DaemonSetServices,
-} from '../components/kubernetes/workloads/DaemonSet'
-import Job, {
- JobConditions,
- JobEvents,
- JobPods,
-} from '../components/kubernetes/workloads/Job'
+import ReplicaSets from '../components/kubernetes/workloads/ReplicaSets'
import ReplicationController, {
ReplicationControllerEvents,
ReplicationControllerPods,
ReplicationControllerServices,
} from '../components/kubernetes/workloads/ReplicationController'
-import Ingress, {
- IngressEvents,
- IngressInfo,
-} from '../components/kubernetes/network/Ingress'
-import CronJob, {
- CronJobEvents,
- CronJobJobs,
-} from '../components/kubernetes/workloads/CronJob'
-import IngressClass from '../components/kubernetes/network/IngressClass'
-import NetworkPolicy, {
- NetworkPolicyInfo,
-} from '../components/kubernetes/network/NetworkPolicy'
-import PersistentVolumeClaim from '../components/kubernetes/storage/PersistentVolumeClaim'
-import StorageClass, {
- StorageClassPersistentVolumes,
-} from '../components/kubernetes/storage/StorageClass'
-import ConfigMap, {
- ConfigMapData,
-} from '../components/kubernetes/configuration/ConfigMap'
-import Namespace, {
- NamespaceEvents,
-} from '../components/kubernetes/cluster/Namespace'
-
-import Raw from '../components/kubernetes/common/Raw'
-
-import ServiceAccounts from '../components/kubernetes/rbac/ServiceAccounts'
-
-import ServiceAccount from '../components/kubernetes/rbac/ServiceAccount'
-
-import HorizontalPodAutoscalers from '../components/kubernetes/cluster/HorizontalPodAutoscalers'
-
-import CustomResource, {
- CustomResourceEvents,
-} from '../components/kubernetes/customresources/CustomResource'
-
-import Root from '../components/kubernetes/Cluster'
+import ReplicationControllers from '../components/kubernetes/workloads/ReplicationControllers'
+import StatefulSet, {
+ StatefulSetEvents,
+ StatefulSetPods,
+} from '../components/kubernetes/workloads/StatefulSet'
+import StatefulSets from '../components/kubernetes/workloads/StatefulSets'
+import Workloads from '../components/kubernetes/workloads/Workloads'
import {
+ AUDIT_REL_PATH,
CLUSTER_REL_PATH,
- CLUSTER_ROLES_REL_PATH,
CLUSTER_ROLE_BINDINGS_REL_PATH,
- CONFIGURATION_REL_PATH,
+ CLUSTER_ROLES_REL_PATH,
CONFIG_MAPS_REL_PATH,
+ CONFIGURATION_REL_PATH,
CRON_JOBS_REL_PATH,
CUSTOM_RESOURCES_REL_PATH,
DAEMON_SETS_REL_PATH,
DEPLOYMENTS_REL_PATH,
EVENTS_REL_PATH,
HPAS_REL_PATH,
- INGRESSES_REL_PATH,
INGRESS_CLASSES_REL_PATH,
+ INGRESSES_REL_PATH,
JOBS_REL_PATH,
KUBERNETES_ABS_PATH,
NAMESPACED_RESOURCE_DETAILS_REL_PATH,
@@ -158,18 +160,18 @@ import {
NETWORK_POLICIES_REL_PATH,
NETWORK_REL_PATH,
NODES_REL_PATH,
- PERSISTENT_VOLUMES_REL_PATH,
PERSISTENT_VOLUME_CLAIMS_REL_PATH,
+ PERSISTENT_VOLUMES_REL_PATH,
PODS_REL_PATH,
RBAC_REL_PATH,
- REPLICATION_CONTROLLERS_REL_PATH,
REPLICA_SETS_REL_PATH,
+ REPLICATION_CONTROLLERS_REL_PATH,
RESOURCE_DETAILS_REL_PATH,
- ROLES_REL_PATH,
ROLE_BINDINGS_REL_PATH,
+ ROLES_REL_PATH,
SECRETS_REL_PATH,
- SERVICES_REL_PATH,
SERVICE_ACCOUNTS_REL_PATH,
+ SERVICES_REL_PATH,
STATEFUL_SETS_REL_PATH,
STORAGE_CLASSES_REL_PATH,
STORAGE_REL_PATH,
@@ -386,6 +388,10 @@ export const kubernetesRoutes = (
path={CUSTOM_RESOURCES_REL_PATH}
element={}
/>
+ }
+ />