From 1fdd2294ebc0e420873a6296db4628245c970844 Mon Sep 17 00:00:00 2001 From: dblum Date: Fri, 20 Jul 2018 14:08:43 -0600 Subject: [PATCH 1/3] case function, tests --- aws-env.go | 50 ++++++++++++++++++++++---------- aws-env_test.go | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 16 deletions(-) create mode 100644 aws-env_test.go diff --git a/aws-env.go b/aws-env.go index 2c24b2f..9847cab 100644 --- a/aws-env.go +++ b/aws-env.go @@ -1,14 +1,20 @@ package main import ( + "flag" "fmt" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ssm" "log" "os" "strings" - "flag" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/ssm" +) + +const ( + upper = "upper" + lower = "lower" ) func main() { @@ -17,13 +23,19 @@ func main() { return } - recursivePtr := flag.Bool("recursive", false, "recursively process parameters on path") - flag.Parse() + recursivePtr := flag.Bool("recursive", false, "recursively process parameters on path") + convertCase := flag.String("case", "upper", "Converts ENV Key to upper or lower case") + flag.Parse() + + if *convertCase == "upper" || *convertCase == "lower" { + } else { + log.Fatal("Unsupported case option. Must be 'upper' or 'lower'") + } sess := CreateSession() client := CreateClient(sess) - ExportVariables(client, os.Getenv("AWS_ENV_PATH"), *recursivePtr, "") + ExportVariables(client, os.Getenv("AWS_ENV_PATH"), *recursivePtr, *convertCase, "") } func CreateSession() *session.Session { @@ -34,12 +46,12 @@ func CreateClient(sess *session.Session) *ssm.SSM { return ssm.New(sess) } -func ExportVariables(client *ssm.SSM, path string, recursive bool, nextToken string) { - input := &ssm.GetParametersByPathInput{ - Path: &path, - WithDecryption: aws.Bool(true), - Recursive: aws.Bool(recursive), - } +func ExportVariables(client *ssm.SSM, path string, recursive bool, convertCase string, nextToken string) { + input := &ssm.GetParametersByPathInput{ + Path: &path, + WithDecryption: aws.Bool(true), + Recursive: aws.Bool(recursive), + } if nextToken != "" { input.SetNextToken(nextToken) @@ -52,20 +64,26 @@ func ExportVariables(client *ssm.SSM, path string, recursive bool, nextToken str } for _, element := range output.Parameters { - PrintExportParameter(path, element) + PrintExportParameter(path, element, convertCase) } if output.NextToken != nil { - ExportVariables(client, path, recursive, *output.NextToken) + ExportVariables(client, path, recursive, convertCase, *output.NextToken) } } -func PrintExportParameter(path string, parameter *ssm.Parameter) { +func PrintExportParameter(path string, parameter *ssm.Parameter, convertCase string) { name := *parameter.Name value := *parameter.Value env := strings.Replace(strings.Trim(name[len(path):], "/"), "/", "_", -1) value = strings.Replace(value, "\n", "\\n", -1) + switch convertCase { + case upper: + env = strings.ToUpper(env) + case lower: + env = strings.ToLower(env) + } fmt.Printf("export %s=$'%s'\n", env, value) } diff --git a/aws-env_test.go b/aws-env_test.go new file mode 100644 index 0000000..08c354d --- /dev/null +++ b/aws-env_test.go @@ -0,0 +1,77 @@ +package main + +import ( + "bytes" + "io" + "os" + "testing" + + "github.com/aws/aws-sdk-go/service/ssm" +) + +type testCaseSlice struct { + Name string + Value string + Path string + ConvertCase string + + ExpectedValue string +} + +func TestPrintExportParamater(t *testing.T) { + testCases := []testCaseSlice{ + { + Name: "/production/mysql_password", + Value: "passwerd", + Path: "/production", + ConvertCase: "upper", + + ExpectedValue: "export MYSQL_PASSWORD=$'passwerd", + }, + { + + Name: "/production/mysql_password", + Value: "passwerd", + Path: "/production", + ConvertCase: "lower", + + ExpectedValue: "export mysql_password=$'passwerd", + }, + } + for _, testCase := range testCases { + + fakeSSM := &ssm.Parameter{ + Name: &testCase.Name, + Value: &testCase.Value, + } + + old := os.Stdout // keep backup of the real stdout + r, w, _ := os.Pipe() + os.Stdout = w + + PrintExportParameter(testCase.Path, fakeSSM, testCase.ConvertCase) + outC := make(chan string) + // copy the output in a separate goroutine so printing can't block indefinitely + go func() { + var buf bytes.Buffer + io.Copy(&buf, r) + outC <- buf.String() + }() + + // back to normal state + w.Close() + os.Stdout = old // restoring the real stdout + out := <-outC + // fmt.Println(out) + + if testCase.ConvertCase == "upper" && out != testCase.ExpectedValue { + t.Errorf("Action: %scase failed. We expected: %s. But we got: %s.", testCase.ConvertCase, testCase.ExpectedValue, out) + + } + if testCase.ConvertCase == "lower" && out != testCase.ExpectedValue { + t.Errorf("Action: %scase failed. We expected: %s. But we got: %s.", testCase.ConvertCase, testCase.ExpectedValue, out) + + } + + } +} From b15c56ca557c6e9b03c65a4e4bb80d8afca2ee30 Mon Sep 17 00:00:00 2001 From: dblum Date: Fri, 20 Jul 2018 14:28:41 -0600 Subject: [PATCH 2/3] Fix test, update readme --- README.md | 22 ++++++++++++++++++++++ aws-env_test.go | 13 +++---------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 69cc4b8..46be898 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ $ export DB_USERNAME=$'Username' $ export DB_PASSWORD=$'SecretPassword' ``` +### Optional Flags +*Recursive* You can also pass the `--recursive` flag. When specified, aws-env will recursively fetch parameters starting from the base path specified in `AWS_ENV_PATH`. For the exported environment variables, any `/` characters from sub-paths will be converted to `_` characters. For example: @@ -47,7 +49,27 @@ $ aws ssm put-parameter --name /prod/my-app/db1/DB_PASSWORD --value "OtherSecret $ export db0_DB_PASSWORD=$'SecretPassword' $ export db1_DB_PASSWORD=$'OtherSecretPassword' ``` +*Case* +You can also pass `--case ` to convert the ENV **KEY** to upper or lower case +With the following parameters: +``` +$ aws ssm put-parameter --name /prod/my-app/db_password --value "SecretPassword" --type SecureString --key-id "alias/aws/ssm0" --region us-west-2 +``` + +`eval $(AWS_ENV_PATH=/prod/my-app/ AWS_REGION=us-west-2 ./aws-env --case upper)` will output: +``` +$ export DB_PASSWORD=$'SecretPassword' +``` + +``` +$ aws ssm put-parameter --name /prod/my-app/DB_PASSWORD --value "SecretPassword" --type SecureString --key-id "alias/aws/ssm0" --region us-west-2 +``` + +`eval $(AWS_ENV_PATH=/prod/my-app/ AWS_REGION=us-west-2 ./aws-env --case lower)` will output: +``` +$ export db_password=$'SecretPassword' +``` ## Example Dockerfile ``` diff --git a/aws-env_test.go b/aws-env_test.go index 08c354d..7a84287 100644 --- a/aws-env_test.go +++ b/aws-env_test.go @@ -26,7 +26,7 @@ func TestPrintExportParamater(t *testing.T) { Path: "/production", ConvertCase: "upper", - ExpectedValue: "export MYSQL_PASSWORD=$'passwerd", + ExpectedValue: "export MYSQL_PASSWORD=$'passwerd'\n", }, { @@ -35,7 +35,7 @@ func TestPrintExportParamater(t *testing.T) { Path: "/production", ConvertCase: "lower", - ExpectedValue: "export mysql_password=$'passwerd", + ExpectedValue: "export mysql_password=$'passwerd'\n", }, } for _, testCase := range testCases { @@ -62,16 +62,9 @@ func TestPrintExportParamater(t *testing.T) { w.Close() os.Stdout = old // restoring the real stdout out := <-outC - // fmt.Println(out) - if testCase.ConvertCase == "upper" && out != testCase.ExpectedValue { + if out != testCase.ExpectedValue { t.Errorf("Action: %scase failed. We expected: %s. But we got: %s.", testCase.ConvertCase, testCase.ExpectedValue, out) - } - if testCase.ConvertCase == "lower" && out != testCase.ExpectedValue { - t.Errorf("Action: %scase failed. We expected: %s. But we got: %s.", testCase.ConvertCase, testCase.ExpectedValue, out) - - } - } } From d2ac8af18ff1ad9a45f5981015c17199accecd09 Mon Sep 17 00:00:00 2001 From: dblum Date: Fri, 27 Jul 2018 15:28:28 -0600 Subject: [PATCH 3/3] Use const instead of string, add make test --- Makefile | 5 ++++- aws-env.go | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 6908907..63651de 100644 --- a/Makefile +++ b/Makefile @@ -1,2 +1,5 @@ build: - bash build.sh \ No newline at end of file + bash build.sh + +test: + go test . \ No newline at end of file diff --git a/aws-env.go b/aws-env.go index 9847cab..d9e5438 100644 --- a/aws-env.go +++ b/aws-env.go @@ -24,10 +24,10 @@ func main() { } recursivePtr := flag.Bool("recursive", false, "recursively process parameters on path") - convertCase := flag.String("case", "upper", "Converts ENV Key to upper or lower case") + convertCase := flag.String("case", upper, "Converts ENV Key to upper or lower case") flag.Parse() - if *convertCase == "upper" || *convertCase == "lower" { + if *convertCase == upper || *convertCase == lower { } else { log.Fatal("Unsupported case option. Must be 'upper' or 'lower'") }