Skip to content

Commit

Permalink
surface tags for node pools
Browse files Browse the repository at this point in the history
  • Loading branch information
hana-akamai committed Dec 3, 2024
1 parent d57c38d commit 808b96c
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 29 deletions.
2 changes: 2 additions & 0 deletions packages/api-v4/src/kubernetes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface KubeNodePoolResponse {
count: number;
id: number;
nodes: PoolNodeResponse[];
tags: string[];
type: string;
autoscaler: AutoscaleSettings;
disk_encryption?: EncryptionStatus; // @TODO LDE: remove optionality once LDE is fully rolled out
Expand All @@ -42,6 +43,7 @@ export interface CreateNodePoolData {
export interface UpdateNodePoolData {
autoscaler: AutoscaleSettings;
count: number;
tags: string[];
}

export interface AutoscaleSettings {
Expand Down
1 change: 1 addition & 0 deletions packages/manager/src/factories/kubernetesCluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const nodePoolFactory = Factory.Sync.makeFactory<KubeNodePoolResponse>({
disk_encryption: 'enabled',
id: Factory.each((id) => id),
nodes: kubeLinodeFactory.buildList(3),
tags: [],
type: 'g6-standard-1',
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type { EncryptionStatus } from '@linode/api-v4/lib/linodes/types';

interface Props {
autoscaler: AutoscaleSettings;
clusterId: number;
encryptionStatus: EncryptionStatus | undefined;
handleClickResize: (poolId: number) => void;
isOnlyNodePool: boolean;
Expand All @@ -30,12 +31,14 @@ interface Props {
openRecycleAllNodesDialog: (poolId: number) => void;
openRecycleNodeDialog: (nodeID: string, linodeLabel: string) => void;
poolId: number;
tags: string[];
typeLabel: string;
}

export const NodePool = (props: Props) => {
const {
autoscaler,
clusterId,
encryptionStatus,
handleClickResize,
isOnlyNodePool,
Expand All @@ -45,6 +48,7 @@ export const NodePool = (props: Props) => {
openRecycleAllNodesDialog,
openRecycleNodeDialog,
poolId,
tags,
typeLabel,
} = props;

Expand Down Expand Up @@ -134,10 +138,12 @@ export const NodePool = (props: Props) => {
</Hidden>
</Paper>
<NodeTable
clusterId={clusterId}
encryptionStatus={encryptionStatus}
nodes={nodes}
openRecycleNodeDialog={openRecycleNodeDialog}
poolId={poolId}
tags={tags}
typeLabel={typeLabel}
/>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export const NodePoolsDisplay = (props: Props) => {
{poolsError && <ErrorState errorText={poolsError[0].reason} />}
<Stack spacing={2}>
{_pools?.map((thisPool) => {
const { disk_encryption, id, nodes } = thisPool;
const { disk_encryption, id, nodes, tags } = thisPool;

const thisPoolType = types?.find(
(thisType) => thisType.id === thisPool.type
Expand All @@ -131,12 +131,14 @@ export const NodePoolsDisplay = (props: Props) => {
setIsRecycleNodeOpen(true);
}}
autoscaler={thisPool.autoscaler}
clusterId={clusterID}
encryptionStatus={disk_encryption}
handleClickResize={handleOpenResizeDrawer}
isOnlyNodePool={pools?.length === 1}
key={id}
nodes={nodes ?? []}
poolId={thisPool.id}
tags={tags}
typeLabel={typeLabel}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ import { kubeLinodeFactory } from 'src/factories/kubernetesCluster';
import { linodeFactory } from 'src/factories/linodes';
import { renderWithTheme } from 'src/utilities/testHelpers';

import { NodeTable, Props, encryptionStatusTestId } from './NodeTable';
import { NodeTable, encryptionStatusTestId } from './NodeTable';

import type { Props } from './NodeTable';

const mockLinodes = linodeFactory.buildList(3);

const mockKubeNodes = kubeLinodeFactory.buildList(3);

const props: Props = {
clusterId: 1,
encryptionStatus: 'enabled',
nodes: mockKubeNodes,
openRecycleNodeDialog: vi.fn(),
poolId: 1,
tags: [],
typeLabel: 'Linode 2G',
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Box, TooltipIcon, Typography } from '@linode/ui';
import { enqueueSnackbar } from 'notistack';
import * as React from 'react';

import Lock from 'src/assets/icons/lock.svg';
Expand All @@ -12,11 +13,13 @@ import { Table } from 'src/components/Table';
import { TableBody } from 'src/components/TableBody';
import { TableCell } from 'src/components/TableCell';
import { TableContentWrapper } from 'src/components/TableContentWrapper/TableContentWrapper';
import { TableFooter } from 'src/components/TableFooter';
import { TableHead } from 'src/components/TableHead';
import { TableRow } from 'src/components/TableRow';
import { TableSortCell } from 'src/components/TableSortCell';
import { TagCell } from 'src/components/TagCell/TagCell';
import { useUpdateNodePoolMutation } from 'src/queries/kubernetes';
import { useAllLinodesQuery } from 'src/queries/linodes/linodes';
import { getAPIErrorOrDefault } from 'src/utilities/errorUtils';

import { NodeRow as _NodeRow } from './NodeRow';
import { StyledTypography, StyledVerticalDivider } from './NodeTable.styles';
Expand All @@ -27,21 +30,25 @@ import type { EncryptionStatus } from '@linode/api-v4/lib/linodes/types';
import type { LinodeWithMaintenance } from 'src/utilities/linodes';

export interface Props {
clusterId: number;
encryptionStatus: EncryptionStatus | undefined;
nodes: PoolNodeResponse[];
openRecycleNodeDialog: (nodeID: string, linodeLabel: string) => void;
poolId: number;
tags: string[];
typeLabel: string;
}

export const encryptionStatusTestId = 'encryption-status-fragment';

export const NodeTable = React.memo((props: Props) => {
const {
clusterId,
encryptionStatus,
nodes,
openRecycleNodeDialog,
poolId,
tags,
typeLabel,
} = props;

Expand All @@ -50,6 +57,25 @@ export const NodeTable = React.memo((props: Props) => {
isDiskEncryptionFeatureEnabled,
} = useIsDiskEncryptionFeatureEnabled();

const { mutateAsync: updateNodePool } = useUpdateNodePoolMutation(
clusterId,
poolId
);

const updateTags = React.useCallback(
(tags: string[]) => {
return updateNodePool({ tags }).catch((e) =>
enqueueSnackbar(
getAPIErrorOrDefault(e, 'Error updating tags')[0].reason,
{
variant: 'error',
}
)
);
},
[updateNodePool]
);

const rowData = nodes.map((thisNode) => nodeToRow(thisNode, linodes ?? []));

return (
Expand Down Expand Up @@ -131,33 +157,46 @@ export const NodeTable = React.memo((props: Props) => {
})}
</TableContentWrapper>
</TableBody>
<TableFooter>
<TableRow>
<TableCell colSpan={4}>
{isDiskEncryptionFeatureEnabled &&
encryptionStatus !== undefined ? (
<Box
alignItems="center"
data-testid={encryptionStatusTestId}
display="flex"
flexDirection="row"
>
<Typography>Pool ID {poolId}</Typography>
<StyledVerticalDivider />
<EncryptedStatus
tooltipText={
DISK_ENCRYPTION_NODE_POOL_GUIDANCE_COPY
}
encryptionStatus={encryptionStatus}
/>
</Box>
) : (
<Typography>Pool ID {poolId}</Typography>
)}
</TableCell>
</TableRow>
</TableFooter>
</Table>
<Box
sx={(theme) => ({
background: theme.bg.bgPaper,
})}
alignItems="center"
display="flex"
justifyContent="space-between"
px={2}
>
<Box
alignItems="center"
data-testid={encryptionStatusTestId}
display="flex"
flexDirection="row"
width="100%"
>
{isDiskEncryptionFeatureEnabled &&
encryptionStatus !== undefined ? (
<>
<Typography>Pool ID {poolId}</Typography>
<StyledVerticalDivider />
<EncryptedStatus
encryptionStatus={encryptionStatus}
tooltipText={DISK_ENCRYPTION_NODE_POOL_GUIDANCE_COPY}
/>
</>
) : (
<Typography>Pool ID {poolId}</Typography>
)}
</Box>
<TagCell
sx={{
width: '100%',
}}
tags={tags}
updateTags={updateTags}
view="inline"
/>
</Box>
<PaginationFooter
count={count}
eventCategory="Node Table"
Expand Down

0 comments on commit 808b96c

Please sign in to comment.