testcontainers 9.10.1 → 9.12.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/package.json +3 -1
  2. package/dist/src/docker/client/docker-client-types.d.ts +23 -0
  3. package/dist/src/docker/client/docker-client-types.js +2 -0
  4. package/dist/src/docker/client/docker-client.d.ts +1 -17
  5. package/dist/src/docker/client/docker-client.js +54 -23
  6. package/dist/src/docker/client/strategy/configuration-strategy.d.ts +1 -1
  7. package/dist/src/docker/client/strategy/configuration-strategy.js +2 -4
  8. package/dist/src/docker/client/strategy/docker-client-strategy.d.ts +1 -1
  9. package/dist/src/docker/client/strategy/npipe-socket-strategy.d.ts +1 -1
  10. package/dist/src/docker/client/strategy/npipe-socket-strategy.js +1 -5
  11. package/dist/src/docker/client/strategy/rootless-unix-socket-strategy.d.ts +1 -1
  12. package/dist/src/docker/client/strategy/rootless-unix-socket-strategy.js +1 -2
  13. package/dist/src/docker/client/strategy/testcontainers-host-strategy.d.ts +1 -1
  14. package/dist/src/docker/client/strategy/testcontainers-host-strategy.js +2 -7
  15. package/dist/src/docker/client/strategy/unix-socket-strategy.d.ts +1 -1
  16. package/dist/src/docker/client/strategy/unix-socket-strategy.js +1 -5
  17. package/dist/src/docker/functions/container/create-container.d.ts +1 -1
  18. package/dist/src/docker/functions/container/create-container.js +2 -2
  19. package/dist/src/docker/functions/create-labels.d.ts +1 -2
  20. package/dist/src/docker/functions/create-labels.js +2 -3
  21. package/dist/src/docker/functions/image/build-image.d.ts +2 -1
  22. package/dist/src/docker/functions/image/build-image.js +2 -2
  23. package/dist/src/docker/functions/network/create-network.d.ts +1 -1
  24. package/dist/src/docker/functions/network/create-network.js +2 -2
  25. package/dist/src/docker/remote-docker-unix-socket-path.d.ts +2 -2
  26. package/dist/src/docker/types.d.ts +3 -0
  27. package/dist/src/docker-compose/docker-compose-client.d.ts +9 -0
  28. package/dist/src/docker-compose/docker-compose-client.js +221 -0
  29. package/dist/src/docker-compose/docker-compose-options.d.ts +6 -0
  30. package/dist/src/docker-compose/docker-compose-options.js +49 -0
  31. package/dist/src/docker-compose-environment/docker-compose-environment.js +8 -9
  32. package/dist/src/docker-compose-environment/started-docker-compose-environment.d.ts +1 -2
  33. package/dist/src/docker-compose-environment/started-docker-compose-environment.js +5 -4
  34. package/dist/src/docker-compose-environment/stopped-docker-compose-environment.d.ts +1 -2
  35. package/dist/src/docker-compose-environment/stopped-docker-compose-environment.js +3 -2
  36. package/dist/src/file-lock.d.ts +1 -0
  37. package/dist/src/file-lock.js +47 -0
  38. package/dist/src/generic-container/generic-container-builder.d.ts +4 -1
  39. package/dist/src/generic-container/generic-container-builder.js +4 -5
  40. package/dist/src/generic-container/generic-container.d.ts +8 -4
  41. package/dist/src/generic-container/generic-container.js +75 -72
  42. package/dist/src/generic-container/started-generic-container.d.ts +2 -1
  43. package/dist/src/generic-container/started-generic-container.js +10 -0
  44. package/dist/src/index.d.ts +1 -1
  45. package/dist/src/modules/abstract-started-container.d.ts +2 -1
  46. package/dist/src/modules/abstract-started-container.js +5 -0
  47. package/dist/src/modules/selenium/selenium-container.js +11 -8
  48. package/dist/src/network.js +3 -3
  49. package/dist/src/port-forwarder.js +2 -2
  50. package/dist/src/reaper.d.ts +5 -14
  51. package/dist/src/reaper.js +124 -114
  52. package/dist/src/system-info.d.ts +2 -0
  53. package/dist/src/system-info.js +38 -6
  54. package/dist/src/test-container.d.ts +3 -5
  55. package/dist/src/wait-strategy/composite-wait-strategy.js +4 -1
  56. package/dist/src/wait-strategy/health-check-wait-strategy.js +1 -0
  57. package/dist/src/wait-strategy/host-port-wait-strategy.js +1 -0
  58. package/dist/src/wait-strategy/http-wait-strategy.js +1 -0
  59. package/dist/src/wait-strategy/log-wait-strategy.js +1 -0
  60. package/dist/src/wait-strategy/shell-wait-strategy.js +1 -0
  61. package/package.json +3 -1
  62. package/dist/src/docker/session-id.d.ts +0 -1
  63. package/dist/src/docker/session-id.js +0 -5
  64. package/dist/src/docker-compose/default-docker-compose-options.d.ts +0 -3
  65. package/dist/src/docker-compose/default-docker-compose-options.js +0 -51
  66. package/dist/src/docker-compose/functions/docker-compose-down.d.ts +0 -3
  67. package/dist/src/docker-compose/functions/docker-compose-down.js +0 -39
  68. package/dist/src/docker-compose/functions/docker-compose-pull.d.ts +0 -2
  69. package/dist/src/docker-compose/functions/docker-compose-pull.js +0 -35
  70. package/dist/src/docker-compose/functions/docker-compose-stop.d.ts +0 -2
  71. package/dist/src/docker-compose/functions/docker-compose-stop.js +0 -29
  72. package/dist/src/docker-compose/functions/docker-compose-up.d.ts +0 -2
  73. package/dist/src/docker-compose/functions/docker-compose-up.js +0 -41
  74. /package/dist/src/docker-compose/{functions/container-name-resolver.d.ts → container-name-resolver.d.ts} +0 -0
  75. /package/dist/src/docker-compose/{functions/container-name-resolver.js → container-name-resolver.js} +0 -0
@@ -9,139 +9,149 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.ReaperInstance = void 0;
12
+ exports.startReaper = exports.registerComposeProjectForCleanup = exports.registerSessionIdForCleanup = void 0;
13
13
  const net_1 = require("net");
14
14
  const logger_1 = require("./logger");
15
15
  const generic_container_1 = require("./generic-container/generic-container");
16
- const session_id_1 = require("./docker/session-id");
17
16
  const images_1 = require("./images");
18
- const port_1 = require("./port");
19
17
  const labels_1 = require("./labels");
20
18
  const wait_1 = require("./wait-strategy/wait");
21
19
  const retry_strategy_1 = require("./retry-strategy");
22
20
  const remote_docker_unix_socket_path_1 = require("./docker/remote-docker-unix-socket-path");
23
21
  const docker_client_1 = require("./docker/client/docker-client");
22
+ const isReaperEnabled = process.env.TESTCONTAINERS_RYUK_DISABLED !== "true";
23
+ let reaper;
24
+ function registerSessionIdForCleanup(sessionId) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ if (!reaper) {
27
+ yield (0, docker_client_1.getDockerClient)();
28
+ }
29
+ (yield reaper).addSession(sessionId);
30
+ });
31
+ }
32
+ exports.registerSessionIdForCleanup = registerSessionIdForCleanup;
33
+ function registerComposeProjectForCleanup(project) {
34
+ return __awaiter(this, void 0, void 0, function* () {
35
+ if (!reaper) {
36
+ yield (0, docker_client_1.getDockerClient)();
37
+ }
38
+ (yield reaper).addProject(project);
39
+ });
40
+ }
41
+ exports.registerComposeProjectForCleanup = registerComposeProjectForCleanup;
42
+ function startReaper(dockerClient, sessionId, existingReaperContainer) {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ reaper = !isReaperEnabled
45
+ ? yield createDisabledReaper()
46
+ : existingReaperContainer
47
+ ? yield useExistingReaper(dockerClient, sessionId, existingReaperContainer)
48
+ : yield createNewReaper(dockerClient, sessionId);
49
+ });
50
+ }
51
+ exports.startReaper = startReaper;
52
+ function createDisabledReaper() {
53
+ return __awaiter(this, void 0, void 0, function* () {
54
+ return new DisabledReaper();
55
+ });
56
+ }
57
+ function useExistingReaper(dockerClient, sessionId, reaperContainer) {
58
+ return __awaiter(this, void 0, void 0, function* () {
59
+ logger_1.log.debug(`Reusing existing Reaper for session "${sessionId}"...`);
60
+ const reaperPort = getReaperPublicPort(reaperContainer);
61
+ const socket = yield connectToReaperSocket(dockerClient.host, reaperPort, sessionId, reaperContainer.Id);
62
+ return new RealReaper(sessionId, socket);
63
+ });
64
+ }
65
+ function getReaperPublicPort(reaperContainer) {
66
+ var _a;
67
+ const port = (_a = reaperContainer.Ports.find((port) => port.PrivatePort == 8080)) === null || _a === void 0 ? void 0 : _a.PublicPort;
68
+ if (!port) {
69
+ throw new Error("Expected Reaper to map exposed port 8080");
70
+ }
71
+ return port;
72
+ }
73
+ function createNewReaper(dockerClient, sessionId) {
74
+ return __awaiter(this, void 0, void 0, function* () {
75
+ const remoteDockerUnixSocketPath = (0, remote_docker_unix_socket_path_1.getRemoteDockerUnixSocketPath)(dockerClient);
76
+ logger_1.log.debug(`Creating new Reaper for session "${sessionId}" with socket path "${remoteDockerUnixSocketPath}"...`);
77
+ const startedContainer = yield createAndStartReaperContainer(sessionId, remoteDockerUnixSocketPath);
78
+ const containerId = startedContainer.getId();
79
+ const host = startedContainer.getHost();
80
+ const port = startedContainer.getMappedPort(8080);
81
+ const socket = yield connectToReaperSocket(host, port, sessionId, containerId);
82
+ return new RealReaper(sessionId, socket);
83
+ });
84
+ }
85
+ function createAndStartReaperContainer(sessionId, socketPath) {
86
+ return __awaiter(this, void 0, void 0, function* () {
87
+ const exposedPort = process.env["TESTCONTAINERS_RYUK_PORT"]
88
+ ? { container: 8080, host: Number(process.env["TESTCONTAINERS_RYUK_PORT"]) }
89
+ : 8080;
90
+ const container = new generic_container_1.GenericContainer(images_1.REAPER_IMAGE)
91
+ .withName(`testcontainers-ryuk-${sessionId}`)
92
+ .withExposedPorts(exposedPort)
93
+ .withBindMounts([{ source: socketPath, target: "/var/run/docker.sock" }])
94
+ .withWaitStrategy(wait_1.Wait.forLogMessage(/.+ Started!/));
95
+ if (process.env.TESTCONTAINERS_RYUK_PRIVILEGED === "true") {
96
+ container.withPrivilegedMode();
97
+ }
98
+ return yield container.start();
99
+ });
100
+ }
101
+ function connectToReaperSocket(host, port, sessionId, containerId) {
102
+ return __awaiter(this, void 0, void 0, function* () {
103
+ const retryResult = yield new retry_strategy_1.IntervalRetryStrategy(1000).retryUntil((attempt) => {
104
+ return new Promise((resolve) => {
105
+ logger_1.log.debug(`Connecting to Reaper (attempt ${attempt + 1}) on "${host}:${port}"...`, { containerId });
106
+ const socket = new net_1.Socket();
107
+ socket
108
+ .unref()
109
+ .on("timeout", () => logger_1.log.error(`Reaper ${containerId} socket timed out`))
110
+ .on("error", (err) => logger_1.log.error(`Reaper ${containerId} socket error: ${err}`))
111
+ .on("close", (hadError) => {
112
+ if (hadError) {
113
+ logger_1.log.error(`Connection to Reaper closed with error`, { containerId });
114
+ }
115
+ else {
116
+ logger_1.log.warn(`Connection to Reaper closed`, { containerId });
117
+ }
118
+ resolve(undefined);
119
+ })
120
+ .connect(port, host, () => {
121
+ logger_1.log.debug(`Connected to Reaper`, { containerId });
122
+ resolve(socket);
123
+ });
124
+ });
125
+ }, (result) => result !== undefined, () => {
126
+ const message = `Failed to connect to Reaper`;
127
+ logger_1.log.error(message, { containerId });
128
+ return new Error(message);
129
+ }, 4000);
130
+ if (retryResult instanceof net_1.Socket) {
131
+ return retryResult;
132
+ }
133
+ else {
134
+ throw retryResult;
135
+ }
136
+ });
137
+ }
24
138
  class RealReaper {
25
- constructor(container, socket) {
26
- this.container = container;
139
+ constructor(sessionId, socket) {
140
+ this.sessionId = sessionId;
27
141
  this.socket = socket;
28
142
  }
143
+ addSession(sessionId) {
144
+ this.socket.write(`label=${labels_1.LABEL_TESTCONTAINERS_SESSION_ID}=${sessionId}\r\n`);
145
+ }
29
146
  addProject(projectName) {
30
147
  this.socket.write(`label=com.docker.compose.project=${projectName}\r\n`);
31
148
  }
32
- getContainerId() {
33
- return this.container.getId();
34
- }
35
- stop() {
36
- this.socket.end();
37
- }
38
149
  }
39
150
  class DisabledReaper {
40
- addProject() {
151
+ addSession() {
41
152
  // noop
42
153
  }
43
- stop() {
154
+ addProject() {
44
155
  // noop
45
156
  }
46
- getContainerId() {
47
- return "";
48
- }
49
- }
50
- class ReaperInstance {
51
- static getInstance() {
52
- return __awaiter(this, void 0, void 0, function* () {
53
- if (!this.instance) {
54
- if (this.isEnabled()) {
55
- this.instance = this.createRealInstance();
56
- }
57
- else {
58
- this.instance = this.createDisabledInstance();
59
- }
60
- }
61
- return this.instance;
62
- });
63
- }
64
- static stopInstance() {
65
- return __awaiter(this, void 0, void 0, function* () {
66
- if (this.instance) {
67
- const reaper = yield this.instance;
68
- reaper.stop();
69
- this.instance = undefined;
70
- }
71
- });
72
- }
73
- static isEnabled() {
74
- return process.env.TESTCONTAINERS_RYUK_DISABLED !== "true";
75
- }
76
- static isPrivileged() {
77
- return process.env.TESTCONTAINERS_RYUK_PRIVILEGED === "true";
78
- }
79
- static createDisabledInstance() {
80
- logger_1.log.debug(`Not creating new Reaper for session "${session_id_1.sessionId}"`);
81
- return Promise.resolve(new DisabledReaper());
82
- }
83
- static createRealInstance() {
84
- return __awaiter(this, void 0, void 0, function* () {
85
- const containerPort = process.env["TESTCONTAINERS_RYUK_PORT"]
86
- ? { container: 8080, host: Number(process.env["TESTCONTAINERS_RYUK_PORT"]) }
87
- : 8080;
88
- const dockerClient = yield (0, docker_client_1.getDockerClient)();
89
- const remoteDockerUnixSocketPath = (0, remote_docker_unix_socket_path_1.getRemoteDockerUnixSocketPath)(dockerClient);
90
- logger_1.log.debug(`Creating new Reaper for session "${session_id_1.sessionId}" with socket path "${remoteDockerUnixSocketPath}"...`);
91
- const container = new generic_container_1.GenericContainer(images_1.REAPER_IMAGE)
92
- .withName(`testcontainers-ryuk-${session_id_1.sessionId}`)
93
- .withExposedPorts(containerPort)
94
- .withBindMounts([
95
- {
96
- source: remoteDockerUnixSocketPath,
97
- target: "/var/run/docker.sock",
98
- },
99
- ])
100
- .withWaitStrategy(wait_1.Wait.forLogMessage(/.+ Started!/));
101
- if (this.isPrivileged()) {
102
- container.withPrivilegedMode();
103
- }
104
- const startedContainer = yield container.start();
105
- const containerId = startedContainer.getId();
106
- const host = startedContainer.getHost();
107
- const port = startedContainer.getMappedPort(8080);
108
- const retryStrategy = new retry_strategy_1.IntervalRetryStrategy(1000);
109
- const retryResult = yield retryStrategy.retryUntil((attempt) => {
110
- return new Promise((resolve) => {
111
- logger_1.log.debug(`Connecting to Reaper (attempt ${attempt + 1}) on "${host}:${port}"...`, { containerId });
112
- const socket = new net_1.Socket();
113
- socket
114
- .unref()
115
- .on("timeout", () => logger_1.log.error(`Reaper ${containerId} socket timed out`))
116
- .on("error", (err) => logger_1.log.error(`Reaper ${containerId} socket error: ${err}`))
117
- .on("close", (hadError) => {
118
- if (hadError) {
119
- logger_1.log.error(`Connection to Reaper closed with error`, { containerId });
120
- }
121
- else {
122
- logger_1.log.warn(`Connection to Reaper closed`, { containerId });
123
- }
124
- resolve(undefined);
125
- })
126
- .connect((0, port_1.getContainerPort)(port), host, () => {
127
- logger_1.log.debug(`Connected to Reaper`, { containerId });
128
- socket.write(`label=${labels_1.LABEL_TESTCONTAINERS_SESSION_ID}=${session_id_1.sessionId}\r\n`);
129
- const reaper = new RealReaper(startedContainer, socket);
130
- resolve(reaper);
131
- });
132
- });
133
- }, (result) => result !== undefined, () => {
134
- const message = `Failed to connect to Reaper`;
135
- logger_1.log.error(message, { containerId });
136
- return new Error(message);
137
- }, 4000);
138
- if (retryResult instanceof RealReaper) {
139
- return retryResult;
140
- }
141
- else {
142
- throw retryResult;
143
- }
144
- });
145
- }
146
157
  }
147
- exports.ReaperInstance = ReaperInstance;
@@ -13,5 +13,7 @@ type NodeInfo = {
13
13
  };
14
14
  export type DockerComposeInfo = {
15
15
  version: string;
16
+ compatability: DockerComposeCompatibility;
16
17
  };
18
+ export type DockerComposeCompatibility = "v1" | "v2";
17
19
  export {};
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -11,11 +34,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
34
  Object.defineProperty(exports, "__esModule", { value: true });
12
35
  exports.getSystemInfo = void 0;
13
36
  const logger_1 = require("./logger");
14
- const docker_compose_1 = require("docker-compose");
37
+ const docker_compose_1 = __importStar(require("docker-compose"));
15
38
  const get_info_1 = require("./docker/functions/get-info");
16
39
  let systemInfo;
17
40
  const getSystemInfo = (dockerode) => __awaiter(void 0, void 0, void 0, function* () {
18
- var _a;
41
+ var _a, _b;
19
42
  if (systemInfo !== undefined) {
20
43
  return systemInfo;
21
44
  }
@@ -24,7 +47,7 @@ const getSystemInfo = (dockerode) => __awaiter(void 0, void 0, void 0, function*
24
47
  const dockerInfo = yield (0, get_info_1.getDockerInfo)(dockerode);
25
48
  const dockerComposeInfo = yield getDockerComposeInfo();
26
49
  systemInfo = { nodeInfo, dockerInfo, dockerComposeInfo };
27
- logger_1.log.debug(`Node version: ${nodeInfo.version}, Platform: ${nodeInfo.platform}, Arch: ${nodeInfo.architecture}, OS: ${dockerInfo.operatingSystem}, Version: ${dockerInfo.serverVersion}, Arch: ${dockerInfo.architecture}, CPUs: ${dockerInfo.cpus}, Memory: ${dockerInfo.memory}, Compose installed: ${dockerComposeInfo !== undefined}, Compose version: ${(_a = dockerComposeInfo === null || dockerComposeInfo === void 0 ? void 0 : dockerComposeInfo.version) !== null && _a !== void 0 ? _a : "N/A"}`);
50
+ logger_1.log.debug(`Node version: ${nodeInfo.version}, Platform: ${nodeInfo.platform}, Arch: ${nodeInfo.architecture}, OS: ${dockerInfo.operatingSystem}, Version: ${dockerInfo.serverVersion}, Arch: ${dockerInfo.architecture}, CPUs: ${dockerInfo.cpus}, Memory: ${dockerInfo.memory}, Compose installed: ${dockerComposeInfo !== undefined}, Compose version: ${(_a = dockerComposeInfo === null || dockerComposeInfo === void 0 ? void 0 : dockerComposeInfo.version) !== null && _a !== void 0 ? _a : "N/A"}, Compose compatibility: ${(_b = dockerComposeInfo === null || dockerComposeInfo === void 0 ? void 0 : dockerComposeInfo.compatability) !== null && _b !== void 0 ? _b : "N/A"}`);
28
51
  return systemInfo;
29
52
  });
30
53
  exports.getSystemInfo = getSystemInfo;
@@ -38,11 +61,20 @@ const getNodeInfo = () => {
38
61
  const getDockerComposeInfo = () => __awaiter(void 0, void 0, void 0, function* () {
39
62
  try {
40
63
  return {
41
- version: (yield (0, docker_compose_1.version)()).data.version,
64
+ version: (yield docker_compose_1.default.version()).data.version,
65
+ compatability: "v1",
42
66
  };
43
67
  }
44
68
  catch (err) {
45
- logger_1.log.info(`Unable to detect docker-compose version, is it installed? ${err}`);
46
- return undefined;
69
+ try {
70
+ return {
71
+ version: (yield docker_compose_1.v2.version()).data.version,
72
+ compatability: "v2",
73
+ };
74
+ }
75
+ catch (_c) {
76
+ logger_1.log.warn(`Unable to detect DockerCompose version, is it installed? ${err}`);
77
+ return undefined;
78
+ }
47
79
  }
48
80
  });
@@ -4,7 +4,7 @@ import { PortWithOptionalBinding } from "./port";
4
4
  import { PullPolicy } from "./pull-policy";
5
5
  import { WaitStrategy } from "./wait-strategy/wait-strategy";
6
6
  import { Readable } from "stream";
7
- import { BindMount, ContentToCopy, Environment, ExecResult, ExtraHost, FileToCopy, Labels, ResourcesQuota, TmpFs, Ulimits } from "./docker/types";
7
+ import { BindMount, ContentToCopy, DirectoryToCopy, Environment, ExecResult, ExtraHost, FileToCopy, Labels, ResourcesQuota, TmpFs, Ulimits } from "./docker/types";
8
8
  import { StartedNetwork } from "./network";
9
9
  export interface TestContainer {
10
10
  start(): Promise<StartedTestContainer>;
@@ -28,6 +28,7 @@ export interface TestContainer {
28
28
  withPullPolicy(pullPolicy: PullPolicy): this;
29
29
  withReuse(): this;
30
30
  withCopyFilesToContainer(filesToCopy: FileToCopy[]): this;
31
+ withCopyDirectoriesToContainer(directoriesToCopy: DirectoryToCopy[]): this;
31
32
  withCopyContentToContainer(contentsToCopy: ContentToCopy[]): this;
32
33
  withWorkingDir(workingDir: string): this;
33
34
  withResourcesQuota(resourcesQuota: ResourcesQuota): this;
@@ -42,10 +43,6 @@ export interface StopOptions {
42
43
  remove: boolean;
43
44
  removeVolumes: boolean;
44
45
  }
45
- export interface DockerComposeDownOptions {
46
- timeout: number;
47
- removeVolumes: boolean;
48
- }
49
46
  export interface StartedTestContainer {
50
47
  stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;
51
48
  restart(options?: Partial<RestartOptions>): Promise<void>;
@@ -59,6 +56,7 @@ export interface StartedTestContainer {
59
56
  getNetworkId(networkName: string): string;
60
57
  getIpAddress(networkName: string): string;
61
58
  copyArchiveFromContainer(path: string): Promise<NodeJS.ReadableStream>;
59
+ copyDirectoriesToContainer(directoriesToCopy: DirectoryToCopy[]): Promise<void>;
62
60
  copyFilesToContainer(filesToCopy: FileToCopy[]): Promise<void>;
63
61
  copyContentToContainer(contentsToCopy: ContentToCopy[]): Promise<void>;
64
62
  exec(command: string | string[]): Promise<ExecResult>;
@@ -30,7 +30,10 @@ class CompositeWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
30
30
  }, this.deadline);
31
31
  }
32
32
  Promise.all(this.waitStrategies.map((waitStrategy) => waitStrategy.waitUntilReady(container, boundPorts, startTime)))
33
- .then(() => resolve())
33
+ .then(() => {
34
+ logger_1.log.debug(`Composite wait strategy complete`, { containerId: container.id });
35
+ resolve();
36
+ })
34
37
  .catch((err) => reject(err))
35
38
  .finally(() => {
36
39
  if (deadlineTimeout) {
@@ -29,6 +29,7 @@ class HealthCheckWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
29
29
  logger_1.log.error(message, { containerId: container.id });
30
30
  throw new Error(message);
31
31
  }
32
+ logger_1.log.debug(`Health check wait strategy complete`, { containerId: container.id });
32
33
  });
33
34
  }
34
35
  }
@@ -34,6 +34,7 @@ class HostPortWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
34
34
  yield this.waitForPort(container, hostPort, portCheck);
35
35
  logger_1.log.debug(`Host port ${hostPort} ready`, { containerId: container.id });
36
36
  }
37
+ logger_1.log.debug(`Host port wait strategy complete`, { containerId: container.id });
37
38
  });
38
39
  }
39
40
  waitForInternalPorts(portCheck, container, boundPorts) {
@@ -106,6 +106,7 @@ class HttpWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
106
106
  logger_1.log.error(message, { containerId: container.id });
107
107
  throw new Error(message);
108
108
  }, this.startupTimeout);
109
+ logger_1.log.debug(`HTTP wait strategy complete`, { containerId: container.id });
109
110
  });
110
111
  }
111
112
  getAgent() {
@@ -47,6 +47,7 @@ class LogWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
47
47
  if (++count === this.times) {
48
48
  stream.destroy();
49
49
  clearTimeout(timeout);
50
+ logger_1.log.debug(`Log wait strategy complete`, { containerId: container.id });
50
51
  resolve();
51
52
  }
52
53
  }
@@ -32,6 +32,7 @@ class ShellWaitStrategy extends wait_strategy_1.AbstractWaitStrategy {
32
32
  logger_1.log.error(message, { containerId: container.id });
33
33
  throw new Error(message);
34
34
  }, this.startupTimeout);
35
+ logger_1.log.debug(`Shell wait strategy complete`, { containerId: container.id });
35
36
  });
36
37
  }
37
38
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "testcontainers",
3
3
  "author": "Cristian Greco",
4
- "version": "9.10.1",
4
+ "version": "9.12.0-beta.0",
5
5
  "main": "dist/src/index",
6
6
  "types": "dist/src/index",
7
7
  "keywords": [
@@ -47,6 +47,7 @@
47
47
  "dockerode": "^3.3.5",
48
48
  "get-port": "^5.1.1",
49
49
  "node-fetch": "^2.6.12",
50
+ "proper-lockfile": "^4.1.2",
50
51
  "properties-reader": "^2.2.0",
51
52
  "ssh-remote-port-forward": "^1.0.4",
52
53
  "tar-fs": "^2.1.1",
@@ -61,6 +62,7 @@
61
62
  "@types/node": "^18.16.19",
62
63
  "@types/node-fetch": "^2.6.4",
63
64
  "@types/pg": "^8.10.2",
65
+ "@types/proper-lockfile": "^4.1.2",
64
66
  "@types/properties-reader": "^2.1.1",
65
67
  "@types/selenium-webdriver": "^4.1.15",
66
68
  "@types/tar-fs": "^2.0.1",
@@ -1 +0,0 @@
1
- export declare const sessionId: string;
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sessionId = void 0;
4
- const uuid_1 = require("../uuid");
5
- exports.sessionId = new uuid_1.RandomUuid().nextUuid();
@@ -1,3 +0,0 @@
1
- import { IDockerComposeOptions } from "docker-compose";
2
- import { DockerComposeOptions } from "./docker-compose-options";
3
- export declare const defaultDockerComposeOptions: ({ environment, ...options }: DockerComposeOptions) => Promise<Partial<IDockerComposeOptions>>;
@@ -1,51 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __rest = (this && this.__rest) || function (s, e) {
12
- var t = {};
13
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
- t[p] = s[p];
15
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
- t[p[i]] = s[p[i]];
19
- }
20
- return t;
21
- };
22
- Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.defaultDockerComposeOptions = void 0;
24
- const docker_client_1 = require("../docker/client/docker-client");
25
- const logger_1 = require("../logger");
26
- const os_1 = require("os");
27
- const type_guards_1 = require("../type-guards");
28
- const defaultDockerComposeOptions = (_a) => __awaiter(void 0, void 0, void 0, function* () {
29
- var _b;
30
- var { environment = {} } = _a, options = __rest(_a, ["environment"]);
31
- const { composeEnvironment } = yield (0, docker_client_1.getDockerClient)();
32
- const log = (_b = options.logger) !== null && _b !== void 0 ? _b : logger_1.composeLog;
33
- return {
34
- log: false,
35
- callback: log.enabled()
36
- ? (chunk) => {
37
- chunk
38
- .toString()
39
- .split(os_1.EOL)
40
- .filter(type_guards_1.isNotEmptyString)
41
- .forEach((line) => log.trace(line.trim()));
42
- }
43
- : undefined,
44
- cwd: options.filePath,
45
- config: options.files,
46
- composeOptions: options.composeOptions,
47
- commandOptions: options.commandOptions,
48
- env: Object.assign(Object.assign(Object.assign(Object.assign({}, process.env), { COMPOSE_PROJECT_NAME: options.projectName }), composeEnvironment), environment),
49
- };
50
- });
51
- exports.defaultDockerComposeOptions = defaultDockerComposeOptions;
@@ -1,3 +0,0 @@
1
- import { DockerComposeOptions } from "../docker-compose-options";
2
- import { DockerComposeDownOptions } from "../../test-container";
3
- export declare const dockerComposeDown: (options: DockerComposeOptions, downOptions: DockerComposeDownOptions) => Promise<void>;
@@ -1,39 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.dockerComposeDown = void 0;
13
- const logger_1 = require("../../logger");
14
- const default_docker_compose_options_1 = require("../default-docker-compose-options");
15
- const docker_compose_1 = require("docker-compose");
16
- const dockerComposeDown = (options, downOptions) => __awaiter(void 0, void 0, void 0, function* () {
17
- logger_1.log.info(`Downing DockerCompose environment...`);
18
- try {
19
- yield (0, docker_compose_1.down)(Object.assign(Object.assign({}, (yield (0, default_docker_compose_options_1.defaultDockerComposeOptions)(options))), { commandOptions: commandOptions(downOptions) }));
20
- logger_1.log.info(`Downed DockerCompose environment`);
21
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
- }
23
- catch (err) {
24
- const errorMessage = err.err || err.message || err;
25
- logger_1.log.error(`Failed to down DockerCompose environment: ${errorMessage}`);
26
- throw new Error(errorMessage);
27
- }
28
- });
29
- exports.dockerComposeDown = dockerComposeDown;
30
- const commandOptions = (options) => {
31
- const result = [];
32
- if (options.removeVolumes) {
33
- result.push("-v");
34
- }
35
- if (options.timeout) {
36
- result.push("-t", `${options.timeout / 1000}`);
37
- }
38
- return result;
39
- };
@@ -1,2 +0,0 @@
1
- import { DockerComposeOptions } from "../docker-compose-options";
2
- export declare const dockerComposePull: (options: DockerComposeOptions, services?: Array<string>) => Promise<void>;
@@ -1,35 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.dockerComposePull = void 0;
13
- const logger_1 = require("../../logger");
14
- const docker_compose_1 = require("docker-compose");
15
- const default_docker_compose_options_1 = require("../default-docker-compose-options");
16
- const dockerComposePull = (options, services) => __awaiter(void 0, void 0, void 0, function* () {
17
- try {
18
- if (services) {
19
- logger_1.log.info(`Pulling DockerCompose environment images "${services.join('", "')}"...`);
20
- yield (0, docker_compose_1.pullMany)(services, yield (0, default_docker_compose_options_1.defaultDockerComposeOptions)(Object.assign(Object.assign({}, options), { logger: logger_1.pullLog })));
21
- }
22
- else {
23
- logger_1.log.info(`Pulling DockerCompose environment images...`);
24
- yield (0, docker_compose_1.pullAll)(yield (0, default_docker_compose_options_1.defaultDockerComposeOptions)(Object.assign(Object.assign({}, options), { logger: logger_1.pullLog })));
25
- }
26
- logger_1.log.info(`Pulled DockerCompose environment`);
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
- }
29
- catch (err) {
30
- const errorMessage = err.err || err.message || err || "";
31
- logger_1.log.error(`Failed to pull DockerCompose environment images: ${errorMessage.trim()}`);
32
- throw new Error(errorMessage);
33
- }
34
- });
35
- exports.dockerComposePull = dockerComposePull;
@@ -1,2 +0,0 @@
1
- import { DockerComposeOptions } from "../docker-compose-options";
2
- export declare const dockerComposeStop: (options: DockerComposeOptions) => Promise<void>;
@@ -1,29 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.dockerComposeStop = void 0;
13
- const logger_1 = require("../../logger");
14
- const docker_compose_1 = require("docker-compose");
15
- const default_docker_compose_options_1 = require("../default-docker-compose-options");
16
- const dockerComposeStop = (options) => __awaiter(void 0, void 0, void 0, function* () {
17
- logger_1.log.info(`Stopping DockerCompose environment...`);
18
- try {
19
- yield (0, docker_compose_1.stop)(yield (0, default_docker_compose_options_1.defaultDockerComposeOptions)(options));
20
- logger_1.log.info(`Stopped DockerCompose environment`);
21
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
- }
23
- catch (err) {
24
- const errorMessage = err.err || err.message || err;
25
- logger_1.log.error(`Failed to stop DockerCompose environment: ${errorMessage}`);
26
- throw new Error(errorMessage);
27
- }
28
- });
29
- exports.dockerComposeStop = dockerComposeStop;