summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2026-08-20 21:45:20 +0200
committerMel <mel@rnrd.eu>2026-08-20 21:45:20 +0200
commit6a4c0a16118d0b545c3c5f6a08ecad432940c1cf (patch)
tree39da9f54ce2d8a3c2401d4744b2cad6c65565ed1
parentb52c860a7b1d3f57abc442bb8c1257f228d49536 (diff)
downloadddnnss-6a4c0a16118d0b545c3c5f6a08ecad432940c1cf.tar.zst
ddnnss-6a4c0a16118d0b545c3c5f6a08ecad432940c1cf.zip
Clean logging for modules
Signed-off-by: Mel <mel@rnrd.eu>
-rw-r--r--config.go4
-rw-r--r--main.go119
-rw-r--r--provider/dummy.go7
-rw-r--r--provider/provider.go10
-rw-r--r--source/file.go2
-rw-r--r--source/source.go10
-rw-r--r--source/static.go1
-rw-r--r--source/url.go2
8 files changed, 106 insertions, 49 deletions
diff --git a/config.go b/config.go
index 9cd614d..eaf9d50 100644
--- a/config.go
+++ b/config.go
@@ -43,10 +43,10 @@ func LoadConfig(path string) (*Config, error) {
return nil, fmt.Errorf("record %d: type must be A or AAAA", i)
}
if _, ok := cfg.Providers[r.Provider]; !ok {
- return nil, fmt.Errorf("record %d: unknown provider %q", i, r.Provider)
+ return nil, fmt.Errorf("record %d: unknown provider '%s'", i, r.Provider)
}
if _, ok := cfg.Sources[r.Source]; !ok {
- return nil, fmt.Errorf("record %d: unknown source %q", i, r.Source)
+ return nil, fmt.Errorf("record %d: unknown source '%s'", i, r.Source)
}
}
return &cfg, nil
diff --git a/main.go b/main.go
index cc99e9e..96a3ae7 100644
--- a/main.go
+++ b/main.go
@@ -27,50 +27,55 @@ func main() {
return
}
- slog.Info("ddnnss!", slog.String("version", version))
+ baseLog := slog.New(slog.NewTextHandler(os.Stderr, nil))
+ baseLog.Info("ddnnss!", slog.String("version", version))
cfg, err := LoadConfig(*configPath)
if err != nil {
- slog.Error("could not load config", slog.String("error", err.Error()))
+ baseLog.Error("could not load config", slog.String("error", err.Error()))
os.Exit(1)
}
- providers := map[string]provider.Provider{}
- sources := map[string]source.Source{}
+ providers, sources := createModules(baseLog, cfg)
- slog.Info("starting new cycle", slog.Int("records", len(cfg.Records)))
+ baseLog.Info("starting new cycle", slog.Int("records", len(cfg.Records)))
failed := false
for _, r := range cfg.Records {
fqdn := r.Name + "." + r.Zone
- log := slog.With("record", fqdn, "type", r.Type)
+ log := baseLog.With(
+ slog.Group("record",
+ slog.String("fqdn", fqdn),
+ slog.String("type", string(r.Type)),
+ ),
+ )
+
+ sourceName, providerName := r.Source, r.Provider
log.Info(
"ensuring record",
- slog.String("provider", r.Provider),
- slog.String("source", r.Source),
+ slog.String("provider", providerName),
+ slog.String("source", sourceName),
)
- p, ok := providers[r.Provider]
- if !ok {
- p, err = provider.New(log, cfg.Providers[r.Provider])
- if err != nil {
- log.Error("provider setup failed", "provider", r.Provider, "error", err)
- failed = true
- continue
- }
- providers[r.Provider] = p
+ s, ok := sources[sourceName]
+ if !ok || s == nil {
+ log.Error(
+ "skipping record, failed creating source",
+ slog.String("source", sourceName),
+ )
+ failed = true
+ continue
}
- s, ok := sources[r.Source]
- if !ok {
- s, err = source.New(log, cfg.Sources[r.Source])
- if err != nil {
- log.Error("source setup failed", "source", r.Source, "error", err)
- failed = true
- continue
- }
- sources[r.Source] = s
+ p, ok := providers[providerName]
+ if !ok || p == nil {
+ log.Error(
+ "skipping record, failed creating provider",
+ slog.String("provider", providerName),
+ )
+ failed = true
+ continue
}
family := source.IPv4
@@ -78,15 +83,22 @@ func main() {
family = source.IPv6
}
if !s.Supports(family) {
- log.Error("source cannot provide the needed address family",
- "source", r.Source, "family", family)
+ log.Error(
+ "skipping record, source cannot provide the needed address family",
+ slog.String("source", sourceName),
+ slog.String("family", string(family)),
+ )
failed = true
continue
}
addr, err := s.Lookup(family)
if err != nil {
- log.Error("address lookup failed", "source", r.Source, "error", err)
+ log.Error(
+ "failed record, address lookup failed",
+ slog.String("source", sourceName),
+ slog.String("error", err.Error()),
+ )
failed = true
continue
}
@@ -94,25 +106,62 @@ func main() {
prev, changed, err := p.Ensure(r.Zone, r.Name, r.Type, addr)
switch {
case err != nil:
- log.Error("update failed", "error", err)
+ log.Error("record update failed", slog.String("error", err.Error()))
failed = true
case changed && prev == "":
- log.Info("record created", "addr", addr)
+ log.Info("record created", slog.String("addr", addr.String()))
case changed:
- log.Info("record updated", "from", prev, "to", addr)
+ log.Info("record updated", slog.String("from", prev), slog.String("to", addr.String()))
default:
log.Info("record unchanged", "addr", addr)
}
}
- slog.Info(
- "cycle finished",
+ baseLog.Info(
+ "cycle finished!",
slog.Int("records", len(cfg.Records)),
slog.Bool("failed", failed),
)
if failed {
- slog.Error("not all records were ensured successfully")
+ baseLog.Error("not all records were ensured successfully")
os.Exit(1)
}
}
+
+func createModules(log *slog.Logger, cfg *Config) (map[string]provider.Provider, map[string]source.Source) {
+ sources := map[string]source.Source{}
+ providers := map[string]provider.Provider{}
+
+ for name, c := range cfg.Sources {
+ s, err := source.New(log, name, c)
+ if err != nil {
+ log.Error(
+ "failed creating source",
+ slog.String("name", name),
+ slog.String("kind", string(c.Kind)),
+ slog.String("error", err.Error()),
+ )
+ sources[name] = nil
+ continue
+ }
+ sources[name] = s
+ }
+
+ for name, c := range cfg.Providers {
+ p, err := provider.New(log, name, c)
+ if err != nil {
+ log.Error(
+ "failed creating provider",
+ slog.String("name", name),
+ slog.String("kind", string(c.Kind)),
+ slog.String("error", err.Error()),
+ )
+ providers[name] = nil
+ continue
+ }
+ providers[name] = p
+ }
+
+ return providers, sources
+}
diff --git a/provider/dummy.go b/provider/dummy.go
index bec5907..1f64f6f 100644
--- a/provider/dummy.go
+++ b/provider/dummy.go
@@ -17,15 +17,12 @@ type dummy struct {
var _ Provider = (*dummy)(nil)
func newDummy(log *slog.Logger) (*dummy, error) {
- return &dummy{log: log.With(slog.String("provider", "dummy"))}, nil
+ return &dummy{log: log}, nil
}
-func (d *dummy) Ensure(zone, name string, rtype RecordType, addr netip.Addr) (string, bool, error) {
+func (d *dummy) Ensure(_ string, _ string, _ RecordType, addr netip.Addr) (string, bool, error) {
d.log.Info(
"asked to ensure record, but nothing happened",
- slog.String("zone", zone),
- slog.String("name", name),
- slog.String("record", string(rtype)),
slog.String("addr", addr.String()),
)
return "", true, nil
diff --git a/provider/provider.go b/provider/provider.go
index ee31ba8..ce4a715 100644
--- a/provider/provider.go
+++ b/provider/provider.go
@@ -63,7 +63,15 @@ type Provider interface {
Ensure(zone, name string, rtype RecordType, addr netip.Addr) (string, bool, error)
}
-func New(log *slog.Logger, cfg Config) (Provider, error) {
+func New(log *slog.Logger, name string, cfg Config) (Provider, error) {
+ log = log.With(
+ slog.Group(
+ "provider",
+ slog.String("name", name),
+ slog.String("kind", string(cfg.Kind)),
+ ),
+ )
+
switch cfg.Kind {
case KindDummy:
return newDummy(log)
diff --git a/source/file.go b/source/file.go
index 4ef0e7c..004868f 100644
--- a/source/file.go
+++ b/source/file.go
@@ -20,8 +20,6 @@ type fileSource struct {
var _ Source = (*fileSource)(nil)
func newFile(log *slog.Logger, cfg Config) (*fileSource, error) {
- log = log.With(slog.String("source", "file"))
-
if _, err := os.Stat(cfg.Path); errors.Is(err, os.ErrNotExist) {
return nil, fmt.Errorf("cannot access file for source: %w", err)
}
diff --git a/source/source.go b/source/source.go
index 6fe139c..ffa380a 100644
--- a/source/source.go
+++ b/source/source.go
@@ -40,7 +40,15 @@ type Source interface {
Lookup(Family) (netip.Addr, error)
}
-func New(log *slog.Logger, cfg Config) (Source, error) {
+func New(log *slog.Logger, name string, cfg Config) (Source, error) {
+ log = log.With(
+ slog.Group(
+ "source",
+ slog.String("name", name),
+ slog.String("kind", string(cfg.Kind)),
+ ),
+ )
+
if cfg.Family != IPv4 && cfg.Family != IPv6 {
return nil, fmt.Errorf("%s source needs family set to ipv4 or ipv6", cfg.Kind)
}
diff --git a/source/static.go b/source/static.go
index d2645d6..4b27e5a 100644
--- a/source/static.go
+++ b/source/static.go
@@ -17,7 +17,6 @@ type staticSource struct {
var _ Source = (*staticSource)(nil)
func newStatic(log *slog.Logger, cfg Config) (*staticSource, error) {
- log = log.With("source", "static")
addr, err := parse(cfg.Value, cfg.Family)
if err != nil {
log.Error(
diff --git a/source/url.go b/source/url.go
index 067d48b..41452be 100644
--- a/source/url.go
+++ b/source/url.go
@@ -21,8 +21,6 @@ type urlSource struct {
var _ Source = (*urlSource)(nil)
func newURL(log *slog.Logger, cfg Config) (*urlSource, error) {
- log = log.With("source", "url")
-
url, err := nurl.ParseRequestURI(cfg.URL)
if err != nil {
return nil, fmt.Errorf("invalid url for source: %w", err)