Files
spinifex/tests/e2e/lb/testdata/client-userdata.sh
T
joshsiv-mulga afa933ac05 feat(e2e): share probe client across both internal LB suites + SG fixes
- Replaces per-suite probe client with a single shared VM launched in the
  fixture. Saves ~60s by avoiding a cold boot between the ALB and NLB
  internal suites.
- Client cloud-init exposes a JSON trigger endpoint on :9090 in addition
  to the http.server on :80 (results dir). Each suite POSTs
  {proto, ip, count, outfile, http_port, tcp_port} to run a probe loop
  against the LB private IP and writes the result file under /tmp/httpd
  for the driver to fetch back.
- configureDefaultSG now uses the structured IpPermissions form (top-level
  shortcut is silently ignored by vpcd — tracked separately) and opens
  port 9090 in addition to 80 + 9000.
- deleteLB captures the underlying sys.micro VM id via the LB ENI before
  delete, then polls DescribeLoadBalancers until LoadBalancerNotFound so
  the next suite doesn't race the capacity reclaim.
- Internal_NLB sleeps 15s up front to let the ALB sys.micro deallocate
  fully before its own createLB fires. DescribeLoadBalancers can report
  the ALB gone before the vCPU/memory allocation is actually released on
  capacity-tight dev hosts; without this settle, NLB's createLB trips the
  sys.micro reserve and lands in terminal state=failed. Still cheaper
  than cold-booting a per-suite client.
2026-05-18 16:10:12 +10:00

60 lines
2.3 KiB
Bash

#!/bin/bash
# Shared probe client. Long-lived across both internal LB suites — saves
# the ~60s second cold boot the per-suite client would otherwise incur.
#
# - Port 80: python http.server, serves /tmp/httpd (status + results files)
# - Port 9090: tiny trigger server. POST JSON {proto, ip, count, outfile}
# runs the probe loop synchronously and writes the result
# file under /tmp/httpd so the driver can curl it back.
set -eu
mkdir -p /tmp/httpd
cd /tmp/httpd
echo "ready" > status.txt
nohup python3 -m http.server 80 --bind 0.0.0.0 > /dev/null 2>&1 &
cat > /tmp/trigger.py <<'PYEOF'
import http.server, json, os, socketserver, subprocess
OUT_DIR = "/tmp/httpd"
class Handler(http.server.BaseHTTPRequestHandler):
def do_POST(self):
try:
n = int(self.headers.get("Content-Length", 0))
body = json.loads(self.rfile.read(n).decode())
proto = body["proto"]
ip = body["ip"]
count = int(body.get("count", 20))
outfile = body["outfile"]
tcp_port = int(body.get("tcp_port", 9000))
http_port = int(body.get("http_port", 80))
except Exception as exc:
self.send_response(400); self.end_headers()
self.wfile.write(f"bad request: {exc}".encode())
return
path = os.path.join(OUT_DIR, outfile)
with open(path, "w") as fh:
for _ in range(count):
if proto == "http":
r = subprocess.run(
["curl", "-s", "--max-time", "5", f"http://{ip}:{http_port}/"],
capture_output=True, text=True)
fh.write(r.stdout.strip() + "\n")
else:
r = subprocess.run(
["bash", "-c", f'echo "" | nc -w2 {ip} {tcp_port} 2>/dev/null || true'],
capture_output=True, text=True)
fh.write(r.stdout.strip() + "\n")
self.send_response(200); self.end_headers()
self.wfile.write(b"ok")
def log_message(self, *a, **kw):
pass
socketserver.TCPServer.allow_reuse_address = True
socketserver.TCPServer(("0.0.0.0", 9090), Handler).serve_forever()
PYEOF
nohup python3 /tmp/trigger.py > /tmp/trigger.log 2>&1 &