From 9c63736489569adf07537b9b01dc5e84f23f9651 Mon Sep 17 00:00:00 2001 From: Christian Schwarz Date: Tue, 14 May 2024 19:18:22 +0200 Subject: [PATCH] treat empty `jobs` & empty YAML as valid & ship empty `jobs` in deb/rpm (#788) fixes https://github.com/zrepl/zrepl/issues/784 obsoletes https://github.com/zrepl/zrepl/pull/787 --- config/config.go | 25 ++++++++++--------------- config/config_minimal_test.go | 10 +--------- config/config_test.go | 19 ++++++++++++++++++- config/samples/empty.yml | 0 packaging/systemd-default-zrepl.yml | 4 +--- 5 files changed, 30 insertions(+), 28 deletions(-) create mode 100644 config/samples/empty.yml diff --git a/config/config.go b/config/config.go index 6c56cc3..f4b84c0 100644 --- a/config/config.go +++ b/config/config.go @@ -5,7 +5,6 @@ import ( "io/ioutil" "log/syslog" "os" - "reflect" "time" "github.com/pkg/errors" @@ -24,7 +23,7 @@ const ( ) type Config struct { - Jobs []JobEnum `yaml:"jobs"` + Jobs []JobEnum `yaml:"jobs,optional"` Global *Global `yaml:"global,optional,fromdefaults"` } @@ -299,18 +298,6 @@ type Global struct { Serve *GlobalServe `yaml:"serve,optional,fromdefaults"` } -func Default(i interface{}) { - v := reflect.ValueOf(i) - if v.Kind() != reflect.Ptr { - panic(v) - } - y := `{}` - err := yaml.Unmarshal([]byte(y), v.Interface()) - if err != nil { - panic(err) - } -} - type ConnectEnum struct { Ret interface{} } @@ -696,8 +683,16 @@ func ParseConfigBytes(bytes []byte) (*Config, error) { if err := yaml.UnmarshalStrict(bytes, &c); err != nil { return nil, err } + if c != nil { + return c, nil + } + // There was no yaml document in the file, deserialize from default. + // => See TestFromdefaultsEmptyDoc in yaml-config package. + if err := yaml.UnmarshalStrict([]byte("{}"), &c); err != nil { + return nil, err + } if c == nil { - return nil, fmt.Errorf("config is empty or only consists of comments") + panic("the fallback to deserialize from `{}` should work") } return c, nil } diff --git a/config/config_minimal_test.go b/config/config_minimal_test.go index 74747bf..ef87d38 100644 --- a/config/config_minimal_test.go +++ b/config/config_minimal_test.go @@ -2,16 +2,8 @@ package config import ( "testing" - - "github.com/stretchr/testify/assert" ) -func TestConfigEmptyFails(t *testing.T) { - conf, err := testConfig(t, "\n") - assert.Nil(t, conf) - assert.Error(t, err) -} - func TestJobsOnlyWorks(t *testing.T) { testValidConfig(t, ` jobs: @@ -34,7 +26,7 @@ jobs: keep_sender: - type: not_replicated keep_receiver: - - type: last_n + - type: last_n count: 1 `) } diff --git a/config/config_test.go b/config/config_test.go index 443f013..52387fb 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -22,6 +22,8 @@ func TestSampleConfigsAreParsedWithoutErrors(t *testing.T) { t.Errorf("glob failed: %+v", err) } + paths = append(paths, "../packaging/systemd-default-zrepl.yml") + for _, p := range paths { if path.Ext(p) != ".yml" { @@ -84,7 +86,7 @@ func trimSpaceEachLineAndPad(s, pad string) string { func TestTrimSpaceEachLineAndPad(t *testing.T) { foo := ` foo - bar baz + bar baz ` assert.Equal(t, " \n foo\n bar baz\n \n", trimSpaceEachLineAndPad(foo, " ")) } @@ -138,3 +140,18 @@ func TestCronSpec(t *testing.T) { } } + +func TestEmptyConfig(t *testing.T) { + cases := []string{ + "", + "\n", + "---", + "---\n", + } + for _, input := range cases { + config := testValidConfig(t, input) + require.NotNil(t, config) + require.NotNil(t, config.Global) + require.Empty(t, config.Jobs) + } +} diff --git a/config/samples/empty.yml b/config/samples/empty.yml new file mode 100644 index 0000000..e69de29 diff --git a/packaging/systemd-default-zrepl.yml b/packaging/systemd-default-zrepl.yml index d473aa0..9747090 100644 --- a/packaging/systemd-default-zrepl.yml +++ b/packaging/systemd-default-zrepl.yml @@ -5,9 +5,7 @@ global: format: human level: warn -jobs: -# - name: foo -# type: bar +jobs: [] # see USR_SHARE_ZREPL/examples # or https://zrepl.github.io/configuration/overview.html