From f2fa9b2cc6203e8900de4274fa883c158f8380d5 Mon Sep 17 00:00:00 2001 From: Cristian Greco Date: Wed, 5 Apr 2023 09:32:48 +0100 Subject: [PATCH 1/3] Add static helper for pull policy --- docs/features/containers.md | 4 ++-- docs/features/images.md | 6 +++--- src/docker/functions/image/build-image.ts | 4 ++-- .../generic-container-builder.ts | 6 +++--- .../generic-container-dockerfile.test.ts | 4 ++-- src/generic-container/generic-container.test.ts | 4 ++-- src/generic-container/generic-container.ts | 6 +++--- src/index.ts | 2 +- src/pull-policy.ts | 16 +++++++++++++--- src/test-container.ts | 4 ++-- 10 files changed, 33 insertions(+), 23 deletions(-) diff --git a/docs/features/containers.md b/docs/features/containers.md index 704a65187..e71426b36 100644 --- a/docs/features/containers.md +++ b/docs/features/containers.md @@ -21,10 +21,10 @@ const container = await new GenericContainer("alpine:3.10").start(); Testcontainers will automatically pull an image if it doesn't exist. This is configurable: ```javascript -const { GenericContainer, AlwaysPullPolicy } = require("testcontainers"); +const { GenericContainer, PullPolicy } = require("testcontainers"); const container = await new GenericContainer("alpine") - .withPullPolicy(new AlwaysPullPolicy()) + .withPullPolicy(PullPolicy.alwaysPull()) .start(); ``` diff --git a/docs/features/images.md b/docs/features/images.md index fb9d8311a..d22a4d210 100644 --- a/docs/features/images.md +++ b/docs/features/images.md @@ -14,16 +14,16 @@ const container = await GenericContainer const startedContainer = await container.start(); ``` -### With pull policy +### With a pull policy Testcontainers will automatically pull an image if it doesn't exist. This is configurable: ```javascript -const { GenericContainer, AlwaysPullPolicy } = require("testcontainers"); +const { GenericContainer, PullPolicy } = require("testcontainers"); const container = await GenericContainer .fromDockerfile("/path/to/build-context") - .withPullPolicy(new AlwaysPullPolicy()) + .withPullPolicy(PullPolicy.alwaysPull()) .build(); ``` diff --git a/src/docker/functions/image/build-image.ts b/src/docker/functions/image/build-image.ts index ff1d1e7a5..59d3d620f 100644 --- a/src/docker/functions/image/build-image.ts +++ b/src/docker/functions/image/build-image.ts @@ -1,5 +1,5 @@ import { DockerImageName } from "../../../docker-image-name"; -import { PullPolicy } from "../../../pull-policy"; +import { ImagePullPolicy } from "../../../pull-policy"; import { log } from "../../../logger"; import tar from "tar-fs"; import byline from "byline"; @@ -16,7 +16,7 @@ export type BuildImageOptions = { context: string; dockerfileName: string; buildArgs: BuildArgs; - pullPolicy: PullPolicy; + pullPolicy: ImagePullPolicy; registryConfig: RegistryConfig; cache: boolean; }; diff --git a/src/generic-container/generic-container-builder.ts b/src/generic-container/generic-container-builder.ts index 3e7911d37..95c0fc246 100644 --- a/src/generic-container/generic-container-builder.ts +++ b/src/generic-container/generic-container-builder.ts @@ -1,5 +1,5 @@ import { AuthConfig, BuildArgs, RegistryConfig } from "../docker/types"; -import { DefaultPullPolicy, PullPolicy } from "../pull-policy"; +import { ImagePullPolicy, PullPolicy } from "../pull-policy"; import { RandomUuid, Uuid } from "../uuid"; import { ReaperInstance } from "../reaper"; import { DockerImageName } from "../docker-image-name"; @@ -14,7 +14,7 @@ import { imageExists } from "../docker/functions/image/image-exists"; export class GenericContainerBuilder { private buildArgs: BuildArgs = {}; - private pullPolicy: PullPolicy = new DefaultPullPolicy(); + private pullPolicy: ImagePullPolicy = PullPolicy.defaultPolicy(); private cache = true; constructor( @@ -28,7 +28,7 @@ export class GenericContainerBuilder { return this; } - public withPullPolicy(pullPolicy: PullPolicy): this { + public withPullPolicy(pullPolicy: ImagePullPolicy): this { this.pullPolicy = pullPolicy; return this; } diff --git a/src/generic-container/generic-container-dockerfile.test.ts b/src/generic-container/generic-container-dockerfile.test.ts index 318af482c..4acbd71c0 100644 --- a/src/generic-container/generic-container-dockerfile.test.ts +++ b/src/generic-container/generic-container-dockerfile.test.ts @@ -1,6 +1,6 @@ import path from "path"; import { GenericContainer } from "./generic-container"; -import { AlwaysPullPolicy } from "../pull-policy"; +import { PullPolicy } from "../pull-policy"; import { Wait } from "../wait-strategy/wait"; import { checkContainerIsHealthy, getEvents } from "../test-helper"; @@ -23,7 +23,7 @@ describe("GenericContainer Dockerfile", () => { if (!process.env["CI_PODMAN"]) { it("should use pull policy", async () => { const containerSpec = GenericContainer.fromDockerfile(path.resolve(fixtures, "docker")).withPullPolicy( - new AlwaysPullPolicy() + PullPolicy.alwaysPull() ); await containerSpec.build(); diff --git a/src/generic-container/generic-container.test.ts b/src/generic-container/generic-container.test.ts index cb5e5ee77..b06357ccc 100644 --- a/src/generic-container/generic-container.test.ts +++ b/src/generic-container/generic-container.test.ts @@ -2,7 +2,7 @@ import fetch from "node-fetch"; import path from "path"; import getPort from "get-port"; import { GenericContainer } from "./generic-container"; -import { AlwaysPullPolicy } from "../pull-policy"; +import { PullPolicy } from "../pull-policy"; import { checkContainerIsHealthy, getEvents } from "../test-helper"; import { getContainerById } from "../docker/functions/container/get-container"; @@ -235,7 +235,7 @@ describe("GenericContainer", () => { }); const container2 = await new GenericContainer("cristianrgreco/testcontainer:1.1.14") - .withPullPolicy(new AlwaysPullPolicy()) + .withPullPolicy(PullPolicy.alwaysPull()) .withExposedPorts(8080) .start(); diff --git a/src/generic-container/generic-container.ts b/src/generic-container/generic-container.ts index e4b6ff001..a25ca36f2 100644 --- a/src/generic-container/generic-container.ts +++ b/src/generic-container/generic-container.ts @@ -3,7 +3,7 @@ import AsyncLock from "async-lock"; import { BoundPorts } from "../bound-ports"; import { containerLog, log } from "../logger"; import { PortWithOptionalBinding } from "../port"; -import { DefaultPullPolicy, PullPolicy } from "../pull-policy"; +import { ImagePullPolicy, PullPolicy } from "../pull-policy"; import { ReaperInstance } from "../reaper"; import { DockerImageName } from "../docker-image-name"; import { StartedTestContainer, TestContainer } from "../test-container"; @@ -53,7 +53,7 @@ export class GenericContainer implements TestContainer { protected tarToCopy?: archiver.Archiver; protected networkMode?: string; protected networkAliases: string[] = []; - protected pullPolicy: PullPolicy = new DefaultPullPolicy(); + protected pullPolicy: ImagePullPolicy = PullPolicy.defaultPolicy(); constructor(readonly image: string) { const imageName = DockerImageName.fromString(image); @@ -362,7 +362,7 @@ export class GenericContainer implements TestContainer { return this; } - public withPullPolicy(pullPolicy: PullPolicy): this { + public withPullPolicy(pullPolicy: ImagePullPolicy): this { this.pullPolicy = pullPolicy; return this; } diff --git a/src/index.ts b/src/index.ts index f1a6bcf74..fd0395d61 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,7 +12,7 @@ export { Network, StartedNetwork, StoppedNetwork } from "./network"; export { Wait } from "./wait-strategy/wait"; export { StartupCheckStrategy, StartupStatus } from "./wait-strategy/startup-check-strategy"; -export { PullPolicy, DefaultPullPolicy, AlwaysPullPolicy } from "./pull-policy"; +export { PullPolicy, ImagePullPolicy } from "./pull-policy"; export { InspectResult } from "./docker/functions/container/inspect-container"; export { AbstractStartedContainer } from "./modules/abstract-started-container"; diff --git a/src/pull-policy.ts b/src/pull-policy.ts index de7f67c53..8e8fd4fb7 100644 --- a/src/pull-policy.ts +++ b/src/pull-policy.ts @@ -1,15 +1,25 @@ -export interface PullPolicy { +export interface ImagePullPolicy { shouldPull(): boolean; } -export class DefaultPullPolicy implements PullPolicy { +class DefaultPullPolicy implements ImagePullPolicy { public shouldPull(): boolean { return false; } } -export class AlwaysPullPolicy implements PullPolicy { +class AlwaysPullPolicy implements ImagePullPolicy { public shouldPull(): boolean { return true; } } + +export class PullPolicy { + public static defaultPolicy(): ImagePullPolicy { + return new DefaultPullPolicy(); + } + + public static alwaysPull(): ImagePullPolicy { + return new AlwaysPullPolicy(); + } +} diff --git a/src/test-container.ts b/src/test-container.ts index 6e629b641..d4a0dd119 100644 --- a/src/test-container.ts +++ b/src/test-container.ts @@ -1,5 +1,5 @@ import { PortWithOptionalBinding } from "./port"; -import { PullPolicy } from "./pull-policy"; +import { ImagePullPolicy } from "./pull-policy"; import { WaitStrategy } from "./wait-strategy/wait-strategy"; import { Readable } from "stream"; import { @@ -53,7 +53,7 @@ export interface TestContainer { withUser(user: string): this; - withPullPolicy(pullPolicy: PullPolicy): this; + withPullPolicy(pullPolicy: ImagePullPolicy): this; withReuse(): this; From 7280c99474423146aec1784f8d11e79c22931723 Mon Sep 17 00:00:00 2001 From: Cristian Greco Date: Wed, 5 Apr 2023 09:40:41 +0100 Subject: [PATCH 2/3] Document custom pull policies --- docs/features/containers.md | 16 ++++++++++++++++ docs/features/images.md | 17 +++++++++++++++++ src/pull-policy.test.ts | 19 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 src/pull-policy.test.ts diff --git a/docs/features/containers.md b/docs/features/containers.md index e71426b36..7b44e36d2 100644 --- a/docs/features/containers.md +++ b/docs/features/containers.md @@ -28,6 +28,22 @@ const container = await new GenericContainer("alpine") .start(); ``` +#### Custom pull policy + +```typescript +const { GenericContainer, ImagePullPolicy } = require("testcontainers"); + +class CustomPullPolicy implements ImagePullPolicy { + public shouldPull(): boolean { + return true; + } +} + +const container = await new GenericContainer("alpine") + .withPullPolicy(new CustomPullPolicy()) + .start(); +``` + ### With a command ```javascript diff --git a/docs/features/images.md b/docs/features/images.md index d22a4d210..ba8793609 100644 --- a/docs/features/images.md +++ b/docs/features/images.md @@ -27,6 +27,23 @@ const container = await GenericContainer .build(); ``` +#### Custom pull policy + +```typescript +const { GenericContainer, ImagePullPolicy } = require("testcontainers"); + +class CustomPullPolicy implements ImagePullPolicy { + public shouldPull(): boolean { + return true; + } +} + +const container = await GenericContainer + .fromDockerfile("/path/to/build-context") + .withPullPolicy(new CustomPullPolicy()) + .build(); +``` + ### With build arguments ```javascript diff --git a/src/pull-policy.test.ts b/src/pull-policy.test.ts new file mode 100644 index 000000000..d7d397166 --- /dev/null +++ b/src/pull-policy.test.ts @@ -0,0 +1,19 @@ +import { PullPolicy, ImagePullPolicy } from "./index"; + +test("default pull policy should return false", () => { + expect(PullPolicy.defaultPolicy().shouldPull()).toBe(false); +}); + +test("always pull policy should return true", () => { + expect(PullPolicy.alwaysPull().shouldPull()).toBe(true); +}); + +test("should be able to create a custom pull policy", () => { + class CustomPullPolicy implements ImagePullPolicy { + public shouldPull(): boolean { + return true; + } + } + + expect(new CustomPullPolicy().shouldPull()).toBe(true); +}); From 41a840e215ce8359b1278f48b26ccb90078fb00d Mon Sep 17 00:00:00 2001 From: Cristian Greco Date: Thu, 13 Apr 2023 10:33:35 +0100 Subject: [PATCH 3/3] Fix import --- .../docker-compose-environment.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/docker-compose-environment/docker-compose-environment.ts b/src/docker-compose-environment/docker-compose-environment.ts index a4cd99970..4fa0b8293 100644 --- a/src/docker-compose-environment/docker-compose-environment.ts +++ b/src/docker-compose-environment/docker-compose-environment.ts @@ -17,7 +17,7 @@ import { dockerComposeDown } from "../docker-compose/functions/docker-compose-do import { dockerComposeUp } from "../docker-compose/functions/docker-compose-up"; import { waitForContainer } from "../wait-for-container"; import { defaultWaitStrategy } from "../wait-strategy/default-wait-strategy"; -import { DefaultPullPolicy, PullPolicy } from "../pull-policy"; +import { ImagePullPolicy, PullPolicy } from "../pull-policy"; import { dockerComposePull } from "../docker-compose/functions/docker-compose-pull"; export class DockerComposeEnvironment { @@ -30,7 +30,7 @@ export class DockerComposeEnvironment { private environmentFile = ""; private profiles: string[] = []; private environment: Environment = {}; - private pullPolicy: PullPolicy = new DefaultPullPolicy(); + private pullPolicy: ImagePullPolicy = PullPolicy.defaultPolicy(); private waitStrategy: { [containerName: string]: WaitStrategy } = {}; private startupTimeout = 60_000; @@ -66,7 +66,7 @@ export class DockerComposeEnvironment { return this; } - public withPullPolicy(pullPolicy: PullPolicy): this { + public withPullPolicy(pullPolicy: ImagePullPolicy): this { this.pullPolicy = pullPolicy; return this; }