summaryrefslogtreecommitdiff
path: root/source/file.go
blob: 004868f9168104fda65188b88cb2d6e0d751b3f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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) {
	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
}