#!/usr/bin/env bash set -euo pipefail DOCKER_BIN="${DOCKER_BIN:-/usr/local/bin/docker}" if [[ ! -x "${DOCKER_BIN}" ]]; then DOCKER_BIN="$(command -v docker)" fi fetch_with_retry() { local url="$1" shift local output="" local attempt for attempt in 1 2 3 4 5 6 7 8 9 10; do if output="$(curl -k -fsS --compressed "$@" "$url")"; then printf '%s' "$output" return 0 fi echo "not-ready url=${url} attempt=${attempt}" >&2 sleep 10 done return 1 } echo "== containers ==" "${DOCKER_BIN}" ps --filter 'name=nodedc-platform' --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' echo "== launcher storage check ==" "${DOCKER_BIN}" exec nodedc-platform-launcher-1 sh -lc \ 'touch /app/server/storage/.write-test /app/server/storage/uploads/.write-test && rm /app/server/storage/.write-test /app/server/storage/uploads/.write-test && echo storage-ok' echo "== launcher -> authentik api check ==" "${DOCKER_BIN}" exec nodedc-platform-launcher-1 sh -lc ' echo "$NODEDC_AUTHENTIK_BASE_URL" getent hosts nodedc-platform-authentik-server for attempt in 1 2 3 4 5 6 7 8 9 10; do if wget -qSO- \ --header "Authorization: Bearer $NODEDC_AUTHENTIK_SERVICE_TOKEN" \ "$NODEDC_AUTHENTIK_BASE_URL/api/v3/core/groups/?search=nodedc_admin" \ >/tmp/authentik-api-check.json \ 2>/tmp/authentik-api-check.headers; then head -n 25 /tmp/authentik-api-check.headers exit 0 fi head -n 25 /tmp/authentik-api-check.headers || true echo "authentik-api-not-ready attempt=$attempt" sleep 10 done exit 1 ' echo "== notification core health check ==" "${DOCKER_BIN}" exec nodedc-platform-notification-core-1 sh -lc \ 'wget -qSO- http://127.0.0.1:5185/healthz 2>&1 | head -n 25' echo "== ai workspace hub health check ==" "${DOCKER_BIN}" exec nodedc-platform-ai-workspace-hub-1 sh -lc \ 'node -e '"'"'fetch("http://127.0.0.1:18081/healthz").then(async (response) => { console.log(await response.text()); process.exit(response.ok ? 0 : 1); }).catch((error) => { console.error(error); process.exit(1); })'"'"'' echo "== ai workspace assistant health check ==" "${DOCKER_BIN}" exec nodedc-platform-ai-workspace-assistant-1 sh -lc \ 'node -e '"'"'fetch("http://127.0.0.1:18082/healthz").then(async (response) => { console.log(await response.text()); process.exit(response.ok ? 0 : 1); }).catch((error) => { console.error(error); process.exit(1); })'"'"'' echo "== auth flow check ==" auth_flow="$(fetch_with_retry https://id.nodedc.ru/if/flow/default-authentication-flow/)" printf '%s' "$auth_flow" \ | grep -aE 'syncFormFieldsBeforeSubmit|branding_custom_css = ""|Запросить доступ' echo "== public admin closed check ==" id_admin_status="$( curl -k -sS -o /dev/null -w '%{http_code}' https://id.nodedc.ru/if/admin/ )" if [[ "$id_admin_status" != "404" ]]; then echo "public id admin is not closed: status=${id_admin_status}" exit 1 fi echo "public-id-admin-closed-ok" echo "== technical admin css check ==" auth_admin_page="$( fetch_with_retry http://127.0.0.1:18080/if/admin/ -H 'Host: auth-admin.nas.nodedc' )" printf '%s' "$auth_admin_page" \ | grep -aE '|authentikBrand.branding_custom_css = ""' auth_admin_flow="$( fetch_with_retry http://127.0.0.1:18080/if/flow/default-authentication-flow/ -H 'Host: auth-admin.nas.nodedc' )" if printf '%s' "$auth_admin_flow" | grep -aq '|authentikBrand.branding_custom_css = ""' echo "== launcher bundle check ==" launcher_html="$(fetch_with_retry https://hub.nodedc.ru/ -H 'Accept: text/html')" launcher_asset="$( printf '%s' "$launcher_html" \ | grep -aoE 'index-[A-Za-z0-9_-]+\.js' \ | head -n 1 )" test -n "$launcher_asset" echo "launcher_asset=${launcher_asset}" if fetch_with_retry "https://hub.nodedc.ru/assets/${launcher_asset}" \ | grep -aq 'Заявка ожидает подтверждения'; then echo "old pending gate still present" exit 1 fi echo "launcher-pending-gate-ok" echo "runtime-verify-ok"