From 2a431021e4bd4625f6d2d8efb64c5b854d35703e Mon Sep 17 00:00:00 2001 From: Ole Claussen Date: Thu, 5 Apr 2018 20:55:46 +0200 Subject: [PATCH] implement search for configuration file --- config/config.go | 2 +- context/config.go | 96 +++++++++++++++++++++++++++++++++++++++++++++-- image/build.go | 6 ++- 3 files changed, 99 insertions(+), 5 deletions(-) diff --git a/config/config.go b/config/config.go index 0175349..1a15ac0 100644 --- a/config/config.go +++ b/config/config.go @@ -12,8 +12,8 @@ type Config struct { Contexts map[string]ContextConfig `yaml:"contexts,omitempty"` } -// TODO: error handling // TODO: validation +// TODO: check if there are unknown keys func Load(filename string) (*Config, error) { bytes, err := ioutil.ReadFile(filename) if err != nil { diff --git a/context/config.go b/context/config.go index 7143223..c9fd34d 100644 --- a/context/config.go +++ b/context/config.go @@ -1,18 +1,108 @@ package context import ( + "fmt" + "os" + "os/user" + "path/filepath" + "github.com/oclaussen/dodo/config" ) +var ( + configFileNames = []string{ + "dodo.yaml", + "dodo.yml", + "dodo.json", + ".dodo.yaml", + ".dodo.yml", + ".dodo.json", + } +) + func (context *Context) ensureConfig() error { if context.Config != nil { return nil } - config, err := config.Load(context.Options.Filename) + if context.Options.Filename != "" { + config, err := findConfigInFile(context.Name, context.Options.Filename) + if err != nil { + return err + } + context.Config = config + return nil + } + config, err := findConfigAnywhere(context.Name) if err != nil { return err } - contextConfig := config.Contexts[context.Name] - context.Config = &contextConfig + context.Config = config return nil } + +func findConfigDirectories() ([]string, error) { + var configDirectories []string + + workingDir, err := os.Getwd() + if err != nil { + return configDirectories, err + } + for directory := workingDir; directory != "/"; directory = filepath.Dir(directory) { + configDirectories = append(configDirectories, directory) + } + configDirectories = append(configDirectories, "/") + + user, err := user.Current() + if err != nil { + return configDirectories, err + } + configDirectories = append(configDirectories, user.HomeDir) + configDirectories = append(configDirectories, filepath.Join(user.HomeDir, ".config", "dodo")) + + configDirectories = append(configDirectories, "/etc") + + return configDirectories, nil +} + +func findConfigAnywhere(contextName string) (*config.ContextConfig, error) { + directories, err := findConfigDirectories() + if err != nil { + return nil, err + } + + for _, directory := range directories { + config, err := findConfigInDirectory(contextName, directory) + if err == nil { + return config, err + } + // TODO: log error + } + return nil, fmt.Errorf("Could not find configuration for context '%s' in any configuration file", contextName) +} + +func findConfigInDirectory(contextName string, directory string) (*config.ContextConfig, error) { + for _, filename := range configFileNames { + path, _ := filepath.Abs(filepath.Join(directory, filename)) + // TODO: log error + config, err := findConfigInFile(contextName, path) + if err == nil { + return config, err + } + // TODO: log error + } + return nil, fmt.Errorf("Could not find configuration for context '%s' in directory '%s'", directory) +} + +func findConfigInFile(contextName string, filename string) (*config.ContextConfig, error) { + config, err := config.Load(filename) + if err != nil { + return nil, err + } + if config.Contexts == nil { + return nil, fmt.Errorf("File '%s' does not contain any context configurations", filename) + } + if contextConfig, ok := config.Contexts[contextName]; ok { + return &contextConfig, nil + } + return nil, fmt.Errorf("File '%s' does not contain configuration for context '%s'", filename, contextName) +} diff --git a/image/build.go b/image/build.go index b1a4915..bec84de 100644 --- a/image/build.go +++ b/image/build.go @@ -62,8 +62,12 @@ func BuildImage(client *docker.Client, config *config.ContextConfig) (string, er return "", err } + err = <-errChan + if err != nil { + return "", err + } if image == "" { return "", errors.New("Build complete, but the server did not send an image id.") } - return image, <-errChan + return image, nil }