Skip to content

Commit 1f68067

Browse files
authored
Add Etcd module (#1004)
1 parent e25eb33 commit 1f68067

File tree

9 files changed

+233
-8
lines changed

9 files changed

+233
-8
lines changed

docs/modules/etcd.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Etcd Module
2+
3+
[Etcd](https://etcd.io/) is a strongly consistent, distributed key-value store that provides a reliable way to store data that needs to be accessed by a distributed system or cluster of machines.
4+
5+
## Install
6+
7+
```bash
8+
npm install @testcontainers/etcd --save-dev
9+
```
10+
11+
## Examples
12+
13+
<!--codeinclude-->
14+
[Read and write key-value pairs:](../../packages/modules/etcd/src/etcd-container.test.ts) inside_block:readWrite
15+
<!--/codeinclude-->
16+
17+
<!--codeinclude-->
18+
[Subscribe to key changes:](../../packages/modules/etcd/src/etcd-container.test.ts) inside_block:subscribe
19+
<!--/codeinclude-->

mkdocs.yml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
site_name: Testcontainers for NodeJS
22
site_url: https://node.testcontainers.org
3-
repo_name: 'testcontainers-node'
4-
repo_url: 'https://github.com/testcontainers/testcontainers-node'
3+
repo_name: "testcontainers-node"
4+
repo_url: "https://github.com/testcontainers/testcontainers-node"
55
edit_uri: edit/main/docs/
66

77
theme:
8-
name: 'material'
9-
custom_dir: 'docs/site/theme'
8+
name: "material"
9+
custom_dir: "docs/site/theme"
1010
palette:
1111
scheme: testcontainers
1212
font:
1313
text: Roboto
1414
code: Roboto Mono
15-
logo: 'site/logo.svg'
16-
favicon: 'site/favicon.ico'
15+
logo: "site/logo.svg"
16+
favicon: "site/favicon.ico"
1717

1818
extra_css:
19-
- 'site/css/extra.css'
20-
- 'site/css/tc-header.css'
19+
- "site/css/extra.css"
20+
- "site/css/tc-header.css"
2121

2222
plugins:
2323
- search
@@ -56,6 +56,7 @@ nav:
5656
- Couchbase: modules/couchbase.md
5757
- CockroachDB: modules/cockroachdb.md
5858
- Elasticsearch: modules/elasticsearch.md
59+
- Etcd: modules/etcd.md
5960
- EventStoreDB: modules/eventstoredb.md
6061
- GCloud: modules/gcloud.md
6162
- HiveMQ: modules/hivemq.md

package-lock.json

Lines changed: 41 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/modules/etcd/package.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "@testcontainers/etcd",
3+
"version": "10.21.0",
4+
"license": "MIT",
5+
"keywords": [
6+
"etcd",
7+
"etcd3",
8+
"testing",
9+
"docker",
10+
"testcontainers"
11+
],
12+
"description": "Etcd module for Testcontainers",
13+
"homepage": "https://github.com/testcontainers/testcontainers-node#readme",
14+
"repository": {
15+
"type": "git",
16+
"url": "https://github.com/testcontainers/testcontainers-node"
17+
},
18+
"bugs": {
19+
"url": "https://github.com/testcontainers/testcontainers-node/issues"
20+
},
21+
"main": "build/index.js",
22+
"files": [
23+
"build"
24+
],
25+
"publishConfig": {
26+
"access": "public"
27+
},
28+
"scripts": {
29+
"prepack": "shx cp ../../../README.md . && shx cp ../../../LICENSE .",
30+
"build": "tsc --project tsconfig.build.json"
31+
},
32+
"devDependencies": {
33+
"etcd3": "^1.1.2"
34+
},
35+
"dependencies": {
36+
"testcontainers": "^10.26.0"
37+
}
38+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { Etcd3 } from "etcd3";
2+
import { setTimeout } from "node:timers/promises";
3+
import { EtcdContainer, StartedEtcdContainer } from "./etcd-container";
4+
5+
describe("etcd", () => {
6+
it("should construct a container", { timeout: 30_000 }, async () => {
7+
const container = await new EtcdContainer().start();
8+
expect(container).toBeInstanceOf(StartedEtcdContainer);
9+
container.stop();
10+
});
11+
12+
// readWrite {
13+
it("should connect and perform read/write operations", async () => {
14+
const container = await new EtcdContainer().start();
15+
const client = new Etcd3({
16+
hosts: container.getClientEndpoint(),
17+
});
18+
const key = "foo";
19+
const value = "bar";
20+
21+
await client.put(key).value(value);
22+
const result = await client.get(key).string();
23+
expect(result).toEqual(value);
24+
25+
await container.stop();
26+
});
27+
// }
28+
29+
// subscribe {
30+
it("should subscribe to key changes", async () => {
31+
const subscriber = vi.fn();
32+
const container = await new EtcdContainer().start();
33+
const client = new Etcd3({
34+
hosts: container.getClientEndpoint(),
35+
});
36+
const key = "foo";
37+
const value = "bar";
38+
const watcher = await client.watch().key(key).create();
39+
watcher.on("put", subscriber);
40+
await client.put(key).value(value);
41+
await setTimeout(1_000);
42+
expect(subscriber).toHaveBeenCalled();
43+
await watcher.cancel();
44+
await container.stop();
45+
});
46+
// }
47+
});
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { AbstractStartedContainer, GenericContainer, Wait } from "testcontainers";
2+
3+
const ETCD_CLIENT_PORT = 2379;
4+
const ETCD_PEER_PORT = 2380;
5+
6+
export class EtcdContainer extends GenericContainer {
7+
constructor(image = "quay.io/coreos/etcd:v3.6.0", nodeName = "etcd-test") {
8+
super(image);
9+
this.withExposedPorts(ETCD_CLIENT_PORT, ETCD_PEER_PORT)
10+
.withCommand([
11+
"etcd",
12+
"--name",
13+
nodeName,
14+
"--initial-advertise-peer-urls",
15+
`http://0.0.0.0:${ETCD_PEER_PORT}`,
16+
"--advertise-client-urls",
17+
`http://0.0.0.0:${ETCD_CLIENT_PORT}`,
18+
"--listen-peer-urls",
19+
`http://0.0.0.0:${ETCD_PEER_PORT}`,
20+
"--listen-client-urls",
21+
`http://0.0.0.0:${ETCD_CLIENT_PORT}`,
22+
])
23+
.withWaitStrategy(Wait.forLogMessage(/"status":"SERVING"/));
24+
}
25+
26+
public override async start(): Promise<StartedEtcdContainer> {
27+
return new StartedEtcdContainer(await super.start());
28+
}
29+
}
30+
31+
export class StartedEtcdContainer extends AbstractStartedContainer {
32+
public getClientPort(): number {
33+
return this.startedTestContainer.getMappedPort(ETCD_CLIENT_PORT);
34+
}
35+
36+
public getPeerPort(): number {
37+
return this.startedTestContainer.getMappedPort(ETCD_PEER_PORT);
38+
}
39+
40+
public getClientEndpoint(): string {
41+
return `http://${this.getHost()}:${this.getClientPort()}`;
42+
}
43+
44+
public getPeerEndpoint(): string {
45+
return `http://${this.getHost()}:${this.getPeerPort()}`;
46+
}
47+
}

packages/modules/etcd/src/index.ts

Whitespace-only changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"exclude": [
4+
"build",
5+
"src/**/*.test.ts"
6+
],
7+
"references": [
8+
{
9+
"path": "../../testcontainers"
10+
}
11+
]
12+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"extends": "../../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"rootDir": "src",
5+
"outDir": "build",
6+
"paths": {
7+
"testcontainers": [
8+
"../../testcontainers/src"
9+
]
10+
}
11+
},
12+
"exclude": [
13+
"build"
14+
],
15+
"references": [
16+
{
17+
"path": "../../testcontainers"
18+
}
19+
]
20+
}

0 commit comments

Comments
 (0)