From b7c708a6c89ad7d4736946afee02ea9cd8fa8882 Mon Sep 17 00:00:00 2001 From: Christoph Petrausch Date: Tue, 26 Mar 2024 15:48:07 +0100 Subject: [PATCH] Make configuration serializable This changes allows other go code bases to serialize the configuration to a file. --- config/config.go | 10 ++++++++++ config/config_test.go | 33 +++++++++++++++++++++++++++++++++ config/duration.go | 4 ++++ config/target.go | 9 +++++++++ target.go | 2 +- 5 files changed, 57 insertions(+), 1 deletion(-) diff --git a/config/config.go b/config/config.go index 2bf17e6..5ee55ad 100644 --- a/config/config.go +++ b/config/config.go @@ -42,6 +42,16 @@ func FromYAML(r io.Reader) (*Config, error) { return c, nil } +// ToYAML encodes the given configuration to the writer as YAML +func ToYAML(w io.Writer, cfg *Config) error { + err := yaml.NewEncoder(w).Encode(cfg) + if err != nil { + return fmt.Errorf("failed to encode YAML: %w", err) + } + + return nil +} + func (cfg *Config) TargetConfigByAddr(addr string) TargetConfig { for _, t := range cfg.Targets { if t.Addr == addr { diff --git a/config/config_test.go b/config/config_test.go index c8cdbb3..a1839b7 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -3,6 +3,7 @@ package config import ( + "bytes" "os" "reflect" "testing" @@ -65,3 +66,35 @@ func TestParseConfig(t *testing.T) { t.Errorf("expected options.disable-ipv6 to be %v, got %v", expected, c.Options.DisableIPv6) } } + +func TestRoundtrip(t *testing.T) { + f, err := os.Open("testdata/config_test.yml") + if err != nil { + t.Error("failed to open file", err) + t.FailNow() + } + + c, err := FromYAML(f) + if err != nil { + t.Error("failed to read file", err) + t.FailNow() + } + + buf := bytes.NewBuffer(nil) + err = ToYAML(buf, c) + if err != nil { + t.Error("failed to encode config", err) + t.FailNow() + } + + after, err := FromYAML(buf) + if err != nil { + t.Error("failed to read config again", err) + t.FailNow() + } + + if !reflect.DeepEqual(c, after) { + t.Error("config after Decode(Encode(cfg)) didn't match") + t.FailNow() + } +} diff --git a/config/duration.go b/config/duration.go index 39229b1..42c973d 100644 --- a/config/duration.go +++ b/config/duration.go @@ -22,6 +22,10 @@ func (d *duration) UnmarshalYAML(unmashal func(interface{}) error) error { return nil } +func (d duration) MarshalYAML() (interface{}, error) { + return d.Duration().String(), nil +} + // Duration is a convenience getter. func (d duration) Duration() time.Duration { return time.Duration(d) diff --git a/config/target.go b/config/target.go index 61769f2..695b33d 100644 --- a/config/target.go +++ b/config/target.go @@ -25,3 +25,12 @@ func (d *TargetConfig) UnmarshalYAML(unmashal func(interface{}) error) error { return nil } + +func (d TargetConfig) MarshalYAML() (interface{}, error) { + if d.Labels == nil { + return d.Addr, nil + } + ret := make(map[string]map[string]string) + ret[d.Addr] = d.Labels + return ret, nil +} diff --git a/target.go b/target.go index 838a335..4865803 100644 --- a/target.go +++ b/target.go @@ -76,7 +76,7 @@ func (t *target) addOrUpdateMonitor(monitor *mon.Monitor, opts targetOpts) error addrs, err := t.resolver.LookupIPAddr(context.Background(), t.host) if err != nil { - return fmt.Errorf("error resolving target: %w", err) + return fmt.Errorf("error resolving target '%s': %w", t.host, err) } var sanitizedAddrs []net.IPAddr