From 210f7b22039f3528827b0773113010f7f1b767cc Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Tue, 13 Sep 2022 17:08:01 -0700 Subject: [PATCH] fix(docker): stop containers started with `npx playwright docker start` (#17316) This patch makes `npx playwright docker stop` command to stop containers that were launched with previous playwright version. --- packages/playwright-test/src/cli.ts | 2 +- packages/playwright-test/src/docker/docker.ts | 29 +++++++++---------- .../playwright-test/src/docker/dockerApi.ts | 4 +++ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/playwright-test/src/cli.ts b/packages/playwright-test/src/cli.ts index 00a370bafe..b5f6ac0c54 100644 --- a/packages/playwright-test/src/cli.ts +++ b/packages/playwright-test/src/cli.ts @@ -55,7 +55,7 @@ function addDockerCommand(program: Command) { dockerCommand.command('stop') .description('stop docker container') .action(async function(options) { - await docker.stopPlaywrightContainer(); + await docker.stopAllPlaywrightContainers(); }); dockerCommand.command('delete-image', { hidden: true }) diff --git a/packages/playwright-test/src/docker/docker.ts b/packages/playwright-test/src/docker/docker.ts index df0dbf9622..d7faf9c820 100644 --- a/packages/playwright-test/src/docker/docker.ts +++ b/packages/playwright-test/src/docker/docker.ts @@ -28,6 +28,8 @@ import type { FullConfig, Reporter, Suite } from '../../types/testReporter'; const VRT_IMAGE_DISTRO = 'focal'; const VRT_IMAGE_NAME = `playwright:local-${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`; const VRT_CONTAINER_NAME = `playwright-${getPlaywrightVersion()}-${VRT_IMAGE_DISTRO}`; +const VRT_CONTAINER_LABEL_NAME = 'dev.playwright.vrt-service.version'; +const VRT_CONTAINER_LABEL_VALUE = '1'; export async function startPlaywrightContainer() { await checkDockerEngineIsRunningOrDie(); @@ -50,16 +52,15 @@ export async function startPlaywrightContainer() { ].join('\n')); } -export async function stopPlaywrightContainer() { +export async function stopAllPlaywrightContainers() { await checkDockerEngineIsRunningOrDie(); - const container = await findRunningDockerContainer(); - if (!container) - return; - await dockerApi.stopContainer({ + const allContainers = await dockerApi.listContainers(); + const vrtContainers = allContainers.filter(container => container.labels[VRT_CONTAINER_LABEL_NAME] === VRT_CONTAINER_LABEL_VALUE); + await Promise.all(vrtContainers.map(container => dockerApi.stopContainer({ containerId: container.containerId, waitUntil: 'removed', - }); + }))); } export async function deletePlaywrightImage() { @@ -70,7 +71,7 @@ export async function deletePlaywrightImage() { return; if (await containerInfo()) - await stopPlaywrightContainer(); + await stopAllPlaywrightContainers(); await dockerApi.removeImage(dockerImage.imageId); } @@ -168,7 +169,9 @@ interface ContainerInfo { } async function containerInfo(): Promise { - const container = await findRunningDockerContainer(); + const allContainers = await dockerApi.listContainers(); + const pwDockerImage = await findDockerImage(VRT_IMAGE_NAME); + const container = allContainers.find(container => container.imageId === pwDockerImage?.imageId && container.state === 'running'); if (!container) return undefined; const logLines = await dockerApi.getContainerLogs(container.containerId); @@ -218,6 +221,9 @@ async function ensurePlaywrightContainerOrDie(): Promise { name: VRT_CONTAINER_NAME, autoRemove: true, ports: [5400, 7900], + labels: { + [VRT_CONTAINER_LABEL_NAME]: VRT_CONTAINER_LABEL_VALUE, + }, }); // Wait for the service to become available. @@ -251,10 +257,3 @@ async function findDockerImage(imageName: string): Promise image.names.includes(imageName)); } -async function findRunningDockerContainer(): Promise { - const containers = await dockerApi.listContainers(); - const dockerImage = await findDockerImage(VRT_IMAGE_NAME); - const container = dockerImage ? containers.find(container => container.imageId === dockerImage.imageId) : undefined; - return container?.state === 'running' ? container : undefined; -} - diff --git a/packages/playwright-test/src/docker/dockerApi.ts b/packages/playwright-test/src/docker/dockerApi.ts index e9598d604d..7698d8e8f5 100644 --- a/packages/playwright-test/src/docker/dockerApi.ts +++ b/packages/playwright-test/src/docker/dockerApi.ts @@ -33,6 +33,7 @@ export interface PortBinding { export interface DockerContainer { containerId: string; + labels: Record; imageId: string; state: 'created'|'restarting'|'running'|'removing'|'paused'|'exited'|'dead'; names: string[]; @@ -51,6 +52,7 @@ export async function listContainers(): Promise { hostPort: portInfo.PublicPort, containerPort: portInfo.PrivatePort, })) ?? [], + labels: container.Labels ?? {}, })); } @@ -58,6 +60,7 @@ interface LaunchContainerOptions { imageId: string; autoRemove: boolean; command?: string[]; + labels?: Record; ports?: Number[]; name?: string; waitUntil?: 'not-running' | 'next-exit' | 'removed'; @@ -72,6 +75,7 @@ export async function launchContainer(options: LaunchContainerOptions): Promise< } const container = await postJSON(`/containers/create` + (options.name ? '?name=' + options.name : ''), { Cmd: options.command, + Labels: options.labels ?? {}, AttachStdout: true, AttachStderr: true, Image: options.imageId,