diff --git a/assets/src/components/kubernetes/cluster/Node.tsx b/assets/src/components/kubernetes/cluster/Node.tsx index d14ab75d6a..838077ec66 100644 --- a/assets/src/components/kubernetes/cluster/Node.tsx +++ b/assets/src/components/kubernetes/cluster/Node.tsx @@ -1,5 +1,101 @@ -import { ReactElement } from 'react' +import { ReactElement, useMemo } from 'react' +import { SidecarItem, useSetBreadcrumbs } from '@pluralsh/design-system' +import { Outlet, useOutletContext, useParams } from 'react-router-dom' + +import { + Common_EventList as EventListT, + Common_Event as EventT, + NodeEventsQuery, + NodeEventsQueryVariables, + NodeQueryVariables, + Node_Node as NodeT, + useNodeEventsQuery, + useNodeQuery, +} from '../../../generated/graphql-kubernetes' +import { KubernetesClient } from '../../../helpers/kubernetes.client' +import LoadingIndicator from '../../utils/LoadingIndicator' +import { MetadataSidecar, useKubernetesCluster } from '../utils' +import { getResourceDetailsAbsPath } from '../../../routes/kubernetesRoutesConsts' + +import ResourceDetails, { TabEntry } from '../ResourceDetails' + +import { ResourceList } from '../ResourceList' + +import { getBreadcrumbs } from './Namespaces' +import { NamespacePhaseChip } from './utils' +import { COLUMNS } from './Events' + +const directory: Array = [ + { path: '', label: 'Info' }, + { path: 'events', label: 'Events' }, + { path: 'raw', label: 'Raw' }, +] as const export default function Node(): ReactElement { - return
Node details
+ const cluster = useKubernetesCluster() + const { clusterId, name = '' } = useParams() + const { data, loading } = useNodeQuery({ + client: KubernetesClient(clusterId ?? ''), + skip: !clusterId, + pollInterval: 30_000, + variables: { + name, + } as NodeQueryVariables, + }) + + const namespace = data?.handleGetNodeDetail + + useSetBreadcrumbs( + useMemo( + () => [ + ...getBreadcrumbs(cluster), + { + label: name ?? '', + url: getResourceDetailsAbsPath(clusterId, 'namespace', name), + }, + ], + [cluster, clusterId, name] + ) + ) + + if (loading) return + + return ( + + + + + + } + > + + + ) +} + +export function NodeInfo(): ReactElement { + const node = useOutletContext() as NodeT + + return
TODO
+} + +export function NodeEvents(): ReactElement { + const { name } = useParams() + + return ( + + namespaced + columns={COLUMNS} + query={useNodeEventsQuery} + queryOptions={{ + variables: { name } as NodeEventsQueryVariables, + }} + queryName="handleGetNodeEvents" + itemsKey="events" + disableOnRowClick + /> + ) } diff --git a/assets/src/generated/graphql-kubernetes.ts b/assets/src/generated/graphql-kubernetes.ts index a45e2aaf4f..59a4b05767 100644 --- a/assets/src/generated/graphql-kubernetes.ts +++ b/assets/src/generated/graphql-kubernetes.ts @@ -4739,6 +4739,17 @@ export type NodeQueryVariables = Exact<{ export type NodeQuery = { __typename?: 'Query', handleGetNodeDetail?: { __typename?: 'node_NodeDetail', providerID: string, containerImages: Array, podCIDR: string, phase: string, errors: Array, typeMeta: { __typename?: 'types_TypeMeta', kind?: string | null, restartable?: boolean | null, scalable?: boolean | null }, objectMeta: { __typename?: 'types_ObjectMeta', uid?: string | null, name?: string | null, namespace?: string | null, labels?: any | null, annotations?: any | null, creationTimestamp?: string | null }, nodeInfo: { __typename?: 'v1_NodeSystemInfo', architecture: string, bootID: string, containerRuntimeVersion: string, kernelVersion: string, kubeletVersion: string, kubeProxyVersion: string, machineID: string, operatingSystem: string, osImage: string, systemUUID: string } } | null }; +export type NodeEventsQueryVariables = Exact<{ + name: Scalars['String']['input']; + filterBy?: InputMaybe; + sortBy?: InputMaybe; + itemsPerPage?: InputMaybe; + page?: InputMaybe; +}>; + + +export type NodeEventsQuery = { __typename?: 'Query', handleGetNodeEvents?: { __typename?: 'common_EventList', listMeta: { __typename?: 'types_ListMeta', totalItems: number }, events: Array<{ __typename?: 'common_Event', objectName?: string | null, objectNamespace?: string | null, reason: string, type: string, message: string, sourceComponent: string, sourceHost: string, count: number, firstSeen: string, lastSeen: string, typeMeta: { __typename?: 'types_TypeMeta', kind?: string | null, restartable?: boolean | null, scalable?: boolean | null }, objectMeta: { __typename?: 'types_ObjectMeta', uid?: string | null, name?: string | null, namespace?: string | null, labels?: any | null, annotations?: any | null, creationTimestamp?: string | null } } | null> } | null }; + export type NamespacedResourceQueryVariables = Exact<{ kind: Scalars['String']['input']; name: Scalars['String']['input']; @@ -6282,6 +6293,56 @@ export type NodeQueryHookResult = ReturnType; export type NodeLazyQueryHookResult = ReturnType; export type NodeSuspenseQueryHookResult = ReturnType; export type NodeQueryResult = Apollo.QueryResult; +export const NodeEventsDocument = gql` + query NodeEvents($name: String!, $filterBy: String, $sortBy: String, $itemsPerPage: String, $page: String) { + handleGetNodeEvents( + name: $name + filterBy: $filterBy + sortBy: $sortBy + itemsPerPage: $itemsPerPage + page: $page + ) @rest(type: "common_EventList", path: "node/{args.name}/event?filterBy={args.filterBy}&sortBy={args.sortBy}&itemsPerPage={args.itemsPerPage}&page={args.page}") { + ...EventList + } +} + ${EventListFragmentDoc}`; + +/** + * __useNodeEventsQuery__ + * + * To run a query within a React component, call `useNodeEventsQuery` and pass it any options that fit your needs. + * When your component renders, `useNodeEventsQuery` 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 } = useNodeEventsQuery({ + * variables: { + * name: // value for 'name' + * filterBy: // value for 'filterBy' + * sortBy: // value for 'sortBy' + * itemsPerPage: // value for 'itemsPerPage' + * page: // value for 'page' + * }, + * }); + */ +export function useNodeEventsQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(NodeEventsDocument, options); + } +export function useNodeEventsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(NodeEventsDocument, options); + } +export function useNodeEventsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(NodeEventsDocument, options); + } +export type NodeEventsQueryHookResult = ReturnType; +export type NodeEventsLazyQueryHookResult = ReturnType; +export type NodeEventsSuspenseQueryHookResult = ReturnType; +export type NodeEventsQueryResult = Apollo.QueryResult; export const NamespacedResourceDocument = gql` query NamespacedResource($kind: String!, $name: String!, $namespace: String!) { handleGetResource(kind: $kind, name: $name, namespace: $namespace) @rest(path: "_raw/{args.kind}/namespace/{args.namespace}/name/{args.name}") { diff --git a/assets/src/graph-kubernetes/cluster/namespace.graphql b/assets/src/graph-kubernetes/cluster/namespace.graphql index dae3fb3804..ff514c0009 100644 --- a/assets/src/graph-kubernetes/cluster/namespace.graphql +++ b/assets/src/graph-kubernetes/cluster/namespace.graphql @@ -30,8 +30,7 @@ query Namespaces( } query Namespace($name: String!) { - handleGetNamespaceDetail(name: $name) - @rest(path: "namespace/{args.name}") { + handleGetNamespaceDetail(name: $name) @rest(path: "namespace/{args.name}") { typeMeta @type(name: "types_TypeMeta") { ...TypeMeta } @@ -72,7 +71,6 @@ query Namespace($name: String!) { } } - query NamespaceEvents( $name: String! $filterBy: String @@ -87,10 +85,10 @@ query NamespaceEvents( itemsPerPage: $itemsPerPage page: $page ) - @rest( - type: "common_EventList" - path: "namespace/{args.name}/event?filterBy={args.filterBy}&sortBy={args.sortBy}&itemsPerPage={args.itemsPerPage}&page={args.page}" - ) { + @rest( + type: "common_EventList" + path: "namespace/{args.name}/event?filterBy={args.filterBy}&sortBy={args.sortBy}&itemsPerPage={args.itemsPerPage}&page={args.page}" + ) { ...EventList } } diff --git a/assets/src/graph-kubernetes/cluster/node.graphql b/assets/src/graph-kubernetes/cluster/node.graphql index 991c2c50c6..f42dc2321c 100644 --- a/assets/src/graph-kubernetes/cluster/node.graphql +++ b/assets/src/graph-kubernetes/cluster/node.graphql @@ -41,8 +41,7 @@ query Nodes( } query Node($name: String!) { - handleGetNodeDetail(name: $name) - @rest(path: "node/{args.name}") { + handleGetNodeDetail(name: $name) @rest(path: "node/{args.name}") { typeMeta @type(name: "types_TypeMeta") { ...TypeMeta } @@ -68,3 +67,25 @@ query Node($name: String!) { errors } } + +query NodeEvents( + $name: String! + $filterBy: String + $sortBy: String + $itemsPerPage: String + $page: String +) { + handleGetNodeEvents( + name: $name + filterBy: $filterBy + sortBy: $sortBy + itemsPerPage: $itemsPerPage + page: $page + ) + @rest( + type: "common_EventList" + path: "node/{args.name}/event?filterBy={args.filterBy}&sortBy={args.sortBy}&itemsPerPage={args.itemsPerPage}&page={args.page}" + ) { + ...EventList + } +} diff --git a/assets/src/routes/kubernetesRoutes.tsx b/assets/src/routes/kubernetesRoutes.tsx index 16a1753359..ea7ed52236 100644 --- a/assets/src/routes/kubernetesRoutes.tsx +++ b/assets/src/routes/kubernetesRoutes.tsx @@ -44,7 +44,10 @@ import ConfigMaps from '../components/kubernetes/configuration/ConfigMaps' import Secrets from '../components/kubernetes/configuration/Secrets' import Cluster from '../components/kubernetes/cluster/Cluster' import Nodes from '../components/kubernetes/cluster/Nodes' -import Node from '../components/kubernetes/cluster/Node' +import Node, { + NodeEvents, + NodeInfo, +} from '../components/kubernetes/cluster/Node' import Events from '../components/kubernetes/cluster/Events' import Namespaces from '../components/kubernetes/cluster/Namespaces' import CustomResourceDefinitions from '../components/kubernetes/customresources/CustomResourceDefinitions' @@ -472,10 +475,23 @@ export const kubernetesRoutes = [ , // Cluster } - />, + > + } + /> + } + /> + } + /> + , }