Skip to content

Commit 0890956

Browse files
zacajzacaj
andauthored
Add ability to copy archives into containers (#932)
Co-authored-by: zacaj <[email protected]>
1 parent 6f78dcc commit 0890956

File tree

6 files changed

+35
-0
lines changed

6 files changed

+35
-0
lines changed

docs/features/containers.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,10 @@ const container = await new GenericContainer("alpine")
133133
content: "hello world",
134134
target: "/remote/file2.txt"
135135
}])
136+
.withCopyArchivesToContainer([{
137+
tar: nodeReadable,
138+
target: "/some/nested/remotedir"
139+
}])
136140
.start();
137141
```
138142

@@ -153,6 +157,7 @@ container.copyContentToContainer([{
153157
content: "hello world",
154158
target: "/remote/file2.txt"
155159
}])
160+
container.copyArchiveToContainer(nodeReadable, "/some/nested/remotedir");
156161
```
157162

158163
An optional `mode` can be specified in octal for setting file permissions:

packages/testcontainers/src/generic-container/abstract-started-container.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ export class AbstractStartedContainer implements StartedTestContainer {
8383
return this.startedTestContainer.copyContentToContainer(contentsToCopy);
8484
}
8585

86+
public copyArchiveToContainer(tar: Readable, target = "/"): Promise<void> {
87+
return this.startedTestContainer.copyArchiveToContainer(tar, target);
88+
}
89+
8690
public copyArchiveFromContainer(path: string): Promise<NodeJS.ReadableStream> {
8791
return this.startedTestContainer.copyArchiveFromContainer(path);
8892
}

packages/testcontainers/src/generic-container/generic-container.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { PortForwarderInstance, SSHD_IMAGE } from "../port-forwarder/port-forwar
1010
import { getReaper, REAPER_IMAGE } from "../reaper/reaper";
1111
import { StartedTestContainer, TestContainer } from "../test-container";
1212
import {
13+
ArchiveToCopy,
1314
BindMount,
1415
ContentToCopy,
1516
DirectoryToCopy,
@@ -57,6 +58,7 @@ export class GenericContainer implements TestContainer {
5758
protected filesToCopy: FileToCopy[] = [];
5859
protected directoriesToCopy: DirectoryToCopy[] = [];
5960
protected contentsToCopy: ContentToCopy[] = [];
61+
protected archivesToCopy: ArchiveToCopy[] = [];
6062
protected healthCheck?: HealthCheck;
6163

6264
constructor(image: string) {
@@ -180,6 +182,10 @@ export class GenericContainer implements TestContainer {
180182
await client.container.putArchive(container, archive, "/");
181183
}
182184

185+
for (const archive of this.archivesToCopy) {
186+
await client.container.putArchive(container, archive.tar, archive.target);
187+
}
188+
183189
log.info(`Starting container for image "${this.createOpts.Image}"...`, { containerId: container.id });
184190
if (this.containerCreated) {
185191
await this.containerCreated(container.id);
@@ -458,6 +464,11 @@ export class GenericContainer implements TestContainer {
458464
return this;
459465
}
460466

467+
public withCopyArchivesToContainer(archivesToCopy: ArchiveToCopy[]): this {
468+
this.archivesToCopy = [...this.archivesToCopy, ...archivesToCopy];
469+
return this;
470+
}
471+
461472
public withWorkingDir(workingDir: string): this {
462473
this.createOpts.WorkingDir = workingDir;
463474
return this;

packages/testcontainers/src/generic-container/started-generic-container.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,13 @@ export class StartedGenericContainer implements StartedTestContainer {
200200
log.debug(`Copied content to container`, { containerId: this.container.id });
201201
}
202202

203+
public async copyArchiveToContainer(tar: Readable, target = "/"): Promise<void> {
204+
log.debug(`Copying archive to container...`, { containerId: this.container.id });
205+
const client = await getContainerRuntimeClient();
206+
await client.container.putArchive(this.container, tar, target);
207+
log.debug(`Copied archive to container`, { containerId: this.container.id });
208+
}
209+
203210
public async copyArchiveFromContainer(path: string): Promise<NodeJS.ReadableStream> {
204211
log.debug(`Copying archive "${path}" from container...`, { containerId: this.container.id });
205212
const client = await getContainerRuntimeClient();

packages/testcontainers/src/test-container.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Readable } from "stream";
22
import { StartedNetwork } from "./network/network";
33
import {
4+
ArchiveToCopy,
45
BindMount,
56
CommitOptions,
67
ContentToCopy,
@@ -44,6 +45,7 @@ export interface TestContainer {
4445
withCopyFilesToContainer(filesToCopy: FileToCopy[]): this;
4546
withCopyDirectoriesToContainer(directoriesToCopy: DirectoryToCopy[]): this;
4647
withCopyContentToContainer(contentsToCopy: ContentToCopy[]): this;
48+
withCopyArchivesToContainer(archivesToCopy: ArchiveToCopy[]): this;
4749

4850
withWorkingDir(workingDir: string): this;
4951
withResourcesQuota(resourcesQuota: ResourcesQuota): this;
@@ -77,6 +79,7 @@ export interface StartedTestContainer {
7779
getNetworkId(networkName: string): string;
7880
getIpAddress(networkName: string): string;
7981
copyArchiveFromContainer(path: string): Promise<NodeJS.ReadableStream>;
82+
copyArchiveToContainer(tar: Readable, target?: string): Promise<void>;
8083
copyDirectoriesToContainer(directoriesToCopy: DirectoryToCopy[]): Promise<void>;
8184
copyFilesToContainer(filesToCopy: FileToCopy[]): Promise<void>;
8285
copyContentToContainer(contentsToCopy: ContentToCopy[]): Promise<void>;

packages/testcontainers/src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ export type ContentToCopy = {
3939
mode?: number;
4040
};
4141

42+
export type ArchiveToCopy = {
43+
tar: Readable;
44+
target: string;
45+
};
46+
4247
export type TmpFs = { [dir in string]: string };
4348

4449
export type Ulimits = { [name: string]: { hard: number | undefined; soft: number | undefined } };

0 commit comments

Comments
 (0)