diff --git a/config/config.go b/config/config.go index afe75d0..3ce4381 100644 --- a/config/config.go +++ b/config/config.go @@ -203,13 +203,13 @@ type ConnectCommon struct { type TCPConnect struct { ConnectCommon `yaml:",inline"` - Address string `yaml:"address"` + Address string `yaml:"address,hostport"` DialTimeout time.Duration `yaml:"dial_timeout,zeropositive,default=10s"` } type TLSConnect struct { ConnectCommon `yaml:",inline"` - Address string `yaml:"address"` + Address string `yaml:"address,hostport"` Ca string `yaml:"ca"` Cert string `yaml:"cert"` Key string `yaml:"key"` @@ -245,13 +245,13 @@ type ServeCommon struct { type TCPServe struct { ServeCommon `yaml:",inline"` - Listen string `yaml:"listen"` + Listen string `yaml:"listen,hostport"` Clients map[string]string `yaml:"clients"` } type TLSServe struct { ServeCommon `yaml:",inline"` - Listen string `yaml:"listen"` + Listen string `yaml:"listen,hostport"` Ca string `yaml:"ca"` Cert string `yaml:"cert"` Key string `yaml:"key"` @@ -313,7 +313,7 @@ type SyslogLoggingOutlet struct { type TCPLoggingOutlet struct { LoggingOutletCommon `yaml:",inline"` - Address string `yaml:"address"` + Address string `yaml:"address,hostport"` Net string `yaml:"net,default=tcp"` RetryInterval time.Duration `yaml:"retry_interval,positive,default=10s"` TLS *TCPLoggingOutletTLS `yaml:"tls,optional"` @@ -331,7 +331,7 @@ type MonitoringEnum struct { type PrometheusMonitoring struct { Type string `yaml:"type"` - Listen string `yaml:"listen"` + Listen string `yaml:"listen,hostport"` } type SyslogFacility syslog.Priority diff --git a/config/config_test.go b/config/config_test.go index 2c17740..512b025 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -1,13 +1,17 @@ package config import ( + "bufio" "bytes" + "fmt" "path" "path/filepath" + "strings" "testing" "text/template" "github.com/kr/pretty" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -65,3 +69,20 @@ func testConfig(t *testing.T, input string) (*Config, error) { t.Helper() return ParseConfigBytes([]byte(input)) } + +func trimSpaceEachLineAndPad(s, pad string) string { + var out strings.Builder + scan := bufio.NewScanner(strings.NewReader(s)) + for scan.Scan() { + fmt.Fprintf(&out, "%s%s\n", pad, bytes.TrimSpace(scan.Bytes())) + } + return out.String() +} + +func TestTrimSpaceEachLineAndPad(t *testing.T) { + foo := ` + foo + bar baz + ` + assert.Equal(t, " \n foo\n bar baz\n \n", trimSpaceEachLineAndPad(foo, " ")) +} diff --git a/config/config_transport_test.go b/config/config_transport_test.go new file mode 100644 index 0000000..b5ed087 --- /dev/null +++ b/config/config_transport_test.go @@ -0,0 +1,99 @@ +package config + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestTransportConnect(t *testing.T) { + tmpl := ` +jobs: +- name: foo + type: push + connect: +%s + filesystems: {"<": true} + snapshotting: + type: manual + pruning: + keep_sender: + - type: last_n + count: 10 + keep_receiver: + - type: last_n + count: 10 +` + + mconf := func(s string) string { return fmt.Sprintf(tmpl, s) } + + type test struct { + Name string + ExpectError bool + Connect string + } + + testTable := []test{ + { + Name: "tcp_with_address_and_port", + ExpectError: false, + Connect: ` + type: tcp + address: 10.0.0.23:42 + `, + }, + { + Name: "tls_with_host_and_port", + ExpectError: false, + Connect: ` + type: tls + address: "server1.foo.bar:8888" + ca: /etc/zrepl/ca.crt + cert: /etc/zrepl/backupserver.fullchain + key: /etc/zrepl/backupserver.key + server_cn: "server1" + `, + }, + { + Name: "tcp_without_port", + ExpectError: true, + Connect: ` + type: tcp + address: 10.0.0.23 + `, + }, + { + Name: "tls_without_port", + ExpectError: true, + Connect: ` + type: tls + address: 10.0.0.23 + ca: /etc/zrepl/ca.crt + cert: /etc/zrepl/backupserver.fullchain + key: /etc/zrepl/backupserver.key + server_cn: "server1" + `, + }, + } + + for _, tc := range testTable { + t.Run(tc.Name, func(t *testing.T) { + require.NotEmpty(t, tc.Connect) + connect := trimSpaceEachLineAndPad(tc.Connect, " ") + conf := mconf(connect) + config, err := testConfig(t, conf) + if tc.ExpectError && err == nil { + t.Errorf("expected test failure, but got valid config %v", config) + return + } + if !tc.ExpectError && err != nil { + t.Errorf("not expecint test failure but got error: %s", err) + return + } + t.Logf("error=%v", err) + t.Logf("config=%v", config) + }) + } + +} diff --git a/go.mod b/go.mod index f8b4cb2..1bf6566 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,7 @@ require ( github.com/yudai/gojsondiff v0.0.0-20170107030110-7b1b7adf999d github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect github.com/yudai/pp v2.0.1+incompatible // indirect - github.com/zrepl/yaml-config v0.0.0-20190903123849-809f4603401a + github.com/zrepl/yaml-config v0.0.0-20190928121844-af7ca3f8448f golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c // indirect golang.org/x/net v0.0.0-20190313220215-9f648a60d977 golang.org/x/sync v0.0.0-20190423024810-112230192c58 diff --git a/go.sum b/go.sum index 74586a8..646a246 100644 --- a/go.sum +++ b/go.sum @@ -275,6 +275,8 @@ github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcm github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/zrepl/yaml-config v0.0.0-20190903123849-809f4603401a h1:l37btErUqI1yNmt5mf8kzglbeQfo32+TRacnxthiuck= github.com/zrepl/yaml-config v0.0.0-20190903123849-809f4603401a/go.mod h1:JmNwisZzOvW4GfpfLvhZ+gtyKLsIiA+WC+wNKJGJaFg= +github.com/zrepl/yaml-config v0.0.0-20190928121844-af7ca3f8448f h1:3MuiGfgMHCSwKUcsuI7ODbi50j+evTB7SsoOBMNC5Fk= +github.com/zrepl/yaml-config v0.0.0-20190928121844-af7ca3f8448f/go.mod h1:JmNwisZzOvW4GfpfLvhZ+gtyKLsIiA+WC+wNKJGJaFg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=