Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [WD-14882] Adjust Listen and Connect Inputs #890

Merged
merged 1 commit into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 36 additions & 75 deletions src/components/forms/ProxyDeviceForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import { deviceKeyToLabel } from "util/devices";
import { ensureEditMode } from "util/instanceEdit";
import NewProxyBtn from "components/forms/NewProxyBtn";
import ConfigFieldDescription from "pages/settings/ConfigFieldDescription";
import { optionEnabledDisabled, optionYesNo } from "util/instanceOptions";
import { optionEnabledDisabled } from "util/instanceOptions";
import { getProxyAddress } from "util/proxyDevices";

interface Props {
formik: InstanceAndProfileFormikProps;
Expand Down Expand Up @@ -84,6 +85,8 @@ const ProxyDeviceForm: FC<Props> = ({ formik, project }) => {
}[],
value?: string,
help?: string,
onChange?: (value: string) => void,
disabledText?: string,
) => {
const key = `devices.${index}.${fieldName}`;

Expand All @@ -99,11 +102,14 @@ const ProxyDeviceForm: FC<Props> = ({ formik, project }) => {
onChange={(e) => {
ensureEditMode(formik);
void formik.setFieldValue(key, e.target.value);
onChange?.(e.target.value);
}}
value={value ?? ""}
options={options}
help={<ConfigFieldDescription description={help} />}
className="u-no-margin--bottom"
disabled={disabledText != undefined}
title={disabledText}
/>
),
override: "",
Expand Down Expand Up @@ -187,6 +193,16 @@ const ProxyDeviceForm: FC<Props> = ({ formik, project }) => {
}
const device = formik.values.devices[index] as LxdProxyDevice;

const deviceListenParts = device.listen?.split(":") || [];
const listenType =
deviceListenParts.length > 0 ? deviceListenParts[0] : "tcp";

const deviceConnectParts = device.connect?.split(":") || [];
const connectAddress =
deviceConnectParts.length > 1 ? deviceConnectParts[1] : "";
const connectPort =
deviceConnectParts.length > 2 ? deviceConnectParts[2] : "";

customRows.push(
getConfigurationRowBase({
className: "no-border-top custom-device-name",
Expand Down Expand Up @@ -233,6 +249,11 @@ const ProxyDeviceForm: FC<Props> = ({ formik, project }) => {
],
device.bind,
"Whether to bind the listen address to the instance or host",
(value) => {
Kxiru marked this conversation as resolved.
Show resolved Hide resolved
if (value === "instance" && device.nat === "true") {
void formik.setFieldValue(`devices.${index}.nat`, "false");
}
},
),
);

Expand All @@ -243,84 +264,24 @@ const ProxyDeviceForm: FC<Props> = ({ formik, project }) => {
index,
optionEnabledDisabled,
device.nat,
undefined,
(value) => {
if (value === "true") {
void formik.setFieldValue(
`devices.${index}.connect`,
`${listenType}:${connectAddress}:${connectPort}`,
);
}
},
device.bind === "instance"
? "Only host-bound proxies can use NAT"
: undefined,
),
);

customRows.push(
getProxyDeviceFormRows(
"Use HAProxy Protocol",
"proxy_protocol",
index,
optionYesNo,
device.proxy_protocol,
),
);

customRows.push(
getConfigurationRowBase({
className: "no-border-top inherited-with-form",
configuration: <Label>Listen</Label>,
inherited: (
<Input
name={`devices.${index}.listen`}
id={`devices.${index}.listen`}
key={`devices.${index}.listen`}
onBlur={formik.handleBlur}
onChange={(e) => {
ensureEditMode(formik);
void formik.setFieldValue(
`devices.${index}.listen`,
e.target.value,
);
}}
value={device.listen}
type="text"
help={
<ConfigFieldDescription
description={
"Use the following format to specify the address and port: <type>:<addr>:<port>[-<port>][,<port>]"
}
/>
}
className="u-no-margin--bottom"
/>
),
override: "",
}),
);
getProxyAddress(customRows, device, index, "listen", formik, "Listen");

customRows.push(
getConfigurationRowBase({
className: "no-border-top inherited-with-form",
configuration: <Label>Connect</Label>,
inherited: (
<Input
name={`devices.${index}.connect`}
id={`devices.${index}.connect`}
key={`devices.${index}.connect`}
onBlur={formik.handleBlur}
onChange={(e) => {
ensureEditMode(formik);
void formik.setFieldValue(
`devices.${index}.connect`,
e.target.value,
);
}}
value={device.connect}
type="text"
help={
<ConfigFieldDescription
description={
"Use the following format to specify the address and port: <type>:<addr>:<port>[-<port>][,<port>]"
}
/>
}
className="u-no-margin--bottom"
/>
),
override: "",
}),
);
getProxyAddress(customRows, device, index, "connect", formik, "Connect");
});

if (isProfileLoading) {
Expand Down
21 changes: 21 additions & 0 deletions src/util/instanceOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export const optionYesNo = [
value: "false",
},
];

export const optionEnabledDisabled = [
{
label: "Select option",
Expand All @@ -75,3 +76,23 @@ export const optionEnabledDisabled = [
export const diskPriorities = [...Array(11).keys()].map((i) => {
return { label: i.toString(), value: i };
});

export const proxyAddressTypeOptions = [
{
label: "Select option",
value: "",
disabled: true,
},
{
label: "TCP",
value: "tcp",
},
{
label: "UDP",
value: "udp",
},
{
label: "UNIX",
value: "unix",
},
];
160 changes: 160 additions & 0 deletions src/util/proxyDevices.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { Input, Label, Select } from "@canonical/react-components";
import { MainTableRow } from "@canonical/react-components/dist/components/MainTable/MainTable";
import { getConfigurationRowBase } from "components/ConfigurationRow";
import { LxdProxyDevice } from "types/device";
import { ensureEditMode } from "./instanceEdit";
import { proxyAddressTypeOptions } from "./instanceOptions";
import { InstanceAndProfileFormikProps } from "components/forms/instanceAndProfileFormValues";

type ConnectionType = "listen" | "connect";

export const getProxyAddress = (
customRows: MainTableRow[],
device: LxdProxyDevice,
index: number,
connectionType: ConnectionType,
formik: InstanceAndProfileFormikProps,
headingTitle: string,
) => {
const deviceParts = device[connectionType]?.split(":") || [];
const deviceType = deviceParts.length > 0 ? deviceParts[0] : "tcp";
const deviceAddress = deviceParts.length > 1 ? deviceParts[1] : "";
const devicePort = deviceParts.length > 2 ? deviceParts[2] : "";

customRows.push(
getConfigurationRowBase({
className: "no-border-top inherited-with-form p-heading--6",
configuration: headingTitle,
inherited: "",
override: "",
}),
);

customRows.push(
getConfigurationRowBase({
className: "no-border-top inherited-with-form",
configuration: (
<Label forId={`devices.${index}.${connectionType}`}>Type</Label>
),
inherited: (
<Select
id={`devices.${index}.${connectionType}`}
onChange={(e) => {
ensureEditMode(formik);
const newType = e.target.value;
void formik.setFieldValue(
`devices.${index}.${connectionType}`,
`${newType}:${deviceAddress}:${devicePort}`,
);

if (device.nat === "true") {
const connectParts = device.connect?.split(":") || [];
const connectAddress =
connectParts.length > 1 ? connectParts[1] : "";
const connectPort =
connectParts.length > 2 ? connectParts[2] : "";

void formik.setFieldValue(
`devices.${index}.connect`,
`${newType}:${connectAddress}:${connectPort}`,
);
}
}}
value={deviceType}
options={proxyAddressTypeOptions}
className="u-no-margin--bottom"
disabled={connectionType === "connect" && device.nat === "true"}
title={
device.nat
? "This is determined by the listen type when nat mode is enabled"
: undefined
}
/>
),
override: "",
}),
);

customRows.push(
getConfigurationRowBase({
className: "no-border-top inherited-with-form",
configuration:
deviceType === "unix" ? (
<Label forId={`devices.${index}.${connectionType}.unixsocket`}>
*Socket path
</Label>
) : (
<Label forId={`devices.${index}.${connectionType}.address`}>
*Address
</Label>
),
inherited:
deviceType === "unix" ? (
<Input
id={`devices.${index}.${connectionType}.unixsocket`}
onChange={(e) => {
ensureEditMode(formik);
const socketPath = e.target.value;
void formik.setFieldValue(
`devices.${index}.${connectionType}`,
`unix:${socketPath}`,
);
}}
value={deviceAddress}
placeholder="/<socket_path>"
type="text"
className="u-no-margin--bottom"
/>
) : (
<Input
id={`devices.${index}.${connectionType}.address`}
onChange={(e) => {
ensureEditMode(formik);
const newAddress = e.target.value;
void formik.setFieldValue(
`devices.${index}.${connectionType}`,
`${deviceType}:${newAddress}:${devicePort}`,
);
}}
value={deviceAddress}
placeholder="127.0.0.1"
type="text"
className="u-no-margin--bottom"
/>
),
override: "",
}),
);

deviceType === "unix"
? null
: customRows.push(
getConfigurationRowBase({
className: "no-border-top inherited-with-form",
configuration: (
<Label forId={`devices.${index}.${connectionType}.port`}>
*Port
</Label>
),

inherited: (
<Input
id={`devices.${index}.${connectionType}.port`}
onChange={(e) => {
ensureEditMode(formik);
const newPort = e.target.value;
void formik.setFieldValue(
`devices.${index}.${connectionType}`,
`${deviceType}:${deviceAddress}:${newPort}`,
);
}}
value={devicePort}
placeholder="00[-00]"
type="text"
className="u-no-margin--bottom"
/>
),
override: "",
}),
);
};
Loading