ui(deploy): remove Exposed Ports field from Resources tab
The field was cosmetic — `containerConfig.exposedPorts` only fed Docker's `Config.ExposedPorts` metadata via `withExposedPorts(...)`. It never published a host port and Traefik routing uses `appPort` from the label builder, not this list. Users reading the label "Exposed Ports" reasonably expected it to expose their port externally; removing it until real multi-port Traefik routing lands (tracked in #149). Backend DTOs (`ContainerRequest.exposedPorts`, `ConfigMerger.intList ("exposedPorts")`) are left in place so existing containerConfig JSONB rows continue to deserialize. New writes from the UI will no longer include the field. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -66,7 +66,7 @@ describe('ConfigPanel', () => {
|
||||
},
|
||||
resources: {
|
||||
memoryLimit: '256', memoryReserve: '', cpuRequest: '500', cpuLimit: '',
|
||||
ports: [], appPort: '8080', replicas: '1', deployStrategy: 'blue-green',
|
||||
appPort: '8080', replicas: '1', deployStrategy: 'blue-green',
|
||||
stripPrefix: true, sslOffloading: true, runtimeType: 'auto', customArgs: '',
|
||||
extraNetworks: [],
|
||||
},
|
||||
|
||||
@@ -28,7 +28,6 @@ describe('snapshotToForm', () => {
|
||||
replicas: 3,
|
||||
deploymentStrategy: 'rolling',
|
||||
customEnvVars: { FOO: 'bar', BAZ: 'qux' },
|
||||
exposedPorts: [8080, 9090],
|
||||
},
|
||||
sensitiveKeys: ['SECRET_KEY'],
|
||||
};
|
||||
@@ -36,7 +35,6 @@ describe('snapshotToForm', () => {
|
||||
expect(result.resources.memoryLimit).toBe('1024');
|
||||
expect(result.resources.replicas).toBe('3');
|
||||
expect(result.resources.deployStrategy).toBe('rolling');
|
||||
expect(result.resources.ports).toEqual([8080, 9090]);
|
||||
expect(result.variables.envVars).toEqual([
|
||||
{ key: 'FOO', value: 'bar' },
|
||||
{ key: 'BAZ', value: 'qux' },
|
||||
|
||||
@@ -36,7 +36,6 @@ export function snapshotToForm(
|
||||
memoryReserve: c.memoryReserveMb != null ? String(c.memoryReserveMb) : defaults.resources.memoryReserve,
|
||||
cpuRequest: c.cpuRequest !== undefined ? String(c.cpuRequest) : defaults.resources.cpuRequest,
|
||||
cpuLimit: c.cpuLimit != null ? String(c.cpuLimit) : defaults.resources.cpuLimit,
|
||||
ports: Array.isArray(c.exposedPorts) ? (c.exposedPorts as number[]) : defaults.resources.ports,
|
||||
appPort: c.appPort !== undefined ? String(c.appPort) : defaults.resources.appPort,
|
||||
replicas: c.replicas !== undefined ? String(c.replicas) : defaults.resources.replicas,
|
||||
deployStrategy: (c.deploymentStrategy as string) ?? defaults.resources.deployStrategy,
|
||||
|
||||
@@ -11,24 +11,11 @@ interface Props {
|
||||
}
|
||||
|
||||
export function ResourcesTab({ value, onChange, disabled, isProd = false }: Props) {
|
||||
const [newPort, setNewPort] = useState('');
|
||||
const [newNetwork, setNewNetwork] = useState('');
|
||||
|
||||
const update = <K extends keyof ResourcesFormState>(key: K, v: ResourcesFormState[K]) =>
|
||||
onChange({ ...value, [key]: v });
|
||||
|
||||
function addPort() {
|
||||
const p = parseInt(newPort);
|
||||
if (p && !value.ports.includes(p)) {
|
||||
onChange({ ...value, ports: [...value.ports, p] });
|
||||
setNewPort('');
|
||||
}
|
||||
}
|
||||
|
||||
function removePort(port: number) {
|
||||
if (!disabled) update('ports', value.ports.filter((x) => x !== port));
|
||||
}
|
||||
|
||||
function addNetwork() {
|
||||
const v = newNetwork.trim();
|
||||
if (v && !value.extraNetworks.includes(v)) {
|
||||
@@ -123,35 +110,6 @@ export function ResourcesTab({ value, onChange, disabled, isProd = false }: Prop
|
||||
<span className={styles.cellMeta}>millicores</span>
|
||||
</div>
|
||||
|
||||
<span className={styles.configLabel}>Exposed Ports</span>
|
||||
<div className={styles.portPills}>
|
||||
{value.ports.map((p) => (
|
||||
<span key={p} className={styles.portPill}>
|
||||
{p}
|
||||
<button
|
||||
className={styles.portPillDelete}
|
||||
disabled={disabled}
|
||||
onClick={() => removePort(p)}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</span>
|
||||
))}
|
||||
<input
|
||||
className={styles.portAddInput}
|
||||
disabled={disabled}
|
||||
placeholder="+ port"
|
||||
value={newPort}
|
||||
onChange={(e) => setNewPort(e.target.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
addPort();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span className={styles.configLabel}>App Port</span>
|
||||
<Input
|
||||
disabled={disabled}
|
||||
|
||||
@@ -47,7 +47,6 @@ const defaultResources: ResourcesFormState = {
|
||||
memoryReserve: '',
|
||||
cpuRequest: '500',
|
||||
cpuLimit: '',
|
||||
ports: [],
|
||||
appPort: '8080',
|
||||
replicas: '1',
|
||||
deployStrategy: 'blue-green',
|
||||
|
||||
@@ -23,7 +23,6 @@ export interface ResourcesFormState {
|
||||
memoryReserve: string;
|
||||
cpuRequest: string;
|
||||
cpuLimit: string;
|
||||
ports: number[];
|
||||
appPort: string;
|
||||
replicas: string;
|
||||
deployStrategy: string;
|
||||
@@ -66,7 +65,7 @@ export const defaultForm: DeploymentPageFormState = {
|
||||
},
|
||||
resources: {
|
||||
memoryLimit: '512', memoryReserve: '', cpuRequest: '500', cpuLimit: '',
|
||||
ports: [], appPort: '8080', replicas: '1', deployStrategy: 'blue-green',
|
||||
appPort: '8080', replicas: '1', deployStrategy: 'blue-green',
|
||||
stripPrefix: true, sslOffloading: true, runtimeType: 'auto', customArgs: '',
|
||||
extraNetworks: [],
|
||||
},
|
||||
@@ -108,7 +107,6 @@ export function useDeploymentPageState(
|
||||
memoryReserve: merged.memoryReserveMb != null ? String(merged.memoryReserveMb) : defaultForm.resources.memoryReserve,
|
||||
cpuRequest: String(merged.cpuRequest ?? defaultForm.resources.cpuRequest),
|
||||
cpuLimit: merged.cpuLimit != null ? String(merged.cpuLimit) : defaultForm.resources.cpuLimit,
|
||||
ports: Array.isArray(merged.exposedPorts) ? (merged.exposedPorts as number[]) : defaultForm.resources.ports,
|
||||
appPort: String(merged.appPort ?? defaultForm.resources.appPort),
|
||||
replicas: String(merged.replicas ?? defaultForm.resources.replicas),
|
||||
deployStrategy: String(merged.deploymentStrategy ?? defaultForm.resources.deployStrategy),
|
||||
|
||||
@@ -200,7 +200,6 @@ export default function AppDeploymentPage() {
|
||||
memoryReserveMb: r.memoryReserve ? parseInt(r.memoryReserve) : null,
|
||||
cpuRequest: r.cpuRequest ? parseInt(r.cpuRequest) : null,
|
||||
cpuLimit: r.cpuLimit ? parseInt(r.cpuLimit) : null,
|
||||
exposedPorts: r.ports,
|
||||
customEnvVars: Object.fromEntries(
|
||||
form.variables.envVars.filter((v) => v.key.trim()).map((v) => [v.key, v.value]),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user