From 4774b67ffdc6e87837ca1a2d413fe416f938eeba Mon Sep 17 00:00:00 2001 From: Shlomi Noach Date: Mon, 25 Jul 2016 15:46:37 +0200 Subject: [PATCH] config file supports environment variables --- build.sh | 2 +- go/base/context.go | 17 +++++++++++++++++ vendor/gopkg.in/gcfg.v1/set.go | 8 ++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/build.sh b/build.sh index 5303130..23c54d4 100644 --- a/build.sh +++ b/build.sh @@ -1,7 +1,7 @@ #!/bin/bash # # -RELEASE_VERSION="1.0.3" +RELEASE_VERSION="1.0.4" buildpath=/tmp/gh-ost target=gh-ost diff --git a/go/base/context.go b/go/base/context.go index ebfcd85..295508d 100644 --- a/go/base/context.go +++ b/go/base/context.go @@ -7,6 +7,8 @@ package base import ( "fmt" + "os" + "regexp" "strings" "sync" "sync/atomic" @@ -35,6 +37,10 @@ const ( CutOverTwoStep = iota ) +var ( + envVariableRegexp = regexp.MustCompile("[$][{](.*)[}]") +) + // MigrationContext has the general, global state of migration. It is used by // all components throughout the migration process. type MigrationContext struct { @@ -441,8 +447,19 @@ func (this *MigrationContext) ReadConfigFile() error { if this.ConfigFile == "" { return nil } + gcfg.RelaxedParserMode = true if err := gcfg.ReadFileInto(&this.config, this.ConfigFile); err != nil { return err } + + // We accept user & password in the form "${SOME_ENV_VARIABLE}" in which case we pull + // the given variable from os env + if submatch := envVariableRegexp.FindStringSubmatch(this.config.Client.User); len(submatch) > 1 { + this.config.Client.User = os.Getenv(submatch[1]) + } + if submatch := envVariableRegexp.FindStringSubmatch(this.config.Client.Password); len(submatch) > 1 { + this.config.Client.Password = os.Getenv(submatch[1]) + } + return nil } diff --git a/vendor/gopkg.in/gcfg.v1/set.go b/vendor/gopkg.in/gcfg.v1/set.go index 7252b68..e1b9904 100644 --- a/vendor/gopkg.in/gcfg.v1/set.go +++ b/vendor/gopkg.in/gcfg.v1/set.go @@ -16,6 +16,8 @@ type tag struct { intMode string } +var RelaxedParserMode = false + func newTag(ts string) tag { t := tag{} s := strings.Split(ts, ",") @@ -197,6 +199,9 @@ func set(cfg interface{}, sect, sub, name string, blank bool, value string) erro vCfg := vPCfg.Elem() vSect, _ := fieldFold(vCfg, sect) if !vSect.IsValid() { + if RelaxedParserMode { + return nil + } return fmt.Errorf("invalid section: section %q", sect) } if vSect.Kind() == reflect.Map { @@ -232,6 +237,9 @@ func set(cfg interface{}, sect, sub, name string, blank bool, value string) erro } vVar, t := fieldFold(vSect, name) if !vVar.IsValid() { + if RelaxedParserMode { + return nil + } return fmt.Errorf("invalid variable: "+ "section %q subsection %q variable %q", sect, sub, name) }