Socket
Socket
Sign inDemoInstall

testcontainers

Package Overview
Dependencies
84
Maintainers
1
Versions
238
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 9.5.0 to 9.6.0

dist/src/wait-strategy/composite-wait-strategy.d.ts

6

dist/package.json
{
"name": "testcontainers",
"author": "Cristian Greco",
"version": "9.5.0",
"version": "9.6.0",
"main": "dist/src/index",

@@ -30,4 +30,4 @@ "types": "dist/src/index",

"clean": "rimraf dist",
"test": "cross-env DEBUG=testcontainers,testcontainers:exec,testcontainers:containers jest",
"test:ci": "cross-env DEBUG=testcontainers,testcontainers:exec,testcontainers:containers jest --runInBand --coverage",
"test": "cross-env DEBUG=testcontainers* jest",
"test:ci": "npm run test -- --runInBand --coverage",
"format": "prettier --write package.json \"src/**/*.ts\"",

@@ -34,0 +34,0 @@ "lint": "eslint --fix package.json \"src/**/*.ts\"",

@@ -17,3 +17,3 @@ import { WaitStrategy } from "../wait-strategy/wait-strategy";

private waitStrategy;
private startupTimeout;
private startupTimeout?;
constructor(composeFilePath: string, composeFiles: string | string[], uuid?: Uuid);

@@ -20,0 +20,0 @@ withBuild(): this;

@@ -28,5 +28,5 @@ "use strict";

const wait_for_container_1 = require("../wait-for-container");
const default_wait_strategy_1 = require("../wait-strategy/default-wait-strategy");
const pull_policy_1 = require("../pull-policy");
const docker_compose_pull_1 = require("../docker-compose/functions/docker-compose-pull");
const wait_1 = require("../wait-strategy/wait");
class DockerComposeEnvironment {

@@ -41,3 +41,2 @@ constructor(composeFilePath, composeFiles, uuid = new uuid_1.RandomUuid()) {

this.waitStrategy = {};
this.startupTimeout = 60000;
this.composeFilePath = composeFilePath;

@@ -117,3 +116,8 @@ this.composeFiles = composeFiles;

const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, inspectResult);
const waitStrategy = (this.waitStrategy[containerName] ? this.waitStrategy[containerName] : (0, default_wait_strategy_1.defaultWaitStrategy)(host, container)).withStartupTimeout(this.startupTimeout);
const waitStrategy = this.waitStrategy[containerName]
? this.waitStrategy[containerName]
: wait_1.Wait.forListeningPorts();
if (this.startupTimeout !== undefined) {
waitStrategy.withStartupTimeout(this.startupTimeout);
}
if (logger_1.containerLog.enabled()) {

@@ -126,3 +130,3 @@ (yield (0, container_logs_1.containerLogs)(container))

logger_1.log.info(`Waiting for container ${containerName} to be ready`);
yield (0, wait_for_container_1.waitForContainer)(container, waitStrategy, host, boundPorts);
yield (0, wait_for_container_1.waitForContainer)(container, waitStrategy, boundPorts);
logger_1.log.info(`Container ${containerName} is ready`);

@@ -129,0 +133,0 @@ }

/// <reference types="node" />
import Dockerode from "dockerode";
import { HostIps } from "./lookup-host-ips";
export type Provider = "docker" | "podman";
type DockerClient = {
uri: string;
provider: Provider;
host: string;

@@ -7,0 +9,0 @@ hostIps: HostIps;

@@ -46,3 +46,4 @@ "use strict";

const indexServerAddress = (yield (0, system_info_1.getSystemInfo)(dockerode)).dockerInfo.indexServerAddress;
const host = yield (0, resolve_host_1.resolveHost)(dockerode, indexServerAddress, uri);
const provider = uri.includes("podman.sock") ? "podman" : "docker";
const host = yield (0, resolve_host_1.resolveHost)(dockerode, provider, indexServerAddress, uri);
const hostIps = yield (0, lookup_host_ips_1.lookupHostIps)(host);

@@ -52,3 +53,3 @@ logger_1.log.info(`Using Docker client strategy: ${strategy.getName()}, Docker host: ${host} (${hostIps

.join(", ")})`);
return { uri, host, hostIps, dockerode, indexServerAddress, composeEnvironment };
return { uri, provider, host, hostIps, dockerode, indexServerAddress, composeEnvironment };
}

@@ -55,0 +56,0 @@ else {

import { ExecResult } from "../../types";
import Dockerode from "dockerode";
export declare const execContainer: (container: Dockerode.Container, command: string[], shouldLog?: boolean) => Promise<ExecResult>;
import { Provider } from "../../docker-client";
export declare const execContainer: (dockerode: Dockerode, provider: Provider, container: Dockerode.Container, command: string[], shouldLog?: boolean) => Promise<ExecResult>;

@@ -18,3 +18,4 @@ "use strict";

const byline_1 = __importDefault(require("byline"));
const execContainer = (container, command, shouldLog = true) => __awaiter(void 0, void 0, void 0, function* () {
const demux_stream_1 = require("../demux-stream");
const execContainer = (dockerode, provider, container, command, shouldLog = true) => __awaiter(void 0, void 0, void 0, function* () {
const chunks = [];

@@ -27,3 +28,3 @@ try {

});
const stream = yield startExec(exec);
const stream = yield startExec(dockerode, provider, exec);
stream.on("data", (chunk) => chunks.push(chunk));

@@ -43,7 +44,11 @@ if (shouldLog && logger_1.execLog.enabled()) {

exports.execContainer = execContainer;
const startExec = (exec) => __awaiter(void 0, void 0, void 0, function* () {
const startExec = (dockerode, provider, exec) => __awaiter(void 0, void 0, void 0, function* () {
try {
const stream = yield exec.start({ stdin: true, Detach: false, Tty: true });
stream.setEncoding("utf-8");
return stream;
if (provider === "podman") {
return (0, demux_stream_1.demuxStream)(dockerode, stream);
}
else {
return stream;
}
}

@@ -50,0 +55,0 @@ catch (err) {

@@ -13,6 +13,9 @@ "use strict";

exports.putContainerArchive = void 0;
const stream_1 = require("stream");
const logger_1 = require("../../../logger");
const stream_utils_1 = require("../../../stream-utils");
const putContainerArchive = (options) => __awaiter(void 0, void 0, void 0, function* () {
try {
yield options.container.putArchive(options.stream, { path: options.containerPath });
const stream = yield options.container.putArchive(options.stream, { path: options.containerPath });
yield (0, stream_utils_1.streamToString)(stream_1.Readable.from(stream));
}

@@ -19,0 +22,0 @@ catch (err) {

@@ -16,9 +16,6 @@ "use strict";

exports.imageExists = void 0;
const logger_1 = require("../../../logger");
const async_lock_1 = __importDefault(require("async-lock"));
const list_images_1 = require("./list-images");
const existingImages = new Set();
const imageCheckLock = new async_lock_1.default();
const imageExists = (dockerode, imageName) => __awaiter(void 0, void 0, void 0, function* () {
logger_1.log.debug(`Checking if image exists: ${imageName}`);
return imageCheckLock.acquire(imageName.toString(), () => __awaiter(void 0, void 0, void 0, function* () {

@@ -28,9 +25,15 @@ if (existingImages.has(imageName.toString())) {

}
const images = yield (0, list_images_1.listImages)(dockerode);
images.forEach((name) => {
existingImages.add(name.toString());
});
return existingImages.has(imageName.toString());
try {
yield dockerode.getImage(imageName.toString()).inspect();
existingImages.add(imageName.toString());
return true;
}
catch (err) {
if (err instanceof Error && err.message.toLowerCase().includes("no such image")) {
return false;
}
throw err;
}
}));
});
exports.imageExists = imageExists;

@@ -10,3 +10,2 @@ /// <reference types="node" />

consume(stream: Readable): Promise<void>;
private getOrElse;
}

@@ -14,51 +14,8 @@ "use strict";

consume(stream) {
const messagesById = new Map();
const statusesById = new Map();
return new Promise((resolve) => {
(0, byline_1.default)(stream).on("data", (line) => {
try {
const json = JSON.parse(line);
const { id, status } = json;
const prefix = id
? `Pulling ${this.dockerImageName.toString()} - ${id}`
: `Pulling ${this.dockerImageName.toString()}`;
if (status === "Downloading") {
const { current, total } = json.progressDetail;
const percentage = Math.round(100 * (current / total));
const message = `${prefix} - ${json.status} ${percentage}%`;
const messages = this.getOrElse(messagesById, id, new Set());
if (!messages.has(message)) {
messages.add(message);
this.logger.trace(message);
}
}
else {
const statuses = this.getOrElse(statusesById, id, new Set());
if (!statuses.has(status)) {
statuses.add(status);
const message = `${prefix} - ${json.status}`;
const messages = this.getOrElse(messagesById, id, new Set());
if (!messages.has(message)) {
messages.add(message);
this.logger.trace(message);
}
}
}
}
catch (_a) {
this.logger.warn(`Unexpected message format: ${line}`);
}
});
(0, byline_1.default)(stream).on("data", (line) => this.logger.trace(`Pulling ${this.dockerImageName.toString()}: ${line}`));
stream.on("end", resolve);
});
}
getOrElse(map, key, orElse) {
const value = map.get(key);
if (value === undefined) {
map.set(key, orElse);
return orElse;
}
return value;
}
}
exports.PullStreamParser = PullStreamParser;

@@ -6,2 +6,3 @@ /// <reference types="node" />

import Dockerode from "dockerode";
export declare const resolveHost: (dockerode: Dockerode, indexServerAddress: string, uri: string, env?: NodeJS.ProcessEnv) => Promise<string>;
import { Provider } from "./docker-client";
export declare const resolveHost: (dockerode: Dockerode, provider: Provider, indexServerAddress: string, uri: string, env?: NodeJS.ProcessEnv) => Promise<string>;

@@ -17,3 +17,3 @@ "use strict";

const fs_1 = require("fs");
const resolveHost = (dockerode, indexServerAddress, uri, env = process.env) => __awaiter(void 0, void 0, void 0, function* () {
const resolveHost = (dockerode, provider, indexServerAddress, uri, env = process.env) => __awaiter(void 0, void 0, void 0, function* () {
if (env.TESTCONTAINERS_HOST_OVERRIDE !== undefined) {

@@ -31,3 +31,4 @@ return env.TESTCONTAINERS_HOST_OVERRIDE;

if (isInContainer()) {
const gateway = yield findGateway(dockerode);
const networkName = provider === "podman" ? "podman" : "bridge";
const gateway = yield findGateway(dockerode, networkName);
if (gateway !== undefined) {

@@ -48,6 +49,6 @@ return gateway;

exports.resolveHost = resolveHost;
const findGateway = (dockerode) => __awaiter(void 0, void 0, void 0, function* () {
const findGateway = (dockerode, networkName) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
logger_1.log.debug(`Checking gateway for Docker host`);
const inspectResult = yield dockerode.getNetwork("bridge").inspect();
const inspectResult = yield dockerode.getNetwork(networkName).inspect();
return (_c = (_b = (_a = inspectResult === null || inspectResult === void 0 ? void 0 : inspectResult.IPAM) === null || _a === void 0 ? void 0 : _a.Config) === null || _b === void 0 ? void 0 : _b.find((config) => config.Gateway !== undefined)) === null || _c === void 0 ? void 0 : _c.Gateway;

@@ -54,0 +55,0 @@ });

@@ -16,4 +16,4 @@ import archiver from "archiver";

protected opts: CreateContainerOptions;
protected startupTimeout: number;
protected waitStrategy?: WaitStrategy;
protected startupTimeout?: number;
protected waitStrategy: WaitStrategy;
protected tarToCopy?: archiver.Archiver;

@@ -20,0 +20,0 @@ protected networkMode?: string;

@@ -39,3 +39,3 @@ "use strict";

const create_container_options_1 = require("./create-container-options");
const default_wait_strategy_1 = require("../wait-strategy/default-wait-strategy");
const wait_1 = require("../wait-strategy/wait");
const reusableContainerCreationLock = new async_lock_1.default();

@@ -48,3 +48,3 @@ class GenericContainer {

this.image = image;
this.startupTimeout = 60000;
this.waitStrategy = wait_1.Wait.forListeningPorts();
this.networkAliases = [];

@@ -106,3 +106,2 @@ this.pullPolicy = new pull_policy_1.DefaultPullPolicy();

reuseContainer(container) {
var _a;
return __awaiter(this, void 0, void 0, function* () {

@@ -112,8 +111,10 @@ const { host, hostIps } = yield (0, docker_client_1.dockerClient)();

const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, inspectResult).filter(this.opts.exposedPorts);
const waitStrategy = ((_a = this.waitStrategy) !== null && _a !== void 0 ? _a : (0, default_wait_strategy_1.defaultWaitStrategy)(host, container)).withStartupTimeout(this.startupTimeout);
if (this.startupTimeout !== undefined) {
this.waitStrategy.withStartupTimeout(this.startupTimeout);
}
if (this.containerStarting) {
yield this.containerStarting(inspectResult, true);
}
yield (0, wait_for_container_1.waitForContainer)(container, waitStrategy, host, boundPorts);
const startedContainer = new started_generic_container_1.StartedGenericContainer(container, host, inspectResult, boundPorts, inspectResult.name, waitStrategy);
yield (0, wait_for_container_1.waitForContainer)(container, this.waitStrategy, boundPorts);
const startedContainer = new started_generic_container_1.StartedGenericContainer(container, host, inspectResult, boundPorts, inspectResult.name, this.waitStrategy);
if (this.containerStarted) {

@@ -129,3 +130,2 @@ yield this.containerStarted(startedContainer, inspectResult, true);

startContainer(createContainerOptions) {
var _a;
return __awaiter(this, void 0, void 0, function* () {

@@ -164,3 +164,5 @@ const container = yield (0, create_container_1.createContainer)(createContainerOptions);

const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, inspectResult).filter(this.opts.exposedPorts);
const waitStrategy = ((_a = this.waitStrategy) !== null && _a !== void 0 ? _a : (0, default_wait_strategy_1.defaultWaitStrategy)(host, container)).withStartupTimeout(this.startupTimeout);
if (this.startupTimeout !== undefined) {
this.waitStrategy.withStartupTimeout(this.startupTimeout);
}
if (logger_1.containerLog.enabled()) {

@@ -174,4 +176,4 @@ (yield (0, container_logs_1.containerLogs)(container))

}
yield (0, wait_for_container_1.waitForContainer)(container, waitStrategy, host, boundPorts);
const startedContainer = new started_generic_container_1.StartedGenericContainer(container, host, inspectResult, boundPorts, inspectResult.name, waitStrategy);
yield (0, wait_for_container_1.waitForContainer)(container, this.waitStrategy, boundPorts);
const startedContainer = new started_generic_container_1.StartedGenericContainer(container, host, inspectResult, boundPorts, inspectResult.name, this.waitStrategy);
if (this.containerStarted) {

@@ -178,0 +180,0 @@ yield this.containerStarted(startedContainer, inspectResult, false);

@@ -16,2 +16,4 @@ /// <reference types="node" />

private readonly waitStrategy;
private stoppedContainer?;
private stopContainerLock;
constructor(container: Dockerode.Container, host: string, inspectResult: InspectResult, boundPorts: BoundPorts, name: string, waitStrategy: WaitStrategy);

@@ -18,0 +20,0 @@ protected containerIsStopping?(): Promise<void>;

@@ -11,2 +11,5 @@ "use strict";

};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -25,2 +28,3 @@ exports.StartedGenericContainer = void 0;

const docker_client_1 = require("../docker/docker-client");
const async_lock_1 = __importDefault(require("async-lock"));
class StartedGenericContainer {

@@ -34,6 +38,13 @@ constructor(container, host, inspectResult, boundPorts, name, waitStrategy) {

this.waitStrategy = waitStrategy;
this.stopContainerLock = new async_lock_1.default();
}
stop(options = {}) {
return __awaiter(this, void 0, void 0, function* () {
return this.stopContainer(options);
return this.stopContainerLock.acquire("stop", () => __awaiter(this, void 0, void 0, function* () {
if (this.stoppedContainer) {
return this.stoppedContainer;
}
this.stoppedContainer = yield this.stopContainer(options);
return this.stoppedContainer;
}));
});

@@ -55,3 +66,3 @@ }

this.boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, this.inspectResult).filter(Array.from(this.boundPorts.iterator()).map((port) => port[0]));
yield (0, wait_for_container_1.waitForContainer)(this.container, this.waitStrategy, this.host, this.boundPorts, startTime);
yield (0, wait_for_container_1.waitForContainer)(this.container, this.waitStrategy, this.boundPorts, startTime);
});

@@ -102,3 +113,6 @@ }

exec(command) {
return (0, exec_container_1.execContainer)(this.container, command);
return __awaiter(this, void 0, void 0, function* () {
const { dockerode, provider } = yield (0, docker_client_1.dockerClient)();
return (0, exec_container_1.execContainer)(dockerode, provider, this.container, command);
});
}

@@ -105,0 +119,0 @@ logs() {

@@ -29,3 +29,3 @@ "use strict";

{
content: "-Xms2G\n-Xmx2G\n",
content: "-Xmx2G\n",
target: "/usr/share/elasticsearch/config/jvm.options.d/elasticsearch-default-memory-vm.options",

@@ -32,0 +32,0 @@ },

@@ -5,2 +5,3 @@ import { Uuid } from "./uuid";

private readonly createNetworkOptions;
private readonly uuid;
constructor(createNetworkOptions?: Partial<CreateNetworkOptions>, uuid?: Uuid);

@@ -7,0 +8,0 @@ start(): Promise<StartedNetwork>;

@@ -20,10 +20,13 @@ "use strict";

constructor(createNetworkOptions = {}, uuid = new uuid_1.RandomUuid()) {
this.createNetworkOptions = Object.assign({ name: uuid.nextUuid(), driver: "bridge", checkDuplicate: true, internal: false, attachable: false, ingress: false, enableIPv6: false }, createNetworkOptions);
this.createNetworkOptions = createNetworkOptions;
this.uuid = uuid;
this.createNetworkOptions = createNetworkOptions;
}
start() {
return __awaiter(this, void 0, void 0, function* () {
const options = Object.assign({ name: this.uuid.nextUuid(), driver: "bridge", checkDuplicate: true, internal: false, attachable: false, ingress: false, enableIPv6: false }, this.createNetworkOptions);
yield reaper_1.ReaperInstance.getInstance();
const id = yield (0, create_network_1.createNetwork)(this.createNetworkOptions);
const id = yield (0, create_network_1.createNetwork)(options);
logger_1.log.info(`Started network with ID: ${id}`);
return new StartedNetwork(id, this.createNetworkOptions);
return new StartedNetwork(id, options);
});

@@ -30,0 +33,0 @@ }

import Dockerode from "dockerode";
import { Provider } from "./docker/docker-client";
export interface PortCheck {

@@ -11,8 +12,10 @@ isBound(port: number): Promise<boolean>;

export declare class InternalPortCheck implements PortCheck {
private readonly dockerode;
private readonly provider;
private readonly container;
private isDistroless;
private commandOutputs;
constructor(container: Dockerode.Container);
constructor(dockerode: Dockerode, provider: Provider, container: Dockerode.Container);
isBound(port: number): Promise<boolean>;
private commandOutputsKey;
}

@@ -42,3 +42,5 @@ "use strict";

class InternalPortCheck {
constructor(container) {
constructor(dockerode, provider, container) {
this.dockerode = dockerode;
this.provider = provider;
this.container = container;

@@ -56,3 +58,3 @@ this.isDistroless = false;

];
const commandResults = yield Promise.all(commands.map((command) => (0, exec_container_1.execContainer)(this.container, command, false)));
const commandResults = yield Promise.all(commands.map((command) => (0, exec_container_1.execContainer)(this.dockerode, this.provider, this.container, command, false)));
const isBound = commandResults.some((result) => result.exitCode === 0);

@@ -59,0 +61,0 @@ if (!isBound && logger_1.log.enabled()) {

@@ -45,7 +45,2 @@ /// <reference types="node" />

}
export interface ExecOptions {
tty: boolean;
detach: boolean;
stdin: boolean;
}
export interface StartedTestContainer {

@@ -63,3 +58,3 @@ stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;

getIpAddress(networkName: string): string;
exec(command: string[], options?: Partial<ExecOptions>): Promise<ExecResult>;
exec(command: string[]): Promise<ExecResult>;
logs(): Promise<Readable>;

@@ -66,0 +61,0 @@ }

import Dockerode from "dockerode";
import { BoundPorts } from "./bound-ports";
import { WaitStrategy } from "./wait-strategy/wait-strategy";
export declare const waitForContainer: (container: Dockerode.Container, waitStrategy: WaitStrategy, host: string, boundPorts: BoundPorts, startTime?: Date) => Promise<void>;
export declare const waitForContainer: (container: Dockerode.Container, waitStrategy: WaitStrategy, boundPorts: BoundPorts, startTime?: Date) => Promise<void>;

@@ -16,6 +16,6 @@ "use strict";

const remove_container_1 = require("./docker/functions/container/remove-container");
const waitForContainer = (container, waitStrategy, host, boundPorts, startTime) => __awaiter(void 0, void 0, void 0, function* () {
const waitForContainer = (container, waitStrategy, boundPorts, startTime) => __awaiter(void 0, void 0, void 0, function* () {
logger_1.log.debug(`Waiting for container to be ready: ${container.id}`);
try {
yield waitStrategy.waitUntilReady(container, host, boundPorts, startTime);
yield waitStrategy.waitUntilReady(container, boundPorts, startTime);
logger_1.log.info(`Container is ready: ${container.id}`);

@@ -22,0 +22,0 @@ }

@@ -19,2 +19,3 @@ "use strict";

waitUntilReady(container) {
var _a;
return __awaiter(this, void 0, void 0, function* () {

@@ -25,3 +26,3 @@ logger_1.log.debug(`Waiting for health check for ${container.id}`);

throw new Error(`Health check not healthy after ${timeout}ms for ${container.id}`);
}, this.startupTimeout);
}, (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT);
if (status !== "healthy") {

@@ -28,0 +29,0 @@ throw new Error(`Health check failed: ${status} for ${container.id}`);

@@ -1,2 +0,1 @@

import { PortCheck } from "../port-check";
import Dockerode from "dockerode";

@@ -6,6 +5,3 @@ import { BoundPorts } from "../bound-ports";

export declare class HostPortWaitStrategy extends AbstractWaitStrategy {
private readonly hostPortCheck;
private readonly internalPortCheck;
constructor(hostPortCheck: PortCheck, internalPortCheck: PortCheck);
waitUntilReady(container: Dockerode.Container, host: string, boundPorts: BoundPorts): Promise<void>;
waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts): Promise<void>;
private waitForHostPorts;

@@ -12,0 +8,0 @@ private waitForInternalPorts;

@@ -13,21 +13,24 @@ "use strict";

exports.HostPortWaitStrategy = void 0;
const port_check_1 = require("../port-check");
const logger_1 = require("../logger");
const retry_strategy_1 = require("../retry-strategy");
const wait_strategy_1 = require("./wait-strategy");
const docker_client_1 = require("../docker/docker-client");
class HostPortWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
constructor(hostPortCheck, internalPortCheck) {
super();
this.hostPortCheck = hostPortCheck;
this.internalPortCheck = internalPortCheck;
}
waitUntilReady(container, host, boundPorts) {
waitUntilReady(container, boundPorts) {
return __awaiter(this, void 0, void 0, function* () {
yield Promise.all([this.waitForHostPorts(container, boundPorts), this.waitForInternalPorts(container, boundPorts)]);
const { dockerode, provider, host } = yield (0, docker_client_1.dockerClient)();
const hostPortCheck = new port_check_1.HostPortCheck(host);
const internalPortCheck = new port_check_1.InternalPortCheck(dockerode, provider, container);
yield Promise.all([
this.waitForHostPorts(hostPortCheck, container, boundPorts),
this.waitForInternalPorts(internalPortCheck, container, boundPorts),
]);
});
}
waitForHostPorts(container, boundPorts) {
waitForHostPorts(portCheck, container, boundPorts) {
return __awaiter(this, void 0, void 0, function* () {
for (const [, hostPort] of boundPorts.iterator()) {
logger_1.log.debug(`Waiting for host port ${hostPort} for ${container.id}`);
yield this.waitForPort(container, hostPort, this.hostPortCheck);
yield this.waitForPort(container, hostPort, portCheck);
logger_1.log.debug(`Host port ${hostPort} ready for ${container.id}`);

@@ -37,7 +40,7 @@ }

}
waitForInternalPorts(container, boundPorts) {
waitForInternalPorts(portCheck, container, boundPorts) {
return __awaiter(this, void 0, void 0, function* () {
for (const [internalPort] of boundPorts.iterator()) {
logger_1.log.debug(`Waiting for internal port ${internalPort} for ${container.id}`);
yield this.waitForPort(container, internalPort, this.internalPortCheck);
yield this.waitForPort(container, internalPort, portCheck);
logger_1.log.debug(`Internal port ${internalPort} ready for ${container.id}`);

@@ -48,7 +51,8 @@ }

waitForPort(container, port, portCheck) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const startupTimeout = (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT;
yield new retry_strategy_1.IntervalRetryStrategy(100).retryUntil(() => portCheck.isBound(port), (isBound) => isBound, () => {
const timeout = this.startupTimeout;
throw new Error(`Port ${port} not bound after ${timeout}ms for ${container.id}`);
}, this.startupTimeout);
throw new Error(`Port ${port} not bound after ${startupTimeout}ms for ${container.id}`);
}, startupTimeout);
});

@@ -55,0 +59,0 @@ }

@@ -25,4 +25,4 @@ import Dockerode from "dockerode";

allowInsecure(): HttpWaitStrategy;
waitUntilReady(container: Dockerode.Container, host: string, boundPorts: BoundPorts): Promise<void>;
waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts): Promise<void>;
private getAgent;
}

@@ -20,2 +20,3 @@ "use strict";

const https_1 = __importDefault(require("https"));
const docker_client_1 = require("../docker/docker-client");
class HttpWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {

@@ -70,4 +71,7 @@ constructor(path, port) {

}
waitUntilReady(container, host, boundPorts) {
waitUntilReady(container, boundPorts) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const { host } = yield (0, docker_client_1.dockerClient)();
const startupTimeout = (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT;
yield new retry_strategy_1.IntervalRetryStrategy(this.readTimeout).retryUntil(() => __awaiter(this, void 0, void 0, function* () {

@@ -83,3 +87,3 @@ try {

}
catch (_a) {
catch (_b) {
return undefined;

@@ -104,4 +108,4 @@ }

}), () => {
throw new Error(`URL ${this.path} not accessible after ${this.startupTimeout}ms for ${container.id}`);
}, this.startupTimeout);
throw new Error(`URL ${this.path} not accessible after ${startupTimeout}ms for ${container.id}`);
}, startupTimeout);
});

@@ -108,0 +112,0 @@ }

@@ -9,3 +9,3 @@ import Dockerode from "dockerode";

constructor(message: Log | RegExp, times: number);
waitUntilReady(container: Dockerode.Container, host: string, boundPorts: BoundPorts, startTime?: Date): Promise<void>;
waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts, startTime?: Date): Promise<void>;
}

@@ -26,8 +26,9 @@ "use strict";

}
waitUntilReady(container, host, boundPorts, startTime) {
waitUntilReady(container, boundPorts, startTime) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
logger_1.log.debug(`Waiting for log message "${this.message}" for ${container.id}`);
const startupTimeout = (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT;
const stream = yield (0, container_logs_1.containerLogs)(container, { since: startTime });
return new Promise((resolve, reject) => {
const startupTimeout = this.startupTimeout;
const timeout = setTimeout(() => {

@@ -34,0 +35,0 @@ const message = `Log message "${this.message}" not received after ${startupTimeout}ms for ${container.id}`;

@@ -17,2 +17,3 @@ "use strict";

const exec_container_1 = require("../docker/functions/container/exec-container");
const docker_client_1 = require("../docker/docker-client");
class ShellWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {

@@ -24,11 +25,13 @@ constructor(command) {

waitUntilReady(container) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
logger_1.log.debug(`Waiting for successful shell command ${this.command} for ${container.id}`);
const { dockerode, provider } = yield (0, docker_client_1.dockerClient)();
const startupTimeout = (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT;
yield new retry_strategy_1.IntervalRetryStrategy(100).retryUntil(() => __awaiter(this, void 0, void 0, function* () {
const { exitCode } = yield (0, exec_container_1.execContainer)(container, ["/bin/sh", "-c", this.command], false);
const { exitCode } = yield (0, exec_container_1.execContainer)(dockerode, provider, container, ["/bin/sh", "-c", this.command], false);
return exitCode;
}), (exitCode) => exitCode === 0, () => {
const timeout = this.startupTimeout;
throw new Error(`Shell command not successful after ${timeout}ms for ${container.id}`);
}, this.startupTimeout);
throw new Error(`Shell command "${this.command}" not successful after ${startupTimeout}ms for ${container.id}`);
}, startupTimeout);
});

@@ -35,0 +38,0 @@ }

@@ -18,5 +18,7 @@ "use strict";

waitUntilReady(container) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const { dockerode } = yield (0, docker_client_1.dockerClient)();
const startupStatus = yield new retry_strategy_1.IntervalRetryStrategy(1000).retryUntil(() => __awaiter(this, void 0, void 0, function* () { return yield this.checkStartupState(dockerode, container.id); }), (startupStatus) => startupStatus === "SUCCESS" || startupStatus === "FAIL", () => new Error(`Container not accessible after ${this.startupTimeout}ms for ${container.id}`), this.startupTimeout);
const startupTimeout = (_a = this.startupTimeout) !== null && _a !== void 0 ? _a : wait_strategy_1.DEFAULT_STARTUP_TIMEOUT;
const startupStatus = yield new retry_strategy_1.IntervalRetryStrategy(1000).retryUntil(() => __awaiter(this, void 0, void 0, function* () { return yield this.checkStartupState(dockerode, container.id); }), (startupStatus) => startupStatus === "SUCCESS" || startupStatus === "FAIL", () => new Error(`Container not accessible after ${startupTimeout}ms for ${container.id}`), startupTimeout);
if (startupStatus instanceof Error) {

@@ -23,0 +25,0 @@ throw startupStatus;

import { BoundPorts } from "../bound-ports";
import Dockerode from "dockerode";
export declare const DEFAULT_STARTUP_TIMEOUT = 60000;
export interface WaitStrategy {
waitUntilReady(container: Dockerode.Container, host: string, boundPorts: BoundPorts, startTime?: Date): Promise<void>;
waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts, startTime?: Date): Promise<void>;
withStartupTimeout(startupTimeout: number): WaitStrategy;
getStartupTimeout(): number | undefined;
}
export declare abstract class AbstractWaitStrategy implements WaitStrategy {
protected startupTimeout: number;
abstract waitUntilReady(container: Dockerode.Container, host: string, boundPorts: BoundPorts, startTime?: Date): Promise<void>;
withStartupTimeout(startupTimeout: number): WaitStrategy;
protected startupTimeout?: number;
abstract waitUntilReady(container: Dockerode.Container, boundPorts: BoundPorts, startTime?: Date): Promise<void>;
withStartupTimeout(startupTimeout: number): this;
getStartupTimeout(): number | undefined;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractWaitStrategy = void 0;
exports.AbstractWaitStrategy = exports.DEFAULT_STARTUP_TIMEOUT = void 0;
exports.DEFAULT_STARTUP_TIMEOUT = 60000;
class AbstractWaitStrategy {
constructor() {
this.startupTimeout = 60000;
}
withStartupTimeout(startupTimeout) {

@@ -12,3 +10,6 @@ this.startupTimeout = startupTimeout;

}
getStartupTimeout() {
return this.startupTimeout;
}
}
exports.AbstractWaitStrategy = AbstractWaitStrategy;

@@ -5,3 +5,6 @@ import { WaitStrategy } from "./wait-strategy";

import { ShellWaitStrategy } from "./shell-wait-strategy";
import { CompositeWaitStrategy } from "./composite-wait-strategy";
export declare class Wait {
static forAll(waitStrategies: WaitStrategy[]): CompositeWaitStrategy;
static forListeningPorts(): WaitStrategy;
static forLogMessage(message: Log | RegExp, times?: number): WaitStrategy;

@@ -8,0 +11,0 @@ static forHealthCheck(): WaitStrategy;

@@ -8,3 +8,11 @@ "use strict";

const shell_wait_strategy_1 = require("./shell-wait-strategy");
const host_port_wait_strategy_1 = require("./host-port-wait-strategy");
const composite_wait_strategy_1 = require("./composite-wait-strategy");
class Wait {
static forAll(waitStrategies) {
return new composite_wait_strategy_1.CompositeWaitStrategy(waitStrategies);
}
static forListeningPorts() {
return new host_port_wait_strategy_1.HostPortWaitStrategy();
}
static forLogMessage(message, times = 1) {

@@ -11,0 +19,0 @@ return new log_wait_strategy_1.LogWaitStrategy(message, times);

{
"name": "testcontainers",
"author": "Cristian Greco",
"version": "9.5.0",
"version": "9.6.0",
"main": "dist/src/index",

@@ -30,4 +30,4 @@ "types": "dist/src/index",

"clean": "rimraf dist",
"test": "cross-env DEBUG=testcontainers,testcontainers:exec,testcontainers:containers jest",
"test:ci": "cross-env DEBUG=testcontainers,testcontainers:exec,testcontainers:containers jest --runInBand --coverage",
"test": "cross-env DEBUG=testcontainers* jest",
"test:ci": "npm run test -- --runInBand --coverage",
"format": "prettier --write package.json \"src/**/*.ts\"",

@@ -34,0 +34,0 @@ "lint": "eslint --fix package.json \"src/**/*.ts\"",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc