From b52c860a7b1d3f57abc442bb8c1257f228d49536 Mon Sep 17 00:00:00 2001 From: Mel Date: Thu, 20 Aug 2026 06:18:05 +0200 Subject: ddnnss Signed-off-by: Mel --- source/file.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 source/file.go (limited to 'source/file.go') diff --git a/source/file.go b/source/file.go new file mode 100644 index 0000000..4ef0e7c --- /dev/null +++ b/source/file.go @@ -0,0 +1,59 @@ +package source + +import ( + "errors" + "fmt" + "log/slog" + "net/netip" + "os" +) + +// a source that reads the address from a file path. +// useful when your record has to be in-sync with +// some configured address on your machine. +type fileSource struct { + log *slog.Logger + path string + family Family +} + +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) + } + + return &fileSource{log: log, path: cfg.Path, family: cfg.Family}, nil +} + +func (s *fileSource) Supports(f Family) bool { return f == s.family } + +func (s *fileSource) Lookup(Family) (netip.Addr, error) { + s.log.Info( + "will look up address from file source", + slog.String("path", s.path), + slog.String("family", string(s.family)), + ) + + raw, err := os.ReadFile(s.path) + if err != nil { + return netip.Addr{}, fmt.Errorf("file source read failed: %w", err) + } + content := string(raw) + + addr, err := parse(content, s.family) + if err != nil { + s.log.Error( + "source file does not contain address of expected family", + slog.String("path", s.path), + slog.String("expected", string(s.family)), + slog.String("content", content), + ) + return netip.Addr{}, fmt.Errorf("source file contains bad content: %w", err) + } + + return addr, nil +} -- cgit v1.3.1