testcontainers 9.3.0 → 9.4.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 (59) hide show
  1. package/dist/package.json +17 -17
  2. package/dist/src/docker/docker-client.js +2 -45
  3. package/dist/src/docker/functions/container/exec-container.d.ts +1 -7
  4. package/dist/src/docker/functions/container/exec-container.js +4 -4
  5. package/dist/src/docker/resolve-host.d.ts +6 -0
  6. package/dist/src/docker/resolve-host.js +60 -0
  7. package/dist/src/docker-compose/default-docker-compose-options.js +12 -0
  8. package/dist/src/docker-compose/functions/docker-compose-up.js +2 -2
  9. package/dist/src/docker-compose-environment/docker-compose-environment.d.ts +1 -1
  10. package/dist/src/docker-compose-environment/docker-compose-environment.js +7 -5
  11. package/dist/src/dockerfile-parser.js +2 -1
  12. package/dist/src/generic-container/create-container-options.d.ts +3 -0
  13. package/dist/src/generic-container/create-container-options.js +18 -0
  14. package/dist/src/generic-container/generic-container.d.ts +17 -26
  15. package/dist/src/generic-container/generic-container.js +80 -83
  16. package/dist/src/generic-container/started-generic-container.d.ts +5 -3
  17. package/dist/src/generic-container/started-generic-container.js +13 -6
  18. package/dist/src/index.d.ts +3 -2
  19. package/dist/src/index.js +2 -2
  20. package/dist/src/modules/abstract-started-container.d.ts +2 -0
  21. package/dist/src/modules/abstract-started-container.js +10 -1
  22. package/dist/src/modules/arangodb/arangodb-container.js +1 -1
  23. package/dist/src/modules/elasticsearch/elasticsearch-container.js +7 -1
  24. package/dist/src/modules/kafka/kafka-container.d.ts +2 -3
  25. package/dist/src/modules/kafka/kafka-container.js +8 -8
  26. package/dist/src/modules/mongodb/mongodb-container.d.ts +1 -1
  27. package/dist/src/modules/mongodb/mongodb-container.js +2 -2
  28. package/dist/src/modules/mysql/mysql-container.js +1 -1
  29. package/dist/src/modules/nats/nats-container.js +4 -2
  30. package/dist/src/modules/neo4j/neo4j-container.js +1 -1
  31. package/dist/src/modules/postgresql/postgresql-container.js +2 -2
  32. package/dist/src/port-check.js +1 -1
  33. package/dist/src/reaper.js +1 -1
  34. package/dist/src/test-container.d.ts +1 -1
  35. package/dist/src/type-guards.d.ts +2 -0
  36. package/dist/src/type-guards.js +6 -4
  37. package/dist/src/wait-for-container.d.ts +1 -1
  38. package/dist/src/wait-strategy/default-wait-strategy.d.ts +3 -0
  39. package/dist/src/wait-strategy/default-wait-strategy.js +7 -0
  40. package/dist/src/wait-strategy/health-check-wait-strategy.d.ts +5 -0
  41. package/dist/src/wait-strategy/health-check-wait-strategy.js +31 -0
  42. package/dist/src/wait-strategy/host-port-wait-strategy.d.ts +13 -0
  43. package/dist/src/wait-strategy/host-port-wait-strategy.js +54 -0
  44. package/dist/src/{http-wait-strategy.d.ts → wait-strategy/http-wait-strategy.d.ts} +1 -1
  45. package/dist/src/{http-wait-strategy.js → wait-strategy/http-wait-strategy.js} +1 -1
  46. package/dist/src/wait-strategy/log-wait-strategy.d.ts +10 -0
  47. package/dist/src/wait-strategy/log-wait-strategy.js +67 -0
  48. package/dist/src/wait-strategy/shell-wait-strategy.d.ts +7 -0
  49. package/dist/src/wait-strategy/shell-wait-strategy.js +35 -0
  50. package/dist/src/{startup-check-strategy.js → wait-strategy/startup-check-strategy.js} +2 -2
  51. package/dist/src/wait-strategy/wait-strategy.d.ts +11 -0
  52. package/dist/src/wait-strategy/wait-strategy.js +13 -0
  53. package/dist/src/{wait.d.ts → wait-strategy/wait.d.ts} +4 -1
  54. package/dist/src/wait-strategy/wait.js +22 -0
  55. package/package.json +17 -17
  56. package/dist/src/wait-strategy.d.ts +0 -32
  57. package/dist/src/wait-strategy.js +0 -137
  58. package/dist/src/wait.js +0 -17
  59. /package/dist/src/{startup-check-strategy.d.ts → wait-strategy/startup-check-strategy.d.ts} +0 -0
@@ -20,7 +20,6 @@ const logger_1 = require("../logger");
20
20
  const pull_policy_1 = require("../pull-policy");
21
21
  const reaper_1 = require("../reaper");
22
22
  const docker_image_name_1 = require("../docker-image-name");
23
- const wait_strategy_1 = require("../wait-strategy");
24
23
  const port_forwarder_1 = require("../port-forwarder");
25
24
  const pull_image_1 = require("../docker/functions/image/pull-image");
26
25
  const create_container_1 = require("../docker/functions/container/create-container");
@@ -36,6 +35,8 @@ const hash_1 = require("../hash");
36
35
  const get_container_1 = require("../docker/functions/container/get-container");
37
36
  const labels_1 = require("../labels");
38
37
  const wait_for_container_1 = require("../wait-for-container");
38
+ const create_container_options_1 = require("./create-container-options");
39
+ const default_wait_strategy_1 = require("../wait-strategy/default-wait-strategy");
39
40
  const reusableContainerCreationLock = new async_lock_1.default();
40
41
  class GenericContainer {
41
42
  static fromDockerfile(context, dockerfileName = "Dockerfile") {
@@ -43,66 +44,41 @@ class GenericContainer {
43
44
  }
44
45
  constructor(image) {
45
46
  this.image = image;
46
- this.environment = {};
47
- this.networkAliases = [];
48
- this.ports = [];
49
- this.command = [];
50
- this.bindMounts = [];
51
- this.labels = {};
52
- this.tmpFs = {};
53
47
  this.startupTimeout = 60000;
54
- this.useDefaultLogDriver = false;
55
- this.privilegedMode = false;
48
+ this.networkAliases = [];
56
49
  this.pullPolicy = new pull_policy_1.DefaultPullPolicy();
57
- this.reuse = false;
58
- this.extraHosts = [];
59
- this.imageName = docker_image_name_1.DockerImageName.fromString(image);
50
+ const imageName = docker_image_name_1.DockerImageName.fromString(image);
51
+ this.opts = (0, create_container_options_1.initCreateContainerOptions)(imageName, imageName.isReaper());
60
52
  }
61
53
  start() {
62
54
  return __awaiter(this, void 0, void 0, function* () {
63
55
  const { dockerode, indexServerAddress } = yield (0, docker_client_1.dockerClient)();
64
56
  yield (0, pull_image_1.pullImage)(dockerode, indexServerAddress, {
65
- imageName: this.imageName,
57
+ imageName: this.opts.imageName,
66
58
  force: this.pullPolicy.shouldPull(),
67
59
  });
68
- if (!this.reuse && !this.imageName.isReaper()) {
60
+ if (!this.opts.reusable && !this.opts.imageName.isReaper()) {
69
61
  yield reaper_1.ReaperInstance.getInstance();
70
62
  }
71
- if (this.preStart) {
63
+ if (this.beforeContainerStarted) {
64
+ yield this.beforeContainerStarted();
65
+ }
66
+ else if (this.preStart) {
72
67
  yield this.preStart();
73
68
  }
74
- if (!this.imageName.isHelperContainer() && port_forwarder_1.PortForwarderInstance.isRunning()) {
69
+ if (!this.opts.imageName.isHelperContainer() && port_forwarder_1.PortForwarderInstance.isRunning()) {
75
70
  const portForwarder = yield port_forwarder_1.PortForwarderInstance.getInstance();
76
- this.extraHosts.push({ host: "host.testcontainers.internal", ipAddress: portForwarder.getIpAddress() });
71
+ this.opts.extraHosts.push({ host: "host.testcontainers.internal", ipAddress: portForwarder.getIpAddress() });
77
72
  }
78
- const createContainerOptions = {
79
- imageName: this.imageName,
80
- environment: this.environment,
81
- command: this.command,
82
- entrypoint: this.entrypoint,
83
- bindMounts: this.bindMounts,
84
- tmpFs: this.tmpFs,
85
- exposedPorts: this.ports,
86
- name: this.name,
87
- labels: this.labels,
88
- reusable: this.reuse,
89
- networkMode: this.networkAliases.length > 0 ? undefined : this.networkMode,
90
- healthCheck: this.healthCheck,
91
- useDefaultLogDriver: this.useDefaultLogDriver,
92
- privilegedMode: this.privilegedMode,
93
- autoRemove: this.imageName.isReaper(),
94
- extraHosts: this.extraHosts,
95
- ipcMode: this.ipcMode,
96
- ulimits: this.ulimits,
97
- addedCapabilities: this.addedCapabilities,
98
- droppedCapabilities: this.droppedCapabilities,
99
- user: this.user,
100
- workingDir: this.workingDir,
101
- resourcesQuota: this.resourcesQuota,
102
- };
103
- if (this.reuse) {
104
- const containerHash = (0, hash_1.hash)(JSON.stringify(createContainerOptions));
105
- createContainerOptions.labels = Object.assign(Object.assign({}, createContainerOptions.labels), { [labels_1.LABEL_TESTCONTAINERS_CONTAINER_HASH]: containerHash });
73
+ if (this.networkAliases.length > 0) {
74
+ this.opts.networkMode = undefined;
75
+ }
76
+ else {
77
+ this.opts.networkMode = this.networkMode;
78
+ }
79
+ if (this.opts.reusable) {
80
+ const containerHash = (0, hash_1.hash)(JSON.stringify(this.opts));
81
+ this.opts.labels = Object.assign(Object.assign({}, this.opts.labels), { [labels_1.LABEL_TESTCONTAINERS_CONTAINER_HASH]: containerHash });
106
82
  logger_1.log.debug(`Container reuse has been enabled, hash: ${containerHash}`);
107
83
  // We might have several async processes try to create a reusable container
108
84
  // at once, to avoid possibly creating too many of these, use a lock
@@ -115,31 +91,41 @@ class GenericContainer {
115
91
  }
116
92
  else {
117
93
  logger_1.log.debug("No container found to reuse");
118
- return this.startContainer(createContainerOptions);
94
+ return this.startContainer(this.opts);
119
95
  }
120
96
  }));
121
97
  }
122
98
  else {
123
- return this.startContainer(createContainerOptions);
99
+ return this.startContainer(this.opts);
124
100
  }
125
101
  });
126
102
  }
127
- reuseContainer(startedContainer) {
103
+ reuseContainer(container) {
128
104
  var _a;
129
105
  return __awaiter(this, void 0, void 0, function* () {
130
106
  const { host, hostIps } = yield (0, docker_client_1.dockerClient)();
131
- const inspectResult = yield (0, inspect_container_1.inspectContainer)(startedContainer);
132
- const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, inspectResult).filter(this.ports);
133
- const waitStrategy = ((_a = this.waitStrategy) !== null && _a !== void 0 ? _a : (0, wait_strategy_1.defaultWaitStrategy)(host, startedContainer)).withStartupTimeout(this.startupTimeout);
134
- yield (0, wait_for_container_1.waitForContainer)(startedContainer, waitStrategy, host, boundPorts);
135
- return new started_generic_container_1.StartedGenericContainer(startedContainer, host, inspectResult, boundPorts, inspectResult.name, waitStrategy);
107
+ const inspectResult = yield (0, inspect_container_1.inspectContainer)(container);
108
+ const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, inspectResult).filter(this.opts.exposedPorts);
109
+ const waitStrategy = ((_a = this.waitStrategy) !== null && _a !== void 0 ? _a : (0, default_wait_strategy_1.defaultWaitStrategy)(host, container)).withStartupTimeout(this.startupTimeout);
110
+ if (this.containerStarting) {
111
+ yield this.containerStarting(inspectResult, true);
112
+ }
113
+ yield (0, wait_for_container_1.waitForContainer)(container, waitStrategy, host, boundPorts);
114
+ const startedContainer = new started_generic_container_1.StartedGenericContainer(container, host, inspectResult, boundPorts, inspectResult.name, waitStrategy);
115
+ if (this.containerStarted) {
116
+ yield this.containerStarted(startedContainer, inspectResult, true);
117
+ }
118
+ else if (this.postStart) {
119
+ yield this.postStart(startedContainer, inspectResult, boundPorts);
120
+ }
121
+ return startedContainer;
136
122
  });
137
123
  }
138
124
  startContainer(createContainerOptions) {
139
125
  var _a;
140
126
  return __awaiter(this, void 0, void 0, function* () {
141
127
  const container = yield (0, create_container_1.createContainer)(createContainerOptions);
142
- if (!this.imageName.isHelperContainer() && port_forwarder_1.PortForwarderInstance.isRunning()) {
128
+ if (!this.opts.imageName.isHelperContainer() && port_forwarder_1.PortForwarderInstance.isRunning()) {
143
129
  const portForwarder = yield port_forwarder_1.PortForwarderInstance.getInstance();
144
130
  const portForwarderNetworkId = portForwarder.getNetworkId();
145
131
  const excludedNetworks = [portForwarderNetworkId, "none", "host"];
@@ -162,62 +148,73 @@ class GenericContainer {
162
148
  this.tarToCopy.finalize();
163
149
  yield (0, put_container_archive_1.putContainerArchive)({ container, stream: this.tarToCopy, containerPath: "/" });
164
150
  }
165
- logger_1.log.info(`Starting container ${this.imageName} with ID: ${container.id}`);
151
+ logger_1.log.info(`Starting container ${this.opts.imageName} with ID: ${container.id}`);
152
+ if (this.containerCreated) {
153
+ yield this.containerCreated(container.id);
154
+ }
166
155
  yield (0, start_container_1.startContainer)(container);
167
156
  const { host, hostIps } = yield (0, docker_client_1.dockerClient)();
168
157
  const inspectResult = yield (0, inspect_container_1.inspectContainer)(container);
169
- const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, inspectResult).filter(this.ports);
170
- const waitStrategy = ((_a = this.waitStrategy) !== null && _a !== void 0 ? _a : (0, wait_strategy_1.defaultWaitStrategy)(host, container)).withStartupTimeout(this.startupTimeout);
171
- (yield (0, container_logs_1.containerLogs)(container))
172
- .on("data", (data) => logger_1.containerLog.trace(`${container.id}: ${data.trim()}`))
173
- .on("err", (data) => logger_1.containerLog.error(`${container.id}: ${data.trim()}`));
158
+ const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, inspectResult).filter(this.opts.exposedPorts);
159
+ const waitStrategy = ((_a = this.waitStrategy) !== null && _a !== void 0 ? _a : (0, default_wait_strategy_1.defaultWaitStrategy)(host, container)).withStartupTimeout(this.startupTimeout);
160
+ if (logger_1.containerLog.enabled()) {
161
+ (yield (0, container_logs_1.containerLogs)(container))
162
+ .on("data", (data) => logger_1.containerLog.trace(`${container.id}: ${data.trim()}`))
163
+ .on("err", (data) => logger_1.containerLog.error(`${container.id}: ${data.trim()}`));
164
+ }
165
+ if (this.containerStarting) {
166
+ yield this.containerStarting(inspectResult, false);
167
+ }
174
168
  yield (0, wait_for_container_1.waitForContainer)(container, waitStrategy, host, boundPorts);
175
169
  const startedContainer = new started_generic_container_1.StartedGenericContainer(container, host, inspectResult, boundPorts, inspectResult.name, waitStrategy);
176
- if (this.postStart) {
170
+ if (this.containerStarted) {
171
+ yield this.containerStarted(startedContainer, inspectResult, false);
172
+ }
173
+ else if (this.postStart) {
177
174
  yield this.postStart(startedContainer, inspectResult, boundPorts);
178
175
  }
179
176
  return startedContainer;
180
177
  });
181
178
  }
182
179
  get hasExposedPorts() {
183
- return this.ports.length !== 0;
180
+ return this.opts.exposedPorts.length !== 0;
184
181
  }
185
182
  withCommand(command) {
186
- this.command = command;
183
+ this.opts.command = command;
187
184
  return this;
188
185
  }
189
186
  withEntrypoint(entrypoint) {
190
- this.entrypoint = entrypoint;
187
+ this.opts.entrypoint = entrypoint;
191
188
  return this;
192
189
  }
193
190
  withName(name) {
194
- this.name = name;
191
+ this.opts.name = name;
195
192
  return this;
196
193
  }
197
194
  withLabels(labels) {
198
- this.labels = Object.assign(Object.assign({}, this.labels), labels);
195
+ this.opts.labels = Object.assign(Object.assign({}, this.opts.labels), labels);
199
196
  return this;
200
197
  }
201
198
  withEnvironment(environment) {
202
- this.environment = Object.assign(Object.assign({}, this.environment), environment);
199
+ this.opts.environment = Object.assign(Object.assign({}, this.opts.environment), environment);
203
200
  return this;
204
201
  }
205
202
  withTmpFs(tmpFs) {
206
- this.tmpFs = Object.assign(Object.assign({}, this.tmpFs), tmpFs);
203
+ this.opts.tmpFs = Object.assign(Object.assign({}, this.opts.tmpFs), tmpFs);
207
204
  return this;
208
205
  }
209
206
  withUlimits(ulimits) {
210
- this.ulimits = Object.assign(Object.assign({}, this.ulimits), ulimits);
207
+ this.opts.ulimits = Object.assign(Object.assign({}, this.opts.ulimits), ulimits);
211
208
  return this;
212
209
  }
213
210
  withAddedCapabilities(...capabilities) {
214
211
  var _a;
215
- this.addedCapabilities = [...((_a = this.addedCapabilities) !== null && _a !== void 0 ? _a : []), ...capabilities];
212
+ this.opts.addedCapabilities = [...((_a = this.opts.addedCapabilities) !== null && _a !== void 0 ? _a : []), ...capabilities];
216
213
  return this;
217
214
  }
218
215
  withDroppedCapabilities(...capabilities) {
219
216
  var _a;
220
- this.droppedCapabilities = [...((_a = this.droppedCapabilities) !== null && _a !== void 0 ? _a : []), ...capabilities];
217
+ this.opts.droppedCapabilities = [...((_a = this.opts.droppedCapabilities) !== null && _a !== void 0 ? _a : []), ...capabilities];
221
218
  return this;
222
219
  }
223
220
  withNetwork(network) {
@@ -233,19 +230,19 @@ class GenericContainer {
233
230
  return this;
234
231
  }
235
232
  withExtraHosts(extraHosts) {
236
- this.extraHosts = [...this.extraHosts, ...extraHosts];
233
+ this.opts.extraHosts = [...this.opts.extraHosts, ...extraHosts];
237
234
  return this;
238
235
  }
239
236
  withExposedPorts(...ports) {
240
- this.ports = [...this.ports, ...ports];
237
+ this.opts.exposedPorts = [...this.opts.exposedPorts, ...ports];
241
238
  return this;
242
239
  }
243
240
  withBindMounts(bindMounts) {
244
- this.bindMounts = bindMounts.map((bindMount) => (Object.assign({ mode: "rw" }, bindMount)));
241
+ this.opts.bindMounts = bindMounts.map((bindMount) => (Object.assign({ mode: "rw" }, bindMount)));
245
242
  return this;
246
243
  }
247
244
  withHealthCheck(healthCheck) {
248
- this.healthCheck = healthCheck;
245
+ this.opts.healthCheck = healthCheck;
249
246
  return this;
250
247
  }
251
248
  withStartupTimeout(startupTimeoutMs) {
@@ -257,19 +254,19 @@ class GenericContainer {
257
254
  return this;
258
255
  }
259
256
  withDefaultLogDriver() {
260
- this.useDefaultLogDriver = true;
257
+ this.opts.useDefaultLogDriver = true;
261
258
  return this;
262
259
  }
263
260
  withPrivilegedMode() {
264
- this.privilegedMode = true;
261
+ this.opts.privilegedMode = true;
265
262
  return this;
266
263
  }
267
264
  withUser(user) {
268
- this.user = user;
265
+ this.opts.user = user;
269
266
  return this;
270
267
  }
271
268
  withReuse() {
272
- this.reuse = true;
269
+ this.opts.reusable = true;
273
270
  return this;
274
271
  }
275
272
  withPullPolicy(pullPolicy) {
@@ -277,7 +274,7 @@ class GenericContainer {
277
274
  return this;
278
275
  }
279
276
  withIpcMode(ipcMode) {
280
- this.ipcMode = ipcMode;
277
+ this.opts.ipcMode = ipcMode;
281
278
  return this;
282
279
  }
283
280
  withCopyFilesToContainer(filesToCopy) {
@@ -297,7 +294,7 @@ class GenericContainer {
297
294
  return this.tarToCopy;
298
295
  }
299
296
  withWorkingDir(workingDir) {
300
- this.workingDir = workingDir;
297
+ this.opts.workingDir = workingDir;
301
298
  return this;
302
299
  }
303
300
  withResourcesQuota({ memory, cpu }) {
@@ -305,7 +302,7 @@ class GenericContainer {
305
302
  // see Memory, NanoCpus parameters
306
303
  const ram = memory !== undefined ? memory * Math.pow(1024, 3) : undefined;
307
304
  const cpuQuota = cpu !== undefined ? cpu * Math.pow(10, 9) : undefined;
308
- this.resourcesQuota = { memory: ram, cpu: cpuQuota };
305
+ this.opts.resourcesQuota = { memory: ram, cpu: cpuQuota };
309
306
  return this;
310
307
  }
311
308
  }
@@ -1,11 +1,11 @@
1
1
  /// <reference types="node" />
2
- import { ExecOptions, RestartOptions, StartedTestContainer, StopOptions, StoppedTestContainer } from "../test-container";
2
+ import { RestartOptions, StartedTestContainer, StopOptions, StoppedTestContainer } from "../test-container";
3
3
  import Dockerode from "dockerode";
4
4
  import { ExecResult, Labels } from "../docker/types";
5
5
  import { InspectResult } from "../docker/functions/container/inspect-container";
6
6
  import { BoundPorts } from "../bound-ports";
7
7
  import { Readable } from "stream";
8
- import { WaitStrategy } from "../wait-strategy";
8
+ import { WaitStrategy } from "../wait-strategy/wait-strategy";
9
9
  export declare class StartedGenericContainer implements StartedTestContainer {
10
10
  private readonly container;
11
11
  private readonly host;
@@ -14,7 +14,9 @@ export declare class StartedGenericContainer implements StartedTestContainer {
14
14
  private readonly name;
15
15
  private readonly waitStrategy;
16
16
  constructor(container: Dockerode.Container, host: string, inspectResult: InspectResult, boundPorts: BoundPorts, name: string, waitStrategy: WaitStrategy);
17
+ protected containerIsStopping?(): Promise<void>;
17
18
  stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;
19
+ protected containerIsStopped?(): Promise<void>;
18
20
  restart(options?: Partial<RestartOptions>): Promise<void>;
19
21
  private stopContainer;
20
22
  getHost(): string;
@@ -26,6 +28,6 @@ export declare class StartedGenericContainer implements StartedTestContainer {
26
28
  getNetworkNames(): string[];
27
29
  getNetworkId(networkName: string): string;
28
30
  getIpAddress(networkName: string): string;
29
- exec(command: string[], options?: Partial<ExecOptions>): Promise<ExecResult>;
31
+ exec(command: string[]): Promise<ExecResult>;
30
32
  logs(): Promise<Readable>;
31
33
  }
@@ -43,9 +43,11 @@ class StartedGenericContainer {
43
43
  const { hostIps } = yield (0, docker_client_1.dockerClient)();
44
44
  this.inspectResult = yield (0, inspect_container_1.inspectContainer)(this.container);
45
45
  const startTime = this.inspectResult.state.startedAt;
46
- (yield (0, container_logs_1.containerLogs)(this.container, { since: startTime }))
47
- .on("data", (data) => logger_1.containerLog.trace(`${this.container.id}: ${data.trim()}`))
48
- .on("err", (data) => logger_1.containerLog.error(`${this.container.id}: ${data.trim()}`));
46
+ if (logger_1.containerLog.enabled()) {
47
+ (yield (0, container_logs_1.containerLogs)(this.container, { since: startTime }))
48
+ .on("data", (data) => logger_1.containerLog.trace(`${this.container.id}: ${data.trim()}`))
49
+ .on("err", (data) => logger_1.containerLog.error(`${this.container.id}: ${data.trim()}`));
50
+ }
49
51
  this.boundPorts = bound_ports_1.BoundPorts.fromInspectResult(hostIps, this.inspectResult).filter(Array.from(this.boundPorts.iterator()).map((port) => port[0]));
50
52
  yield (0, wait_for_container_1.waitForContainer)(this.container, this.waitStrategy, this.host, this.boundPorts, startTime);
51
53
  });
@@ -53,9 +55,15 @@ class StartedGenericContainer {
53
55
  stopContainer(options = {}) {
54
56
  return __awaiter(this, void 0, void 0, function* () {
55
57
  logger_1.log.info(`Stopping container with ID: ${this.container.id}`);
58
+ if (this.containerIsStopping) {
59
+ yield this.containerIsStopping();
60
+ }
56
61
  const resolvedOptions = Object.assign({ timeout: 0, removeVolumes: true }, options);
57
62
  yield (0, stop_container_1.stopContainer)(this.container, { timeout: resolvedOptions.timeout });
58
63
  yield (0, remove_container_1.removeContainer)(this.container, { removeVolumes: resolvedOptions.removeVolumes });
64
+ if (this.containerIsStopped) {
65
+ yield this.containerIsStopped();
66
+ }
59
67
  return new stopped_generic_container_1.StoppedGenericContainer();
60
68
  });
61
69
  }
@@ -86,9 +94,8 @@ class StartedGenericContainer {
86
94
  getIpAddress(networkName) {
87
95
  return this.inspectResult.networkSettings[networkName].ipAddress;
88
96
  }
89
- exec(command, options = {}) {
90
- const resolvedOptions = Object.assign({ stdin: true, detach: false, tty: true }, options);
91
- return (0, exec_container_1.execContainer)(this.container, command, resolvedOptions);
97
+ exec(command) {
98
+ return (0, exec_container_1.execContainer)(this.container, command);
92
99
  }
93
100
  logs() {
94
101
  return (0, container_logs_1.containerLogs)(this.container);
@@ -7,9 +7,10 @@ export { StartedDockerComposeEnvironment } from "./docker-compose-environment/st
7
7
  export { StoppedDockerComposeEnvironment } from "./docker-compose-environment/stopped-docker-compose-environment";
8
8
  export { DownedDockerComposeEnvironment } from "./docker-compose-environment/downed-docker-compose-environment";
9
9
  export { Network, StartedNetwork, StoppedNetwork } from "./network";
10
- export { Wait } from "./wait";
11
- export { StartupCheckStrategy, StartupStatus } from "./startup-check-strategy";
10
+ export { Wait } from "./wait-strategy/wait";
11
+ export { StartupCheckStrategy, StartupStatus } from "./wait-strategy/startup-check-strategy";
12
12
  export { PullPolicy, DefaultPullPolicy, AlwaysPullPolicy } from "./pull-policy";
13
+ export { InspectResult } from "./docker/functions/container/inspect-container";
13
14
  export { AbstractStartedContainer } from "./modules/abstract-started-container";
14
15
  export { PostgreSqlContainer, StartedPostgreSqlContainer } from "./modules/postgresql/postgresql-container";
15
16
  export { KafkaContainer, StartedKafkaContainer } from "./modules/kafka/kafka-container";
package/dist/src/index.js CHANGED
@@ -19,9 +19,9 @@ var network_1 = require("./network");
19
19
  Object.defineProperty(exports, "Network", { enumerable: true, get: function () { return network_1.Network; } });
20
20
  Object.defineProperty(exports, "StartedNetwork", { enumerable: true, get: function () { return network_1.StartedNetwork; } });
21
21
  Object.defineProperty(exports, "StoppedNetwork", { enumerable: true, get: function () { return network_1.StoppedNetwork; } });
22
- var wait_1 = require("./wait");
22
+ var wait_1 = require("./wait-strategy/wait");
23
23
  Object.defineProperty(exports, "Wait", { enumerable: true, get: function () { return wait_1.Wait; } });
24
- var startup_check_strategy_1 = require("./startup-check-strategy");
24
+ var startup_check_strategy_1 = require("./wait-strategy/startup-check-strategy");
25
25
  Object.defineProperty(exports, "StartupCheckStrategy", { enumerable: true, get: function () { return startup_check_strategy_1.StartupCheckStrategy; } });
26
26
  var pull_policy_1 = require("./pull-policy");
27
27
  Object.defineProperty(exports, "DefaultPullPolicy", { enumerable: true, get: function () { return pull_policy_1.DefaultPullPolicy; } });
@@ -5,7 +5,9 @@ import { Readable } from "stream";
5
5
  export declare class AbstractStartedContainer implements StartedTestContainer {
6
6
  protected readonly startedTestContainer: StartedTestContainer;
7
7
  constructor(startedTestContainer: StartedTestContainer);
8
+ protected containerStopping?(): Promise<void>;
8
9
  stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;
10
+ protected containerStopped?(): Promise<void>;
9
11
  restart(options?: Partial<RestartOptions>): Promise<void>;
10
12
  getHost(): string;
11
13
  getFirstMappedPort(): number;
@@ -15,7 +15,16 @@ class AbstractStartedContainer {
15
15
  this.startedTestContainer = startedTestContainer;
16
16
  }
17
17
  stop(options) {
18
- return this.startedTestContainer.stop(options);
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ if (this.containerStopping) {
20
+ yield this.containerStopping();
21
+ }
22
+ const stoppedContainer = this.startedTestContainer.stop(options);
23
+ if (this.containerStopped) {
24
+ yield this.containerStopped();
25
+ }
26
+ return stoppedContainer;
27
+ });
19
28
  }
20
29
  restart(options) {
21
30
  return __awaiter(this, void 0, void 0, function* () {
@@ -28,7 +28,7 @@ class ArangoDBContainer extends __1.GenericContainer {
28
28
  start: { get: () => super.start }
29
29
  });
30
30
  return __awaiter(this, void 0, void 0, function* () {
31
- this.withExposedPorts(...(this.hasExposedPorts ? this.ports : [ARANGODB_PORT]))
31
+ this.withExposedPorts(...(this.hasExposedPorts ? this.opts.exposedPorts : [ARANGODB_PORT]))
32
32
  .withWaitStrategy(__1.Wait.forLogMessage("Have fun!"))
33
33
  .withEnvironment({ ARANGO_ROOT_PASSWORD: this.password })
34
34
  .withStartupTimeout(120000);
@@ -22,8 +22,14 @@ class ElasticsearchContainer extends __1.GenericContainer {
22
22
  start: { get: () => super.start }
23
23
  });
24
24
  return __awaiter(this, void 0, void 0, function* () {
25
- this.withExposedPorts(...(this.hasExposedPorts ? this.ports : [ELASTIC_SEARCH_HTTP_PORT]))
25
+ this.withExposedPorts(...(this.hasExposedPorts ? this.opts.exposedPorts : [ELASTIC_SEARCH_HTTP_PORT]))
26
26
  .withEnvironment({ "discovery.type": "single-node" })
27
+ .withCopyContentToContainer([
28
+ {
29
+ content: "-Xms2G\n-Xmx2G\n",
30
+ target: "/usr/share/elasticsearch/config/jvm.options.d/elasticsearch-default-memory-vm.options",
31
+ },
32
+ ])
27
33
  .withStartupTimeout(120000);
28
34
  return new StartedElasticsearchContainer(yield _super.start.call(this));
29
35
  });
@@ -1,5 +1,4 @@
1
1
  import { GenericContainer } from "../../generic-container/generic-container";
2
- import { BoundPorts } from "../../bound-ports";
3
2
  import { StartedTestContainer } from "../..";
4
3
  import { AbstractStartedContainer } from "../abstract-started-container";
5
4
  import { InspectResult } from "../../docker/functions/container/inspect-container";
@@ -32,9 +31,9 @@ export declare class KafkaContainer extends GenericContainer {
32
31
  constructor(image?: string);
33
32
  withZooKeeper(host: string, port: number): this;
34
33
  withSaslSslListener(options: SaslSslListenerOptions): this;
35
- protected preStart(): Promise<void>;
34
+ protected beforeContainerStarted(): Promise<void>;
36
35
  start(): Promise<StartedKafkaContainer>;
37
- protected postStart(container: StartedTestContainer, inspectResult: InspectResult, boundPorts: BoundPorts): Promise<void>;
36
+ protected containerStarted(container: StartedTestContainer, inspectResult: InspectResult): Promise<void>;
38
37
  private addPlaintextAndSecureListener;
39
38
  private addPlaintextListener;
40
39
  private updateAdvertisedListeners;
@@ -44,7 +44,7 @@ class KafkaContainer extends generic_container_1.GenericContainer {
44
44
  this.saslSslConfig = options;
45
45
  return this;
46
46
  }
47
- preStart() {
47
+ beforeContainerStarted() {
48
48
  return __awaiter(this, void 0, void 0, function* () {
49
49
  const network = this.networkMode && this.networkAliases.length > 0 ? this.networkAliases[0] : "localhost";
50
50
  this.withEnvironment({ KAFKA_ADVERTISED_LISTENERS: `BROKER://${network}:${KAFKA_BROKER_PORT}` });
@@ -81,9 +81,9 @@ class KafkaContainer extends generic_container_1.GenericContainer {
81
81
  return new StartedKafkaContainer(yield _super.start.call(this));
82
82
  });
83
83
  }
84
- postStart(container, inspectResult, boundPorts) {
84
+ containerStarted(container, inspectResult) {
85
85
  return __awaiter(this, void 0, void 0, function* () {
86
- yield this.updateAdvertisedListeners(container, inspectResult, boundPorts);
86
+ yield this.updateAdvertisedListeners(container, inspectResult);
87
87
  if (this.saslSslConfig) {
88
88
  yield this.createUser(container, this.saslSslConfig.sasl);
89
89
  }
@@ -117,12 +117,12 @@ class KafkaContainer extends generic_container_1.GenericContainer {
117
117
  KAFKA_LISTENERS: `PLAINTEXT://0.0.0.0:${KAFKA_PORT},BROKER://0.0.0.0:${KAFKA_BROKER_PORT}`,
118
118
  }).withExposedPorts(KAFKA_PORT);
119
119
  }
120
- updateAdvertisedListeners(container, inspectResult, boundPorts) {
120
+ updateAdvertisedListeners(container, inspectResult) {
121
121
  return __awaiter(this, void 0, void 0, function* () {
122
122
  const brokerAdvertisedListener = `BROKER://${inspectResult.hostname}:${KAFKA_BROKER_PORT}`;
123
- let bootstrapServers = `PLAINTEXT://${container.getHost()}:${boundPorts.getBinding(KAFKA_PORT)}`;
123
+ let bootstrapServers = `PLAINTEXT://${container.getHost()}:${container.getMappedPort(KAFKA_PORT)}`;
124
124
  if (this.saslSslConfig) {
125
- bootstrapServers = `${bootstrapServers},SECURE://${container.getHost()}:${boundPorts.getBinding(this.saslSslConfig.port)}`;
125
+ bootstrapServers = `${bootstrapServers},SECURE://${container.getHost()}:${container.getMappedPort(this.saslSslConfig.port)}`;
126
126
  }
127
127
  const { output, exitCode } = yield container.exec([
128
128
  "kafka-configs",
@@ -132,7 +132,7 @@ class KafkaContainer extends generic_container_1.GenericContainer {
132
132
  "--entity-type",
133
133
  "brokers",
134
134
  "--entity-name",
135
- this.environment["KAFKA_BROKER_ID"],
135
+ this.opts.environment["KAFKA_BROKER_ID"],
136
136
  "--add-config",
137
137
  `advertised.listeners=[${bootstrapServers},${brokerAdvertisedListener}]`,
138
138
  ]);
@@ -149,7 +149,7 @@ class KafkaContainer extends generic_container_1.GenericContainer {
149
149
  // At the time of writing kafka-configs displays a warning stating that the 'zookeeper' flag is deprecated in favor of 'bootstrap-server'.
150
150
  // Unfortunately, 'bootstrap-server' can only be used to set quotas and not to create a user.
151
151
  "--zookeeper",
152
- this.environment["KAFKA_ZOOKEEPER_CONNECT"],
152
+ this.opts.environment["KAFKA_ZOOKEEPER_CONNECT"],
153
153
  "--entity-type",
154
154
  "users",
155
155
  "--entity-name",
@@ -5,7 +5,7 @@ export declare class MongoDBContainer extends GenericContainer {
5
5
  private readonly dockerImageName;
6
6
  constructor(image?: string);
7
7
  start(): Promise<StartedMongoDBContainer>;
8
- protected postStart(startedTestContainer: StartedTestContainer): Promise<void>;
8
+ protected containerStarted(startedTestContainer: StartedTestContainer): Promise<void>;
9
9
  private initReplicaSet;
10
10
  private executeMongoEvalCommand;
11
11
  private buildMongoEvalCommand;
@@ -12,7 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.StartedMongoDBContainer = exports.MongoDBContainer = void 0;
13
13
  const generic_container_1 = require("../../generic-container/generic-container");
14
14
  const abstract_started_container_1 = require("../abstract-started-container");
15
- const wait_1 = require("../../wait");
15
+ const wait_1 = require("../../wait-strategy/wait");
16
16
  const docker_image_name_1 = require("../../docker-image-name");
17
17
  const MONGODB_PORT = 27017;
18
18
  class MongoDBContainer extends generic_container_1.GenericContainer {
@@ -32,7 +32,7 @@ class MongoDBContainer extends generic_container_1.GenericContainer {
32
32
  return new StartedMongoDBContainer(yield _super.start.call(this));
33
33
  });
34
34
  }
35
- postStart(startedTestContainer) {
35
+ containerStarted(startedTestContainer) {
36
36
  return __awaiter(this, void 0, void 0, function* () {
37
37
  yield this.initReplicaSet(startedTestContainer);
38
38
  });
@@ -42,7 +42,7 @@ class MySqlContainer extends generic_container_1.GenericContainer {
42
42
  start: { get: () => super.start }
43
43
  });
44
44
  return __awaiter(this, void 0, void 0, function* () {
45
- this.withExposedPorts(...(this.hasExposedPorts ? this.ports : [MYSQL_PORT]))
45
+ this.withExposedPorts(...(this.hasExposedPorts ? this.opts.exposedPorts : [MYSQL_PORT]))
46
46
  .withEnvironment({
47
47
  MYSQL_DATABASE: this.database,
48
48
  MYSQL_ROOT_PASSWORD: this.rootPassword,
@@ -12,7 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.StartedNatsContainer = exports.NatsContainer = void 0;
13
13
  const generic_container_1 = require("../../generic-container/generic-container");
14
14
  const abstract_started_container_1 = require("../abstract-started-container");
15
- const wait_1 = require("../../wait");
15
+ const wait_1 = require("../../wait-strategy/wait");
16
16
  const CLIENT_PORT = 4222;
17
17
  const ROUTING_PORT_FOR_CLUSTERING = 6222;
18
18
  const HTTP_MANAGEMENT_PORT = 8222;
@@ -64,7 +64,9 @@ class NatsContainer extends generic_container_1.GenericContainer {
64
64
  return result;
65
65
  }
66
66
  this.withCommand(buildCmdsFromArgs(this.args))
67
- .withExposedPorts(...(this.hasExposedPorts ? this.ports : [CLIENT_PORT, ROUTING_PORT_FOR_CLUSTERING, HTTP_MANAGEMENT_PORT]))
67
+ .withExposedPorts(...(this.hasExposedPorts
68
+ ? this.opts.exposedPorts
69
+ : [CLIENT_PORT, ROUTING_PORT_FOR_CLUSTERING, HTTP_MANAGEMENT_PORT]))
68
70
  .withWaitStrategy(wait_1.Wait.forLogMessage(/.*Server is ready.*/))
69
71
  .withStartupTimeout(120000);
70
72
  return new StartedNatsContainer(yield _super.start.call(this), this.getUser(), this.getPass());
@@ -38,7 +38,7 @@ class Neo4jContainer extends __1.GenericContainer {
38
38
  start: { get: () => super.start }
39
39
  });
40
40
  return __awaiter(this, void 0, void 0, function* () {
41
- this.withExposedPorts(...(this.hasExposedPorts ? this.ports : [BOLT_PORT, HTTP_PORT]))
41
+ this.withExposedPorts(...(this.hasExposedPorts ? this.opts.exposedPorts : [BOLT_PORT, HTTP_PORT]))
42
42
  .withWaitStrategy(__1.Wait.forLogMessage("Started."))
43
43
  .withEnvironment({ NEO4J_AUTH: `${USERNAME}/${this.password}` })
44
44
  .withStartupTimeout(120000);