diff --git a/src/components/forms/ProxyDeviceForm.tsx b/src/components/forms/ProxyDeviceForm.tsx index d332ea27ac..83b2a6fe9f 100644 --- a/src/components/forms/ProxyDeviceForm.tsx +++ b/src/components/forms/ProxyDeviceForm.tsx @@ -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; @@ -84,6 +85,8 @@ const ProxyDeviceForm: FC = ({ formik, project }) => { }[], value?: string, help?: string, + onChange?: (value: string) => void, + disabledText?: string, ) => { const key = `devices.${index}.${fieldName}`; @@ -99,11 +102,14 @@ const ProxyDeviceForm: FC = ({ formik, project }) => { onChange={(e) => { ensureEditMode(formik); void formik.setFieldValue(key, e.target.value); + onChange?.(e.target.value); }} value={value ?? ""} options={options} help={} className="u-no-margin--bottom" + disabled={disabledText != undefined} + title={disabledText} /> ), override: "", @@ -187,6 +193,16 @@ const ProxyDeviceForm: FC = ({ 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", @@ -233,6 +249,11 @@ const ProxyDeviceForm: FC = ({ formik, project }) => { ], device.bind, "Whether to bind the listen address to the instance or host", + (value) => { + if (value === "instance" && device.nat === "true") { + void formik.setFieldValue(`devices.${index}.nat`, "false"); + } + }, ), ); @@ -243,84 +264,24 @@ const ProxyDeviceForm: FC = ({ 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: , - inherited: ( - { - ensureEditMode(formik); - void formik.setFieldValue( - `devices.${index}.listen`, - e.target.value, - ); - }} - value={device.listen} - type="text" - help={ - ::[-][,]" - } - /> - } - className="u-no-margin--bottom" - /> - ), - override: "", - }), - ); + getProxyAddress(customRows, device, index, "listen", formik, "Listen"); - customRows.push( - getConfigurationRowBase({ - className: "no-border-top inherited-with-form", - configuration: , - inherited: ( - { - ensureEditMode(formik); - void formik.setFieldValue( - `devices.${index}.connect`, - e.target.value, - ); - }} - value={device.connect} - type="text" - help={ - ::[-][,]" - } - /> - } - className="u-no-margin--bottom" - /> - ), - override: "", - }), - ); + getProxyAddress(customRows, device, index, "connect", formik, "Connect"); }); if (isProfileLoading) { diff --git a/src/util/instanceOptions.tsx b/src/util/instanceOptions.tsx index 354788e339..8ec38a04bd 100644 --- a/src/util/instanceOptions.tsx +++ b/src/util/instanceOptions.tsx @@ -56,6 +56,7 @@ export const optionYesNo = [ value: "false", }, ]; + export const optionEnabledDisabled = [ { label: "Select option", @@ -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", + }, +]; diff --git a/src/util/proxyDevices.tsx b/src/util/proxyDevices.tsx new file mode 100644 index 0000000000..3df3a2445a --- /dev/null +++ b/src/util/proxyDevices.tsx @@ -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: ( + + ), + inherited: ( + { + ensureEditMode(formik); + const socketPath = e.target.value; + void formik.setFieldValue( + `devices.${index}.${connectionType}`, + `unix:${socketPath}`, + ); + }} + value={deviceAddress} + placeholder="/" + type="text" + className="u-no-margin--bottom" + /> + ) : ( + { + 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: ( + + ), + + inherited: ( + { + 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: "", + }), + ); +};