@celilo/e2e 0.20.5 → 0.20.6
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.
- package/docker/Dockerfile.management +30 -0
- package/docker/Dockerfile.socks-proxy +5 -0
- package/package.json +2 -2
- package/src/socks-proxy.ts +32 -11
- package/src/types.ts +8 -0
|
@@ -124,6 +124,36 @@ ENV NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt
|
|
|
124
124
|
# fall through to Bun's normal resolution.
|
|
125
125
|
RUN printf '[install.scopes]\n"@celilo" = "http://npm-registry.lab"\n' > /root/.bunfig.toml
|
|
126
126
|
|
|
127
|
+
# --- The fleet browser runtime (managed-browser-runtime) ----------------------
|
|
128
|
+
#
|
|
129
|
+
# Browser-driven health checks (celilo-web-console is the first) resolve
|
|
130
|
+
# `/var/lib/celilo/browsers/current/chrome` and a descriptor describing what
|
|
131
|
+
# was installed. This image provisions that runtime the way the celilo-mgmt
|
|
132
|
+
# role does on a real management host (`modules/celilo-mgmt/ansible/roles/
|
|
133
|
+
# celilo-mgmt/tasks/debian.yml`), pinned to the SAME playwright version that
|
|
134
|
+
# role declares — the fleet's single browser-version declaration. A module
|
|
135
|
+
# bundling a different client is a pin-drift finding, not a failure: the
|
|
136
|
+
# consumer passes the stable path explicitly.
|
|
137
|
+
#
|
|
138
|
+
# Revision comes from the pinned client itself (`install --dry-run`), never
|
|
139
|
+
# from a hand-maintained version→revision table — same reasoning as the role.
|
|
140
|
+
ARG PLAYWRIGHT_VERSION=1.60.0
|
|
141
|
+
RUN set -eux; \
|
|
142
|
+
REVISION="$(PLAYWRIGHT_BROWSERS_PATH=/var/lib/celilo/browsers bun x "playwright-core@${PLAYWRIGHT_VERSION}" install --dry-run chromium-headless-shell \
|
|
143
|
+
| grep -oE 'chromium_headless_shell-[0-9]+' | head -1 | cut -d- -f2)"; \
|
|
144
|
+
PLAYWRIGHT_BROWSERS_PATH=/var/lib/celilo/browsers bun x "playwright-core@${PLAYWRIGHT_VERSION}" install chromium-headless-shell; \
|
|
145
|
+
PLAYWRIGHT_BROWSERS_PATH=/var/lib/celilo/browsers bun x "playwright-core@${PLAYWRIGHT_VERSION}" install-deps chromium-headless-shell; \
|
|
146
|
+
BIN="$(find /var/lib/celilo/browsers/chromium_headless_shell-"${REVISION}" -type f \
|
|
147
|
+
\( -name chrome-headless-shell -o -name headless_shell \) | head -1)"; \
|
|
148
|
+
test -x "${BIN}"; \
|
|
149
|
+
mkdir -p /var/lib/celilo/browsers/current; \
|
|
150
|
+
ln -sf "${BIN}" /var/lib/celilo/browsers/current/chrome; \
|
|
151
|
+
BROWSER_VERSION="$(/var/lib/celilo/browsers/current/chrome --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -1)"; \
|
|
152
|
+
printf '{"schemaVersion":1,"browser":"chromium","flavor":"headless-shell","browserVersion":"%s","playwrightVersion":"%s","revision":"%s","writtenBy":"e2e management image"}' \
|
|
153
|
+
"${BROWSER_VERSION}" "${PLAYWRIGHT_VERSION}" "${REVISION}" \
|
|
154
|
+
> /var/lib/celilo/browsers/current/celilo-browser.json; \
|
|
155
|
+
cat /var/lib/celilo/browsers/current/celilo-browser.json
|
|
156
|
+
|
|
127
157
|
# Standard modules pre-packaged as .netapp files — built by e2e-build.
|
|
128
158
|
# Tests import from /netapps/<module>.netapp instead of the monorepo mount.
|
|
129
159
|
COPY netapps/ /netapps/
|
|
@@ -18,6 +18,11 @@ RUN apt-get update && apt-get install -y \
|
|
|
18
18
|
iproute2 \
|
|
19
19
|
iputils-ping \
|
|
20
20
|
dnsutils \
|
|
21
|
+
# wireguard-tools: the control-plane-vpn vantage. A browser that reaches
|
|
22
|
+
# celilo-web-console (secure-mgmt, VPN-only per D7) must enter as a real
|
|
23
|
+
# VPN peer — the proxy brings up a wg tunnel, it does not attach directly
|
|
24
|
+
# to the zone. Needs /dev/net/tun at `docker run` time (socks-proxy.ts).
|
|
25
|
+
wireguard-tools \
|
|
21
26
|
&& rm -rf /var/lib/apt/lists/*
|
|
22
27
|
|
|
23
28
|
COPY config/socks/danted.conf /etc/danted.conf
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@celilo/e2e",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.6",
|
|
4
4
|
"description": "E2E test infrastructure for Celilo-deployed applications. Provides a simulated internet with DNS hierarchy, ACME server, firewalls, and target machines in Docker.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"README.md"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@celilo/capabilities": "^
|
|
41
|
+
"@celilo/capabilities": "^6.0.0",
|
|
42
42
|
"@celilo/cli-display": "^0.2.0",
|
|
43
43
|
"@celilo/event-bus": "^0.7.0",
|
|
44
44
|
"@celilo/terraform-fake": "^0.3.1",
|
package/src/socks-proxy.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { existsSync } from 'node:fs';
|
|
|
3
3
|
import { createConnection } from 'node:net';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { progress } from './progress';
|
|
6
|
+
import type { ExecResult, SocksProxyHandle } from './types';
|
|
6
7
|
|
|
7
8
|
/** Package root — `docker/` and `config/` live here. */
|
|
8
9
|
const PACKAGE_ROOT = join(__dirname, '..');
|
|
@@ -37,17 +38,6 @@ export interface SocksProxyOptions {
|
|
|
37
38
|
nameserver?: string;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
export interface SocksProxyHandle {
|
|
41
|
-
/** URL the host can use to reach the proxy, e.g. 'socks5://127.0.0.1:54321' */
|
|
42
|
-
hostUrl: string;
|
|
43
|
-
/** The published host port (the second half of hostUrl) */
|
|
44
|
-
hostPort: number;
|
|
45
|
-
/** Container name (deterministic per project + vantage) */
|
|
46
|
-
containerName: string;
|
|
47
|
-
/** Tear down the proxy. Idempotent. */
|
|
48
|
-
stop(): Promise<void>;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
41
|
/**
|
|
52
42
|
* Custom image with dante-server + an entrypoint that fixes routing
|
|
53
43
|
* and DNS for the chosen vantage. Built from
|
|
@@ -139,6 +129,11 @@ export async function startSocksProxy(
|
|
|
139
129
|
`--network ${networkName}`,
|
|
140
130
|
`--ip ${cfg.ip}`,
|
|
141
131
|
'--cap-add NET_ADMIN',
|
|
132
|
+
// wireguard-tools in the image plus the TUN device let the proxy bring
|
|
133
|
+
// up a real WireGuard tunnel, which is how a browser enters the
|
|
134
|
+
// topology as a control-plane-vpn peer (celilo-web-console's only
|
|
135
|
+
// client path, D7). Harmless for the plain vantages.
|
|
136
|
+
'--device /dev/net/tun',
|
|
142
137
|
`-e VANTAGE=${vantage}`,
|
|
143
138
|
...(options.nameserver ? [`-e NAMESERVER_OVERRIDE=${options.nameserver}`] : []),
|
|
144
139
|
'-p 127.0.0.1::1080',
|
|
@@ -224,6 +219,32 @@ function makeHandle(containerName: string, port: number): SocksProxyHandle {
|
|
|
224
219
|
hostUrl: `socks5://127.0.0.1:${port}`,
|
|
225
220
|
hostPort: port,
|
|
226
221
|
containerName,
|
|
222
|
+
/**
|
|
223
|
+
* Run a command inside the proxy container.
|
|
224
|
+
*
|
|
225
|
+
* The proxy is started with `docker run`, not compose, so
|
|
226
|
+
* `net.exec` (a `docker compose exec`) cannot reach it. The
|
|
227
|
+
* control-plane-vpn test uses this to bring the proxy's WireGuard
|
|
228
|
+
* tunnel up after the tunnel has deployed — the peer is the proxy,
|
|
229
|
+
* so the browser behind it enters the topology the way a real
|
|
230
|
+
* admin laptop does.
|
|
231
|
+
*/
|
|
232
|
+
async exec(cmd, timeoutMs = 60_000): Promise<ExecResult> {
|
|
233
|
+
try {
|
|
234
|
+
const stdout = execSync(`docker exec ${containerName} bash -c ${JSON.stringify(cmd)}`, {
|
|
235
|
+
timeout: timeoutMs,
|
|
236
|
+
stdio: 'pipe',
|
|
237
|
+
}).toString();
|
|
238
|
+
return { stdout, stderr: '', exitCode: 0 };
|
|
239
|
+
} catch (err: unknown) {
|
|
240
|
+
const e = err as { stdout?: Buffer; stderr?: Buffer; status?: number };
|
|
241
|
+
return {
|
|
242
|
+
stdout: e.stdout?.toString() ?? '',
|
|
243
|
+
stderr: e.stderr?.toString() ?? String(err),
|
|
244
|
+
exitCode: e.status ?? 1,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
},
|
|
227
248
|
async stop(): Promise<void> {
|
|
228
249
|
if (stopped) return;
|
|
229
250
|
stopped = true;
|
package/src/types.ts
CHANGED
|
@@ -220,6 +220,14 @@ export interface SocksProxyHandle {
|
|
|
220
220
|
hostPort: number;
|
|
221
221
|
/** Container name (deterministic per project + vantage) */
|
|
222
222
|
containerName: string;
|
|
223
|
+
/**
|
|
224
|
+
* Run a command inside the proxy container (raw `docker exec`).
|
|
225
|
+
*
|
|
226
|
+
* The proxy is started with `docker run`, not compose, so `net.exec`
|
|
227
|
+
* cannot reach it. The control-plane-vpn browser test uses this to bring
|
|
228
|
+
* the proxy's WireGuard tunnel up after the tunnel has deployed.
|
|
229
|
+
*/
|
|
230
|
+
exec(cmd: string, timeoutMs?: number): Promise<ExecResult>;
|
|
223
231
|
/** Tear down the proxy. Idempotent. */
|
|
224
232
|
stop(): Promise<void>;
|
|
225
233
|
}
|