@celilo/e2e 0.20.4 → 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.greenwave-sim +1 -1
- package/docker/Dockerfile.ip-echo +1 -1
- package/docker/Dockerfile.isitup +1 -1
- package/docker/Dockerfile.management +31 -1
- package/docker/Dockerfile.npm-registry-sim +1 -1
- package/docker/Dockerfile.proxmox-sim +1 -1
- package/docker/Dockerfile.registry +1 -1
- package/docker/Dockerfile.signal-sim +1 -1
- package/docker/Dockerfile.socks-proxy +5 -0
- package/package.json +3 -3
- package/scripts/dockerhub-login.sh +26 -0
- package/src/socks-proxy.ts +32 -11
- package/src/types.ts +8 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
FROM oven/bun:
|
|
1
|
+
FROM oven/bun:1.4.2@sha256:9114c058aeae42162ee16dd5084b95fe9473970bb6bcb5b232ab1630f0546895
|
|
2
2
|
|
|
3
3
|
# iproute2 so the entrypoint can see its own addressing when debugging; the
|
|
4
4
|
# service itself needs no routing changes (it sits on internet-external with
|
package/docker/Dockerfile.isitup
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
FROM oven/bun:
|
|
1
|
+
FROM oven/bun:1.4.2@sha256:9114c058aeae42162ee16dd5084b95fe9473970bb6bcb5b232ab1630f0546895
|
|
2
2
|
|
|
3
3
|
# Caddy (for ACME/TLS termination) + tools needed by entrypoint.sh.
|
|
4
4
|
# iproute2 provides `ip` so the entrypoint can rewrite the default route
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
FROM oven/bun:
|
|
1
|
+
FROM oven/bun:1.4.2@sha256:9114c058aeae42162ee16dd5084b95fe9473970bb6bcb5b232ab1630f0546895
|
|
2
2
|
|
|
3
3
|
# This Dockerfile produces a *vanilla* management image — bun + unzip +
|
|
4
4
|
# bunfig, no celilo. `cele2e build-infra` runs install.sh inside a
|
|
@@ -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/
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# arrives: it can queue an inbound reply, fail a recipient inside a success,
|
|
7
7
|
# and revoke the device link on demand — none of which the real unlinked
|
|
8
8
|
# daemon can be made to do.
|
|
9
|
-
FROM oven/bun:1@sha256:9114c058aeae42162ee16dd5084b95fe9473970bb6bcb5b232ab1630f0546895
|
|
9
|
+
FROM oven/bun:1.4.2@sha256:9114c058aeae42162ee16dd5084b95fe9473970bb6bcb5b232ab1630f0546895
|
|
10
10
|
|
|
11
11
|
WORKDIR /app
|
|
12
12
|
COPY simulators/signal-cli/server.ts ./server.ts
|
|
@@ -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,9 +38,9 @@
|
|
|
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
|
-
"@celilo/event-bus": "^0.
|
|
43
|
+
"@celilo/event-bus": "^0.7.0",
|
|
44
44
|
"@celilo/terraform-fake": "^0.3.1",
|
|
45
45
|
"yaml": "^2.8.0",
|
|
46
46
|
"zod": "^3.24.1"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Authenticate the builder to Docker Hub before any e2e image build.
|
|
3
|
+
#
|
|
4
|
+
# celilo#1376: the e2e base images are digest-pinned, which makes a pull
|
|
5
|
+
# REPRODUCIBLE — it does not make it ALLOWED. Docker Hub meters anonymous pulls
|
|
6
|
+
# per source IP, and once the builder's share is spent every pull fails at
|
|
7
|
+
# `load metadata` with:
|
|
8
|
+
#
|
|
9
|
+
# ERROR: pull access denied ... insufficient_scope: authorization failed
|
|
10
|
+
#
|
|
11
|
+
# which reads like a missing image rather than a spent quota. An authenticated
|
|
12
|
+
# pull draws on the account's much larger allowance instead.
|
|
13
|
+
#
|
|
14
|
+
# No credentials configured (a fork, a local run) => stay anonymous and say so,
|
|
15
|
+
# rather than failing the build for a quota that may well not be spent.
|
|
16
|
+
set -eu
|
|
17
|
+
|
|
18
|
+
if [ -z "${DOCKERHUB_USERNAME:-}" ] || [ -z "${DOCKERHUB_TOKEN:-}" ]; then
|
|
19
|
+
echo "DOCKERHUB_USERNAME/DOCKERHUB_TOKEN unset — pulling Docker Hub anonymously."
|
|
20
|
+
echo "Anonymous pulls share this host's IP quota; a spent quota fails as"
|
|
21
|
+
echo "'insufficient_scope: authorization failed' at 'load metadata' (celilo#1376)."
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
printf '%s' "${DOCKERHUB_TOKEN}" |
|
|
26
|
+
docker login --username "${DOCKERHUB_USERNAME}" --password-stdin
|
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
|
}
|