v0.292.0: cloudflared readiness health check (R-841) — tunnel --metrics localhost:20241 run + Docker healthcheck on cloudflared's own /ready; the host agent reports running/not_running/unknown from State.Health
gates / gates (push) Successful in 28s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-04 13:16:26 +02:00
parent badc9c2a0c
commit 09e634de31
6 changed files with 55 additions and 10 deletions
+2 -2
View File
@@ -178,8 +178,8 @@ func TestCloudflaredRender(t *testing.T) {
if !strings.Contains(compose, CloudflaredImage) {
t.Errorf("expected pinned cloudflared image %q", CloudflaredImage)
}
if !strings.Contains(compose, "command: tunnel run") {
t.Error("expected `command: tunnel run`")
if !strings.Contains(compose, "command: tunnel --metrics localhost:20241 run") { // R-841: fixed metrics address
t.Error("expected `command: tunnel --metrics localhost:20241 run`")
}
}
@@ -6,7 +6,17 @@ services:
image: {{.Image}}
container_name: cloudflared
restart: unless-stopped
command: tunnel run
# R-841: metrics on the container's own loopback at a FIXED port, and a health check that asks cloudflared itself
# whether the tunnel is CONNECTED (`/ready`: 200 with readyConnections > 0, else 503 — measured 2026-10-04: with a
# wrong token the container stays "running" while /ready is 503). The host agent reads the result with
# `docker inspect` (State.Health) and reports the tunnel as running | not_running | unknown.
command: tunnel --metrics localhost:20241 run
healthcheck:
test: ["CMD", "cloudflared", "tunnel", "--metrics", "localhost:20241", "ready"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
environment:
- TUNNEL_TOKEN={{.CFTunnelToken}}
dns:
@@ -282,3 +282,23 @@ func TestReconcileFileBrowserImage_MovesOnlyTheImage(t *testing.T) {
t.Fatalf("an up-to-date file browser was touched: err %v calls %+v", err, *calls)
}
}
// R-841: the cloudflared compose carries a health check that asks cloudflared whether the tunnel is CONNECTED, and
// pins the metrics address it asks. Red-proof: drop the healthcheck block from the template and this fails.
func TestRenderCloudflared_HasAReadinessHealthcheck(t *testing.T) {
for _, tunnel := range []bool{false, true} {
f, err := infra.RenderCloudflared(infra.CloudflaredData{CFTunnelToken: "tok", Tunnel: tunnel})
if err != nil {
t.Fatal(err)
}
c := f["docker-compose.yml"].Content
for _, want := range []string{
"command: tunnel --metrics localhost:20241 run",
`test: ["CMD", "cloudflared", "tunnel", "--metrics", "localhost:20241", "ready"]`,
} {
if !strings.Contains(c, want) {
t.Fatalf("tunnel=%v: compose lacks %q:\n%s", tunnel, want, c)
}
}
}
}