Compare commits

..
4 Commits
Author SHA1 Message Date
Zeusina aae200eeea fix: 🐛 fixed failed error message on non changes 2026-03-15 21:35:59 +03:00
Zeusina c51e4ea188 feat: implemented token auth 2026-03-15 21:00:42 +03:00
Zeusina 4dbe4da184 feat: add cloudflare auto ttl 2026-03-15 19:34:38 +03:00
Zeusina 735e2052e8 feat: init commit with main func 2026-03-15 19:29:27 +03:00
5 changed files with 25 additions and 52 deletions
-3
View File
@@ -79,9 +79,6 @@ RECONCILE_INTERVAL=60s
# Coalesces rapid bursts (e.g. rolling restarts) into a single reconcile. # Coalesces rapid bursts (e.g. rolling restarts) into a single reconcile.
DEBOUNCE_DELAY=5s DEBOUNCE_DELAY=5s
# Log level for watcher output. Allowed: debug, info, warn, error
LOG_LEVEL=info
# ── Docker ──────────────────────────────────────────────────────────────────── # ── Docker ────────────────────────────────────────────────────────────────────
# Docker daemon endpoint. Leave empty to use the default Unix socket. # Docker daemon endpoint. Leave empty to use the default Unix socket.
+3 -2
View File
@@ -13,8 +13,9 @@ traefik-dns-watcher
.env .env
.env.local .env.local
# IDE settings # IDE settings (keep MCP config)
.vscode/ .vscode/*
!.vscode/mcp.json
# OS files # OS files
.DS_Store .DS_Store
+13
View File
@@ -0,0 +1,13 @@
{
"servers": {
"git": {
"type": "stdio",
"command": "git-mcp-go",
"args": [
"serve",
"D:\\Projects\\DevOps\\traefik-dns-watcher"
]
}
},
"inputs": []
}
-8
View File
@@ -30,7 +30,6 @@ type Config struct {
ReconcileInterval time.Duration ReconcileInterval time.Duration
DebounceDelay time.Duration DebounceDelay time.Duration
LogLevel string
RecordTTL int RecordTTL int
CloudflareAutoTTL bool CloudflareAutoTTL bool
@@ -99,13 +98,6 @@ func LoadConfig() (*Config, error) {
return nil, fmt.Errorf("CF_AUTO_TTL: invalid boolean %q: %w", autoTTLStr, err) return nil, fmt.Errorf("CF_AUTO_TTL: invalid boolean %q: %w", autoTTLStr, err)
} }
cfg.LogLevel = strings.ToLower(envOrDefault("LOG_LEVEL", "info"))
switch cfg.LogLevel {
case "debug", "info", "warn", "error":
default:
return nil, fmt.Errorf("LOG_LEVEL: invalid value %q (allowed: debug, info, warn, error)", cfg.LogLevel)
}
cfg.ExcludeRouters = make(map[string]struct{}) cfg.ExcludeRouters = make(map[string]struct{})
if v := os.Getenv("EXCLUDE_ROUTERS"); v != "" { if v := os.Getenv("EXCLUDE_ROUTERS"); v != "" {
for _, r := range strings.Split(v, ",") { for _, r := range strings.Split(v, ",") {
+9 -39
View File
@@ -22,28 +22,21 @@ func main() {
return return
} }
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
})))
cfg, err := LoadConfig() cfg, err := LoadConfig()
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "configuration error:", err) slog.Error("configuration error", "error", err)
os.Exit(1) os.Exit(1)
} }
logLevel, err := parseLogLevel(cfg.LogLevel)
if err != nil {
fmt.Fprintln(os.Stderr, "configuration error:", err)
os.Exit(1)
}
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: logLevel,
})))
slog.Info("traefik-dns-watcher starting", slog.Info("traefik-dns-watcher starting",
"traefik_url", cfg.TraefikURL, "traefik_url", cfg.TraefikURL,
"zones", cfg.Zones, "zones", cfg.Zones,
"repo_path", cfg.RepoPath, "repo_path", cfg.RepoPath,
"dynamic_dir", cfg.DynamicDir, "dynamic_dir", cfg.DynamicDir,
"log_level", cfg.LogLevel,
"git_https_token_enabled", cfg.GitAuthToken != "", "git_https_token_enabled", cfg.GitAuthToken != "",
"git_auth_username", cfg.GitAuthUsername, "git_auth_username", cfg.GitAuthUsername,
"reconcile_interval", cfg.ReconcileInterval, "reconcile_interval", cfg.ReconcileInterval,
@@ -122,21 +115,6 @@ func main() {
slog.Info("traefik-dns-watcher stopped") slog.Info("traefik-dns-watcher stopped")
} }
func parseLogLevel(v string) (slog.Level, error) {
switch strings.ToLower(v) {
case "debug":
return slog.LevelDebug, nil
case "info":
return slog.LevelInfo, nil
case "warn":
return slog.LevelWarn, nil
case "error":
return slog.LevelError, nil
default:
return 0, fmt.Errorf("LOG_LEVEL: invalid value %q (allowed: debug, info, warn, error)", v)
}
}
// maybeHandleGitAskpass serves username/password for git HTTPS auth in non-interactive mode. // maybeHandleGitAskpass serves username/password for git HTTPS auth in non-interactive mode.
// This process mode is only enabled for git child processes that set TDW_GIT_ASKPASS=1. // This process mode is only enabled for git child processes that set TDW_GIT_ASKPASS=1.
func maybeHandleGitAskpass() bool { func maybeHandleGitAskpass() bool {
@@ -195,8 +173,7 @@ type dockerEvent struct {
Type string `json:"Type"` Type string `json:"Type"`
Action string `json:"Action"` Action string `json:"Action"`
Actor struct { Actor struct {
ID string `json:"ID"` ID string `json:"ID"`
Attributes map[string]string `json:"Attributes"`
} `json:"Actor"` } `json:"Actor"`
} }
@@ -210,7 +187,7 @@ func runDockerEventLoop(ctx context.Context, trigger func()) error {
return fmt.Errorf("build docker HTTP client: %w", err) return fmt.Errorf("build docker HTTP client: %w", err)
} }
filterVal := `{"type":["container"],"event":["start","stop","die","destroy"]}` filterVal := `{"type":["container"]}`
eventsURL := baseURL + "/events?filters=" + url.QueryEscape(filterVal) eventsURL := baseURL + "/events?filters=" + url.QueryEscape(filterVal)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, eventsURL, nil) req, err := http.NewRequestWithContext(ctx, http.MethodGet, eventsURL, nil)
@@ -244,20 +221,13 @@ func runDockerEventLoop(ctx context.Context, trigger func()) error {
if evt.Type != "container" { if evt.Type != "container" {
continue continue
} }
// Docker may append extra details after ":" for some event kinds. switch evt.Action {
// We only care about the base action token.
action := evt.Action
if idx := strings.Index(action, ":"); idx >= 0 {
action = strings.TrimSpace(action[:idx])
}
switch action {
case "start", "stop", "die", "destroy": case "start", "stop", "die", "destroy":
actorID := evt.Actor.ID actorID := evt.Actor.ID
if len(actorID) > 12 { if len(actorID) > 12 {
actorID = actorID[:12] actorID = actorID[:12]
} }
slog.Debug("docker event received", "action", action, "id", actorID) slog.Debug("docker event received", "action", evt.Action, "id", actorID)
trigger() trigger()
} }
} }