From 569645a050dec9db212b9e49bde6ed2537012407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Wed, 1 Jul 2020 14:34:44 +0200 Subject: [PATCH] Support `hosts.yml` existing while `config.yml` does not After a person copies `hosts.yml` to a headless system, they will still be forced to go through re-authentication flow unless they copy or initialize a `config.yml` as well. This fixes respecting authentication info from `hosts.yml` even if `config.yml` is missing. --- internal/config/config_file.go | 6 ++++- internal/config/config_file_test.go | 36 +++++++++++++++++++++++------ internal/config/config_type.go | 8 +++++-- internal/config/testing.go | 6 ++++- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/internal/config/config_file.go b/internal/config/config_file.go index 49a2770d3..af2c2d560 100644 --- a/internal/config/config_file.go +++ b/internal/config/config_file.go @@ -138,7 +138,11 @@ func migrateConfig(filename string) error { func ParseConfig(filename string) (Config, error) { _, root, err := parseConfigFile(filename) if err != nil { - return nil, err + if os.IsNotExist(err) { + root = NewBlankRoot() + } else { + return nil, err + } } if isLegacy(root) { diff --git a/internal/config/config_file_test.go b/internal/config/config_file_test.go index d19130bb5..f921d2c67 100644 --- a/internal/config/config_file_test.go +++ b/internal/config/config_file_test.go @@ -110,14 +110,36 @@ github.com: } func Test_parseConfigFile(t *testing.T) { - fileContents := []string{"", " ", "\n"} - for _, contents := range fileContents { - t.Run(fmt.Sprintf("contents: %q", contents), func(t *testing.T) { - defer StubConfig(contents, "")() + tests := []struct { + contents string + wantsErr bool + }{ + { + contents: "", + wantsErr: true, + }, + { + contents: " ", + wantsErr: false, + }, + { + contents: "\n", + wantsErr: false, + }, + } + + for _, tt := range tests { + t.Run(fmt.Sprintf("contents: %q", tt.contents), func(t *testing.T) { + defer StubConfig(tt.contents, "")() _, yamlRoot, err := parseConfigFile("config.yml") - eq(t, err, nil) - eq(t, yamlRoot.Content[0].Kind, yaml.MappingNode) - eq(t, len(yamlRoot.Content[0].Content), 0) + if tt.wantsErr != (err != nil) { + t.Fatalf("got error: %v", err) + } + if tt.wantsErr { + return + } + assert.Equal(t, yaml.MappingNode, yamlRoot.Content[0].Kind) + assert.Equal(t, 0, len(yamlRoot.Content[0].Content)) }) } } diff --git a/internal/config/config_type.go b/internal/config/config_type.go index a57d21dec..85e5c0d4a 100644 --- a/internal/config/config_type.go +++ b/internal/config/config_type.go @@ -123,7 +123,11 @@ func NewConfig(root *yaml.Node) Config { } func NewBlankConfig() Config { - return NewConfig(&yaml.Node{ + return NewConfig(NewBlankRoot()) +} + +func NewBlankRoot() *yaml.Node { + return &yaml.Node{ Kind: yaml.DocumentNode, Content: []*yaml.Node{ { @@ -168,7 +172,7 @@ func NewBlankConfig() Config { }, }, }, - }) + } } // This type implements a Config interface and represents a config file on disk. diff --git a/internal/config/testing.go b/internal/config/testing.go index 59c2ff212..a49178705 100644 --- a/internal/config/testing.go +++ b/internal/config/testing.go @@ -42,7 +42,11 @@ func StubConfig(main, hosts string) func() { ReadConfigFile = func(fn string) ([]byte, error) { switch path.Base(fn) { case "config.yml": - return []byte(main), nil + if main == "" { + return []byte(nil), os.ErrNotExist + } else { + return []byte(main), nil + } case "hosts.yml": if hosts == "" { return []byte(nil), os.ErrNotExist