From 5f8a0eeb7d3691e53ee50dfba9632ca8b888d12d Mon Sep 17 00:00:00 2001 From: "Brandon Waterloo [MSFT]" <36966225+bwateratmsft@users.noreply.github.com> Date: Fri, 27 Jun 2025 16:00:59 -0400 Subject: [PATCH 1/3] HostPorts are strings --- .../clients/DockerClientBase/DockerInspectContainerRecord.ts | 4 ++-- .../src/clients/PodmanClient/PodmanInspectContainerRecord.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/vscode-container-client/src/clients/DockerClientBase/DockerInspectContainerRecord.ts b/packages/vscode-container-client/src/clients/DockerClientBase/DockerInspectContainerRecord.ts index 43eeada6..9eee9b9f 100644 --- a/packages/vscode-container-client/src/clients/DockerClientBase/DockerInspectContainerRecord.ts +++ b/packages/vscode-container-client/src/clients/DockerClientBase/DockerInspectContainerRecord.ts @@ -12,7 +12,7 @@ import { parseDockerLikeEnvironmentVariables } from './parseDockerLikeEnvironmen const DockerInspectContainerPortHostSchema = z.object({ HostIp: z.string().optional(), - HostPort: z.number().optional(), + HostPort: z.string().optional(), }); const DockerInspectContainerBindMountSchema = z.object({ @@ -103,7 +103,7 @@ export function normalizeDockerInspectContainerRecord(container: DockerInspectCo const [port, protocol] = rawPort.split('/'); return { hostIp: hostBinding?.[0]?.HostIp, - hostPort: hostBinding?.[0]?.HostPort, + hostPort: hostBinding?.[0]?.HostPort ? parseInt(hostBinding[0].HostPort) : undefined, containerPort: parseInt(port), protocol: protocol.toLowerCase() === 'tcp' ? 'tcp' diff --git a/packages/vscode-container-client/src/clients/PodmanClient/PodmanInspectContainerRecord.ts b/packages/vscode-container-client/src/clients/PodmanClient/PodmanInspectContainerRecord.ts index 95cadb6f..e43ea3e7 100644 --- a/packages/vscode-container-client/src/clients/PodmanClient/PodmanInspectContainerRecord.ts +++ b/packages/vscode-container-client/src/clients/PodmanClient/PodmanInspectContainerRecord.ts @@ -12,7 +12,7 @@ import { parseDockerLikeEnvironmentVariables } from '../DockerClientBase/parseDo const PodmanInspectContainerPortHostSchema = z.object({ HostIp: z.string().optional(), - HostPort: z.number().optional(), + HostPort: z.string().optional(), }); const PodmanInspectContainerBindMountSchema = z.object({ @@ -102,7 +102,7 @@ export function normalizePodmanInspectContainerRecord(container: PodmanInspectCo const [port, protocol] = rawPort.split('/'); return { hostIp: hostBinding?.[0]?.HostIp, - hostPort: hostBinding?.[0]?.HostPort, + hostPort: hostBinding?.[0]?.HostPort ? parseInt(hostBinding[0].HostPort) : undefined, containerPort: parseInt(port), protocol: protocol.toLowerCase() === 'tcp' ? 'tcp' From b182e225bf1a6f89cd359357ae4954557dfcee3e Mon Sep 17 00:00:00 2001 From: "Brandon Waterloo [MSFT]" <36966225+bwateratmsft@users.noreply.github.com> Date: Fri, 27 Jun 2025 16:05:37 -0400 Subject: [PATCH 2/3] Better container E2E automation --- .../src/test/ContainersClientE2E.test.ts | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/vscode-container-client/src/test/ContainersClientE2E.test.ts b/packages/vscode-container-client/src/test/ContainersClientE2E.test.ts index 3061cd02..4230bb07 100644 --- a/packages/vscode-container-client/src/test/ContainersClientE2E.test.ts +++ b/packages/vscode-container-client/src/test/ContainersClientE2E.test.ts @@ -298,6 +298,8 @@ describe('(integration) ContainersClientE2E', function () { } // Create a container that will stay running + // For fun we'll add a network, volume, a bind mount, and some ports to it and verify those in both + // it('ListContainersCommand') and it('InspectContainersCommand') testContainerId = await defaultRunner.getCommandRunner()( client.runContainer({ imageRef: imageToTest, @@ -305,9 +307,6 @@ describe('(integration) ContainersClientE2E', function () { name: testContainerName, }) ) as string; - - expect(testContainerId).to.be.a('string'); - expect(await validateContainerExists(client, defaultRunner, { containerId: testContainerId })).to.be.ok; }); after('Containers', async function () { @@ -322,16 +321,28 @@ describe('(integration) ContainersClientE2E', function () { }); it('RunContainerCommand', async function () { - // This is already fully tested in the before('Containers') hook and the it('StopContainersCommand') test + // Ensure the container was created + expect(testContainerId).to.be.a('string'); + expect(await validateContainerExists(client, defaultRunner, { containerId: testContainerId })).to.be.ok; }); it('ListContainersCommand', async function () { const container = await validateContainerExists(client, defaultRunner, { containerId: testContainerId }) as ListContainersItem; expect(container).to.be.ok; + + // Validate some important properties expect(container.name).to.equal(testContainerName); expect(container.state).to.be.a('string'); expect(container.image).to.be.an('object'); expect(container.createdAt).to.be.instanceOf(Date); + + // Validate the network + + // Validate the bind mount + + // Validate the volume + + // Validate the ports }); it('InspectContainersCommand', async function () { @@ -344,16 +355,26 @@ describe('(integration) ContainersClientE2E', function () { expect(containers.length).to.equal(1); const container = containers[0]; + + // Validate some important properties expect(container.id).to.equal(testContainerId); expect(container.name).to.include(testContainerName); expect(container.image).to.be.an('object'); expect(container.environmentVariables).to.be.an('object'); - expect(container.ports).to.be.an('array'); expect(container.labels).to.be.an('object'); expect(container.entrypoint).to.be.an('array'); expect(container.command).to.be.an('array'); expect(container.createdAt).to.be.instanceOf(Date); expect(container.raw).to.be.a('string'); + + // Validate the network + + // Validate the bind mount + + // Validate the volume + + // Validate the ports + expect(container.ports).to.be.an('array'); }); it('ExecContainerCommand', async function () { From 889feadd654b665ba07bfc75d364c41096746907 Mon Sep 17 00:00:00 2001 From: "Brandon Waterloo [MSFT]" <36966225+bwateratmsft@users.noreply.github.com> Date: Fri, 27 Jun 2025 17:08:34 -0400 Subject: [PATCH 3/3] Add a few more `satisfies` --- .../clients/DockerClientBase/DockerInspectContainerRecord.ts | 4 ++-- .../src/clients/PodmanClient/PodmanInspectContainerRecord.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/vscode-container-client/src/clients/DockerClientBase/DockerInspectContainerRecord.ts b/packages/vscode-container-client/src/clients/DockerClientBase/DockerInspectContainerRecord.ts index dddd8c95..3b98809c 100644 --- a/packages/vscode-container-client/src/clients/DockerClientBase/DockerInspectContainerRecord.ts +++ b/packages/vscode-container-client/src/clients/DockerClientBase/DockerInspectContainerRecord.ts @@ -95,7 +95,7 @@ export function normalizeDockerInspectContainerRecord(container: DockerInspectCo gateway: dockerNetwork.Gateway || undefined, ipAddress: dockerNetwork.IPAddress || undefined, macAddress: dockerNetwork.MacAddress || undefined, - }; + } satisfies InspectContainersItemNetwork; }); // Parse the exposed ports for the container and normalize to a PortBinding record @@ -110,7 +110,7 @@ export function normalizeDockerInspectContainerRecord(container: DockerInspectCo : protocol.toLowerCase() === 'udp' ? 'udp' : undefined, - }; + } satisfies PortBinding; }); // Parse the volume and bind mounts associated with the given runtime and normalize to diff --git a/packages/vscode-container-client/src/clients/PodmanClient/PodmanInspectContainerRecord.ts b/packages/vscode-container-client/src/clients/PodmanClient/PodmanInspectContainerRecord.ts index e281e0bf..557970a4 100644 --- a/packages/vscode-container-client/src/clients/PodmanClient/PodmanInspectContainerRecord.ts +++ b/packages/vscode-container-client/src/clients/PodmanClient/PodmanInspectContainerRecord.ts @@ -94,7 +94,7 @@ export function normalizePodmanInspectContainerRecord(container: PodmanInspectCo gateway: dockerNetwork.Gateway || undefined, ipAddress: dockerNetwork.IPAddress || undefined, macAddress: dockerNetwork.MacAddress || undefined, - }; + } satisfies InspectContainersItemNetwork; }); // Parse the exposed ports for the container and normalize to a PortBinding record @@ -109,7 +109,7 @@ export function normalizePodmanInspectContainerRecord(container: PodmanInspectCo : protocol.toLowerCase() === 'udp' ? 'udp' : undefined, - }; + } satisfies PortBinding; }); // Parse the volume and bind mounts associated with the given runtime and normalize to