feat: add step-by-step connectivity diagnostics to health_check
All checks were successful
Deploy / deploy (push) Successful in 13s
All checks were successful
Deploy / deploy (push) Successful in 13s
Break connectivity check into three stages — DNS resolution, TCP connect, and API auth — each reported separately so failures pinpoint the exact layer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,11 +16,13 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
import argparse
|
import argparse
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from urllib.parse import urlparse
|
||||||
from typing import Dict, List, Optional, Tuple
|
from typing import Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
@@ -177,13 +179,38 @@ class OutlineSync:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def health_check(self) -> bool:
|
def health_check(self) -> bool:
|
||||||
print("Checking API connectivity...", end=" ", flush=True)
|
parsed = urlparse(self.base_url)
|
||||||
|
host = parsed.hostname or "outline"
|
||||||
|
port = parsed.port or (443 if parsed.scheme == "https" else 80)
|
||||||
|
|
||||||
|
print(f"Checking API connectivity to {self.base_url} ...")
|
||||||
|
|
||||||
|
# 1. DNS resolution
|
||||||
|
print(f" DNS resolve {host!r} ... ", end="", flush=True)
|
||||||
|
try:
|
||||||
|
ip = socket.gethostbyname(host)
|
||||||
|
print(f"✓ ({ip})")
|
||||||
|
except socket.gaierror as exc:
|
||||||
|
print(f"✗ DNS failed: {exc}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 2. TCP reachability
|
||||||
|
print(f" TCP connect {ip}:{port} ... ", end="", flush=True)
|
||||||
|
try:
|
||||||
|
with socket.create_connection((host, port), timeout=5):
|
||||||
|
print("✓")
|
||||||
|
except (socket.timeout, ConnectionRefusedError, OSError) as exc:
|
||||||
|
print(f"✗ {exc}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 3. API authentication
|
||||||
|
print(f" API auth ... ", end="", flush=True)
|
||||||
result = self._api("/api/auth.info")
|
result = self._api("/api/auth.info")
|
||||||
if result and "data" in result:
|
if result and "data" in result:
|
||||||
user = result["data"].get("user", {})
|
user = result["data"].get("user", {})
|
||||||
print(f"✓ ({user.get('name', 'unknown')})")
|
print(f"✓ (user: {user.get('name', 'unknown')})")
|
||||||
return True
|
return True
|
||||||
print("✗")
|
print("✗ bad response")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_collections(self) -> List[Dict]:
|
def get_collections(self) -> List[Dict]:
|
||||||
|
|||||||
Reference in New Issue
Block a user