Skip to content

Commit

Permalink
upcoming: [M3-8869] - Update types for NodeBalancer UDP support (#11321)
Browse files Browse the repository at this point in the history
* initial types

* small fixes

* support nodes

* update validatoon schemas

* add changesets

* add comment

* clean up types in manager

* add changeset

* clean up validation schemas

* update and fix more nodebalancer schemas

* make validation schema more strict

* more improvements to schemas

---------

Co-authored-by: Banks Nussman <banks@nussman.us>
  • Loading branch information
bnussman-akamai and bnussman authored Dec 9, 2024
1 parent 92fe999 commit 85d62d3
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 76 deletions.
5 changes: 5 additions & 0 deletions packages/api-v4/.changeset/pr-11321-added-1733240671518.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/api-v4": Added
---

Types for UDP NodeBalancer support ([#11321](https://github.com/linode/manager/pull/11321))
102 changes: 93 additions & 9 deletions packages/api-v4/src/nodebalancers/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
type TCPAlgorithm = 'roundrobin' | 'leastconn' | 'source';
type UDPAlgorithm = 'roundrobin' | 'leastconn' | 'ring_hash';

export type Algorithm = TCPAlgorithm | UDPAlgorithm;

export type Protocol = 'http' | 'https' | 'tcp' | 'udp';

type TCPStickiness = 'none' | 'table' | 'http_cookie';
type UDPStickiness = 'none' | 'session' | 'source_ip';

export type Stickiness = TCPStickiness | UDPStickiness;

export interface NodeBalancer {
id: number;
label: string;
hostname: string;
/**
* Maximum number of new TCP connections that a client (identified by a specific source IP)
* is allowed to initiate every second.
*/
client_conn_throttle: number;
/**
* Maximum number of new UDP sessions that a client (identified by a specific source IP)
* is allowed to initiate every second.
*
* @todo Remove optionality once UDP support is live
*/
client_udp_sess_throttle?: number;
region: string;
ipv4: string;
ipv6: null | string;
Expand Down Expand Up @@ -31,11 +54,15 @@ export interface BalancerTransfer {
total: number;
}

/**
* 'none' is reserved for nodes used in UDP configurations. They don't support different modes.
*/
export type NodeBalancerConfigNodeMode =
| 'accept'
| 'reject'
| 'backup'
| 'drain';
| 'drain'
| 'none';

export interface NodeBalancerConfig {
id: number;
Expand All @@ -44,22 +71,31 @@ export interface NodeBalancerConfig {
check_passive: boolean;
ssl_cert: string;
nodes_status: NodesStatus;
protocol: 'http' | 'https' | 'tcp';
protocol: Protocol;
ssl_commonname: string;
check_interval: number;
check_attempts: number;
check_timeout: number;
check_body: string;
check_path: string;
/**
* @todo Remove optionality once UDP support is live
*/
udp_check_port?: number;
/**
* @readonly This is returned by the API but *not* editable
* @todo Remove optionality once UDP support is live
* @default 16
*/
udp_session_timeout?: number;
proxy_protocol: NodeBalancerProxyProtocol;
check: 'none' | 'connection' | 'http' | 'http_body';
ssl_key: string;
stickiness: 'none' | 'table' | 'http_cookie';
algorithm: 'roundrobin' | 'leastconn' | 'source';
stickiness: Stickiness;
algorithm: Algorithm;
ssl_fingerprint: string;
cipher_suite: 'recommended' | 'legacy';
nodes: NodeBalancerConfigNode[];
modifyStatus?: 'new';
}

export type NodeBalancerProxyProtocol = 'none' | 'v1' | 'v2';
Expand All @@ -82,16 +118,48 @@ export interface NodeBalancerStats {

export interface CreateNodeBalancerConfig {
port?: number;
protocol?: 'http' | 'https' | 'tcp';
algorithm?: 'roundrobin' | 'leastconn' | 'source';
stickiness?: 'none' | 'table' | 'http_cookie';
/**
* If `udp` is chosen:
* - `check_passive` must be `false` or unset
* - `proxy_protocol` must be `none` or unset
* - The various SSL related fields like `ssl_cert`, `ssl_key`, `cipher_suite_recommended` should not be set
*/
protocol?: Protocol;
/**
* @default "none"
*/
proxy_protocol?: NodeBalancerProxyProtocol;
/**
* The algorithm for this configuration.
*
* TCP and HTTP support `roundrobin`, `leastconn`, and `source`
* UDP supports `roundrobin`, `leastconn`, and `ring_hash`
*
* @default roundrobin
*/
algorithm?: Algorithm;
/**
* Session stickiness for this configuration.
*
* TCP and HTTP support `none`, `table`, and `http_cookie`
* UDP supports `none`, `session`, and `source_ip`
*
* @default `session` for UDP
* @default `none` for TCP and HTTP
*/
stickiness?: Stickiness;
check?: 'none' | 'connection' | 'http' | 'http_body';
check_interval?: number;
check_timeout?: number;
check_attempts?: number;
check_path?: string;
check_body?: string;
check_passive?: boolean;
/**
* Must be between 1 and 65535
* @default 80
*/
udp_check_port?: number;
cipher_suite?: 'recommended' | 'legacy';
ssl_cert?: string;
ssl_key?: string;
Expand All @@ -102,6 +170,9 @@ export type UpdateNodeBalancerConfig = CreateNodeBalancerConfig;
export interface CreateNodeBalancerConfigNode {
address: string;
label: string;
/**
* Should not be specified when creating a node used on a UDP configuration
*/
mode?: NodeBalancerConfigNodeMode;
weight?: number;
}
Expand All @@ -126,8 +197,21 @@ export interface NodeBalancerConfigNodeWithPort extends NodeBalancerConfigNode {
export interface CreateNodeBalancerPayload {
region?: string;
label?: string;
/**
* The connections per second throttle for TCP and HTTP connections
*
* Must be between 0 and 20. Set to 0 to disable throttling.
* @default 0
*/
client_conn_throttle?: number;
configs: any;
/**
* The connections per second throttle for UDP sessions
*
* Must be between 0 and 20. Set to 0 to disable throttling.
* @default 0
*/
client_udp_sess_throttle?: number;
configs: CreateNodeBalancerConfig[];
firewall_id?: number;
tags?: string[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tech Stories
---

Clean up NodeBalancer related types ([#11321](https://github.com/linode/manager/pull/11321))
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export const NodeBalancerConfigPanel = (

const algorithmHelperText = {
leastconn: LEAST_CONNECTIONS_ALGORITHM_HELPER_TEXT,
ring_hash: '', // @todo Add copy as part of UDP NodeBalancer project
roundrobin: ROUND_ROBIN_ALGORITHM_HELPER_TEXT,
source: SOURCE_ALGORITHM_HELPER_TEXT,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ import { sendCreateNodeBalancerEvent } from 'src/utilities/analytics/customEvent
import { getAPIErrorOrDefault } from 'src/utilities/errorUtils';
import { getGDPRDetails } from 'src/utilities/formatRegion';
import { getAPIErrorFor } from 'src/utilities/getAPIErrorFor';
import { PRICE_ERROR_TOOLTIP_TEXT } from 'src/utilities/pricing/constants';
import { DOCS_LINK_LABEL_DC_PRICING } from 'src/utilities/pricing/constants';
import { PRICE_ERROR_TOOLTIP_TEXT } from 'src/utilities/pricing/constants';
import {
getDCSpecificPriceByType,
renderMonthlyPriceToCorrectDecimalPlace,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
getNodeBalancerConfigs,
updateNodeBalancerConfig,
updateNodeBalancerConfigNode,
} from '@linode/api-v4/lib/nodebalancers';
} from '@linode/api-v4';
import { Accordion, Box, Button, Typography } from '@linode/ui';
import { styled } from '@mui/material/styles';
import {
Expand Down Expand Up @@ -49,12 +49,13 @@ import type {
NodeBalancerConfigFieldsWithStatus,
NodeBalancerConfigNodeFields,
} from '../types';
import type { Grants } from '@linode/api-v4';
import type {
APIError,
Grants,
NodeBalancerConfig,
NodeBalancerConfigNode,
} from '@linode/api-v4/lib/nodebalancers';
import type { APIError, ResourcePage } from '@linode/api-v4/lib/types';
ResourcePage,
} from '@linode/api-v4';
import type { Lens } from 'ramda';
import type { RouteComponentProps } from 'react-router-dom';
import type { PromiseLoaderResponse } from 'src/components/PromiseLoader/PromiseLoader';
Expand Down
65 changes: 22 additions & 43 deletions packages/manager/src/features/NodeBalancers/types.ts
Original file line number Diff line number Diff line change
@@ -1,65 +1,44 @@
import type {
NodeBalancerConfigNodeMode,
APIError,
Algorithm,
NodeBalancerConfigNode,
NodeBalancerProxyProtocol,
} from '@linode/api-v4/lib/nodebalancers/types';
import type { APIError } from '@linode/api-v4/lib/types';
Protocol,
Stickiness,
UpdateNodeBalancerConfig,
} from '@linode/api-v4';

export interface NodeBalancerConfigFieldsWithStatus
extends NodeBalancerConfigFields {
/**
* Exists for the sake of local operations
*/
modifyStatus?: 'new';
}
export interface ExtendedNodeBalancerConfigNode {
address: string;
config_id?: number;
errors?: APIError[];
id: number;
label: string;
mode?: NodeBalancerConfigNodeMode;
modifyStatus?: 'delete' | 'new' | 'update';
nodebalancer_id: number;
port?: number;
status: 'DOWN' | 'UP' | 'unknown';
weight?: number;
}

export interface NodeBalancerConfigFields {
algorithm?: 'leastconn' | 'roundrobin' | 'source';
check?: 'connection' | 'http' | 'http_body' | 'none';
check_attempts?: number /** 1..30 */;
check_body?: string;
check_interval?: number;
check_passive?: boolean;
check_path?: string;
check_timeout?: number /** 1..30 */;
cipher_suite?: 'legacy' | 'recommended';
export interface NodeBalancerConfigFields extends UpdateNodeBalancerConfig {
id?: number;
nodes: NodeBalancerConfigNodeFields[];
port?: number /** 1..65535 */;
protocol?: 'http' | 'https' | 'tcp';
proxy_protocol?: NodeBalancerProxyProtocol;
ssl_cert?: string;
ssl_key?: string;
stickiness?: 'http_cookie' | 'none' | 'table';
}

export interface NodeBalancerConfigNodeFields {
export interface NodeBalancerConfigNodeFields
extends Partial<NodeBalancerConfigNode> {
address: string;
config_id?: number;
errors?: APIError[];
id?: number;
label: string;
mode?: NodeBalancerConfigNodeMode;
/* for the sake of local operations */
/**
* Exists for the sake of local operations
*/
modifyStatus?: 'delete' | 'new' | 'update';
nodebalancer_id?: number;
/**
* @note `port` is an "extended" field. The API includes it in the `address`
*/
port?: number;
status?: 'DOWN' | 'UP' | 'unknown';
weight?: number;
}

export interface NodeBalancerConfigPanelProps {
addNode: (nodeIdx?: number) => void;
algorithm: 'leastconn' | 'roundrobin' | 'source';
algorithm: Algorithm;
checkBody: string;
checkPassive: boolean;

Expand Down Expand Up @@ -113,10 +92,10 @@ export interface NodeBalancerConfigPanelProps {
onSslCertificateChange: (v: string) => void;
port: number;
privateKey: string;
protocol: 'http' | 'https' | 'tcp';
protocol: Protocol;
proxyProtocol: NodeBalancerProxyProtocol;
removeNode: (nodeIdx: number) => void;
sessionStickiness: 'http_cookie' | 'none' | 'table';
sessionStickiness: Stickiness;
sslCertificate: string;
submitting?: boolean;
}
3 changes: 1 addition & 2 deletions packages/manager/src/features/NodeBalancers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { filter, isNil } from 'ramda';
import { getErrorMap } from 'src/utilities/errorUtils';

import type {
ExtendedNodeBalancerConfigNode,
NodeBalancerConfigFields,
NodeBalancerConfigFieldsWithStatus,
NodeBalancerConfigNodeFields,
Expand Down Expand Up @@ -51,7 +50,7 @@ export const nodeForRequest = (node: NodeBalancerConfigNodeFields) => ({
weight: +node.weight!,
});

export const formatAddress = (node: ExtendedNodeBalancerConfigNode) => ({
export const formatAddress = (node: NodeBalancerConfigNodeFields) => ({
...node,
address: `${node.address}:${node.port}`,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/validation": Added
---

Validation for UDP NodeBalancer support ([#11321](https://github.com/linode/manager/pull/11321))
Loading

0 comments on commit 85d62d3

Please sign in to comment.