Files
ccs/tests/docker/network-contract.sh
T
Kai (Tam Nhu) Tran 28f08cbb50 docs(docker): document ccs-net contract for sibling containers (#1259)
Add "Connect your app to CLIProxy" section to docker/README.md with:
- Public contract table (network=ccs-net, service DNS=ccs, ports 8317/3000)
- Pattern A: same compose file with external network reference
- Pattern B: docker run --network ccs-net
- Troubleshooting subsection (DNS, missing network, conflict, Podman, MTU)

Add one-line link in README.md pointing to the new section.
Add CHANGELOG entry under Unreleased noting the contract as SemVer-major stable.
Add CONTRIBUTING.md note that changing services.ccs or networks.ccs-net requires major bump.
2026-05-16 12:46:33 -04:00

106 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# tests/docker/network-contract.sh
#
# Verifies the stable ccs-net Docker network contract:
# - Network name: ccs-net
# - Service DNS: ccs
# - CLIProxy: http://ccs:8317
# - Dashboard: http://ccs:3000
#
# Requires: Docker with compose plugin, internet access to pull curlimages/curl
# Usage: bash tests/docker/network-contract.sh
# (called from repo root so docker/compose.yaml path resolves)
#
set -euo pipefail
COMPOSE_FILE="docker/compose.yaml"
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
log() { printf '[i] %s\n' "$*"; }
ok() { printf '[OK] %s\n' "$*"; }
err() { printf '[X] %s\n' "$*" >&2; }
# ---------------------------------------------------------------------------
# Bring stack up; register teardown on any exit
# ---------------------------------------------------------------------------
log "Bringing CCS stack up: $COMPOSE_FILE"
docker compose -f "$COMPOSE_FILE" up -d
cleanup() {
log "Tearing down stack..."
docker compose -f "$COMPOSE_FILE" down -v 2>/dev/null || true
}
trap cleanup EXIT
# ---------------------------------------------------------------------------
# Wait for healthcheck (max 90s)
# ---------------------------------------------------------------------------
log "Waiting for healthcheck to pass (max 90s)..."
WAIT_MAX=45 # 45 x 2s = 90s
HEALTHY=0
for _i in $(seq 1 "$WAIT_MAX"); do
STATUS=$(
docker compose -f "$COMPOSE_FILE" ps --format json 2>/dev/null \
| python3 -c "
import sys, json
data = sys.stdin.read().strip()
if not data:
print('unknown')
raise SystemExit(0)
rows = json.loads('[' + ','.join(data.splitlines()) + ']')
for r in rows:
if 'ccs' in r.get('Service', ''):
print(r.get('Health', 'unknown'))
raise SystemExit(0)
print('unknown')
" 2>/dev/null || echo "unknown"
)
if [ "$STATUS" = "healthy" ]; then
HEALTHY=1
break
fi
log "Health: $STATUS (attempt ${_i}/${WAIT_MAX})"
sleep 2
done
if [ "$HEALTHY" -ne 1 ]; then
err "Container did not become healthy within 90s"
exit 1
fi
ok "Container is healthy"
# ---------------------------------------------------------------------------
# Verify ccs-net network exists on the host
# ---------------------------------------------------------------------------
log "Inspecting ccs-net network..."
docker network inspect ccs-net >/dev/null
ok "ccs-net network exists"
# ---------------------------------------------------------------------------
# Verify DNS resolution from a sibling container on ccs-net
# ---------------------------------------------------------------------------
log "Testing http://ccs:8317 from sibling container..."
docker run --rm \
--network ccs-net \
curlimages/curl:latest \
-fsS --max-time 10 \
http://ccs:8317/ \
>/dev/null
ok "CLIProxy reachable at http://ccs:8317"
log "Testing http://ccs:3000 from sibling container..."
docker run --rm \
--network ccs-net \
curlimages/curl:latest \
-fsS --max-time 10 \
http://ccs:3000/ \
>/dev/null
ok "Dashboard reachable at http://ccs:3000"
# ---------------------------------------------------------------------------
# Done
# ---------------------------------------------------------------------------
ok "network contract verified"