mirror of https://github.com/portainer/portainer
109 lines
3.7 KiB
TypeScript
109 lines
3.7 KiB
TypeScript
import { Node, Endpoints } from 'kubernetes-types/core/v1';
|
|
import { HardDrive } from 'lucide-react';
|
|
import { useMemo } from 'react';
|
|
|
|
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
|
|
import { createStore } from '@/react/kubernetes/datatables/default-kube-datatable-store';
|
|
import { IndexOptional } from '@/react/kubernetes/configs/types';
|
|
import { useEnvironment } from '@/react/portainer/environments/queries';
|
|
|
|
import { Datatable, TableSettingsMenu } from '@@/datatables';
|
|
import { useTableState } from '@@/datatables/useTableState';
|
|
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
|
|
|
|
import { useNodesQuery } from '../nodes.service';
|
|
import { useKubernetesEndpointsQuery } from '../../kubernetesEndpoint.service';
|
|
|
|
import { getColumns } from './columns';
|
|
import { NodeRowData } from './types';
|
|
import { getInternalNodeIpAddress } from './utils';
|
|
|
|
const storageKey = 'k8sNodesDatatable';
|
|
const settingsStore = createStore(storageKey);
|
|
|
|
export function NodesDatatable() {
|
|
const tableState = useTableState(settingsStore, storageKey);
|
|
const environmentId = useEnvironmentId();
|
|
const { data: nodes, ...nodesQuery } = useNodesQuery(environmentId, {
|
|
autoRefreshRate: tableState.autoRefreshRate * 1000,
|
|
});
|
|
const { data: kubernetesEndpoints, ...kubernetesEndpointsQuery } =
|
|
useKubernetesEndpointsQuery(environmentId, {
|
|
autoRefreshRate: tableState.autoRefreshRate * 1000,
|
|
});
|
|
const { data: environment, ...environmentQuery } =
|
|
useEnvironment(environmentId);
|
|
const environmentUrl = environment?.URL;
|
|
const isServerMetricsEnabled =
|
|
!!environment?.Kubernetes?.Configuration.UseServerMetrics;
|
|
const nodeRowData = useNodeRowData(
|
|
nodes,
|
|
kubernetesEndpoints,
|
|
environmentUrl
|
|
);
|
|
|
|
return (
|
|
<Datatable<IndexOptional<NodeRowData>>
|
|
disableSelect
|
|
dataset={nodeRowData ?? []}
|
|
columns={getColumns(isServerMetricsEnabled)}
|
|
settingsManager={tableState}
|
|
isLoading={
|
|
nodesQuery.isLoading ||
|
|
kubernetesEndpointsQuery.isLoading ||
|
|
environmentQuery.isLoading
|
|
}
|
|
emptyContentLabel="No Nodes found"
|
|
title="Nodes"
|
|
titleIcon={HardDrive}
|
|
getRowId={(row) => row.metadata?.uid ?? ''}
|
|
renderTableSettings={() => (
|
|
<TableSettingsMenu>
|
|
<TableSettingsMenuAutoRefresh
|
|
value={tableState.autoRefreshRate}
|
|
onChange={(value) => tableState.setAutoRefreshRate(value)}
|
|
/>
|
|
</TableSettingsMenu>
|
|
)}
|
|
/>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* This function is used to add the isApi property to the node row data.
|
|
*/
|
|
function useNodeRowData(
|
|
nodes?: Node[],
|
|
kubernetesEndpoints?: Endpoints[],
|
|
environmentUrl?: string
|
|
): NodeRowData[] {
|
|
return useMemo<NodeRowData[]>(() => {
|
|
if (!nodes || !kubernetesEndpoints) {
|
|
return [];
|
|
}
|
|
const subsetAddresses = kubernetesEndpoints?.flatMap(
|
|
(endpoint) =>
|
|
endpoint.subsets?.flatMap((subset) => subset.addresses ?? [])
|
|
);
|
|
const nodeRowData = nodes.map((node) => {
|
|
const nodeAddress = getInternalNodeIpAddress(node);
|
|
// if the node address is in the endpoints subset addresses, then it is an api node
|
|
const isApi = subsetAddresses?.some(
|
|
(subsetAddress) => subsetAddress?.ip === nodeAddress
|
|
);
|
|
// if the environment url includes the node address, then it is a published node
|
|
const isPublishedNode =
|
|
!!nodeAddress &&
|
|
!!environmentUrl &&
|
|
environmentUrl?.includes(nodeAddress);
|
|
return {
|
|
...node,
|
|
isApi,
|
|
isPublishedNode,
|
|
Name: `${node.metadata?.name}${isApi ? 'api' : ''}` ?? '',
|
|
};
|
|
});
|
|
return nodeRowData;
|
|
}, [nodes, kubernetesEndpoints, environmentUrl]);
|
|
}
|