From a5f0645aac936878bde051f2c292026f8a899cac Mon Sep 17 00:00:00 2001 From: Eugene Dementiev Date: Mon, 1 Oct 2018 16:48:22 +1300 Subject: [PATCH] Add dotenv command to generate .env --- Dockerfile.build | 2 +- Gopkg.lock | 8 +++++++- README.md | 15 +++++++++++++-- cmd/dotenv.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ cmd/root.go | 2 +- 5 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 cmd/dotenv.go diff --git a/Dockerfile.build b/Dockerfile.build index 5812c42..5ff6440 100644 --- a/Dockerfile.build +++ b/Dockerfile.build @@ -1,4 +1,4 @@ -FROM golang:1.10-alpine as build +FROM golang:1.11-alpine as build RUN apk update && apk add git RUN go get -u github.com/golang/dep/cmd/dep diff --git a/Gopkg.lock b/Gopkg.lock index aa51ef0..c54445e 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -83,6 +83,12 @@ packages = ["."] revision = "0b12d6b5" +[[projects]] + name = "github.com/joho/godotenv" + packages = ["."] + revision = "23d116af351c84513e1946b527c88823e476be13" + version = "v1.3.0" + [[projects]] name = "github.com/pkg/errors" packages = ["."] @@ -104,6 +110,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "5d4badb3db9f275e024257609613168a80c1f9bc146f93b98d5a11f30b19508e" + inputs-digest = "7cefb712d6c13a4e630e4c69a83a4caaa0526b6dcd02db7f0007edc71e82cba2" solver-name = "gps-cdcl" solver-version = 1 diff --git a/README.md b/README.md index 17b7f62..d2eda4d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ SSM Parent ---------- -This is a parent process for Docker with one addition: it can read from AWS SSM Parameter store. +This is mostly a parent process for Docker with one addition: it can read from AWS SSM Parameter store. The way it works is that ssm-parent can be used as an entrypoint for Docker. Firstly, it retrieves all specified parameters, then injects them to the environment, and finally runs the command. @@ -45,7 +45,6 @@ The result will be merged as this: That should be pretty self-explanatory. ``` -$ssm-parent help SSM-Parent is a docker entrypoint. It gets specified parameters (possibly secret) from AWS SSM Parameter Store, @@ -55,11 +54,13 @@ Usage: ssm-parent [command] Available Commands: + dotenv Writes dotenv file help Help about any command print Prints the specified parameters. run Runs the specified command Flags: + -e, --expand Expand arguments and values using shell-style syntax -h, --help help for ssm-parent -n, --name stringArray Name of the SSM parameter to retrieve. Can be specified multiple times. -p, --path stringArray Path to a SSM parameter. Can be specified multiple times. @@ -96,6 +97,16 @@ envsubst < /etc/Caddyfile.env > /etc/Caddyfile exec $@ ``` +### .env file generation + +Sometimes you just want a .env file, and now it is also possible. + +Just specify all the same parameters, but use `dotenv` command instead with a filename to generate `.env` file. +``` +./ssm-parent dotenv -r -p /project/environment dotenv.env +2018/10/01 16:37:59 info Wrote the .env file filename=dotenv.env +``` + ### How to build This project uses https://github.com/golang/dep as a dependency manager. Go v.1.10.1 was used. diff --git a/cmd/dotenv.go b/cmd/dotenv.go new file mode 100644 index 0000000..fef8ec0 --- /dev/null +++ b/cmd/dotenv.go @@ -0,0 +1,48 @@ +package cmd + +import ( + "github.com/apex/log" + "github.com/imdario/mergo" + "github.com/joho/godotenv" + "github.com/spf13/cobra" + "github.com/springload/ssm-parent/ssm" +) + +// dotenvCmd represents the dotenv command +var dotenvCmd = &cobra.Command{ + Use: "dotenv ", + Short: "Writes dotenv file", + Long: `Gathers parameters from SSM Parameter store, writes .env file and exits`, + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + megamap := make(map[string]string) + parameters, err := ssm.GetParameters(names, paths, expand, strict, recursive) + if err != nil { + log.WithError(err).Fatal("Can't get parameters") + } + for _, parameter := range parameters { + err = mergo.Merge(&megamap, ¶meter, mergo.WithOverride) + if err != nil { + log.WithError(err).Fatal("Can't merge maps") + } + } + for key, value := range megamap { + if expand { + megamap[key] = ssm.ExpandValue(value) + } + } + + err = godotenv.Write(megamap, args[0]) + if err != nil { + log.WithError(err).Fatal("Can't write the dotenv file") + } else { + log.WithFields(log.Fields{"filename": args[0]}).Info("Wrote the .env file") + + } + }, +} + +func init() { + rootCmd.AddCommand(dotenvCmd) + +} diff --git a/cmd/root.go b/cmd/root.go index 7f7254e..c19e7bb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -39,5 +39,5 @@ func init() { rootCmd.PersistentFlags().StringArrayVarP(&names, "name", "n", []string{}, "Name of the SSM parameter to retrieve. Can be specified multiple times.") rootCmd.PersistentFlags().BoolVarP(&recursive, "recursive", "r", false, "Walk through the provided SSM paths recursively.") rootCmd.PersistentFlags().BoolVarP(&strict, "strict", "s", false, "Strict mode. Fail if found less parameters than number of names.") - rootCmd.PersistentFlags().BoolVarP(&expand, "expand", "e", false, "Expand arguments and values using /bin/sh") + rootCmd.PersistentFlags().BoolVarP(&expand, "expand", "e", false, "Expand arguments and values using shell-style syntax") }