@celilo/e2e 0.16.0 → 0.17.0

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.
@@ -34,6 +34,13 @@ esac
34
34
  ip route del default 2>/dev/null || true
35
35
  ip route add default via "$GATEWAY"
36
36
 
37
+ # An explicit resolver from the caller wins over the vantage default. The proxy
38
+ # is what resolves names for a SOCKS5 client — a browser hands it the hostname
39
+ # and never resolves it itself — so a test driving a browser at a name only the
40
+ # fleet's own resolver knows has to say so here. Modelling a real device: one
41
+ # on the internal zone is handed the fleet's resolver, not a fixed stub.
42
+ NAMESERVER="${NAMESERVER_OVERRIDE:-$NAMESERVER}"
43
+
37
44
  # Bypass docker's embedded resolver — point directly at the in-network
38
45
  # DNS so split-horizon and the namecheap simulator both behave correctly.
39
46
  echo "nameserver $NAMESERVER" > /etc/resolv.conf
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celilo/e2e",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
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",
@@ -37,10 +37,10 @@
37
37
  "README.md"
38
38
  ],
39
39
  "dependencies": {
40
- "@celilo/capabilities": "^1.5.0",
40
+ "@celilo/capabilities": "^2.1.0",
41
41
  "@celilo/cli-display": "^0.2.0",
42
42
  "@celilo/event-bus": "^0.6.0",
43
- "@celilo/terraform-fake": "^0.3.0",
43
+ "@celilo/terraform-fake": "^0.3.1",
44
44
  "yaml": "^2.8.0",
45
45
  "zod": "^3.24.1"
46
46
  },
@@ -708,11 +708,19 @@ function buildNetworkHandle(
708
708
  );
709
709
  }
710
710
  // Kill any prior responder (idempotent: replaces prior values map).
711
+ //
712
+ // Matched on "events respond", NOT "celilo events respond": inside the
713
+ // e2e management image `celilo` is a dev-mode shim that execs `bun run
714
+ // .../index.ts events respond ...`, so the literal word "celilo" never
715
+ // appears contiguous with "events respond" in the resulting process's
716
+ // argv — the old pattern silently matched nothing, so a second
717
+ // `respondWith()` call left the FIRST responder (and its stale values
718
+ // map) running alongside the new one instead of replacing it.
711
719
  dockerExec(
712
720
  projectName,
713
721
  composeDir,
714
722
  'management',
715
- 'pkill -f "celilo events respond" 2>/dev/null || true',
723
+ 'pkill -f "events respond" 2>/dev/null || true',
716
724
  5_000,
717
725
  );
718
726
  // Spawn detached. nohup + & + disown cleanly survives the
@@ -22,6 +22,19 @@ export interface SocksProxyOptions {
22
22
  * zones via the firewall.
23
23
  */
24
24
  vantage?: SocksProxyVantage;
25
+ /**
26
+ * Resolver the proxy should use instead of the vantage's baked default.
27
+ *
28
+ * The PROXY resolves names for a SOCKS5 client: chromium configured with
29
+ * `socks5://` sends the hostname and never resolves it itself. A test driving
30
+ * a browser at a name only the fleet's own resolver knows — anything on a
31
+ * private ingress — therefore has to point the proxy at that resolver.
32
+ *
33
+ * More faithful rather than less: the rig's baked stub answers a fixed
34
+ * split-horizon table, whereas a device on the internal zone is handed the
35
+ * fleet's resolver. Pass the deployed resolver's DNS-ingress address.
36
+ */
37
+ nameserver?: string;
25
38
  }
26
39
 
27
40
  export interface SocksProxyHandle {
@@ -69,8 +82,22 @@ const VANTAGE_CONFIGS: Record<SocksProxyVantage, VantageConfig> = {
69
82
  },
70
83
  };
71
84
 
72
- function containerNameFor(projectName: string, vantage: SocksProxyVantage): string {
73
- return `${projectName}-socks-${vantage}`;
85
+ /**
86
+ * Deterministic per (project, vantage, resolver).
87
+ *
88
+ * The resolver is part of the identity because a proxy is REUSED by name: two
89
+ * calls differing only in `nameserver` would otherwise silently share one
90
+ * container, and the second would resolve through the first's resolver. That
91
+ * failure looks like a DNS bug in the fleet, which is the worst possible place
92
+ * for it to look like anything.
93
+ */
94
+ function containerNameFor(
95
+ projectName: string,
96
+ vantage: SocksProxyVantage,
97
+ nameserver?: string,
98
+ ): string {
99
+ const suffix = nameserver ? `-dns-${nameserver.replace(/\./g, '-')}` : '';
100
+ return `${projectName}-socks-${vantage}${suffix}`;
74
101
  }
75
102
 
76
103
  /**
@@ -85,7 +112,7 @@ export async function startSocksProxy(
85
112
  const vantage = options.vantage ?? 'isp-external';
86
113
  const cfg = VANTAGE_CONFIGS[vantage];
87
114
  const networkName = `${projectName}_${cfg.network}`;
88
- const containerName = containerNameFor(projectName, vantage);
115
+ const containerName = containerNameFor(projectName, vantage, options.nameserver);
89
116
 
90
117
  // Reuse existing container if one is running for this project + vantage
91
118
  const existing = inspectContainer(containerName);
@@ -113,6 +140,7 @@ export async function startSocksProxy(
113
140
  `--ip ${cfg.ip}`,
114
141
  '--cap-add NET_ADMIN',
115
142
  `-e VANTAGE=${vantage}`,
143
+ ...(options.nameserver ? [`-e NAMESERVER_OVERRIDE=${options.nameserver}`] : []),
116
144
  '-p 127.0.0.1::1080',
117
145
  PROXY_IMAGE,
118
146
  ].join(' '),
package/src/types.ts CHANGED
@@ -182,6 +182,20 @@ export class CeliloCommandError extends Error {
182
182
  */
183
183
  export interface ProxyOptions {
184
184
  vantage?: 'isp-external' | 'internal';
185
+ /**
186
+ * Resolver the proxy should use, overriding the vantage's baked default.
187
+ *
188
+ * The proxy is what actually resolves names: a browser configured with
189
+ * `socks5://` hands the HOSTNAME to the proxy and never resolves it itself.
190
+ * So a test driving a browser at a name only the fleet's own resolver knows
191
+ * — anything on a private ingress — must point the proxy at that resolver.
192
+ *
193
+ * This is more faithful, not less: the rig's baked stub answers a fixed
194
+ * split-horizon table, whereas a real device on the internal zone is handed
195
+ * the fleet's resolver by DHCP. Pass the deployed resolver's DNS-ingress
196
+ * address here to model that.
197
+ */
198
+ nameserver?: string;
185
199
  }
186
200
 
187
201
  export interface SocksProxyHandle {