diff --git a/cmd/get.go b/cmd/get.go index 632892d..89669b4 100644 --- a/cmd/get.go +++ b/cmd/get.go @@ -5,11 +5,13 @@ import ( "github.com/pbs/gorson/internal/gorson/io" "github.com/pbs/gorson/internal/gorson/json" + "github.com/pbs/gorson/internal/gorson/util" "github.com/spf13/cobra" ) func get(path string) { - pms := io.ReadFromParameterStore(path) + p := util.NewParameterStorePath(path) + pms := io.ReadFromParameterStore(*p) marshalled := json.Marshal(pms) fmt.Println(marshalled) } diff --git a/cmd/put.go b/cmd/put.go index 6a7ca45..e596dc0 100644 --- a/cmd/put.go +++ b/cmd/put.go @@ -4,13 +4,15 @@ import ( "fmt" "github.com/pbs/gorson/internal/gorson/io" + "github.com/pbs/gorson/internal/gorson/util" "github.com/spf13/cobra" ) var filename string func put(path string, parameters map[string]string) { - io.WriteToParameterStore(parameters, path) + p := util.NewParameterStorePath(path) + io.WriteToParameterStore(parameters, *p) for key := range parameters { fmt.Println("wrote " + path + key) } diff --git a/internal/gorson/io/io.go b/internal/gorson/io/io.go index acb660d..ad67e5b 100644 --- a/internal/gorson/io/io.go +++ b/internal/gorson/io/io.go @@ -9,11 +9,13 @@ import ( "strings" "time" + "github.com/pbs/gorson/internal/gorson/util" + "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/ssm" ) -func getSSMClient(parameterStorePath *string) *ssm.SSM { +func getSSMClient() *ssm.SSM { sess := session.Must(session.NewSessionWithOptions(session.Options{ SharedConfigState: session.SharedConfigEnable, })) @@ -22,9 +24,10 @@ func getSSMClient(parameterStorePath *string) *ssm.SSM { return client } -// ReadFromParameterStore gets all parameters from a given slash-delimited parameter store path -func ReadFromParameterStore(parameterStorePath string) map[string]string { - client := getSSMClient(¶meterStorePath) +// ReadFromParameterStore gets all parameters from a given parameter store path +func ReadFromParameterStore(path util.ParameterStorePath) map[string]string { + client := getSSMClient() + p := path.String() var nextToken *string values := make(map[string]string) @@ -33,7 +36,7 @@ func ReadFromParameterStore(parameterStorePath string) map[string]string { for { decr := true input := ssm.GetParametersByPathInput{ - Path: ¶meterStorePath, + Path: &p, WithDecryption: &decr, } if nextToken != nil { @@ -45,12 +48,12 @@ func ReadFromParameterStore(parameterStorePath string) map[string]string { } outputParams := output.Parameters for index := 0; index < len(outputParams); index++ { - p := outputParams[index] + o := outputParams[index] // we remove the leading path, we want the last element of the // slash-delimited path as the key in our key/value pair. - s := strings.Split(*p.Name, "/") + s := strings.Split(*o.Name, "/") k := s[len(s)-1] - values[k] = *p.Value + values[k] = *o.Value } // we're done paginating, break out of the loop @@ -80,14 +83,14 @@ func writeSingleParameter(c chan string, client *ssm.SSM, name string, value str c <- name } -// WriteToParameterStore writes given parameters to a given slash-delimited parameter store path -func WriteToParameterStore(parameters map[string]string, parameterStorePath string) { - client := getSSMClient(¶meterStorePath) +// WriteToParameterStore writes given parameters to a given parameter store path +func WriteToParameterStore(parameters map[string]string, path util.ParameterStorePath) { + client := getSSMClient() // the jobs channel will receive messages from successful parameter store writes jobs := make(chan string, len(parameters)) for key, value := range parameters { - name := parameterStorePath + key + name := path.String() + key // we pass the jobs channel into the asynchronous write function to receive // success messages go writeSingleParameter(jobs, client, name, value) diff --git a/internal/gorson/util/util.go b/internal/gorson/util/util.go new file mode 100644 index 0000000..cc20538 --- /dev/null +++ b/internal/gorson/util/util.go @@ -0,0 +1,23 @@ +package util + +import "strings" + +type ParameterStorePath struct { + components []string +} + +func (p ParameterStorePath) String() string { + output := "/" + strings.Join(p.components, "/") + "/" + return output +} + +func NewParameterStorePath(input string) *ParameterStorePath { + split := strings.Split(input, "/") + var filtered []string + for _, str := range split { + if str != "" { + filtered = append(filtered, str) + } + } + return &ParameterStorePath{filtered} +} diff --git a/internal/gorson/util/util_test.go b/internal/gorson/util/util_test.go new file mode 100644 index 0000000..c7ac2d4 --- /dev/null +++ b/internal/gorson/util/util_test.go @@ -0,0 +1,37 @@ +package util + +import "testing" + +type testpair struct { + input string + expected string +} + +var testpairs = []testpair{ + { + input: "/EXAMPLE/NAMESPACE/", + expected: "/EXAMPLE/NAMESPACE/", + }, + { + input: "EXAMPLE/NAMESPACE/", + expected: "/EXAMPLE/NAMESPACE/", + }, + { + input: "EXAMPLE/NAMESPACE", + expected: "/EXAMPLE/NAMESPACE/", + }, +} + +func TestParameterStorePath(t *testing.T) { + for _, pair := range testpairs { + p := NewParameterStorePath(pair.input) + output := p.String() + if output != pair.expected { + t.Error( + "For", pair.input, + "expected", pair.expected, + "got", output, + ) + } + } +}