|
9 | 9 | "fmt" |
10 | 10 | "io" |
11 | 11 | "net/http" |
| 12 | + "os" |
12 | 13 | "strings" |
13 | 14 | "time" |
14 | 15 | ) |
@@ -51,25 +52,43 @@ func NewCaddyAdminClient(host string) *CaddyAdminClient { |
51 | 52 |
|
52 | 53 | // Determine which host to use (three-tier fallback) |
53 | 54 | var targetHost string |
| 55 | + var strategyUsed string |
| 56 | + |
54 | 57 | if host != "" && host != "localhost" { |
55 | 58 | // Tier 1: Explicit host provided (e.g., from env var CADDY_ADMIN_HOST) |
56 | 59 | targetHost = host |
| 60 | + strategyUsed = "explicit_host" |
57 | 61 | } else { |
58 | 62 | // Tier 2: Auto-detect container IP via Docker SDK (best approach) |
59 | 63 | // RATIONALE: Bypasses localhost IPv4/IPv6 resolution issues |
60 | 64 | // NON-FATAL: If Docker SDK fails, fall back to localhost |
61 | 65 | ctx := context.Background() |
62 | 66 | if containerIP, err := GetCaddyContainerIP(ctx); err == nil { |
63 | 67 | targetHost = containerIP |
| 68 | + strategyUsed = "docker_sdk" |
64 | 69 | } else { |
65 | 70 | // Tier 3: Fall back to localhost (legacy behavior) |
66 | 71 | // WARNING: May fail with IPv6 resolution issues |
| 72 | + |
| 73 | + // CRITICAL: Log why Docker SDK failed (P0 finding from adversarial analysis) |
| 74 | + // RATIONALE: Silent failures are impossible to debug |
| 75 | + // NOTE: Can't use structured logger here (no RuntimeContext in constructor) |
| 76 | + // Using fmt.Fprintf to stderr as diagnostic output |
| 77 | + fmt.Fprintf(os.Stderr, "WARN: Caddy Admin API - Docker SDK container IP detection failed: %v\n", err) |
| 78 | + fmt.Fprintf(os.Stderr, "WARN: Caddy Admin API - Falling back to localhost:2019 (may fail with IPv6 issues)\n") |
| 79 | + fmt.Fprintf(os.Stderr, "INFO: Caddy Admin API - Run 'eos debug hecate --caddy' to diagnose Docker SDK issues\n") |
| 80 | + |
67 | 81 | targetHost = "localhost" |
| 82 | + strategyUsed = "localhost_fallback" |
68 | 83 | } |
69 | 84 | } |
70 | 85 |
|
71 | 86 | baseURL := fmt.Sprintf("http://%s:%d", targetHost, CaddyAdminAPIPort) |
72 | 87 |
|
| 88 | + // Log which strategy was used for observability (P2 finding from adversarial analysis) |
| 89 | + // NOTE: This goes to stderr so it doesn't pollute stdout but is visible to user |
| 90 | + fmt.Fprintf(os.Stderr, "INFO: Caddy Admin API client created - strategy=%s, url=%s\n", strategyUsed, baseURL) |
| 91 | + |
73 | 92 | return &CaddyAdminClient{ |
74 | 93 | BaseURL: baseURL, |
75 | 94 | HTTPClient: httpClient, |
|
0 commit comments