diff --git a/pkg/vault-handler/dot_env.go b/pkg/vault-handler/dot_env.go index a25a2b1..9c2324c 100644 --- a/pkg/vault-handler/dot_env.go +++ b/pkg/vault-handler/dot_env.go @@ -1,14 +1,16 @@ package vaulthandler import ( + "context" "fmt" "os" "path" "strings" log "github.com/sirupsen/logrus" - "github.com/subosito/gotenv" shellescape "gopkg.in/alessio/shellescape.v1" + "mvdan.cc/sh/expand" + "mvdan.cc/sh/shell" ) // DotEnv represents a .env file @@ -21,29 +23,40 @@ type DotEnv struct { // Prepare by checking if dot-env (".env") file already exists, read it's contents. func (d *DotEnv) Prepare() error { + d.loadFiles() + if !FileExists(d.fullPath) { d.logger.Info("Dot-env file is not found.") return nil } - - d.logger.Info("Reading existing dot-env file contents.") - return d.readExisting() + if err := d.readExisting(); err != nil { + return err + } + return nil } // Write down dot-env file. -func (d *DotEnv) Write() error { +func (d *DotEnv) Write(dryRun bool) error { var f *os.File + var escaped []string var err error - d.loadFiles() + for k, v := range d.data { + d.logger.Infof("Adding key '%s' to dot-env file.", k) + escaped = append(escaped, fmt.Sprintf("%s=%s\n", k, shellescape.Quote(v))) + } + + if dryRun { + d.logger.Info("[DRY-RUN] Skipping writting dot-env file.") + return nil + } if f, err = os.OpenFile(d.fullPath, os.O_CREATE|os.O_RDWR, 0600); err != nil { return err } defer f.Close() - - for k, v := range d.data { - if _, err = f.WriteString(fmt.Sprintf("%s=%s\n", k, shellescape.Quote(v))); err != nil { + for _, s := range escaped { + if _, err = f.WriteString(s); err != nil { return err } } @@ -52,35 +65,41 @@ func (d *DotEnv) Write() error { // readExisting dot-env file, parsing out variable names and values. func (d *DotEnv) readExisting() error { - var f *os.File + var existing map[string]expand.Variable var err error - if f, err = os.Open(d.fullPath); err != nil { + if existing, err = shell.SourceFile(context.TODO(), d.fullPath); err != nil { return err } - defer f.Close() - d.data = gotenv.Parse(f) + for k, v := range existing { + d.logger.Infof("Already existing dot-env variable '%s'", k) + d.put(k, v.String()) + } return nil } -// envVarName format a variable name based on a File instance. -func (d *DotEnv) envVarName(file *File) string { - name := fmt.Sprintf("%s_%s_%s", file.Group, file.Properties.Name, file.Properties.Extension) - return strings.ToUpper(name) -} - // loadFiles loop over array of Files, load contents func (d *DotEnv) loadFiles() { for _, file := range d.files { k := d.envVarName(file) - if _, found := d.data[k]; found { - d.logger.Warnf("Variable '%s' is already preset on '%s'!", k, d.fullPath) - } v := string(file.Payload) d.logger.Tracef("Adding entry on dot-env: '%s'='%s'", k, v) - d.data[k] = v + d.put(k, v) + } +} + +// envVarName format a variable name based on a File instance. +func (d *DotEnv) envVarName(file *File) string { + name := fmt.Sprintf("%s_%s_%s", file.Group, file.Properties.Name, file.Properties.Extension) + return strings.ToUpper(name) +} + +func (d *DotEnv) put(k, v string) { + if _, found := d.data[k]; found { + d.logger.Warnf("Key '%s' is being overwritten!", k) } + d.data[k] = v } // NewDotEnv creates a new instance. diff --git a/pkg/vault-handler/dot_env_test.go b/pkg/vault-handler/dot_env_test.go index a724cbb..762761d 100644 --- a/pkg/vault-handler/dot_env_test.go +++ b/pkg/vault-handler/dot_env_test.go @@ -27,7 +27,7 @@ func TestDotEnvPrepare(t *testing.T) { } func TestDotEnvWrite(t *testing.T) { - err := dotEnv.Write() + err := dotEnv.Write(false) assert.Nil(t, err) }