diff --git a/config/config.go b/config/config.go index 1651012..07bb037 100644 --- a/config/config.go +++ b/config/config.go @@ -50,7 +50,9 @@ func NewFromFile(filename string) (*Config, error) { return nil, errors.Wrap(err, "error reading configuration file") } - switch strings.ToLower(filepath.Ext(filename)) { + ext := strings.ToLower(filepath.Ext(filename)) + + switch ext { case ".yml", ".yaml": type intermediate struct { Services []any `yaml:"services"` @@ -68,6 +70,10 @@ func NewFromFile(filename string) (*Config, error) { if err != nil { return nil, errors.Wrap(err, "error marshaling intermediate configuration") } + case ".json": + // no additional action needed + default: + return nil, errors.Errorf("unexpected file format: `%s`", ext) } if err := json.Unmarshal(data, &cfg); err != nil { diff --git a/config/config_test.go b/config/config_test.go index 4c17f1b..3799e99 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -5,15 +5,19 @@ import ( "testing" "time" + "github.com/pkg/errors" "github.com/stretchr/testify/require" ) func TestConfig(t *testing.T) { - r := require.New(t) + type testCase struct { + name string + samplePath string + expOut Config + expError error + } - cfg, err := NewFromFile("testdata/sample.yaml") - r.NoError(err) - r.Equal(&Config{ + sampleConfig := Config{ Services: []Service{ { Name: "http", @@ -57,5 +61,48 @@ func TestConfig(t *testing.T) { Enabled: true, Address: "127.0.0.1:9090", }, - }, cfg) + } + + tcs := []testCase{ + { + name: "YAML configuration", + samplePath: "testdata/sample.yaml", + expOut: sampleConfig, + }, + { + name: "JSON configuration", + samplePath: "testdata/sample.json", + expOut: sampleConfig, + }, + { + name: "wrong config file extension", + samplePath: "testdata/sample.unknown", + expError: errors.New("unexpected file format: `.unknown`"), + }, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + r := require.New(t) + + cfg, err := NewFromFile(tc.samplePath) + if tc.expError == nil { + r.NoError(err) + for i := range tc.expOut.Services { + r.Equalf(tc.expOut.Services[i].Name, cfg.Services[i].Name, "svc#%d", i) + r.Equalf(tc.expOut.Services[i].CheckInterval, cfg.Services[i].CheckInterval, "svc#%d", i) + r.Equalf(tc.expOut.Services[i].CheckOperator, cfg.Services[i].CheckOperator, "svc#%d", i) + for j := range tc.expOut.Services[i].Checks { + r.Equalf(tc.expOut.Services[i].Checks[j].Kind, cfg.Services[i].Checks[j].Kind, "svc#%d check#%d", i, j) + r.JSONEqf(string(tc.expOut.Services[i].Checks[j].Spec), string(cfg.Services[i].Checks[j].Spec), "svc#%d check#%d", i, j) + } + r.Equalf(tc.expOut.Services[i].Peers, cfg.Services[i].Peers, "svc#%d", i) + } + r.Equal(tc.expOut.Metrics, cfg.Metrics) + } else { + r.Error(err) + r.Equal(tc.expError.Error(), err.Error()) + } + }) + } } diff --git a/config/testdata/sample.json b/config/testdata/sample.json new file mode 100644 index 0000000..27f8ef6 --- /dev/null +++ b/config/testdata/sample.json @@ -0,0 +1,63 @@ +{ + "services": [ + { + "name": "http", + "check_operator": "and", + "check_interval": "10s", + "checks": [ + { + "kind": "dns_lookup", + "spec": { + "query": "example.com", + "resolver": "127.0.0.1", + "tries": 3, + "interval": "100ms" + } + }, + { + "kind": "http_2xx", + "spec": { + "address": "127.0.0.1:8080", + "path": "/", + "tries": 3, + "interval": "100ms", + "timeout": "2s" + } + }, + { + "kind": "assigned_address", + "spec": { + "interface": "dummy0", + "ipv4": "10.0.0.128" + } + } + ], + "peers": [ + { + "name": "some_router_1", + "remote_address": "10.0.0.252", + "remote_as": 65000, + "local_address": "10.0.0.1", + "local_as": 65999, + "routes": [ + "10.0.0.128/32" + ] + }, + { + "name": "some_router_2", + "remote_address": "10.0.0.253", + "remote_as": 65000, + "local_address": "10.0.0.1", + "local_as": 65999, + "routes": [ + "10.0.0.128/32" + ] + } + ] + } + ], + "metrics": { + "enabled": true, + "address": "127.0.0.1:9090" + } +} diff --git a/config/testdata/sample.unknown b/config/testdata/sample.unknown new file mode 100644 index 0000000..f1adef6 --- /dev/null +++ b/config/testdata/sample.unknown @@ -0,0 +1 @@ +nothing here diff --git a/go.mod b/go.mod index 6f1907a..d52b307 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.22.3 require ( github.com/pkg/errors v0.9.1 + github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.9.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -11,4 +12,5 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect ) diff --git a/go.sum b/go.sum index 37a2515..dfc6dcd 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,20 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=