From 373e75064269da6461392aa205f472c04f2cdc56 Mon Sep 17 00:00:00 2001 From: Nathan Vecchiarelli Date: Tue, 11 Apr 2017 19:55:23 -0400 Subject: [PATCH 1/3] added support for environment variables, adding value files during runtime and a global kube-context flag to pass down to helm --- helmexec/exec.go | 11 +++++++++-- main.go | 25 ++++++++++++++++++++++--- state/state.go | 18 +++++++++++++++++- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/helmexec/exec.go b/helmexec/exec.go index c55c41ba..28fe1e5c 100644 --- a/helmexec/exec.go +++ b/helmexec/exec.go @@ -15,11 +15,15 @@ const ( type execer struct { writer io.Writer + kubeContext string extra []string } -func NewHelmExec(writer io.Writer) Interface { - return &execer{writer: writer} +func NewHelmExec(writer io.Writer, kubeContext string) Interface { + return &execer{ + writer: writer, + kubeContext: kubeContext, + } } func (helm *execer) SetExtraArgs(args ...string) { @@ -69,6 +73,9 @@ func (helm *execer) exec(args ...string) ([]byte, error) { if len(helm.extra) > 0 { cmdargs = append(cmdargs, helm.extra...) } + if helm.kubeContext != "" { + cmdargs = append(cmdargs, "--kube-context", helm.kubeContext) + } if helm.writer != nil { helm.writer.Write([]byte(fmt.Sprintf("exec: helm %s\n", strings.Join(cmdargs, " ")))) } diff --git a/main.go b/main.go index 51e6eea9..3e2d2710 100644 --- a/main.go +++ b/main.go @@ -31,6 +31,10 @@ func main() { Name: "quiet, q", Usage: "silence output", }, + cli.StringFlag{ + Name: "kube-context", + Usage: "Set kubectl context", + }, } app.Commands = []cli.Command{ @@ -73,6 +77,10 @@ func main() { Value: "", Usage: "pass args to helm exec", }, + cli.StringSliceFlag{ + Name: "values", + Usage: "additional value files to be merged into the command", + }, }, Action: func(c *cli.Context) error { state, helm, err := before(c) @@ -85,7 +93,9 @@ func main() { helm.SetExtraArgs(strings.Split(args, " ")...) } - if errs := state.SyncCharts(helm); err != nil && len(errs) > 0 { + values := c.StringSlice("values") + + if errs := state.SyncCharts(helm, values); err != nil && len(errs) > 0 { for _, err := range errs { fmt.Printf("err: %s", err.Error()) } @@ -97,6 +107,12 @@ func main() { { Name: "sync", Usage: "sync all resources from state file (repos && charts)", + Flags: []cli.Flag{ + cli.StringSliceFlag{ + Name: "values", + Usage: "additional value files to be merged into the command", + }, + }, Action: func(c *cli.Context) error { state, helm, err := before(c) if err != nil { @@ -110,7 +126,9 @@ func main() { os.Exit(1) } - if errs := state.SyncCharts(helm); err != nil && len(errs) > 0 { + values := c.StringSlice("values") + + if errs := state.SyncCharts(helm, values); err != nil && len(errs) > 0 { for _, err := range errs { fmt.Printf("err: %s", err.Error()) } @@ -149,6 +167,7 @@ func main() { func before(c *cli.Context) (*state.HelmState, helmexec.Interface, error) { file := c.GlobalString("file") quiet := c.GlobalBool("quiet") + kubeContext := c.GlobalString("kube-context") state, err := state.ReadFromFile(file) if err != nil { @@ -160,5 +179,5 @@ func before(c *cli.Context) (*state.HelmState, helmexec.Interface, error) { writer = os.Stdout } - return state, helmexec.NewHelmExec(writer), nil + return state, helmexec.NewHelmExec(writer, kubeContext), nil } diff --git a/state/state.go b/state/state.go index 9b0522d3..d491ae2a 100644 --- a/state/state.go +++ b/state/state.go @@ -32,6 +32,7 @@ type ChartSpec struct { Namespace string `yaml:"namespace"` Values []string `yaml:"values"` SetValues []SetValue `yaml:"set"` + EnvValues []SetValue `yaml:"env"` } type SetValue struct { @@ -77,7 +78,7 @@ func (state *HelmState) SyncRepos(helm helmexec.Interface) []error { return nil } -func (state *HelmState) SyncCharts(helm helmexec.Interface) []error { +func (state *HelmState) SyncCharts(helm helmexec.Interface, additonalValues []string) []error { var wg sync.WaitGroup errs := []error{} @@ -85,6 +86,14 @@ func (state *HelmState) SyncCharts(helm helmexec.Interface) []error { wg.Add(1) go func(wg *sync.WaitGroup, chart ChartSpec) { flags, err := flagsForChart(&chart) + for _, value := range additonalValues { + wd, err := os.Getwd() + if err != nil { + errs = append(errs, err) + } + valfile := filepath.Join(wd, value) + flags = append(flags, "--values", valfile) + } if err != nil { errs = append(errs, err) } else { @@ -152,5 +161,12 @@ func flagsForChart(chart *ChartSpec) ([]string, error) { } flags = append(flags, "--set", strings.Join(val, ",")) } + if len(chart.EnvValues) > 0 { + val := []string{} + for _, set := range chart.EnvValues { + val = append(val, fmt.Sprintf("%s=%s", set.Name, os.Getenv(set.Value))) + } + flags = append(flags, "--set", strings.Join(val, ",")) + } return flags, nil } From bc8bbf8e01f7f3df2bcc7cff149572bc29325b12 Mon Sep 17 00:00:00 2001 From: Nathan Vecchiarelli Date: Wed, 12 Apr 2017 10:15:56 -0400 Subject: [PATCH 2/3] documentation updates and tweaking workflows with env vars. It now throws errors if they're not set --- README.md | 19 +++++++++++-------- main.go | 3 ++- state/state.go | 8 +++++++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 75855ddb..8883d5ae 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,9 @@ charts: set: # values (--set) - name: address value: https://vault.example.com + env: # values (--set) but value will be pulled from environment variables. Will throw an error if the environment variable is not set. + - name: db.password + value: DB_PASSWORD # $DB_PASSOWRD needs to be set in the calling environment ex: export DB_PASSWORD='password1' ``` @@ -41,24 +44,24 @@ charts: ``` NAME: - helmfile + helmfile - USAGE: - helmfile [global options] command [command options] [arguments...] + main [global options] command [command options] [arguments...] VERSION: - 0.0.0 + 0.1.0 COMMANDS: - repos sync repositories from state file (helm repo add && help repo update) - charts sync charts from state file (helm repo upgrade --install) - sync sync all resources from state file (repos && charts) - delete delete charts from state file (helm delete) - help, h Shows a list of commands or help for one command + repos sync repositories from state file (helm repo add && helm repo update) + charts sync charts from state file (helm repo upgrade --install) + sync sync all resources from state file (repos && charts) + delete delete charts from state file (helm delete) GLOBAL OPTIONS: --file FILE, -f FILE load config from FILE (default: "charts.yaml") --quiet, -q silence output + --kube-context value Set kubectl context. Uses current context by default --help, -h show help --version, -v print the version ``` diff --git a/main.go b/main.go index 3e2d2710..3876e7da 100644 --- a/main.go +++ b/main.go @@ -21,6 +21,7 @@ func main() { app := cli.NewApp() app.Name = "helmfile" app.Usage = "" + app.Version = "0.1.0" app.Flags = []cli.Flag{ cli.StringFlag{ Name: "file, f", @@ -33,7 +34,7 @@ func main() { }, cli.StringFlag{ Name: "kube-context", - Usage: "Set kubectl context", + Usage: "Set kubectl context. Uses current context by default", }, } diff --git a/state/state.go b/state/state.go index d491ae2a..febc7884 100644 --- a/state/state.go +++ b/state/state.go @@ -7,6 +7,7 @@ import ( "path/filepath" "strings" "sync" + "errors" "github.com/roboll/helmfile/helmexec" @@ -164,7 +165,12 @@ func flagsForChart(chart *ChartSpec) ([]string, error) { if len(chart.EnvValues) > 0 { val := []string{} for _, set := range chart.EnvValues { - val = append(val, fmt.Sprintf("%s=%s", set.Name, os.Getenv(set.Value))) + value, isSet := os.LookupEnv(set.Value) + if isSet { + val = append(val, fmt.Sprintf("%s=%s", set.Name, value)) + } else { + return nil, errors.New(fmt.Sprintf("Unset env var: %s", set.Name)) + } } flags = append(flags, "--set", strings.Join(val, ",")) } From 0de9b224853ef1428d4929c564ecc0bd81f1c9be Mon Sep 17 00:00:00 2001 From: Nathan Vecchiarelli Date: Wed, 12 Apr 2017 11:01:45 -0400 Subject: [PATCH 3/3] updated unset env var message to not be confusing --- state/state.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/state/state.go b/state/state.go index febc7884..83fe4c4c 100644 --- a/state/state.go +++ b/state/state.go @@ -169,7 +169,7 @@ func flagsForChart(chart *ChartSpec) ([]string, error) { if isSet { val = append(val, fmt.Sprintf("%s=%s", set.Name, value)) } else { - return nil, errors.New(fmt.Sprintf("Unset env var: %s", set.Name)) + return nil, errors.New(fmt.Sprintf("Could not find environment var: %s. Please make sure it is set and try again.", set.Name)) } } flags = append(flags, "--set", strings.Join(val, ","))