Merge pull request #2 from natevecc/environment-flags
Environment Variable Support
This commit is contained in:
		
						commit
						5cbf194ee4
					
				
							
								
								
									
										13
									
								
								README.md
								
								
								
								
							
							
						
						
									
										13
									
								
								README.md
								
								
								
								
							|  | @ -29,6 +29,9 @@ charts: | ||||||
|     set:                                 # values (--set) |     set:                                 # values (--set) | ||||||
|       - name: address |       - name: address | ||||||
|         value: https://vault.example.com |         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: | NAME: | ||||||
|    helmfile |    helmfile - | ||||||
| 
 | 
 | ||||||
| USAGE: | USAGE: | ||||||
|    helmfile [global options] command [command options] [arguments...] |    main [global options] command [command options] [arguments...] | ||||||
| 
 | 
 | ||||||
| VERSION: | VERSION: | ||||||
|    0.0.0 |    0.1.0 | ||||||
| 
 | 
 | ||||||
| COMMANDS: | COMMANDS: | ||||||
|      repos    sync repositories from state file (helm repo add && help repo update) |      repos   sync repositories from state file (helm repo add && helm repo update) | ||||||
|      charts  sync charts from state file (helm repo upgrade --install) |      charts  sync charts from state file (helm repo upgrade --install) | ||||||
|      sync    sync all resources from state file (repos && charts) |      sync    sync all resources from state file (repos && charts) | ||||||
|      delete  delete charts from state file (helm delete) |      delete  delete charts from state file (helm delete) | ||||||
|      help, h  Shows a list of commands or help for one command |  | ||||||
| 
 | 
 | ||||||
| GLOBAL OPTIONS: | GLOBAL OPTIONS: | ||||||
|    --file FILE, -f FILE  load config from FILE (default: "charts.yaml") |    --file FILE, -f FILE  load config from FILE (default: "charts.yaml") | ||||||
|    --quiet, -q           silence output |    --quiet, -q           silence output | ||||||
|  |    --kube-context value  Set kubectl context. Uses current context by default | ||||||
|    --help, -h            show help |    --help, -h            show help | ||||||
|    --version, -v         print the version |    --version, -v         print the version | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | @ -15,11 +15,15 @@ const ( | ||||||
| 
 | 
 | ||||||
| type execer struct { | type execer struct { | ||||||
| 	writer io.Writer | 	writer io.Writer | ||||||
|  | 	kubeContext string | ||||||
| 	extra  []string | 	extra  []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func NewHelmExec(writer io.Writer) Interface { | func NewHelmExec(writer io.Writer, kubeContext string) Interface { | ||||||
| 	return &execer{writer: writer} | 	return &execer{ | ||||||
|  | 		writer: writer, | ||||||
|  | 		kubeContext: kubeContext, | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (helm *execer) SetExtraArgs(args ...string) { | func (helm *execer) SetExtraArgs(args ...string) { | ||||||
|  | @ -69,6 +73,9 @@ func (helm *execer) exec(args ...string) ([]byte, error) { | ||||||
| 	if len(helm.extra) > 0 { | 	if len(helm.extra) > 0 { | ||||||
| 		cmdargs = append(cmdargs, helm.extra...) | 		cmdargs = append(cmdargs, helm.extra...) | ||||||
| 	} | 	} | ||||||
|  | 	if helm.kubeContext != "" { | ||||||
|  | 		cmdargs = append(cmdargs, "--kube-context", helm.kubeContext) | ||||||
|  | 	}	 | ||||||
| 	if helm.writer != nil { | 	if helm.writer != nil { | ||||||
| 		helm.writer.Write([]byte(fmt.Sprintf("exec: helm %s\n", strings.Join(cmdargs, " ")))) | 		helm.writer.Write([]byte(fmt.Sprintf("exec: helm %s\n", strings.Join(cmdargs, " ")))) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
							
								
								
									
										26
									
								
								main.go
								
								
								
								
							
							
						
						
									
										26
									
								
								main.go
								
								
								
								
							|  | @ -21,6 +21,7 @@ func main() { | ||||||
| 	app := cli.NewApp() | 	app := cli.NewApp() | ||||||
| 	app.Name = "helmfile" | 	app.Name = "helmfile" | ||||||
| 	app.Usage = "" | 	app.Usage = "" | ||||||
|  | 	app.Version = "0.1.0" | ||||||
| 	app.Flags = []cli.Flag{ | 	app.Flags = []cli.Flag{ | ||||||
| 		cli.StringFlag{ | 		cli.StringFlag{ | ||||||
| 			Name:  "file, f", | 			Name:  "file, f", | ||||||
|  | @ -31,6 +32,10 @@ func main() { | ||||||
| 			Name:  "quiet, q", | 			Name:  "quiet, q", | ||||||
| 			Usage: "silence output", | 			Usage: "silence output", | ||||||
| 		}, | 		}, | ||||||
|  | 		cli.StringFlag{ | ||||||
|  | 			Name: "kube-context", | ||||||
|  | 			Usage: "Set kubectl context. Uses current context by default", | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	app.Commands = []cli.Command{ | 	app.Commands = []cli.Command{ | ||||||
|  | @ -73,6 +78,10 @@ func main() { | ||||||
| 					Value: "", | 					Value: "", | ||||||
| 					Usage: "pass args to helm exec", | 					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 { | 			Action: func(c *cli.Context) error { | ||||||
| 				state, helm, err := before(c) | 				state, helm, err := before(c) | ||||||
|  | @ -85,7 +94,9 @@ func main() { | ||||||
| 					helm.SetExtraArgs(strings.Split(args, " ")...) | 					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 { | 					for _, err := range errs { | ||||||
| 						fmt.Printf("err: %s", err.Error()) | 						fmt.Printf("err: %s", err.Error()) | ||||||
| 					} | 					} | ||||||
|  | @ -97,6 +108,12 @@ func main() { | ||||||
| 		{ | 		{ | ||||||
| 			Name:  "sync", | 			Name:  "sync", | ||||||
| 			Usage: "sync all resources from state file (repos && charts)", | 			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 { | 			Action: func(c *cli.Context) error { | ||||||
| 				state, helm, err := before(c) | 				state, helm, err := before(c) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
|  | @ -110,7 +127,9 @@ func main() { | ||||||
| 					os.Exit(1) | 					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 { | 					for _, err := range errs { | ||||||
| 						fmt.Printf("err: %s", err.Error()) | 						fmt.Printf("err: %s", err.Error()) | ||||||
| 					} | 					} | ||||||
|  | @ -149,6 +168,7 @@ func main() { | ||||||
| func before(c *cli.Context) (*state.HelmState, helmexec.Interface, error) { | func before(c *cli.Context) (*state.HelmState, helmexec.Interface, error) { | ||||||
| 	file := c.GlobalString("file") | 	file := c.GlobalString("file") | ||||||
| 	quiet := c.GlobalBool("quiet") | 	quiet := c.GlobalBool("quiet") | ||||||
|  | 	kubeContext := c.GlobalString("kube-context") | ||||||
| 
 | 
 | ||||||
| 	state, err := state.ReadFromFile(file) | 	state, err := state.ReadFromFile(file) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | @ -160,5 +180,5 @@ func before(c *cli.Context) (*state.HelmState, helmexec.Interface, error) { | ||||||
| 		writer = os.Stdout | 		writer = os.Stdout | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return state, helmexec.NewHelmExec(writer), nil | 	return state, helmexec.NewHelmExec(writer, kubeContext), nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ import ( | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"sync" | 	"sync" | ||||||
|  | 	"errors" | ||||||
| 
 | 
 | ||||||
| 	"github.com/roboll/helmfile/helmexec" | 	"github.com/roboll/helmfile/helmexec" | ||||||
| 
 | 
 | ||||||
|  | @ -32,6 +33,7 @@ type ChartSpec struct { | ||||||
| 	Namespace string     `yaml:"namespace"` | 	Namespace string     `yaml:"namespace"` | ||||||
| 	Values    []string   `yaml:"values"` | 	Values    []string   `yaml:"values"` | ||||||
| 	SetValues []SetValue `yaml:"set"` | 	SetValues []SetValue `yaml:"set"` | ||||||
|  | 	EnvValues []SetValue `yaml:"env"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type SetValue struct { | type SetValue struct { | ||||||
|  | @ -77,7 +79,7 @@ func (state *HelmState) SyncRepos(helm helmexec.Interface) []error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (state *HelmState) SyncCharts(helm helmexec.Interface) []error { | func (state *HelmState) SyncCharts(helm helmexec.Interface, additonalValues []string) []error { | ||||||
| 	var wg sync.WaitGroup | 	var wg sync.WaitGroup | ||||||
| 	errs := []error{} | 	errs := []error{} | ||||||
| 
 | 
 | ||||||
|  | @ -85,6 +87,14 @@ func (state *HelmState) SyncCharts(helm helmexec.Interface) []error { | ||||||
| 		wg.Add(1) | 		wg.Add(1) | ||||||
| 		go func(wg *sync.WaitGroup, chart ChartSpec) { | 		go func(wg *sync.WaitGroup, chart ChartSpec) { | ||||||
| 			flags, err := flagsForChart(&chart) | 			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 { | 			if err != nil { | ||||||
| 				errs = append(errs, err) | 				errs = append(errs, err) | ||||||
| 			} else { | 			} else { | ||||||
|  | @ -152,5 +162,17 @@ func flagsForChart(chart *ChartSpec) ([]string, error) { | ||||||
| 		} | 		} | ||||||
| 		flags = append(flags, "--set", strings.Join(val, ",")) | 		flags = append(flags, "--set", strings.Join(val, ",")) | ||||||
| 	} | 	} | ||||||
|  | 	if len(chart.EnvValues) > 0 { | ||||||
|  | 		val := []string{} | ||||||
|  | 		for _, set := range chart.EnvValues { | ||||||
|  | 			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("Could not find environment var: %s. Please make sure it is set and try again.", set.Name)) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		flags = append(flags, "--set", strings.Join(val, ",")) | ||||||
|  | 	} | ||||||
| 	return flags, nil | 	return flags, nil | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue