From a7419986def2d5d1fbbd503647ff3c9be1714c3a Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Mon, 30 May 2022 16:33:26 +0200 Subject: [PATCH] Make dotEnv resolution plublic Signed-off-by: Ulysses Souza --- cli/options.go | 77 +++++++++++++++++++++----------------------- cli/options_test.go | 5 +-- utils/stringutils.go | 20 ++++++++++++ 3 files changed, 59 insertions(+), 43 deletions(-) diff --git a/cli/options.go b/cli/options.go index 7365bacb..4bb3c2ae 100644 --- a/cli/options.go +++ b/cli/options.go @@ -145,7 +145,7 @@ func WithDefaultConfigPath(o *ProjectOptions) error { // WithEnv defines a key=value set of variables used for compose file interpolation func WithEnv(env []string) ProjectOptionsFn { return func(o *ProjectOptions) error { - for k, v := range getAsEqualsMap(env) { + for k, v := range utils.GetAsEqualsMap(env) { o.Environment[k] = v } return nil @@ -169,7 +169,7 @@ func WithLoadOptions(loadOptions ...func(*loader.Options)) ProjectOptionsFn { // WithOsEnv imports environment variables from OS func WithOsEnv(o *ProjectOptions) error { - for k, v := range getAsEqualsMap(os.Environ()) { + for k, v := range utils.GetAsEqualsMap(os.Environ()) { if _, set := o.Environment[k]; set { continue } @@ -188,46 +188,59 @@ func WithEnvFile(file string) ProjectOptionsFn { // WithDotEnv imports environment variables from .env file func WithDotEnv(o *ProjectOptions) error { - dotEnvFile := o.EnvFile + wd, err := o.GetWorkingDir() + if err != nil { + return err + } + envMap, err := GetEnvFromFile(o.Environment, wd, o.EnvFile) + if err != nil { + return err + } + for k, v := range envMap { + o.Environment[k] = v + } + return nil +} + +func GetEnvFromFile(currentEnv map[string]string, workingDir string, filename string) (map[string]string, error) { + envMap := make(map[string]string) + + dotEnvFile := filename if dotEnvFile == "" { - wd, err := o.GetWorkingDir() - if err != nil { - return err - } - dotEnvFile = filepath.Join(wd, ".env") + dotEnvFile = filepath.Join(workingDir, ".env") } abs, err := filepath.Abs(dotEnvFile) if err != nil { - return err + return envMap, err } dotEnvFile = abs s, err := os.Stat(dotEnvFile) if os.IsNotExist(err) { - if o.EnvFile != "" { - return errors.Errorf("Couldn't find env file: %s", o.EnvFile) + if filename != "" { + return nil, errors.Errorf("Couldn't find env file: %s", filename) } - return nil + return envMap, nil } if err != nil { - return err + return envMap, err } if s.IsDir() { - if o.EnvFile == "" { - return nil + if filename == "" { + return envMap, nil } - return errors.Errorf("%s is a directory", dotEnvFile) + return envMap, errors.Errorf("%s is a directory", dotEnvFile) } file, err := os.Open(dotEnvFile) if err != nil { - return err + return envMap, err } defer file.Close() env, err := dotenv.ParseWithLookup(file, func(k string) (string, bool) { - v, ok := o.Environment[k] + v, ok := currentEnv[k] if !ok { return "", false @@ -235,15 +248,16 @@ func WithDotEnv(o *ProjectOptions) error { return v, true }) if err != nil { - return err + return envMap, err } for k, v := range env { - if _, set := o.Environment[k]; set { + if _, set := currentEnv[k]; set { continue } - o.Environment[k] = v + envMap[k] = v } - return nil + + return envMap, nil } // WithInterpolation set ProjectOptions to enable/skip interpolation @@ -412,22 +426,3 @@ func absolutePaths(p []string) ([]string, error) { } return paths, nil } - -// getAsEqualsMap split key=value formatted strings into a key : value map -func getAsEqualsMap(em []string) map[string]string { - m := make(map[string]string) - for _, v := range em { - kv := strings.SplitN(v, "=", 2) - m[kv[0]] = kv[1] - } - return m -} - -// getAsEqualsMap format a key : value map into key=value strings -func getAsStringList(em map[string]string) []string { - m := make([]string, 0, len(em)) - for k, v := range em { - m = append(m, fmt.Sprintf("%s=%s", k, v)) - } - return m -} diff --git a/cli/options_test.go b/cli/options_test.go index 8429c441..9d4c65d9 100644 --- a/cli/options_test.go +++ b/cli/options_test.go @@ -23,6 +23,7 @@ import ( "testing" "github.com/compose-spec/compose-go/consts" + "github.com/compose-spec/compose-go/utils" "gotest.tools/v3/assert" ) @@ -231,8 +232,8 @@ func TestProjectNameFromWorkingDir(t *testing.T) { func TestEnvMap(t *testing.T) { m := map[string]string{} m["foo"] = "bar" - l := getAsStringList(m) + l := utils.GetAsStringList(m) assert.Equal(t, l[0], "foo=bar") - m = getAsEqualsMap(l) + m = utils.GetAsEqualsMap(l) assert.Equal(t, m["foo"], "bar") } diff --git a/utils/stringutils.go b/utils/stringutils.go index bd95e7bb..182ddf83 100644 --- a/utils/stringutils.go +++ b/utils/stringutils.go @@ -17,6 +17,7 @@ package utils import ( + "fmt" "strconv" "strings" ) @@ -36,3 +37,22 @@ func StringToBool(s string) bool { b, _ := strconv.ParseBool(strings.ToLower(strings.TrimSpace(s))) return b } + +// GetAsEqualsMap split key=value formatted strings into a key : value map +func GetAsEqualsMap(em []string) map[string]string { + m := make(map[string]string) + for _, v := range em { + kv := strings.SplitN(v, "=", 2) + m[kv[0]] = kv[1] + } + return m +} + +// GetAsEqualsMap format a key : value map into key=value strings +func GetAsStringList(em map[string]string) []string { + m := make([]string, 0, len(em)) + for k, v := range em { + m = append(m, fmt.Sprintf("%s=%s", k, v)) + } + return m +}