diff --git a/tests/unit/proxy-route-caddy.bats b/tests/unit/proxy-route-caddy.bats index cfe82c9c1..f64f6f412 100644 --- a/tests/unit/proxy-route-caddy.bats +++ b/tests/unit/proxy-route-caddy.bats @@ -37,6 +37,14 @@ teardown() { echo "status: $status" assert_success + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 + # Without --strip-prefix, /api/v0/Procfile reaches api as /api/v0/Procfile # which python's http.server returns 404 for. A 404 here proves the route # reaches api - web's catch-all would have returned 200. @@ -56,6 +64,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "" "404" run /bin/bash -c "dokku proxy:route:set $TEST_APP api /api/v0 --port 5001 --strip-prefix" @@ -64,6 +80,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "python3 -m http.server" } @@ -81,6 +105,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "" "404" run /bin/bash -c "dokku proxy:route:set $TEST_APP api /api/v0 --port 5001 --strip-prefix" @@ -89,6 +121,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "python3 -m http.server" run /bin/bash -c "dokku proxy:route:remove $TEST_APP /api/v0" @@ -107,17 +147,29 @@ teardown() { echo "status: $status" assert_success - local body="" + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 + + # Poll the response body via file to avoid shell-quoting issues with JSON + # bodies that contain embedded double quotes. + rm -f /tmp/route-removed-body + local attempt=0 for attempt in $(seq 1 30); do - run curl --connect-to "${TEST_APP}.${DOKKU_DOMAIN}:80:localhost:80" -kSs "http://${TEST_APP}.${DOKKU_DOMAIN}:80/api/v0/Procfile" - body="$output" - if ! grep -q 'python3 -m http.server' <<<"$body"; then + curl --connect-to "${TEST_APP}.${DOKKU_DOMAIN}:80:localhost:80" -kSso /tmp/route-removed-body "http://${TEST_APP}.${DOKKU_DOMAIN}:80/api/v0/Procfile" || true + if ! grep -q 'python3 -m http.server' /tmp/route-removed-body 2>/dev/null; then break fi sleep 1 done - echo "final body attempt $attempt: $body" - run /bin/bash -c "grep -c 'python3 -m http.server' <<<\"$body\" || true" + echo "final body attempt $attempt:" + cat /tmp/route-removed-body + echo + run /bin/bash -c "grep -c 'python3 -m http.server' /tmp/route-removed-body || true" assert_output "0" } diff --git a/tests/unit/proxy-route-nginx.bats b/tests/unit/proxy-route-nginx.bats index 5bad68a87..988762e6a 100644 --- a/tests/unit/proxy-route-nginx.bats +++ b/tests/unit/proxy-route-nginx.bats @@ -99,18 +99,21 @@ teardown() { # return 200 for /api/v0/Procfile so the polling loop in # assert_http_localhost_response_contains exits on status alone before # nginx picks up the new config. Hand-roll a retry that polls the BODY - # until it no longer contains api's marker. - local body="" + # written to a file (avoids shell-quoting issues with JSON bodies that + # contain embedded double quotes). + rm -f /tmp/route-removed-body + local attempt=0 for attempt in $(seq 1 30); do - run curl --connect-to "${TEST_APP}.${DOKKU_DOMAIN}:80:localhost:80" -kSs "http://${TEST_APP}.${DOKKU_DOMAIN}:80/api/v0/Procfile" - body="$output" - if ! grep -q 'python3 -m http.server' <<<"$body"; then + curl --connect-to "${TEST_APP}.${DOKKU_DOMAIN}:80:localhost:80" -kSso /tmp/route-removed-body "http://${TEST_APP}.${DOKKU_DOMAIN}:80/api/v0/Procfile" || true + if ! grep -q 'python3 -m http.server' /tmp/route-removed-body 2>/dev/null; then break fi sleep 1 done - echo "final body attempt $attempt: $body" - run /bin/bash -c "grep -c 'python3 -m http.server' <<<\"$body\" || true" + echo "final body attempt $attempt:" + cat /tmp/route-removed-body + echo + run /bin/bash -c "grep -c 'python3 -m http.server' /tmp/route-removed-body || true" assert_output "0" } diff --git a/tests/unit/proxy-route-openresty.bats b/tests/unit/proxy-route-openresty.bats index 3053542ff..3a43e14d4 100644 --- a/tests/unit/proxy-route-openresty.bats +++ b/tests/unit/proxy-route-openresty.bats @@ -37,6 +37,14 @@ teardown() { echo "status: $status" assert_success + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 + # Without --strip-prefix, /api/v0/Procfile reaches api as /api/v0/Procfile # which python's http.server returns 404 for. A 404 here proves the route # reaches api - web's catch-all would have returned 200. @@ -56,6 +64,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "" "404" run /bin/bash -c "dokku proxy:route:set $TEST_APP api /api/v0 --port 5001 --strip-prefix" @@ -64,6 +80,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "python3 -m http.server" } @@ -81,6 +105,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "" "404" run /bin/bash -c "dokku proxy:route:set $TEST_APP api /api/v0 --port 5001 --strip-prefix" @@ -89,6 +121,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "python3 -m http.server" run /bin/bash -c "dokku proxy:route:remove $TEST_APP /api/v0" @@ -107,17 +147,29 @@ teardown() { echo "status: $status" assert_success - local body="" + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 + + # Poll the response body via file to avoid shell-quoting issues with JSON + # bodies that contain embedded double quotes. + rm -f /tmp/route-removed-body + local attempt=0 for attempt in $(seq 1 30); do - run curl --connect-to "${TEST_APP}.${DOKKU_DOMAIN}:80:localhost:80" -kSs "http://${TEST_APP}.${DOKKU_DOMAIN}:80/api/v0/Procfile" - body="$output" - if ! grep -q 'python3 -m http.server' <<<"$body"; then + curl --connect-to "${TEST_APP}.${DOKKU_DOMAIN}:80:localhost:80" -kSso /tmp/route-removed-body "http://${TEST_APP}.${DOKKU_DOMAIN}:80/api/v0/Procfile" || true + if ! grep -q 'python3 -m http.server' /tmp/route-removed-body 2>/dev/null; then break fi sleep 1 done - echo "final body attempt $attempt: $body" - run /bin/bash -c "grep -c 'python3 -m http.server' <<<\"$body\" || true" + echo "final body attempt $attempt:" + cat /tmp/route-removed-body + echo + run /bin/bash -c "grep -c 'python3 -m http.server' /tmp/route-removed-body || true" assert_output "0" } diff --git a/tests/unit/proxy-route-traefik.bats b/tests/unit/proxy-route-traefik.bats index cb5f0e0ea..0c19d48b4 100644 --- a/tests/unit/proxy-route-traefik.bats +++ b/tests/unit/proxy-route-traefik.bats @@ -39,6 +39,14 @@ teardown() { echo "status: $status" assert_success + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 + # Without --strip-prefix, /api/v0/Procfile reaches api as /api/v0/Procfile # which python's http.server returns 404 for. A 404 here proves the route # reaches api - web's catch-all would have returned 200. @@ -58,6 +66,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "" "404" run /bin/bash -c "dokku proxy:route:set $TEST_APP api /api/v0 --port 5001 --strip-prefix" @@ -66,6 +82,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "python3 -m http.server" } @@ -84,6 +108,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "" "404" # Switch to --strip-prefix and verify api now serves the Procfile. @@ -93,6 +125,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 assert_http_localhost_response_contains "http" "${TEST_APP}.${DOKKU_DOMAIN}" "80" "/api/v0/Procfile" "python3 -m http.server" run /bin/bash -c "dokku proxy:route:remove $TEST_APP /api/v0" @@ -112,20 +152,31 @@ teardown() { echo "status: $status" assert_success + # Surface the actual labels attached to the api container so CI logs show + # whether docker-args-process-deploy emitted them correctly. + run /bin/bash -c "docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1 | jq . 2>/dev/null || docker inspect ${TEST_APP}.api.1 --format '{{json .Config.Labels}}' 2>&1" + echo "api labels: $output" + + # Give the daemon a moment to read the new labels. + sleep 5 + # After ps:rebuild, traefik recreates the api container without the route # labels, but there is still a race with traefik picking up the new state. - # Hand-roll a retry that polls the BODY until api's marker is gone. - local body="" + # Poll the response body via file to avoid shell-quoting issues with JSON + # bodies that contain embedded double quotes. + rm -f /tmp/route-removed-body + local attempt=0 for attempt in $(seq 1 30); do - run curl --connect-to "${TEST_APP}.${DOKKU_DOMAIN}:80:localhost:80" -kSs "http://${TEST_APP}.${DOKKU_DOMAIN}:80/api/v0/Procfile" - body="$output" - if ! grep -q 'python3 -m http.server' <<<"$body"; then + curl --connect-to "${TEST_APP}.${DOKKU_DOMAIN}:80:localhost:80" -kSso /tmp/route-removed-body "http://${TEST_APP}.${DOKKU_DOMAIN}:80/api/v0/Procfile" || true + if ! grep -q 'python3 -m http.server' /tmp/route-removed-body 2>/dev/null; then break fi sleep 1 done - echo "final body attempt $attempt: $body" - run /bin/bash -c "grep -c 'python3 -m http.server' <<<\"$body\" || true" + echo "final body attempt $attempt:" + cat /tmp/route-removed-body + echo + run /bin/bash -c "grep -c 'python3 -m http.server' /tmp/route-removed-body || true" assert_output "0" }