Files
tiennm99 c953c94dcf feat: sync Cloudflare DNS records with Traefik container hosts
Create a record for each Host(...) in running containers' Traefik router
labels, tagged with a configurable comment and optional tags, and delete
owned records once their host has been down for DELETE_AFTER.
2026-10-11 03:01:45 +07:00

45 lines
1.3 KiB
Go

package main
import (
"regexp"
"strings"
)
var (
routerRuleLabel = regexp.MustCompile(`^traefik\.http\.routers\.[^.]+\.rule$`)
hostMatcher = regexp.MustCompile(`Host\(([^)]*)\)`)
backtickValue = regexp.MustCompile("`([^`]+)`")
)
// HostsFromLabels returns the hostnames that a container's Traefik HTTP
// router rules match with Host(...), lowercased and deduplicated.
// HostRegexp and other matchers are ignored. A container labelled
// traefik.enable=false yields nothing.
func HostsFromLabels(labels map[string]string) []string {
if strings.EqualFold(strings.TrimSpace(labels["traefik.enable"]), "false") {
return nil
}
seen := map[string]bool{}
var hosts []string
for key, rule := range labels {
if !routerRuleLabel.MatchString(key) {
continue
}
for _, m := range hostMatcher.FindAllStringSubmatch(rule, -1) {
for _, v := range backtickValue.FindAllStringSubmatch(m[1], -1) {
host := strings.ToLower(strings.TrimSuffix(strings.TrimSpace(v[1]), "."))
if host != "" && !seen[host] {
seen[host] = true
hosts = append(hosts, host)
}
}
}
}
return hosts
}
// InDomain reports whether host is domain itself or a name under it.
func InDomain(host, domain string) bool {
return host == domain || strings.HasSuffix(host, "."+domain)
}