diff options
Diffstat (limited to 'source/file.go')
| -rw-r--r-- | source/file.go | 59 |
1 files changed, 59 insertions, 0 deletions
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 +} |
