Skip to content

Commit

Permalink
--eval prints exports to get env vars into current session
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Jones committed Jun 19, 2018
1 parent 11b4391 commit 8f5c63d
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 40 deletions.
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <path-to-yaml-file> <command>
```sh
yml2env <path-to-yaml-file> [<command> | --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

Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.1.0
1.2.0
52 changes: 44 additions & 8 deletions yml2env.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"gopkg.in/yaml.v2"
)

var usage = "yml2env <YAML file> <command>"
var usage = "yml2env <YAML file> [<command> | --env]"

func main() {
args := os.Args
Expand All @@ -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)
}
}
}

Expand Down Expand Up @@ -81,15 +92,15 @@ 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]

if key, ok := item.Key.(string); ok {
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)
Expand All @@ -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
}

Expand Down Expand Up @@ -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)
}
}
74 changes: 47 additions & 27 deletions yml2env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

var _ = Describe("yml2env", func() {
var cliPath string
usage := "yml2env <YAML file> <command>"
usage := "yml2env <YAML file> \\[<command> | --env\\]"

BeforeSuite(func() {
var err error
Expand Down Expand Up @@ -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'"))
})
})
})

0 comments on commit 8f5c63d

Please sign in to comment.