From bf95e87c5d1f77648188d13f1cc9425b18ffda32 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Sat, 24 Jan 2026 16:41:07 -0800 Subject: [PATCH] Add nettest container for CI/CD network debugging Add a simple Alpine-based container that tests connectivity to tailnet services (forge.tail8d86e.ts.net and registry.tail8d86e.ts.net). This helps diagnose networking issues when building containers from: - Docker on indri (during CI builds) - Minikube pods (manual testing) The workflow triggers on nettest-v* tags and also runs the container after building to verify Docker network access. Co-Authored-By: Claude Opus 4.5 --- .forgejo/workflows/build-nettest.yaml | 42 +++++++++ containers/nettest/Dockerfile | 24 +++++ containers/nettest/test-connectivity.sh | 115 ++++++++++++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 .forgejo/workflows/build-nettest.yaml create mode 100644 containers/nettest/Dockerfile create mode 100644 containers/nettest/test-connectivity.sh diff --git a/.forgejo/workflows/build-nettest.yaml b/.forgejo/workflows/build-nettest.yaml new file mode 100644 index 0000000..8597b01 --- /dev/null +++ b/.forgejo/workflows/build-nettest.yaml @@ -0,0 +1,42 @@ +# Build workflow for nettest container +# Triggered by tags: nettest-v* +# +# This container tests network connectivity to tailnet services. +# Use it to debug CI/CD networking issues. +name: Build nettest + +on: + push: + tags: + - 'nettest-v*' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Extract version from tag + id: version + run: | + # Tag is like "nettest-v1.0.0", extract "v1.0.0" + VERSION="${GITHUB_REF_NAME#nettest-}" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "Building version: $VERSION" + + - name: Build and push image + uses: ./.forgejo/actions/build-push-image + with: + context: containers/nettest + image_name: blumeops/nettest + version: ${{ steps.version.outputs.version }} + + - name: Test connectivity from Docker on indri + run: | + echo "========================================" + echo "Testing connectivity from Docker context" + echo "========================================" + echo "" + # Run the nettest container to verify Docker on indri can reach tailnet services + docker run --rm registry.tail8d86e.ts.net/blumeops/nettest:${{ steps.version.outputs.version }} diff --git a/containers/nettest/Dockerfile b/containers/nettest/Dockerfile new file mode 100644 index 0000000..97b03d6 --- /dev/null +++ b/containers/nettest/Dockerfile @@ -0,0 +1,24 @@ +# Network connectivity test container for blumeops CI/CD debugging +# +# This container tests connectivity to tailnet services from various environments: +# - Docker on indri (during CI build) +# - Minikube pods (manual testing) +# +# Build: +# docker build -t registry.tail8d86e.ts.net/blumeops/nettest:latest . +# +# Run: +# docker run --rm registry.tail8d86e.ts.net/blumeops/nettest:latest + +FROM alpine:3.21 + +RUN apk add --no-cache \ + curl \ + ca-certificates \ + jq \ + bind-tools + +COPY test-connectivity.sh /test-connectivity.sh +RUN chmod +x /test-connectivity.sh + +ENTRYPOINT ["/test-connectivity.sh"] diff --git a/containers/nettest/test-connectivity.sh b/containers/nettest/test-connectivity.sh new file mode 100644 index 0000000..d1fb6e4 --- /dev/null +++ b/containers/nettest/test-connectivity.sh @@ -0,0 +1,115 @@ +#!/bin/ash +# shellcheck shell=dash +# Network connectivity test script for blumeops +# Tests access to tailnet services from within the container + +set -e + +echo "========================================" +echo "BlumeOps Network Connectivity Test" +echo "========================================" +echo "" +echo "Timestamp: $(date -Iseconds)" +echo "Hostname: $(hostname)" +echo "" + +# Test targets +FORGE_HOST="forge.tail8d86e.ts.net" +REGISTRY_HOST="registry.tail8d86e.ts.net" + +test_dns() { + local host="$1" + echo "--- DNS: $host ---" + if nslookup "$host" 2>/dev/null; then + echo "DNS: OK" + return 0 + else + echo "DNS: FAILED" + return 1 + fi +} + +test_https() { + local url="$1" + local name="$2" + echo "" + echo "--- HTTPS: $name ---" + echo "URL: $url" + + # Try to fetch with verbose output + http_code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "$url" 2>&1) || true + + if [ "$http_code" = "200" ] || [ "$http_code" = "401" ] || [ "$http_code" = "302" ]; then + echo "HTTP Status: $http_code" + echo "Result: OK (service reachable)" + return 0 + elif [ -n "$http_code" ] && [ "$http_code" != "000" ]; then + echo "HTTP Status: $http_code" + echo "Result: OK (service reachable, status $http_code)" + return 0 + else + echo "HTTP Status: $http_code" + echo "Result: FAILED (could not connect)" + return 1 + fi +} + +test_registry_api() { + local host="$1" + echo "" + echo "--- Registry API: $host ---" + + # Try to query the registry API + response=$(curl -sf --max-time 10 "https://$host/v2/_catalog" 2>/dev/null) || true + + if [ -n "$response" ]; then + echo "Response: $response" + repo_count=$(echo "$response" | jq -r '.repositories | length' 2>/dev/null) || repo_count="unknown" + echo "Repository count: $repo_count" + echo "Result: OK" + return 0 + else + echo "Result: FAILED (no response from /v2/_catalog)" + return 1 + fi +} + +echo "========================================" +echo "Testing DNS Resolution" +echo "========================================" +dns_ok=0 +test_dns "$FORGE_HOST" && dns_ok=$((dns_ok + 1)) || true +echo "" +test_dns "$REGISTRY_HOST" && dns_ok=$((dns_ok + 1)) || true + +echo "" +echo "========================================" +echo "Testing HTTPS Connectivity" +echo "========================================" +https_ok=0 +test_https "https://$FORGE_HOST" "Forgejo" && https_ok=$((https_ok + 1)) || true +test_https "https://$REGISTRY_HOST/v2/" "Zot Registry" && https_ok=$((https_ok + 1)) || true + +echo "" +echo "========================================" +echo "Testing Registry API" +echo "========================================" +api_ok=0 +test_registry_api "$REGISTRY_HOST" && api_ok=1 || true + +echo "" +echo "========================================" +echo "Summary" +echo "========================================" +echo "DNS tests passed: $dns_ok/2" +echo "HTTPS tests passed: $https_ok/2" +echo "Registry API: $([ $api_ok -eq 1 ] && echo 'OK' || echo 'FAILED')" +echo "" + +if [ "$dns_ok" -eq 2 ] && [ "$https_ok" -eq 2 ] && [ "$api_ok" -eq 1 ]; then + echo "OVERALL: ALL TESTS PASSED" + exit 0 +else + echo "OVERALL: SOME TESTS FAILED" + exit 1 +fi