Skip to content

Commit

Permalink
Refactor To One Binary
Browse files Browse the repository at this point in the history
  • Loading branch information
WillJCJ committed Jun 29, 2018
1 parent 3b5061b commit c6447f1
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 45 deletions.
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@
# Packages from go get
github.com

# Built binaries
paramcopy
paramlist

### macOS ###
# General
.DS_Store
Expand Down
31 changes: 3 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,10 @@

## TODO

- Move both utilities into one binary.
- bash completion for parameter names
- Distribute as a release.
- Write tests!

## paramcopy
Usage

Copies the specified SSM parameter to your clipboard.

## Usage

Make sure valid AWS credentials are accessible in your terminal.

go build pkg/paramcopy.go

./paramcopy parameter

Copies the specified parameter to your clipboard.

### Bash Completion

For now, you need the paramlist binary in the same directory for bash completion.

source <(./paramcopy -completion-bash)
go build pkg/paramlist.go

## paramlist

There's also a untility to list SSM parameters.

It was creted for use in the bash completion.

You can specify at least one prefix to filter the parameter names by.
param [copy|list]
50 changes: 37 additions & 13 deletions cmd/param/param.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import (
"fmt"
"os"

"github.com/atotto/clipboard"
"github.com/posener/complete"
"github.com/willjcj/param/pkg/paramcopy"
"github.com/willjcj/param/pkg/paramlist"
)

func main() {
Expand All @@ -18,17 +21,26 @@ func main() {
"param",
complete.Command{
Flags: complete.Flags{
"-name": complete.PredictAnything,
"-name": complete.PredictAnything,
"-complete": complete.PredictNothing,
"-uncomplete": complete.PredictNothing,
"-h": complete.PredictNothing,
"-help": complete.PredictNothing,
"-y": complete.PredictNothing,
},
Sub: complete.Commands{
"copy": complete.Command{
// TODO fill with list output
Args: complete.PredictNothing,
},
"list": complete.Command{
// TODO fill with list output
Args: complete.PredictNothing,
},
},
},
)

// AddFlags adds the completion flags to the program flags,
// in case of using non-default flag set, it is possible to pass
// it as an argument.
// it is possible to set custom flags name
// so when one will type 'self -h', he will see '-complete' to install the
// completion and -uncomplete to uninstall it.
cmp.CLI.InstallName = "complete"
cmp.CLI.UninstallName = "uncomplete"
cmp.AddFlags(nil)
Expand All @@ -44,11 +56,23 @@ func main() {
return
}

// if the completion did not do anything, we can run our program logic here.
if name == "" {
fmt.Println("Your name is missing")
os.Exit(1)
}
// command := os.Args[0]
subCommand := os.Args[1]

if subCommand == "copy" {
paramName := os.Args[2]

decryptedParameter := paramcopy.GetDecryptedParameter(paramName)

fmt.Println("Hi,", name)
clipboard.WriteAll(decryptedParameter)
fmt.Printf("Copied %s to clipboard.\n", paramName)
} else if subCommand == "list" {
prefixes := os.Args[2:]

params := paramlist.DescribeParameters(prefixes)

for _, param := range params {
fmt.Println(param)
}
}
}
55 changes: 55 additions & 0 deletions pkg/paramcopy/paramcopy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package paramcopy

import (
"flag"
"fmt"
"os"
"path"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ssm"
)

var service = createSSMService()

var usage = fmt.Sprintf("Usage: \n %s paramter_name", path.Base(os.Args[0]))

func getName() string {
if flag.NArg() < 1 {
exitErrorf("Parameter name required.\n%s", usage)
} else if flag.NArg() > 1 {
exitErrorf("Too many parameters.\n%s", usage)
}

return flag.Arg(0)
}

func GetDecryptedParameter(name string) string {
output, err := service.GetParameter(&ssm.GetParameterInput{
Name: aws.String(name),
WithDecryption: aws.Bool(true),
})
if err != nil {
exitErrorf("Unable to describe parameters, %v", err)
}
return *output.Parameter.Value
}

func createSSMService() *ssm.SSM {
sess, err := session.NewSession(&aws.Config{
Region: aws.String("eu-west-1")},
)

if err != nil {
exitErrorf("Unable to describe parameters, %v", err)
}

// Create SSM service client
return ssm.New(sess)
}

func exitErrorf(msg string, args ...interface{}) {
fmt.Fprintf(os.Stderr, msg+"\n", args...)
os.Exit(1)
}
97 changes: 97 additions & 0 deletions pkg/paramlist/paramlist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package paramlist

import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/droundy/goopt"
"os"
"sort"
)

var service = createSSMService()

func createSSMService() *ssm.SSM {
sess, err := session.NewSession(&aws.Config{
Region: aws.String("eu-west-1")},
)

if err != nil {
exitErrorf("Unable to describe parameters, %v", err)
}

// Create SSM service client
return ssm.New(sess)
}

func initGoOpt() {
goopt.Description = func() string {
return "Get parameter names from AWS SSM with optional prefixes."
}
goopt.Version = version
goopt.Summary = "paramlist [prefixes]"
goopt.Parse(nil)
}

func DescribeParameters(prefixes []string) []string {
paramNames := []string{}
if len(prefixes) <= 0 {
paramNames = getAllParamNames()
} else {
for _, prefix := range prefixes {
for _, name := range getParamNames(prefix) {
paramNames = appendIfMissing(paramNames, name)
}
}
}
sort.Strings(paramNames)
return paramNames
}

func getParamNames(prefix string) []string {
// Fix passing empty string to SSM API
if len(prefix) < 1 {
return getAllParamNames()
}

filters := []*ssm.ParametersFilter{&ssm.ParametersFilter{
Key: aws.String("Name"),
Values: []*string{aws.String(prefix)},
}}
paramNames := []string{}
err := service.DescribeParametersPages(&ssm.DescribeParametersInput{
Filters: filters},
func(page *ssm.DescribeParametersOutput, lastPage bool) bool {
for _, parameter := range page.Parameters {
paramNames = append(paramNames, aws.StringValue(parameter.Name))
}
return true
})

if err != nil {
exitErrorf("Unable to describe parameters, %v", err)
}

return paramNames
}

func getAllParamNames() []string {
return getParamNames(" ")
}

func appendIfMissing(slice []string, s string) []string {
for _, ele := range slice {
if ele == s {
return slice
}
}
return append(slice, s)
}

func exitErrorf(msg string, args ...interface{}) {
fmt.Fprintf(os.Stderr, msg+"\n", args...)
os.Exit(1)
}

var version string = "πŸ˜‚πŸ‘ŒπŸ’―πŸ”₯πŸ”₯πŸ˜‚"

0 comments on commit c6447f1

Please sign in to comment.