test(pipelock): integration test for apply_allowlist_change (PRD 0015)
test / unit (pull_request) Successful in 16s
test / integration (pull_request) Successful in 1m8s

Phase 4 of PRD 0015. End-to-end test against real Docker:

- Brings up a real pipelock sidecar via the production
  DockerPipelockProxy bring-up + pipelock_tls_init.
- Calls apply_allowlist_change to add a new host.
- Polls the live /etc/pipelock.yaml until the new host shows up
  (bridging the docker-restart window).
- Verifies api_allowlist contains both old + new hosts and
  tls_interception block is preserved.
- Smaller cases: invalid hostname raises, missing sidecar raises,
  fetch_current_allowlist returns one-per-line format.

Skipped under GITEA_ACTIONS because pipelock_tls_init bind-mounts a
host path that doesn't share fs in the runner, matching the
existing pipelock smoke test's skip pattern.

Drive-by fix: fetch_current_yaml now uses `docker cp` (daemon-API
tarball copy) instead of `docker exec cat` because the pipelock
image is distroless and has no shell utilities.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 05:07:26 -04:00
parent 1d58d62c47
commit 4fada1651b
2 changed files with 180 additions and 11 deletions
+28 -11
View File
@@ -65,19 +65,36 @@ def render_allowlist_content(hosts: list[str]) -> str:
def fetch_current_yaml(slug: str) -> str:
"""Read the live /etc/pipelock.yaml from the running pipelock
sidecar. Raises PipelockApplyError if the read fails."""
"""Read the live /etc/pipelock.yaml from the pipelock sidecar.
Uses `docker cp` (not `docker exec cat`) because the pipelock
image is distroless and has no shell utilities. `docker cp` is a
daemon-API tarball copy — works on stopped containers too, and
doesn't need anything in the container's PATH.
Raises PipelockApplyError if the read fails."""
container = pipelock_container_name(slug)
r = subprocess.run(
["docker", "exec", container, "cat", PIPELOCK_YAML_IN_CONTAINER],
capture_output=True, text=True, check=False,
)
if r.returncode != 0:
raise PipelockApplyError(
f"could not read pipelock.yaml from {container}: "
f"{(r.stderr or '').strip() or 'container not running?'}"
fd, tmp_path = tempfile.mkstemp(prefix="cb-pipelock-fetch.", suffix=".yaml")
os.close(fd)
try:
r = subprocess.run(
[
"docker", "cp",
f"{container}:{PIPELOCK_YAML_IN_CONTAINER}", tmp_path,
],
capture_output=True, text=True, check=False,
)
return r.stdout
if r.returncode != 0:
raise PipelockApplyError(
f"could not fetch pipelock.yaml from {container}: "
f"{(r.stderr or '').strip() or 'container not running?'}"
)
return Path(tmp_path).read_text()
finally:
try:
Path(tmp_path).unlink()
except OSError:
pass
def fetch_current_allowlist(slug: str) -> str: