test: add bash test suite covering pipelock helpers and smoke flows
Adds tests/ with a tiny bash assert harness, manifest fixtures, and a
runner. No framework dependency — each test file is self-contained
and exits 0 on pass / 1 on fail; tests/run_tests.sh aggregates.
Unit tests (no docker):
- pipelock_naming: container_name, proxy_url, proxy_host_port shape
- pipelock_classify: _pipelock_is_ipv4_literal classifier coverage
- pipelock_allowlist: bottle_allowlist + ssh hostnames/ip_cidrs/
trusted_domains + effective_allowlist union/dedup/sort, plus
rejection of non-string entries
- pipelock_yaml: emitter shape (mode/enforce/api_allowlist/forward_proxy/
dlp), conditional ssrf+trusted_domains blocks, secret hygiene
(manifest env values must not appear in YAML), file mode 600
Integration tests (require docker, skip cleanly otherwise):
- pipelock_image: pinned digest's ENTRYPOINT is /pipelock and CMD
contains 'run' and the binary --version succeeds — would catch a
future image bump that changes the launcher's argv contract
- pipelock_sidecar_smoke: docker create + cp YAML to /etc/pipelock.yaml
+ start, then probe /health — the regression test for the bug
where the YAML was written to /etc/pipelock/ (parent dir absent in
the distroless image)
- dry_run_plan: cli.sh start --dry-run shows the egress line,
counts the bottle's entry into the effective allowlist, prints
the dry-run banner, and creates zero docker resources
- orphan_cleanup: the cleanup primitives the start-flow trap depends
on (network_remove, pipelock_stop) are idempotent against
missing/never-existed resources, so the trap is safe even if
pipelock_start dies before everything is wired up
Assisted-by: Claude Code
This commit is contained in:
Executable
+63
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# Integration: cli.sh start --dry-run renders the planned shape and
|
||||
# does not create any docker resources. Confirms the preflight contract
|
||||
# from PRD 0001 (allowlist line in the plan, no docker side effects).
|
||||
TEST_NAME="dry_run_plan"
|
||||
|
||||
. "$(dirname "$0")/../lib/common.sh"
|
||||
|
||||
skip_test_if_no_docker
|
||||
|
||||
work_dir="$(mktemp -d)"
|
||||
manifest="${work_dir}/claude-bottle.json"
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$work_dir"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Manifest with an egress.allowlist so we can grep for a known host.
|
||||
cat > "$manifest" <<'JSON'
|
||||
{
|
||||
"bottles": {
|
||||
"dev": {
|
||||
"egress": { "allowlist": ["example.org"] }
|
||||
}
|
||||
},
|
||||
"agents": {
|
||||
"demo": {
|
||||
"skills": [],
|
||||
"prompt": "",
|
||||
"bottle": "dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
JSON
|
||||
|
||||
# Snapshot docker state before we run.
|
||||
nets_before="$(docker network ls --format '{{.Name}}' | grep -c '^claude-bottle' || true)"
|
||||
ctrs_before="$(docker ps -a --format '{{.Names}}' | grep -c '^claude-bottle' || true)"
|
||||
|
||||
# Override HOME so the user's ~/claude-bottle.json doesn't leak in via
|
||||
# manifest_resolve's home+cwd merge.
|
||||
out="$(cd "$work_dir" \
|
||||
&& HOME="$work_dir" CLAUDE_BOTTLE_DRY_RUN=1 \
|
||||
"${REPO_ROOT}/cli.sh" start demo 2>&1 || true)"
|
||||
|
||||
assert_contains "$out" "egress" "preflight: egress line present"
|
||||
# 7 baked defaults + 1 bottle entry = 8. The summary line shows the
|
||||
# total count regardless of which entries fit in the visible
|
||||
# "<a>, <b>, <c>, +N more" prefix, so this assertion is robust against
|
||||
# alphabetical sort order changes.
|
||||
assert_match "$out" "8 hosts allowed" "preflight: bottle entry counted in effective allowlist"
|
||||
assert_contains "$out" "api.anthropic.com" "preflight: baked default shown"
|
||||
assert_contains "$out" "dry-run requested" "dry-run banner present"
|
||||
assert_not_contains "$out" "/dev/tty" "no /dev/tty prompt reached (dry-run exited first)"
|
||||
|
||||
# No docker side effects.
|
||||
nets_after="$(docker network ls --format '{{.Name}}' | grep -c '^claude-bottle' || true)"
|
||||
ctrs_after="$(docker ps -a --format '{{.Names}}' | grep -c '^claude-bottle' || true)"
|
||||
assert_eq "$nets_before" "$nets_after" "dry-run: no claude-bottle networks created"
|
||||
assert_eq "$ctrs_before" "$ctrs_after" "dry-run: no claude-bottle containers created"
|
||||
|
||||
test_summary
|
||||
Reference in New Issue
Block a user