forked from testcontainers/testcontainers-node
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathopensearch-container.ts
More file actions
113 lines (96 loc) · 3.33 KB
/
opensearch-container.ts
File metadata and controls
113 lines (96 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { AbstractStartedContainer, GenericContainer, StartedTestContainer, Wait } from "testcontainers";
import zxcvbn from "zxcvbn";
const OPENSEARCH_HTTP_PORT = 9200;
const OPENSEARCH_TRANSPORT_PORT = 9300;
const OPENSEARCH_PERFORMANCE_ANALYZER_PORT = 9600;
export class OpenSearchContainer extends GenericContainer {
// default to security on, with a strong demo password
private securityEnabled = true;
private password = "yourStrong(!)P@ssw0rd";
private readonly username = "admin";
// HTTPS + Basic Auth wait strategy
private readonly defaultWaitStrategy = Wait.forHttp("/", OPENSEARCH_HTTP_PORT).withBasicCredentials(
this.username,
this.password
);
constructor(image: string) {
super(image);
this.withExposedPorts(OPENSEARCH_HTTP_PORT, OPENSEARCH_TRANSPORT_PORT, OPENSEARCH_PERFORMANCE_ANALYZER_PORT)
.withEnvironment({
"discovery.type": "single-node",
// disable security plugin if requested
"plugins.security.disabled": (!this.securityEnabled).toString(),
})
.withWaitStrategy(this.defaultWaitStrategy)
.withStartupTimeout(120_000);
}
/**
* Toggle OpenSearch security plugin on/off.
*/
public withSecurityEnabled(enabled: boolean): this {
this.securityEnabled = enabled;
this.withEnvironment({
"plugins.security.disabled": (!enabled).toString(),
});
return this;
}
/**
* Override the 'admin' password.
* Enforces OpenSearch’s requirement of zxcvbn score ≥ 3
*/
public withPassword(password: string): this {
const { score } = zxcvbn(password);
if (score < 3) {
throw new Error(
`Password "${password}" is too weak (zxcvbn score ${score}). Must score ≥ 3 to meet OpenSearch security requirements.`
);
}
this.password = password;
this.defaultWaitStrategy.withBasicCredentials(this.username, this.password);
return this;
}
/**
* Start the container, injecting the initial-admin-password env var,
* then wrap in our typed StartedOpenSearchContainer.
*/
public override async start(): Promise<StartedOpenSearchContainer> {
this.withEnvironment({
OPENSEARCH_INITIAL_ADMIN_PASSWORD: this.password,
});
if (this.securityEnabled) {
this.defaultWaitStrategy.usingTls().allowInsecure();
}
const started = await super.start();
return new StartedOpenSearchContainer(started, this.username, this.password, this.securityEnabled);
}
}
export class StartedOpenSearchContainer extends AbstractStartedContainer {
constructor(
override readonly startedTestContainer: StartedTestContainer,
private readonly username: string,
private readonly password: string,
private readonly securityEnabled: boolean
) {
super(startedTestContainer);
}
/** Mapped HTTP(S) port */
public getPort(): number {
return this.getMappedPort(OPENSEARCH_HTTP_PORT);
}
/** Get the URL schema needed for connecting to this container */
public getSchema(): string {
return this.securityEnabled ? "https" : "http";
}
/** HTTPS endpoint URL */
public getHttpUrl(): string {
return `${this.getSchema()}://${this.getHost()}:${this.getPort()}`;
}
/** Admin username (always 'admin' by default) */
public getUsername(): string {
return this.username;
}
/** Admin password */
public getPassword(): string {
return this.password;
}
}