diff --git a/Dockerfile b/Dockerfile index 096068a..f87a996 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,16 @@ FROM nginx:alpine -RUN apk add python3 py3-pip supervisor -RUN pip3 install --break-system-packages google-cloud-run +RUN apk add curl jq bash supervisor COPY nginx.conf /etc/nginx/nginx.conf -COPY supervisord.conf /etc/supervisord.conf +COPY supervisor/supervisord.conf /etc/supervisord.conf RUN mkdir -p /var/log/supervisor +RUN mkdir -p /etc/supervisor/conf.d -COPY cleanup_watcher.py /usr/local/bin/cleanup_watcher.py -RUN chmod +x /usr/local/bin/cleanup_watcher.py +COPY supervisor/conf.d /etc/supervisor/conf.d + +COPY cleanup.bash /usr/local/bin/cleanup.bash +RUN chmod +x /usr/local/bin/cleanup.bash CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] \ No newline at end of file diff --git a/cleanup.bash b/cleanup.bash new file mode 100644 index 0000000..72aeb4a --- /dev/null +++ b/cleanup.bash @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +set -uo pipefail + +PARENT="${PARENT:?PARENT env var required}" +SERVICE_NAME="${K_SERVICE:?K_SERVICE env var required}" + +# ============================================= +# Cleanup / Crash Handler +# ============================================= +cleanup() { + EXIT_CODE=$? + if [ $EXIT_CODE -ne 0 ]; then + echo "==================================================================" + echo "❌ SCRIPT CRASHED with exit code ${EXIT_CODE}" + echo " This usually means something went wrong during health checking" + echo " or during the delete operation." + echo "==================================================================" + else + echo "Script finished normally." + fi +} + +# Catch errors, interrupts, and normal exit +trap cleanup EXIT +trap 'echo "❌ Script interrupted (SIGINT)"; exit 1' INT +trap 'echo "❌ Script terminated (SIGTERM)"; exit 1' TERM + +delete_service() { + echo "Flask appears down → Deleting service ${PARENT}/services/${SERVICE_NAME}" + + # Get an OAuth2 access token from the GCE/Cloud Run metadata server + local token + token=$(curl -s -H "Metadata-Flavor: Google" \ + "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \ + | jq -r .access_token) + + if [ -z "$token" ]; then + echo "Delete failed: could not obtain access token" + return 1 + fi + + local http_code + http_code=$(curl -s -o /tmp/delete_response.json -w "%{http_code}" \ + -X DELETE \ + -H "Authorization: Bearer ${token}" \ + "https://run.googleapis.com/v2/${PARENT}/services/${SERVICE_NAME}") + + if [[ "$http_code" == 2* ]]; then + echo "Service deletion request accepted (HTTP ${http_code})" + else + echo "Delete failed (HTTP ${http_code}): $(cat /tmp/delete_response.json)" + fi +} + +while true; do + sleep 30 + response=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 "http://127.0.0.1/geode/health") + echo "response ${response}" + + if [ "$response" != "200" ]; then + delete_service + break + fi +done + +echo "Health check loop ended." \ No newline at end of file diff --git a/cleanup_watcher.py b/cleanup_watcher.py deleted file mode 100644 index 81da247..0000000 --- a/cleanup_watcher.py +++ /dev/null @@ -1,31 +0,0 @@ -import os -import time -import requests -from google.cloud import run_v2 - - -PARENT = os.getenv("PARENT") -SERVICE_NAME = os.getenv("K_SERVICE") - - -def delete_service(): - print("Deleting service") - client = run_v2.ServicesClient() - name = f"{PARENT}/services/{SERVICE_NAME}" - try: - print(f"Flask appears down → Deleting service {name}") - client.delete_service(name=name) - except Exception as e: - print(f"Delete failed: {e}") - - -while True: - time.sleep(30) - try: - response = requests.get("http://127.0.0.1/geode/health", timeout=5) - print("response", response, flush=True) - if response.status_code != 200: - raise Exception("Bad status") - except Exception: - delete_service() - break diff --git a/supervisor/conf.d/cleanup.conf b/supervisor/conf.d/cleanup.conf new file mode 100644 index 0000000..4429623 --- /dev/null +++ b/supervisor/conf.d/cleanup.conf @@ -0,0 +1,8 @@ +[program:cleanup] +command=bash /usr/local/bin/cleanup.bash +autostart=true +autorestart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 \ No newline at end of file diff --git a/supervisor/conf.d/nginx.conf b/supervisor/conf.d/nginx.conf new file mode 100644 index 0000000..7162fb9 --- /dev/null +++ b/supervisor/conf.d/nginx.conf @@ -0,0 +1,8 @@ +[program:nginx] +command=nginx -g 'daemon off;' +autostart=true +autorestart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 \ No newline at end of file diff --git a/supervisor/supervisord.conf b/supervisor/supervisord.conf new file mode 100644 index 0000000..be54755 --- /dev/null +++ b/supervisor/supervisord.conf @@ -0,0 +1,8 @@ +[supervisord] +nodaemon=true +logfile=/dev/stdout +logfile_maxbytes=0 +pidfile=/var/run/supervisord.pid + +[include] +files = /etc/supervisor/conf.d/*.conf \ No newline at end of file diff --git a/supervisord.conf b/supervisord.conf deleted file mode 100644 index 448e6b2..0000000 --- a/supervisord.conf +++ /dev/null @@ -1,23 +0,0 @@ -[supervisord] -nodaemon=true -logfile=/dev/stdout -logfile_maxbytes=0 -pidfile=/var/run/supervisord.pid - -[program:nginx] -command=nginx -g 'daemon off;' -autostart=true -autorestart=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - -[program:cleanup-watcher] -command=python3 /usr/local/bin/cleanup_watcher.py -autostart=true -autorestart=true -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 \ No newline at end of file