From abb1dc4eb6d7057cd6712abb3e29a0576f8d797d Mon Sep 17 00:00:00 2001 From: Alexander Neumann Date: Mon, 14 May 2018 23:21:24 +0200 Subject: [PATCH] wip --- internal/ui/config/config.go | 86 +++++++++++-------- internal/ui/config/config_test.go | 16 ++++ internal/ui/config/testdata/all.golden | 26 ++++-- .../ui/config/testdata/backend-local.golden | 16 ++-- internal/ui/config/testdata/repo_local.golden | 8 +- 5 files changed, 97 insertions(+), 55 deletions(-) diff --git a/internal/ui/config/config.go b/internal/ui/config/config.go index 83b4cfbcf..eb6388b24 100644 --- a/internal/ui/config/config.go +++ b/internal/ui/config/config.go @@ -27,9 +27,25 @@ type Config struct { // Backend configures a backend. type Backend struct { Type string `hcl:"type"` - User string `hcl:"user" valid_for:"sftp"` - Host string `hcl:"host" valid_for:"sftp"` - Path string `hcl:"path" valid_for:"sftp,local"` + + *BackendLocal `hcl:"-" json:"local"` + *BackendSFTP `hcl:"-" json:"sftp"` +} + +// BackendLocal configures a local backend. +type BackendLocal struct { + Type string `hcl:"type"` + + Path string `hcl:"path"` +} + +// BackendSFTP configures an sftp backend. +type BackendSFTP struct { + Type string `hcl:"type"` + + User string `hcl:"user"` + Host string `hcl:"host"` + Path string `hcl:"path"` } // Backup sets the options for the "backup" command. @@ -166,58 +182,49 @@ func parseBackends(root *ast.ObjectList) (map[string]Backend, error) { be.Type = "local" } - if _, ok := backends[name]; ok { - return nil, errors.Errorf("backend %q at line %v, column %v already configured", - name, obj.Pos().Line, obj.Pos().Column) + var target interface{} + switch be.Type { + case "local": + be.BackendLocal = &BackendLocal{} + target = be.BackendLocal + case "sftp": + be.BackendSFTP = &BackendSFTP{} + target = be.BackendSFTP + default: + return nil, errors.Errorf("unknown backend type %q at line %v, column %v", + be.Type, obj.Pos().Line, obj.Pos().Column) } // check structure of the backend object innerBlock, ok := obj.Val.(*ast.ObjectType) if !ok { - return nil, errors.Errorf("unable to verify structure of backend %q at line %v, column %v already configured", + return nil, errors.Errorf("unable to verify structure of backend %q at line %v, column %v", name, obj.Pos().Line, obj.Pos().Column) } - // check valid fields - err = validateObjects(innerBlock.List, validBackendFieldNames(be.Type)) + // check allowed types + err = validateObjects(innerBlock.List, listTags(target, "hcl")) if err != nil { return nil, err } + err = hcl.DecodeObject(target, innerBlock) + if err != nil { + return nil, errors.Errorf("parsing backend %q (type %s) at line %v, column %v failed: %v", + name, be.Type, obj.Pos().Line, obj.Pos().Column, err) + } + + if _, ok := backends[name]; ok { + return nil, errors.Errorf("backend %q at line %v, column %v already configured", + name, obj.Pos().Line, obj.Pos().Column) + } + backends[name] = be } return backends, nil } -// validBackendFieldNames returns a set of names of valid options for the backend type be. -func validBackendFieldNames(be string) map[string]struct{} { - target := Backend{} - vi := reflect.ValueOf(target) - - attr := make(map[string]struct{}) - for i := 0; i < vi.NumField(); i++ { - typeField := vi.Type().Field(i) - tag := typeField.Tag.Get("valid_for") - name := typeField.Tag.Get("hcl") - - if tag == "" { - // if the tag is not specified, it's valid for all backend types - attr[name] = struct{}{} - continue - } - - for _, v := range strings.Split(tag, ",") { - if be == v { - attr[name] = struct{}{} - break - } - } - } - - return attr -} - // Load loads a config from a file. func Load(filename string) (Config, error) { buf, err := ioutil.ReadFile(filename) @@ -351,3 +358,8 @@ func ApplyEnv(cfg interface{}, env []string) error { return nil } + +// ApplyOptions takes a list of Options and applies them to the config. +func ApplyOptions(cfg interface{}, opts map[string]string) error { + return errors.New("not implemented") +} diff --git a/internal/ui/config/config_test.go b/internal/ui/config/config_test.go index 19493d668..757048bfe 100644 --- a/internal/ui/config/config_test.go +++ b/internal/ui/config/config_test.go @@ -100,6 +100,22 @@ func TestInvalidConfigs(t *testing.T) { }`, err: `unknown option "user"`, }, + { + config: `backend "foo" { + path = "/foo" + } + + backend "foo" { + path = "/bar" + }`, + err: `backend "foo" already configured`, + }, + { + config: `backend "foo" { + type = "xxx" + }`, + err: `unknown backend type "xxx"`, + }, } for _, test := range tests { diff --git a/internal/ui/config/testdata/all.golden b/internal/ui/config/testdata/all.golden index bed065a1d..c4eed0835 100644 --- a/internal/ui/config/testdata/all.golden +++ b/internal/ui/config/testdata/all.golden @@ -5,21 +5,29 @@ "Backends": { "local": { "Type": "local", - "User": "", - "Host": "", - "Path": "/foo/bar" + "local": { + "Type": "local", + "Path": "/foo/bar" + }, + "sftp": null }, "local2": { "Type": "local", - "User": "", - "Host": "", - "Path": "/foo/bar" + "local": { + "Type": "", + "Path": "/foo/bar" + }, + "sftp": null }, "sftp": { "Type": "sftp", - "User": "foo", - "Host": "bar", - "Path": "/foo/bar" + "local": null, + "sftp": { + "Type": "sftp", + "User": "foo", + "Host": "bar", + "Path": "/foo/bar" + } } }, "Backup": { diff --git a/internal/ui/config/testdata/backend-local.golden b/internal/ui/config/testdata/backend-local.golden index 441621397..a25a9a40c 100644 --- a/internal/ui/config/testdata/backend-local.golden +++ b/internal/ui/config/testdata/backend-local.golden @@ -5,15 +5,19 @@ "Backends": { "bar": { "Type": "local", - "User": "", - "Host": "", - "Path": "/srv/data/repo" + "local": { + "Type": "", + "Path": "/srv/data/repo" + }, + "sftp": null }, "foo": { "Type": "local", - "User": "", - "Host": "", - "Path": "/srv/data/repo" + "local": { + "Type": "local", + "Path": "/srv/data/repo" + }, + "sftp": null } }, "Backup": { diff --git a/internal/ui/config/testdata/repo_local.golden b/internal/ui/config/testdata/repo_local.golden index c43bbcc7d..544b78f2f 100644 --- a/internal/ui/config/testdata/repo_local.golden +++ b/internal/ui/config/testdata/repo_local.golden @@ -5,9 +5,11 @@ "Backends": { "test": { "Type": "local", - "User": "", - "Host": "", - "Path": "/foo/bar/baz" + "local": { + "Type": "local", + "Path": "/foo/bar/baz" + }, + "sftp": null } }, "Backup": {