From fa4ef5d31315f4f57860a1a62732575ffa95ae8d Mon Sep 17 00:00:00 2001 From: Sohan Kshirsagar Date: Mon, 16 Mar 2026 18:21:59 -0700 Subject: [PATCH 1/6] test: enforce strict replay sandboxing in e2e fixtures --- .../aiohttp/e2e-tests/.tusk/config.yaml | 2 + .../aiohttp/e2e-tests/docker-compose.yml | 5 ++ .../django/e2e-tests/.tusk/config.yaml | 2 + .../django/e2e-tests/docker-compose.yml | 5 ++ .../e2e_common/Dockerfile.base | 58 ++++++++++--------- .../fastapi/e2e-tests/.tusk/config.yaml | 2 + .../fastapi/e2e-tests/docker-compose.yml | 5 ++ .../fastapi/e2e-tests/requirements.txt | 3 +- .../flask/e2e-tests/.tusk/config.yaml | 2 + .../flask/e2e-tests/docker-compose.yml | 5 ++ .../grpc/e2e-tests/.tusk/config.yaml | 2 + .../grpc/e2e-tests/docker-compose.yml | 5 ++ .../grpc/e2e-tests/src/greeter_pb2_grpc.py | 2 +- .../httpx/e2e-tests/.tusk/config.yaml | 2 + .../httpx/e2e-tests/docker-compose.yml | 5 ++ .../httpx/e2e-tests/requirements.txt | 3 +- .../psycopg/e2e-tests/.tusk/config.yaml | 2 + .../psycopg/e2e-tests/docker-compose.yml | 5 ++ .../psycopg2/e2e-tests/.tusk/config.yaml | 2 + .../psycopg2/e2e-tests/docker-compose.yml | 5 ++ .../redis/e2e-tests/.tusk/config.yaml | 2 + .../redis/e2e-tests/docker-compose.yml | 5 ++ .../requests/e2e-tests/.tusk/config.yaml | 2 + .../requests/e2e-tests/docker-compose.yml | 5 ++ .../sqlalchemy/e2e-tests/.tusk/config.yaml | 2 + .../sqlalchemy/e2e-tests/docker-compose.yml | 5 ++ .../sqlalchemy/e2e-tests/run.sh | 0 .../urllib/e2e-tests/.tusk/config.yaml | 2 + .../urllib/e2e-tests/docker-compose.yml | 5 ++ .../urllib3/e2e-tests/.tusk/config.yaml | 2 + .../urllib3/e2e-tests/docker-compose.yml | 5 ++ .../django-postgres/.tusk/config.yaml | 4 ++ .../django-postgres/docker-compose.yml | 5 ++ .../django-redis/.tusk/config.yaml | 4 ++ .../django-redis/docker-compose.yml | 5 ++ .../fastapi-postgres/.tusk/config.yaml | 4 ++ .../fastapi-postgres/docker-compose.yml | 5 ++ .../fastapi-sqlalchemy/.tusk/config.yaml | 4 ++ .../fastapi-sqlalchemy/docker-compose.yml | 5 ++ drift/stack-tests/fastapi-sqlalchemy/run.sh | 0 40 files changed, 162 insertions(+), 31 deletions(-) mode change 100644 => 100755 drift/instrumentation/sqlalchemy/e2e-tests/run.sh mode change 100644 => 100755 drift/stack-tests/fastapi-sqlalchemy/run.sh diff --git a/drift/instrumentation/aiohttp/e2e-tests/.tusk/config.yaml b/drift/instrumentation/aiohttp/e2e-tests/.tusk/config.yaml index c98214b..7d40a7d 100644 --- a/drift/instrumentation/aiohttp/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/aiohttp/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/aiohttp/e2e-tests/docker-compose.yml b/drift/instrumentation/aiohttp/e2e-tests/docker-compose.yml index 2989a5c..14976cb 100644 --- a/drift/instrumentation/aiohttp/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/aiohttp/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/aiohttp/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/django/e2e-tests/.tusk/config.yaml b/drift/instrumentation/django/e2e-tests/.tusk/config.yaml index c39e52e..ec41d3a 100644 --- a/drift/instrumentation/django/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/django/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/django/e2e-tests/docker-compose.yml b/drift/instrumentation/django/e2e-tests/docker-compose.yml index b466d23..801a3c7 100644 --- a/drift/instrumentation/django/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/django/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/django/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/e2e_common/Dockerfile.base b/drift/instrumentation/e2e_common/Dockerfile.base index c05b64a..303af74 100644 --- a/drift/instrumentation/e2e_common/Dockerfile.base +++ b/drift/instrumentation/e2e_common/Dockerfile.base @@ -3,7 +3,7 @@ # This base image contains: # - Python 3.9 (minimum supported version) # - Tusk CLI (for running replay tests) -# - System utilities (curl, postgresql-client) +# - System utilities (curl, postgresql-client, socat, bubblewrap) # # Build this image before running e2e tests: # docker build -t python-e2e-base:latest -f drift/instrumentation/e2e-common/Dockerfile.base . @@ -12,38 +12,40 @@ FROM python:3.9-slim # Install system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ - curl \ - postgresql-client \ - && rm -rf /var/lib/apt/lists/* + curl \ + postgresql-client \ + socat \ + bubblewrap \ + && rm -rf /var/lib/apt/lists/* # Install Tusk CLI # The CLI is downloaded from GitHub releases (tar.gz archives) ARG TUSK_CLI_VERSION=latest RUN set -ex && \ - if [ "$TUSK_CLI_VERSION" = "latest" ]; then \ - # Get the latest version tag - VERSION=$(curl -s https://api.github.com/repos/Use-Tusk/tusk-drift-cli/releases/latest | grep '"tag_name"' | cut -d '"' -f 4); \ - else \ - VERSION="${TUSK_CLI_VERSION}"; \ - fi && \ - # Remove 'v' prefix if present for the filename - VERSION_NUM=$(echo "$VERSION" | sed 's/^v//') && \ - # Detect architecture (x86_64 or arm64) - ARCH=$(uname -m) && \ - case "$ARCH" in \ - x86_64) ARCH_NAME="x86_64" ;; \ - aarch64|arm64) ARCH_NAME="arm64" ;; \ - *) echo "Unsupported architecture: $ARCH" && exit 1 ;; \ - esac && \ - # Construct download URL (archives are named like tusk-drift-cli_0.1.35_Linux_x86_64.tar.gz) - DOWNLOAD_URL="https://github.com/Use-Tusk/tusk-drift-cli/releases/download/${VERSION}/tusk-drift-cli_${VERSION_NUM}_Linux_${ARCH_NAME}.tar.gz" && \ - echo "Downloading Tusk CLI from: $DOWNLOAD_URL" && \ - curl -fsSL "$DOWNLOAD_URL" -o /tmp/tusk.tar.gz && \ - tar -xzf /tmp/tusk.tar.gz -C /tmp && \ - mv /tmp/tusk /usr/local/bin/tusk && \ - chmod +x /usr/local/bin/tusk && \ - rm -rf /tmp/tusk.tar.gz /tmp/LICENSE /tmp/README.md && \ - tusk --version + if [ "$TUSK_CLI_VERSION" = "latest" ]; then \ + # Get the latest version tag + VERSION=$(curl -s https://api.github.com/repos/Use-Tusk/tusk-drift-cli/releases/latest | grep '"tag_name"' | cut -d '"' -f 4); \ + else \ + VERSION="${TUSK_CLI_VERSION}"; \ + fi && \ + # Remove 'v' prefix if present for the filename + VERSION_NUM=$(echo "$VERSION" | sed 's/^v//') && \ + # Detect architecture (x86_64 or arm64) + ARCH=$(uname -m) && \ + case "$ARCH" in \ + x86_64) ARCH_NAME="x86_64" ;; \ + aarch64|arm64) ARCH_NAME="arm64" ;; \ + *) echo "Unsupported architecture: $ARCH" && exit 1 ;; \ + esac && \ + # Construct download URL (archives are named like tusk-drift-cli_0.1.35_Linux_x86_64.tar.gz) + DOWNLOAD_URL="https://github.com/Use-Tusk/tusk-drift-cli/releases/download/${VERSION}/tusk-drift-cli_${VERSION_NUM}_Linux_${ARCH_NAME}.tar.gz" && \ + echo "Downloading Tusk CLI from: $DOWNLOAD_URL" && \ + curl -fsSL "$DOWNLOAD_URL" -o /tmp/tusk.tar.gz && \ + tar -xzf /tmp/tusk.tar.gz -C /tmp && \ + mv /tmp/tusk /usr/local/bin/tusk && \ + chmod +x /usr/local/bin/tusk && \ + rm -rf /tmp/tusk.tar.gz /tmp/LICENSE /tmp/README.md && \ + tusk --version # Upgrade pip RUN pip install --upgrade pip diff --git a/drift/instrumentation/fastapi/e2e-tests/.tusk/config.yaml b/drift/instrumentation/fastapi/e2e-tests/.tusk/config.yaml index d83870c..f0df935 100644 --- a/drift/instrumentation/fastapi/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/fastapi/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/fastapi/e2e-tests/docker-compose.yml b/drift/instrumentation/fastapi/e2e-tests/docker-compose.yml index c241141..cf2e18c 100644 --- a/drift/instrumentation/fastapi/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/fastapi/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/fastapi/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/fastapi/e2e-tests/requirements.txt b/drift/instrumentation/fastapi/e2e-tests/requirements.txt index 25ca34f..47e8b46 100644 --- a/drift/instrumentation/fastapi/e2e-tests/requirements.txt +++ b/drift/instrumentation/fastapi/e2e-tests/requirements.txt @@ -2,5 +2,6 @@ fastapi>=0.115.0 uvicorn>=0.30.0 requests>=2.32.5 -httpx>=0.27.0 +# Strict replay sandbox routes outbound HTTP through a SOCKS proxy. +httpx[socks]>=0.27.0 diff --git a/drift/instrumentation/flask/e2e-tests/.tusk/config.yaml b/drift/instrumentation/flask/e2e-tests/.tusk/config.yaml index 817477d..78b1271 100644 --- a/drift/instrumentation/flask/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/flask/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/flask/e2e-tests/docker-compose.yml b/drift/instrumentation/flask/e2e-tests/docker-compose.yml index f42b4be..8c73754 100644 --- a/drift/instrumentation/flask/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/flask/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/flask/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/grpc/e2e-tests/.tusk/config.yaml b/drift/instrumentation/grpc/e2e-tests/.tusk/config.yaml index cd9e2bb..05100a8 100644 --- a/drift/instrumentation/grpc/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/grpc/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/grpc/e2e-tests/docker-compose.yml b/drift/instrumentation/grpc/e2e-tests/docker-compose.yml index 6372545..c0d45a7 100644 --- a/drift/instrumentation/grpc/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/grpc/e2e-tests/docker-compose.yml @@ -5,6 +5,11 @@ services: dockerfile: drift/instrumentation/grpc/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/grpc/e2e-tests/src/greeter_pb2_grpc.py b/drift/instrumentation/grpc/e2e-tests/src/greeter_pb2_grpc.py index fa28693..2d32d7e 100644 --- a/drift/instrumentation/grpc/e2e-tests/src/greeter_pb2_grpc.py +++ b/drift/instrumentation/grpc/e2e-tests/src/greeter_pb2_grpc.py @@ -5,7 +5,7 @@ import greeter_pb2 as greeter__pb2 -GRPC_GENERATED_VERSION = '1.76.0' +GRPC_GENERATED_VERSION = '1.78.0' GRPC_VERSION = grpc.__version__ _version_not_supported = False diff --git a/drift/instrumentation/httpx/e2e-tests/.tusk/config.yaml b/drift/instrumentation/httpx/e2e-tests/.tusk/config.yaml index ed91a49..09d36d6 100644 --- a/drift/instrumentation/httpx/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/httpx/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/httpx/e2e-tests/docker-compose.yml b/drift/instrumentation/httpx/e2e-tests/docker-compose.yml index 7db225a..ae57669 100644 --- a/drift/instrumentation/httpx/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/httpx/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/httpx/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/httpx/e2e-tests/requirements.txt b/drift/instrumentation/httpx/e2e-tests/requirements.txt index 9d4518d..8e48040 100644 --- a/drift/instrumentation/httpx/e2e-tests/requirements.txt +++ b/drift/instrumentation/httpx/e2e-tests/requirements.txt @@ -1,4 +1,5 @@ -e /sdk Flask>=3.1.2 -httpx>=0.28.1 +# Strict replay sandbox routes outbound HTTP through a SOCKS proxy. +httpx[socks]>=0.28.1 requests>=2.32.5 diff --git a/drift/instrumentation/psycopg/e2e-tests/.tusk/config.yaml b/drift/instrumentation/psycopg/e2e-tests/.tusk/config.yaml index 3c952d8..d9d8ffa 100644 --- a/drift/instrumentation/psycopg/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/psycopg/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/psycopg/e2e-tests/docker-compose.yml b/drift/instrumentation/psycopg/e2e-tests/docker-compose.yml index 3af56b1..34e6e0a 100644 --- a/drift/instrumentation/psycopg/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/psycopg/e2e-tests/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/instrumentation/psycopg/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/instrumentation/psycopg2/e2e-tests/.tusk/config.yaml b/drift/instrumentation/psycopg2/e2e-tests/.tusk/config.yaml index 1218f96..4e01e23 100644 --- a/drift/instrumentation/psycopg2/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/psycopg2/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/psycopg2/e2e-tests/docker-compose.yml b/drift/instrumentation/psycopg2/e2e-tests/docker-compose.yml index 08cf0b4..608fa98 100644 --- a/drift/instrumentation/psycopg2/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/psycopg2/e2e-tests/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/instrumentation/psycopg2/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/instrumentation/redis/e2e-tests/.tusk/config.yaml b/drift/instrumentation/redis/e2e-tests/.tusk/config.yaml index e86c376..588333a 100644 --- a/drift/instrumentation/redis/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/redis/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/redis/e2e-tests/docker-compose.yml b/drift/instrumentation/redis/e2e-tests/docker-compose.yml index 5d4c39f..84b269c 100644 --- a/drift/instrumentation/redis/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/redis/e2e-tests/docker-compose.yml @@ -13,6 +13,11 @@ services: dockerfile: drift/instrumentation/redis/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: redis: condition: service_healthy diff --git a/drift/instrumentation/requests/e2e-tests/.tusk/config.yaml b/drift/instrumentation/requests/e2e-tests/.tusk/config.yaml index 959280c..6edaa48 100644 --- a/drift/instrumentation/requests/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/requests/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/requests/e2e-tests/docker-compose.yml b/drift/instrumentation/requests/e2e-tests/docker-compose.yml index f1c1591..997da3a 100644 --- a/drift/instrumentation/requests/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/requests/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/requests/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/sqlalchemy/e2e-tests/.tusk/config.yaml b/drift/instrumentation/sqlalchemy/e2e-tests/.tusk/config.yaml index 1f10182..e8bb9d0 100644 --- a/drift/instrumentation/sqlalchemy/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/sqlalchemy/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/sqlalchemy/e2e-tests/docker-compose.yml b/drift/instrumentation/sqlalchemy/e2e-tests/docker-compose.yml index ce99b9b..6a29a0c 100644 --- a/drift/instrumentation/sqlalchemy/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/sqlalchemy/e2e-tests/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/instrumentation/sqlalchemy/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/instrumentation/sqlalchemy/e2e-tests/run.sh b/drift/instrumentation/sqlalchemy/e2e-tests/run.sh old mode 100644 new mode 100755 diff --git a/drift/instrumentation/urllib/e2e-tests/.tusk/config.yaml b/drift/instrumentation/urllib/e2e-tests/.tusk/config.yaml index 41294f6..ee93b43 100644 --- a/drift/instrumentation/urllib/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/urllib/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/urllib/e2e-tests/docker-compose.yml b/drift/instrumentation/urllib/e2e-tests/docker-compose.yml index 32f1585..4beb9b9 100644 --- a/drift/instrumentation/urllib/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/urllib/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/urllib/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/urllib3/e2e-tests/.tusk/config.yaml b/drift/instrumentation/urllib3/e2e-tests/.tusk/config.yaml index 9f66127..a0fbaae 100644 --- a/drift/instrumentation/urllib3/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/urllib3/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/urllib3/e2e-tests/docker-compose.yml b/drift/instrumentation/urllib3/e2e-tests/docker-compose.yml index 40cdfdf..10b39a7 100644 --- a/drift/instrumentation/urllib3/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/urllib3/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/urllib3/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/stack-tests/django-postgres/.tusk/config.yaml b/drift/stack-tests/django-postgres/.tusk/config.yaml index efcd04c..28ba50a 100644 --- a/drift/stack-tests/django-postgres/.tusk/config.yaml +++ b/drift/stack-tests/django-postgres/.tusk/config.yaml @@ -19,3 +19,7 @@ recording: sampling_rate: 1.0 export_spans: false exclude_paths: [] + +replay: + sandbox: + mode: strict diff --git a/drift/stack-tests/django-postgres/docker-compose.yml b/drift/stack-tests/django-postgres/docker-compose.yml index b51fd7f..c20e94f 100644 --- a/drift/stack-tests/django-postgres/docker-compose.yml +++ b/drift/stack-tests/django-postgres/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/stack-tests/django-postgres/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/stack-tests/django-redis/.tusk/config.yaml b/drift/stack-tests/django-redis/.tusk/config.yaml index 2fef147..4f6b316 100644 --- a/drift/stack-tests/django-redis/.tusk/config.yaml +++ b/drift/stack-tests/django-redis/.tusk/config.yaml @@ -22,3 +22,7 @@ recording: sampling_rate: 1.0 export_spans: false exclude_paths: [] + +replay: + sandbox: + mode: strict diff --git a/drift/stack-tests/django-redis/docker-compose.yml b/drift/stack-tests/django-redis/docker-compose.yml index e5ca482..1570b8a 100644 --- a/drift/stack-tests/django-redis/docker-compose.yml +++ b/drift/stack-tests/django-redis/docker-compose.yml @@ -13,6 +13,11 @@ services: dockerfile: drift/stack-tests/django-redis/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: redis: condition: service_healthy diff --git a/drift/stack-tests/fastapi-postgres/.tusk/config.yaml b/drift/stack-tests/fastapi-postgres/.tusk/config.yaml index f6f4023..2ad9679 100644 --- a/drift/stack-tests/fastapi-postgres/.tusk/config.yaml +++ b/drift/stack-tests/fastapi-postgres/.tusk/config.yaml @@ -19,3 +19,7 @@ recording: sampling_rate: 1.0 export_spans: false exclude_paths: [] + +replay: + sandbox: + mode: strict diff --git a/drift/stack-tests/fastapi-postgres/docker-compose.yml b/drift/stack-tests/fastapi-postgres/docker-compose.yml index 1fcdb20..3497e5e 100644 --- a/drift/stack-tests/fastapi-postgres/docker-compose.yml +++ b/drift/stack-tests/fastapi-postgres/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/stack-tests/fastapi-postgres/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/stack-tests/fastapi-sqlalchemy/.tusk/config.yaml b/drift/stack-tests/fastapi-sqlalchemy/.tusk/config.yaml index 9d81eea..746f3ea 100644 --- a/drift/stack-tests/fastapi-sqlalchemy/.tusk/config.yaml +++ b/drift/stack-tests/fastapi-sqlalchemy/.tusk/config.yaml @@ -19,3 +19,7 @@ recording: sampling_rate: 1.0 export_spans: false exclude_paths: [] + +replay: + sandbox: + mode: strict diff --git a/drift/stack-tests/fastapi-sqlalchemy/docker-compose.yml b/drift/stack-tests/fastapi-sqlalchemy/docker-compose.yml index c3aa3c8..25b8a82 100644 --- a/drift/stack-tests/fastapi-sqlalchemy/docker-compose.yml +++ b/drift/stack-tests/fastapi-sqlalchemy/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/stack-tests/fastapi-sqlalchemy/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/stack-tests/fastapi-sqlalchemy/run.sh b/drift/stack-tests/fastapi-sqlalchemy/run.sh old mode 100644 new mode 100755 From a7945361886fa0642ddb38336164477eb8c24543 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Wed, 18 Mar 2026 18:06:33 -0700 Subject: [PATCH 2/6] Run e2e workflow with service logs printed --- .github/workflows/e2e.yml | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index b5048a1..146180e 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -108,6 +108,29 @@ jobs: chmod +x ./drift/instrumentation/${{ matrix.library }}/e2e-tests/run.sh cd ./drift/instrumentation/${{ matrix.library }}/e2e-tests && ./run.sh 8000 + - name: Print replay logs for ${{ matrix.library }} + if: always() + run: | + shopt -s nullglob + logs=(./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs/*) + if [ ${#logs[@]} -eq 0 ]; then + echo "No replay logs found" + exit 0 + fi + + for f in "${logs[@]}"; do + echo "=== $f ===" + cat "$f" + done + + - name: Upload replay logs for ${{ matrix.library }} + if: always() + uses: actions/upload-artifact@v4 + with: + name: e2e-${{ matrix.library }}-replay-logs + path: ./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs/* + if-no-files-found: ignore + - name: Cleanup Docker resources if: always() run: | @@ -186,6 +209,29 @@ jobs: chmod +x ./drift/stack-tests/${{ matrix.test }}/run.sh cd ./drift/stack-tests/${{ matrix.test }} && ./run.sh 8000 + - name: Print replay logs for ${{ matrix.test }} + if: always() + run: | + shopt -s nullglob + logs=(./drift/stack-tests/${{ matrix.test }}/.tusk/logs/*) + if [ ${#logs[@]} -eq 0 ]; then + echo "No replay logs found" + exit 0 + fi + + for f in "${logs[@]}"; do + echo "=== $f ===" + cat "$f" + done + + - name: Upload replay logs for ${{ matrix.test }} + if: always() + uses: actions/upload-artifact@v4 + with: + name: stack-${{ matrix.test }}-replay-logs + path: ./drift/stack-tests/${{ matrix.test }}/.tusk/logs/* + if-no-files-found: ignore + - name: Cleanup Docker resources if: always() run: | @@ -257,6 +303,29 @@ jobs: chmod +x ./drift/instrumentation/requests/e2e-tests/run.sh cd ./drift/instrumentation/requests/e2e-tests && ./run.sh 8000 + - name: Print replay logs for requests smoke test + if: always() + run: | + shopt -s nullglob + logs=(./drift/instrumentation/requests/e2e-tests/.tusk/logs/*) + if [ ${#logs[@]} -eq 0 ]; then + echo "No replay logs found" + exit 0 + fi + + for f in "${logs[@]}"; do + echo "=== $f ===" + cat "$f" + done + + - name: Upload replay logs for requests smoke test + if: always() + uses: actions/upload-artifact@v4 + with: + name: requests-smoke-replay-logs + path: ./drift/instrumentation/requests/e2e-tests/.tusk/logs/* + if-no-files-found: ignore + - name: Cleanup Docker resources if: always() run: | From f27b3bdd7fcb1732aaa9e78368eaf1b7fb393cb4 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Wed, 18 Mar 2026 18:14:31 -0700 Subject: [PATCH 3/6] Fix --- .github/workflows/e2e.yml | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 146180e..8dfd5f8 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -111,8 +111,17 @@ jobs: - name: Print replay logs for ${{ matrix.library }} if: always() run: | + log_dir=./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs + if ! sudo test -d "$log_dir"; then + echo "No replay log directory found" + exit 0 + fi + + sudo chmod -R a+rX "$log_dir" || true + sudo chown -R "$(id -u):$(id -g)" "$log_dir" || true + shopt -s nullglob - logs=(./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs/*) + logs=("$log_dir"/*) if [ ${#logs[@]} -eq 0 ]; then echo "No replay logs found" exit 0 @@ -128,7 +137,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: e2e-${{ matrix.library }}-replay-logs - path: ./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs/* + path: ./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs if-no-files-found: ignore - name: Cleanup Docker resources @@ -212,8 +221,17 @@ jobs: - name: Print replay logs for ${{ matrix.test }} if: always() run: | + log_dir=./drift/stack-tests/${{ matrix.test }}/.tusk/logs + if ! sudo test -d "$log_dir"; then + echo "No replay log directory found" + exit 0 + fi + + sudo chmod -R a+rX "$log_dir" || true + sudo chown -R "$(id -u):$(id -g)" "$log_dir" || true + shopt -s nullglob - logs=(./drift/stack-tests/${{ matrix.test }}/.tusk/logs/*) + logs=("$log_dir"/*) if [ ${#logs[@]} -eq 0 ]; then echo "No replay logs found" exit 0 @@ -229,7 +247,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: stack-${{ matrix.test }}-replay-logs - path: ./drift/stack-tests/${{ matrix.test }}/.tusk/logs/* + path: ./drift/stack-tests/${{ matrix.test }}/.tusk/logs if-no-files-found: ignore - name: Cleanup Docker resources @@ -306,8 +324,17 @@ jobs: - name: Print replay logs for requests smoke test if: always() run: | + log_dir=./drift/instrumentation/requests/e2e-tests/.tusk/logs + if ! sudo test -d "$log_dir"; then + echo "No replay log directory found" + exit 0 + fi + + sudo chmod -R a+rX "$log_dir" || true + sudo chown -R "$(id -u):$(id -g)" "$log_dir" || true + shopt -s nullglob - logs=(./drift/instrumentation/requests/e2e-tests/.tusk/logs/*) + logs=("$log_dir"/*) if [ ${#logs[@]} -eq 0 ]; then echo "No replay logs found" exit 0 @@ -323,7 +350,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: requests-smoke-replay-logs - path: ./drift/instrumentation/requests/e2e-tests/.tusk/logs/* + path: ./drift/instrumentation/requests/e2e-tests/.tusk/logs if-no-files-found: ignore - name: Cleanup Docker resources From e8270397c7985a31842521f72a1982e6c100a5c8 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Wed, 18 Mar 2026 22:14:17 -0700 Subject: [PATCH 4/6] Debug --- .../grpc/e2e-tests/src/grpc_server.py | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py b/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py index 6f321c1..c4290d2 100644 --- a/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py +++ b/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py @@ -1,5 +1,7 @@ """gRPC server for e2e tests.""" +import os +import stat import time from concurrent import futures @@ -9,6 +11,70 @@ import grpc +def _log_device_probe(path: str): + """Print detailed device diagnostics for sandbox debugging.""" + try: + info = os.stat(path) + device_kind = "char" if stat.S_ISCHR(info.st_mode) else "other" + device_id = "-" + if stat.S_ISCHR(info.st_mode): + device_id = f"{os.major(info.st_rdev)}:{os.minor(info.st_rdev)}" + print( + f"[grpc probe] {path}: mode={oct(stat.S_IMODE(info.st_mode))} " + f"kind={device_kind} rdev={device_id} " + f"readable={os.access(path, os.R_OK)} writable={os.access(path, os.W_OK)}", + flush=True, + ) + except OSError as exc: + print( + f"[grpc probe] stat({path}) failed: errno={exc.errno} strerror={exc.strerror}", + flush=True, + ) + return + + try: + fd = os.open(path, os.O_RDONLY) + try: + data = os.read(fd, 1) + print(f"[grpc probe] read({path}) ok: bytes={len(data)}", flush=True) + finally: + os.close(fd) + except OSError as exc: + print( + f"[grpc probe] open/read({path}) failed: errno={exc.errno} strerror={exc.strerror}", + flush=True, + ) + + +def _log_startup_probe(): + """Emit diagnostics to pinpoint sandbox/device failures in CI.""" + print( + f"[grpc probe] pid={os.getpid()} uid={os.getuid()} euid={os.geteuid()} cwd={os.getcwd()}", + flush=True, + ) + try: + dev_entries = ", ".join(sorted(os.listdir("/dev"))) + print(f"[grpc probe] /dev entries: {dev_entries}", flush=True) + except OSError as exc: + print( + f"[grpc probe] listdir(/dev) failed: errno={exc.errno} strerror={exc.strerror}", + flush=True, + ) + + for device_path in ("/dev/urandom", "/dev/random", "/dev/null"): + _log_device_probe(device_path) + + if hasattr(os, "getrandom"): + try: + sample = os.getrandom(1) + print(f"[grpc probe] getrandom() ok: bytes={len(sample)}", flush=True) + except OSError as exc: + print( + f"[grpc probe] getrandom() failed: errno={exc.errno} strerror={exc.strerror}", + flush=True, + ) + + class GreeterServicer(greeter_pb2_grpc.GreeterServicer): """Implementation of the Greeter service.""" @@ -61,11 +127,19 @@ def Chat(self, request_iterator, context): def serve(port: int = 50051): """Start the gRPC server.""" + print("[grpc probe] before startup probe", flush=True) + _log_startup_probe() + print("[grpc probe] before grpc.server()", flush=True) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + print("[grpc probe] after grpc.server()", flush=True) greeter_pb2_grpc.add_GreeterServicer_to_server(GreeterServicer(), server) - server.add_insecure_port(f"[::]:{port}") + print("[grpc probe] after add_GreeterServicer_to_server()", flush=True) + bound_port = server.add_insecure_port(f"[::]:{port}") + print(f"[grpc probe] add_insecure_port returned {bound_port}", flush=True) + print("[grpc probe] before server.start()", flush=True) server.start() - print(f"gRPC server started on port {port}") + print("[grpc probe] after server.start()", flush=True) + print(f"gRPC server started on port {port}", flush=True) return server From 33242789ee90fc5f17e8a2506ad4ecd4cea62ad9 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Thu, 19 Mar 2026 17:07:02 -0700 Subject: [PATCH 5/6] Test with CLI in branch --- .github/workflows/e2e.yml | 77 ++++++++++++++++++- .../docker-compose.cli-override.yml | 7 ++ .../grpc/e2e-tests/src/grpc_server.py | 44 +++++++++++ 3 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 drift/instrumentation/e2e_common/docker-compose.cli-override.yml diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 8dfd5f8..d1f9abb 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -13,6 +13,9 @@ on: - ".github/workflows/e2e.yml" workflow_dispatch: {} +env: + TUSK_CLI_UNDER_TEST_REF: socket-location + jobs: discover: name: Discover Tests @@ -42,9 +45,45 @@ jobs: echo "e2e_matrix=$E2E_TESTS" >> $GITHUB_OUTPUT echo "stack_matrix=$STACK_TESTS" >> $GITHUB_OUTPUT + build-cli-under-test: + name: Build Tusk CLI Under Test + runs-on: ubuntu-latest + steps: + - name: Checkout Tusk CLI under test + uses: actions/checkout@v6 + with: + repository: Use-Tusk/tusk-drift-cli + ref: ${{ env.TUSK_CLI_UNDER_TEST_REF }} + path: tusk-drift-cli-src + fetch-depth: 1 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version-file: tusk-drift-cli-src/go.mod + cache-dependency-path: tusk-drift-cli-src/go.sum + + - name: Build Tusk CLI under test + working-directory: tusk-drift-cli-src + env: + CGO_ENABLED: "0" + GOOS: linux + GOARCH: amd64 + run: | + mkdir -p "$RUNNER_TEMP/tusk-cli-under-test" + go build -trimpath -o "$RUNNER_TEMP/tusk-cli-under-test/tusk" . + + - name: Upload Tusk CLI under test + uses: actions/upload-artifact@v4 + with: + name: tusk-cli-under-test-linux-amd64 + path: ${{ runner.temp }}/tusk-cli-under-test/tusk + if-no-files-found: error + retention-days: 1 + e2e: name: E2E - ${{ matrix.library }} - needs: discover + needs: [discover, build-cli-under-test] runs-on: ubuntu-latest timeout-minutes: 30 strategy: @@ -69,6 +108,15 @@ jobs: with: driver: docker + - name: Download Tusk CLI under test + uses: actions/download-artifact@v4 + with: + name: tusk-cli-under-test-linux-amd64 + path: ./.tmp/tusk-cli-under-test + + - name: Make Tusk CLI under test executable + run: chmod +x ./.tmp/tusk-cli-under-test/tusk + - name: Install SDK dependencies run: uv sync --all-extras @@ -101,7 +149,9 @@ jobs: - name: Run E2E tests for ${{ matrix.library }} env: + COMPOSE_FILE: docker-compose.yml:${{ github.workspace }}/drift/instrumentation/e2e_common/docker-compose.cli-override.yml DOCKER_DEFAULT_PLATFORM: linux/amd64 + TUSK_CLI_BIND_PATH: ${{ github.workspace }}/.tmp/tusk-cli-under-test/tusk TUSK_CLI_VERSION: ${{ steps.tusk-version.outputs.version }} TUSK_USE_RUST_CORE: "1" run: | @@ -153,7 +203,7 @@ jobs: stack: name: Stack - ${{ matrix.test }} - needs: discover + needs: [discover, build-cli-under-test] if: ${{ needs.discover.outputs.stack_matrix != '[]' && needs.discover.outputs.stack_matrix != '' }} runs-on: ubuntu-latest timeout-minutes: 30 @@ -179,6 +229,15 @@ jobs: with: driver: docker + - name: Download Tusk CLI under test + uses: actions/download-artifact@v4 + with: + name: tusk-cli-under-test-linux-amd64 + path: ./.tmp/tusk-cli-under-test + + - name: Make Tusk CLI under test executable + run: chmod +x ./.tmp/tusk-cli-under-test/tusk + - name: Install SDK dependencies run: uv sync --all-extras @@ -211,7 +270,9 @@ jobs: - name: Run stack tests for ${{ matrix.test }} env: + COMPOSE_FILE: docker-compose.yml:${{ github.workspace }}/drift/instrumentation/e2e_common/docker-compose.cli-override.yml DOCKER_DEFAULT_PLATFORM: linux/amd64 + TUSK_CLI_BIND_PATH: ${{ github.workspace }}/.tmp/tusk-cli-under-test/tusk TUSK_CLI_VERSION: ${{ steps.tusk-version.outputs.version }} TUSK_USE_RUST_CORE: "1" run: | @@ -263,6 +324,7 @@ jobs: non-rust-smoke: name: E2E Non-Rust Smoke - requests + needs: build-cli-under-test runs-on: ubuntu-latest timeout-minutes: 30 steps: @@ -282,6 +344,15 @@ jobs: with: driver: docker + - name: Download Tusk CLI under test + uses: actions/download-artifact@v4 + with: + name: tusk-cli-under-test-linux-amd64 + path: ./.tmp/tusk-cli-under-test + + - name: Make Tusk CLI under test executable + run: chmod +x ./.tmp/tusk-cli-under-test/tusk + - name: Install SDK dependencies run: uv sync --all-extras @@ -314,7 +385,9 @@ jobs: - name: Run non-rust smoke test env: + COMPOSE_FILE: docker-compose.yml:${{ github.workspace }}/drift/instrumentation/e2e_common/docker-compose.cli-override.yml DOCKER_DEFAULT_PLATFORM: linux/amd64 + TUSK_CLI_BIND_PATH: ${{ github.workspace }}/.tmp/tusk-cli-under-test/tusk TUSK_CLI_VERSION: ${{ steps.tusk-version.outputs.version }} TUSK_USE_RUST_CORE: "0" run: | diff --git a/drift/instrumentation/e2e_common/docker-compose.cli-override.yml b/drift/instrumentation/e2e_common/docker-compose.cli-override.yml new file mode 100644 index 0000000..d3756d1 --- /dev/null +++ b/drift/instrumentation/e2e_common/docker-compose.cli-override.yml @@ -0,0 +1,7 @@ +services: + app: + volumes: + - type: bind + source: ${TUSK_CLI_BIND_PATH} + target: /usr/local/bin/tusk + read_only: true diff --git a/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py b/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py index c4290d2..7caafe7 100644 --- a/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py +++ b/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py @@ -11,6 +11,48 @@ import grpc +def _log_selected_env(): + """Print relevant environment variables for sandbox debugging.""" + interesting_prefixes = ("TUSK_", "PYTHON", "LD_") + interesting = { + key: value + for key, value in os.environ.items() + if key.startswith(interesting_prefixes) + } + if not interesting: + print("[grpc probe] interesting env: ", flush=True) + return + + for key in sorted(interesting): + print(f"[grpc probe] env {key}={interesting[key]}", flush=True) + + +def _log_mountinfo(prefix: str): + """Print mountinfo entries rooted at a given mount prefix.""" + try: + with open("/proc/self/mountinfo", encoding="utf-8") as handle: + found = False + for raw_line in handle: + line = raw_line.rstrip("\n") + left, separator, _right = line.partition(" - ") + if not separator: + continue + fields = left.split() + if len(fields) < 5: + continue + mount_point = fields[4] + if mount_point == prefix or mount_point.startswith(f"{prefix}/"): + print(f"[grpc probe] mountinfo {mount_point}: {line}", flush=True) + found = True + if not found: + print(f"[grpc probe] mountinfo: no entries found for {prefix}", flush=True) + except OSError as exc: + print( + f"[grpc probe] read(/proc/self/mountinfo) failed: errno={exc.errno} strerror={exc.strerror}", + flush=True, + ) + + def _log_device_probe(path: str): """Print detailed device diagnostics for sandbox debugging.""" try: @@ -52,6 +94,8 @@ def _log_startup_probe(): f"[grpc probe] pid={os.getpid()} uid={os.getuid()} euid={os.geteuid()} cwd={os.getcwd()}", flush=True, ) + _log_selected_env() + _log_mountinfo("/dev") try: dev_entries = ", ".join(sorted(os.listdir("/dev"))) print(f"[grpc probe] /dev entries: {dev_entries}", flush=True) From 69ad3d6cd998fdf60b89ff7297eefeb799f42519 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Fri, 20 Mar 2026 10:00:12 -0700 Subject: [PATCH 6/6] Clean up --- .github/workflows/e2e.yml | 80 +----------- .../docker-compose.cli-override.yml | 7 - .../grpc/e2e-tests/src/grpc_server.py | 122 +----------------- 3 files changed, 7 insertions(+), 202 deletions(-) delete mode 100644 drift/instrumentation/e2e_common/docker-compose.cli-override.yml diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index d1f9abb..a07570c 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -13,9 +13,6 @@ on: - ".github/workflows/e2e.yml" workflow_dispatch: {} -env: - TUSK_CLI_UNDER_TEST_REF: socket-location - jobs: discover: name: Discover Tests @@ -45,45 +42,9 @@ jobs: echo "e2e_matrix=$E2E_TESTS" >> $GITHUB_OUTPUT echo "stack_matrix=$STACK_TESTS" >> $GITHUB_OUTPUT - build-cli-under-test: - name: Build Tusk CLI Under Test - runs-on: ubuntu-latest - steps: - - name: Checkout Tusk CLI under test - uses: actions/checkout@v6 - with: - repository: Use-Tusk/tusk-drift-cli - ref: ${{ env.TUSK_CLI_UNDER_TEST_REF }} - path: tusk-drift-cli-src - fetch-depth: 1 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version-file: tusk-drift-cli-src/go.mod - cache-dependency-path: tusk-drift-cli-src/go.sum - - - name: Build Tusk CLI under test - working-directory: tusk-drift-cli-src - env: - CGO_ENABLED: "0" - GOOS: linux - GOARCH: amd64 - run: | - mkdir -p "$RUNNER_TEMP/tusk-cli-under-test" - go build -trimpath -o "$RUNNER_TEMP/tusk-cli-under-test/tusk" . - - - name: Upload Tusk CLI under test - uses: actions/upload-artifact@v4 - with: - name: tusk-cli-under-test-linux-amd64 - path: ${{ runner.temp }}/tusk-cli-under-test/tusk - if-no-files-found: error - retention-days: 1 - e2e: name: E2E - ${{ matrix.library }} - needs: [discover, build-cli-under-test] + needs: discover runs-on: ubuntu-latest timeout-minutes: 30 strategy: @@ -108,15 +69,6 @@ jobs: with: driver: docker - - name: Download Tusk CLI under test - uses: actions/download-artifact@v4 - with: - name: tusk-cli-under-test-linux-amd64 - path: ./.tmp/tusk-cli-under-test - - - name: Make Tusk CLI under test executable - run: chmod +x ./.tmp/tusk-cli-under-test/tusk - - name: Install SDK dependencies run: uv sync --all-extras @@ -149,9 +101,7 @@ jobs: - name: Run E2E tests for ${{ matrix.library }} env: - COMPOSE_FILE: docker-compose.yml:${{ github.workspace }}/drift/instrumentation/e2e_common/docker-compose.cli-override.yml DOCKER_DEFAULT_PLATFORM: linux/amd64 - TUSK_CLI_BIND_PATH: ${{ github.workspace }}/.tmp/tusk-cli-under-test/tusk TUSK_CLI_VERSION: ${{ steps.tusk-version.outputs.version }} TUSK_USE_RUST_CORE: "1" run: | @@ -189,6 +139,7 @@ jobs: name: e2e-${{ matrix.library }}-replay-logs path: ./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs if-no-files-found: ignore + include-hidden-files: true - name: Cleanup Docker resources if: always() @@ -203,7 +154,7 @@ jobs: stack: name: Stack - ${{ matrix.test }} - needs: [discover, build-cli-under-test] + needs: discover if: ${{ needs.discover.outputs.stack_matrix != '[]' && needs.discover.outputs.stack_matrix != '' }} runs-on: ubuntu-latest timeout-minutes: 30 @@ -229,15 +180,6 @@ jobs: with: driver: docker - - name: Download Tusk CLI under test - uses: actions/download-artifact@v4 - with: - name: tusk-cli-under-test-linux-amd64 - path: ./.tmp/tusk-cli-under-test - - - name: Make Tusk CLI under test executable - run: chmod +x ./.tmp/tusk-cli-under-test/tusk - - name: Install SDK dependencies run: uv sync --all-extras @@ -270,9 +212,7 @@ jobs: - name: Run stack tests for ${{ matrix.test }} env: - COMPOSE_FILE: docker-compose.yml:${{ github.workspace }}/drift/instrumentation/e2e_common/docker-compose.cli-override.yml DOCKER_DEFAULT_PLATFORM: linux/amd64 - TUSK_CLI_BIND_PATH: ${{ github.workspace }}/.tmp/tusk-cli-under-test/tusk TUSK_CLI_VERSION: ${{ steps.tusk-version.outputs.version }} TUSK_USE_RUST_CORE: "1" run: | @@ -310,6 +250,7 @@ jobs: name: stack-${{ matrix.test }}-replay-logs path: ./drift/stack-tests/${{ matrix.test }}/.tusk/logs if-no-files-found: ignore + include-hidden-files: true - name: Cleanup Docker resources if: always() @@ -324,7 +265,6 @@ jobs: non-rust-smoke: name: E2E Non-Rust Smoke - requests - needs: build-cli-under-test runs-on: ubuntu-latest timeout-minutes: 30 steps: @@ -344,15 +284,6 @@ jobs: with: driver: docker - - name: Download Tusk CLI under test - uses: actions/download-artifact@v4 - with: - name: tusk-cli-under-test-linux-amd64 - path: ./.tmp/tusk-cli-under-test - - - name: Make Tusk CLI under test executable - run: chmod +x ./.tmp/tusk-cli-under-test/tusk - - name: Install SDK dependencies run: uv sync --all-extras @@ -385,9 +316,7 @@ jobs: - name: Run non-rust smoke test env: - COMPOSE_FILE: docker-compose.yml:${{ github.workspace }}/drift/instrumentation/e2e_common/docker-compose.cli-override.yml DOCKER_DEFAULT_PLATFORM: linux/amd64 - TUSK_CLI_BIND_PATH: ${{ github.workspace }}/.tmp/tusk-cli-under-test/tusk TUSK_CLI_VERSION: ${{ steps.tusk-version.outputs.version }} TUSK_USE_RUST_CORE: "0" run: | @@ -425,6 +354,7 @@ jobs: name: requests-smoke-replay-logs path: ./drift/instrumentation/requests/e2e-tests/.tusk/logs if-no-files-found: ignore + include-hidden-files: true - name: Cleanup Docker resources if: always() diff --git a/drift/instrumentation/e2e_common/docker-compose.cli-override.yml b/drift/instrumentation/e2e_common/docker-compose.cli-override.yml deleted file mode 100644 index d3756d1..0000000 --- a/drift/instrumentation/e2e_common/docker-compose.cli-override.yml +++ /dev/null @@ -1,7 +0,0 @@ -services: - app: - volumes: - - type: bind - source: ${TUSK_CLI_BIND_PATH} - target: /usr/local/bin/tusk - read_only: true diff --git a/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py b/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py index 7caafe7..6f321c1 100644 --- a/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py +++ b/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py @@ -1,7 +1,5 @@ """gRPC server for e2e tests.""" -import os -import stat import time from concurrent import futures @@ -11,114 +9,6 @@ import grpc -def _log_selected_env(): - """Print relevant environment variables for sandbox debugging.""" - interesting_prefixes = ("TUSK_", "PYTHON", "LD_") - interesting = { - key: value - for key, value in os.environ.items() - if key.startswith(interesting_prefixes) - } - if not interesting: - print("[grpc probe] interesting env: ", flush=True) - return - - for key in sorted(interesting): - print(f"[grpc probe] env {key}={interesting[key]}", flush=True) - - -def _log_mountinfo(prefix: str): - """Print mountinfo entries rooted at a given mount prefix.""" - try: - with open("/proc/self/mountinfo", encoding="utf-8") as handle: - found = False - for raw_line in handle: - line = raw_line.rstrip("\n") - left, separator, _right = line.partition(" - ") - if not separator: - continue - fields = left.split() - if len(fields) < 5: - continue - mount_point = fields[4] - if mount_point == prefix or mount_point.startswith(f"{prefix}/"): - print(f"[grpc probe] mountinfo {mount_point}: {line}", flush=True) - found = True - if not found: - print(f"[grpc probe] mountinfo: no entries found for {prefix}", flush=True) - except OSError as exc: - print( - f"[grpc probe] read(/proc/self/mountinfo) failed: errno={exc.errno} strerror={exc.strerror}", - flush=True, - ) - - -def _log_device_probe(path: str): - """Print detailed device diagnostics for sandbox debugging.""" - try: - info = os.stat(path) - device_kind = "char" if stat.S_ISCHR(info.st_mode) else "other" - device_id = "-" - if stat.S_ISCHR(info.st_mode): - device_id = f"{os.major(info.st_rdev)}:{os.minor(info.st_rdev)}" - print( - f"[grpc probe] {path}: mode={oct(stat.S_IMODE(info.st_mode))} " - f"kind={device_kind} rdev={device_id} " - f"readable={os.access(path, os.R_OK)} writable={os.access(path, os.W_OK)}", - flush=True, - ) - except OSError as exc: - print( - f"[grpc probe] stat({path}) failed: errno={exc.errno} strerror={exc.strerror}", - flush=True, - ) - return - - try: - fd = os.open(path, os.O_RDONLY) - try: - data = os.read(fd, 1) - print(f"[grpc probe] read({path}) ok: bytes={len(data)}", flush=True) - finally: - os.close(fd) - except OSError as exc: - print( - f"[grpc probe] open/read({path}) failed: errno={exc.errno} strerror={exc.strerror}", - flush=True, - ) - - -def _log_startup_probe(): - """Emit diagnostics to pinpoint sandbox/device failures in CI.""" - print( - f"[grpc probe] pid={os.getpid()} uid={os.getuid()} euid={os.geteuid()} cwd={os.getcwd()}", - flush=True, - ) - _log_selected_env() - _log_mountinfo("/dev") - try: - dev_entries = ", ".join(sorted(os.listdir("/dev"))) - print(f"[grpc probe] /dev entries: {dev_entries}", flush=True) - except OSError as exc: - print( - f"[grpc probe] listdir(/dev) failed: errno={exc.errno} strerror={exc.strerror}", - flush=True, - ) - - for device_path in ("/dev/urandom", "/dev/random", "/dev/null"): - _log_device_probe(device_path) - - if hasattr(os, "getrandom"): - try: - sample = os.getrandom(1) - print(f"[grpc probe] getrandom() ok: bytes={len(sample)}", flush=True) - except OSError as exc: - print( - f"[grpc probe] getrandom() failed: errno={exc.errno} strerror={exc.strerror}", - flush=True, - ) - - class GreeterServicer(greeter_pb2_grpc.GreeterServicer): """Implementation of the Greeter service.""" @@ -171,19 +61,11 @@ def Chat(self, request_iterator, context): def serve(port: int = 50051): """Start the gRPC server.""" - print("[grpc probe] before startup probe", flush=True) - _log_startup_probe() - print("[grpc probe] before grpc.server()", flush=True) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - print("[grpc probe] after grpc.server()", flush=True) greeter_pb2_grpc.add_GreeterServicer_to_server(GreeterServicer(), server) - print("[grpc probe] after add_GreeterServicer_to_server()", flush=True) - bound_port = server.add_insecure_port(f"[::]:{port}") - print(f"[grpc probe] add_insecure_port returned {bound_port}", flush=True) - print("[grpc probe] before server.start()", flush=True) + server.add_insecure_port(f"[::]:{port}") server.start() - print("[grpc probe] after server.start()", flush=True) - print(f"gRPC server started on port {port}", flush=True) + print(f"gRPC server started on port {port}") return server