From 8f5c63d6ef664c66d6a448320b2087686d41a0a7 Mon Sep 17 00:00:00 2001 From: Daniel Jones Date: Tue, 19 Jun 2018 09:24:12 +0100 Subject: [PATCH] --eval prints exports to get env vars into current session --- README.md | 14 +++++++--- version | 2 +- yml2env.go | 52 ++++++++++++++++++++++++++++------ yml2env_test.go | 74 +++++++++++++++++++++++++++++++------------------ 4 files changed, 102 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index d58d125..cd5d540 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,21 @@ ![Build Status](http://ci.engineerbetter.com/api/v1/teams/main/pipelines/yml2env/jobs/test/badge) -Executes a command with environment variables taken from a YAML file. +Either executes a command with environment variables taken from a YAML file, or prints a load of `export`s you can `eval` -``` -yml2env +```sh +yml2env [ | --eval] + +# Run command with env vars from YAML file +$ yml2env vars.yml tests.sh + +# Set env vars in current shell +$ eval "$(yml2env var.yml --eval)" ``` ## Why? -It's quite handy for using Concourse `--load-vars-from` files when running local tasks, like tests. +It's quite handy for using Concourse `--load-vars-from` files when running local tasks, like tests. The `--eval` feature is useful when you need to get lots of stuff from the output of a Concourse Terraform resource as env vars. ## Example diff --git a/version b/version index 9084fa2..26aaba0 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.1.0 +1.2.0 diff --git a/yml2env.go b/yml2env.go index 76f6636..33f1244 100644 --- a/yml2env.go +++ b/yml2env.go @@ -13,7 +13,7 @@ import ( "gopkg.in/yaml.v2" ) -var usage = "yml2env " +var usage = "yml2env [ | --env]" func main() { args := os.Args @@ -32,13 +32,24 @@ func main() { bytes := loadYaml(yamlPath) mapSlice := parseYaml(bytes) + mapSlice = uppercaseKeys(mapSlice) envVars := os.Environ() - envVars = addUppercaseKeysToEnv(mapSlice, envVars) + envVars = addToEnv(mapSlice, envVars) - err, _ := run(envVars, args[2:]) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + if args[2] == "--eval" { + if len(args) > 3 { + fmt.Fprintln(os.Stderr, usage) + os.Exit(1) + } + + printExports(mapSlice) + os.Exit(0) + } else { + err, _ := run(envVars, args[2:]) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } } } @@ -81,7 +92,7 @@ func valueToString(item yaml.MapItem) yaml.MapItem { return item } -func addUppercaseKeysToEnv(mapSlice yaml.MapSlice, envVars []string) []string { +func uppercaseKeys(mapSlice yaml.MapSlice) yaml.MapSlice { for i := 0; i < len(mapSlice); i++ { item := mapSlice[i] @@ -89,7 +100,7 @@ func addUppercaseKeysToEnv(mapSlice yaml.MapSlice, envVars []string) []string { key := strings.ToUpper(key) item = valueToString(item) if value, ok := item.Value.(string); ok { - envVars = env.Set(key, value, envVars) + mapSlice[i] = yaml.MapItem{Key: key, Value: value} } else { fmt.Fprintln(os.Stderr, "YAML invalid") os.Exit(1) @@ -100,6 +111,19 @@ func addUppercaseKeysToEnv(mapSlice yaml.MapSlice, envVars []string) []string { } } + return mapSlice +} + +func addToEnv(mapSlice yaml.MapSlice, envVars []string) []string { + for i := 0; i < len(mapSlice); i++ { + item := mapSlice[i] + + key, _ := item.Key.(string) + item = valueToString(item) + value, _ := item.Value.(string) + envVars = env.Set(key, value, envVars) + } + return envVars } @@ -140,3 +164,15 @@ func determineExitCode(cmd *exec.Cmd, err error) (exitCode int) { return } + +func printExports(mapSlice yaml.MapSlice) { + for i := 0; i < len(mapSlice); i++ { + item := mapSlice[i] + + key, _ := item.Key.(string) + key = strings.ToUpper(key) + item = valueToString(item) + value, _ := item.Value.(string) + fmt.Printf("export '%s=%s'\n", key, value) + } +} diff --git a/yml2env_test.go b/yml2env_test.go index 52f2bca..e12b9ff 100644 --- a/yml2env_test.go +++ b/yml2env_test.go @@ -11,7 +11,7 @@ import ( var _ = Describe("yml2env", func() { var cliPath string - usage := "yml2env " + usage := "yml2env \\[ | --env\\]" BeforeSuite(func() { var err error @@ -40,35 +40,55 @@ var _ = Describe("yml2env", func() { Ω(session.Err).ShouldNot(Say("foo")) }) - It("requires a command to invoke", func() { - command := exec.Command(cliPath, "fixtures/vars.yml") - session, err := Start(command, GinkgoWriter, GinkgoWriter) - Ω(err).ShouldNot(HaveOccurred()) - Eventually(session).Should(Exit(1)) - Ω(session.Err).Should(Say(usage)) - }) + Describe("running a command", func() { + It("requires a command to invoke", func() { + command := exec.Command(cliPath, "fixtures/vars.yml") + session, err := Start(command, GinkgoWriter, GinkgoWriter) + Ω(err).ShouldNot(HaveOccurred()) + Eventually(session).Should(Exit(1)) + Ω(session.Err).Should(Say(usage)) + }) - It("invokes the given command passing env vars from the YAML file", func() { - command := exec.Command(cliPath, "fixtures/vars.yml", "fixtures/script.sh") - session, err := Start(command, GinkgoWriter, GinkgoWriter) - Ω(err).ShouldNot(HaveOccurred()) - Eventually(session).Should(Exit(0)) - Ω(session).Should(Say("value from yaml")) - }) + It("invokes the given command passing env vars from the YAML file", func() { + command := exec.Command(cliPath, "fixtures/vars.yml", "fixtures/script.sh") + session, err := Start(command, GinkgoWriter, GinkgoWriter) + Ω(err).ShouldNot(HaveOccurred()) + Eventually(session).Should(Exit(0)) + Ω(session).Should(Say("value from yaml")) + }) - It("invokes the given command passing boolean env vars from the YAML file", func() { - command := exec.Command(cliPath, "fixtures/boolean.yml", "fixtures/script.sh") - session, err := Start(command, GinkgoWriter, GinkgoWriter) - Ω(err).ShouldNot(HaveOccurred()) - Eventually(session).Should(Exit(0)) - Ω(session).Should(Say("true")) + It("invokes the given command passing boolean env vars from the YAML file", func() { + command := exec.Command(cliPath, "fixtures/boolean.yml", "fixtures/script.sh") + session, err := Start(command, GinkgoWriter, GinkgoWriter) + Ω(err).ShouldNot(HaveOccurred()) + Eventually(session).Should(Exit(0)) + Ω(session).Should(Say("true")) + }) + + It("invokes the given command passing integer env vars from the YAML file", func() { + command := exec.Command(cliPath, "fixtures/integer.yml", "fixtures/script.sh") + session, err := Start(command, GinkgoWriter, GinkgoWriter) + Ω(err).ShouldNot(HaveOccurred()) + Eventually(session).Should(Exit(0)) + Ω(session).Should(Say("42")) + }) }) - It("invokes the given command passing integer env vars from the YAML file", func() { - command := exec.Command(cliPath, "fixtures/integer.yml", "fixtures/script.sh") - session, err := Start(command, GinkgoWriter, GinkgoWriter) - Ω(err).ShouldNot(HaveOccurred()) - Eventually(session).Should(Exit(0)) - Ω(session).Should(Say("42")) + Describe("printing out exports", func() { + It("does not accept a subcommand", func() { + command := exec.Command(cliPath, "fixtures/vars.yml", "--eval", "fixtures/script.sh") + session, err := Start(command, GinkgoWriter, GinkgoWriter) + Ω(err).ShouldNot(HaveOccurred()) + Eventually(session).Should(Exit(1)) + Ω(session.Err).Should(Say(usage)) + }) + + It("prints out an export for each var", func() { + command := exec.Command(cliPath, "fixtures/vars.yml", "--eval") + session, err := Start(command, GinkgoWriter, GinkgoWriter) + Ω(err).ShouldNot(HaveOccurred()) + Eventually(session).Should(Exit(0)) + Ω(session).Should(Say("export 'VAR_FROM_YAML=value from yaml'")) + }) }) })