Skip to content

Commit c6447f1

Browse files
committed
Refactor To One Binary
1 parent 3b5061b commit c6447f1

File tree

5 files changed

+192
-45
lines changed

5 files changed

+192
-45
lines changed

β€Ž.gitignore

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@
1717
# Packages from go get
1818
github.com
1919

20-
# Built binaries
21-
paramcopy
22-
paramlist
23-
2420
### macOS ###
2521
# General
2622
.DS_Store

β€ŽREADME.md

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,10 @@
22

33
## TODO
44

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

9-
## paramcopy
9+
Usage
1010

11-
Copies the specified SSM parameter to your clipboard.
12-
13-
## Usage
14-
15-
Make sure valid AWS credentials are accessible in your terminal.
16-
17-
go build pkg/paramcopy.go
18-
19-
./paramcopy parameter
20-
21-
Copies the specified parameter to your clipboard.
22-
23-
### Bash Completion
24-
25-
For now, you need the paramlist binary in the same directory for bash completion.
26-
27-
source <(./paramcopy -completion-bash)
28-
go build pkg/paramlist.go
29-
30-
## paramlist
31-
32-
There's also a untility to list SSM parameters.
33-
34-
It was creted for use in the bash completion.
35-
36-
You can specify at least one prefix to filter the parameter names by.
11+
param [copy|list]

β€Žcmd/param/param.go

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import (
55
"fmt"
66
"os"
77

8+
"github.com/atotto/clipboard"
89
"github.com/posener/complete"
10+
"github.com/willjcj/param/pkg/paramcopy"
11+
"github.com/willjcj/param/pkg/paramlist"
912
)
1013

1114
func main() {
@@ -18,17 +21,26 @@ func main() {
1821
"param",
1922
complete.Command{
2023
Flags: complete.Flags{
21-
"-name": complete.PredictAnything,
24+
"-name": complete.PredictAnything,
25+
"-complete": complete.PredictNothing,
26+
"-uncomplete": complete.PredictNothing,
27+
"-h": complete.PredictNothing,
28+
"-help": complete.PredictNothing,
29+
"-y": complete.PredictNothing,
30+
},
31+
Sub: complete.Commands{
32+
"copy": complete.Command{
33+
// TODO fill with list output
34+
Args: complete.PredictNothing,
35+
},
36+
"list": complete.Command{
37+
// TODO fill with list output
38+
Args: complete.PredictNothing,
39+
},
2240
},
2341
},
2442
)
2543

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

47-
// if the completion did not do anything, we can run our program logic here.
48-
if name == "" {
49-
fmt.Println("Your name is missing")
50-
os.Exit(1)
51-
}
59+
// command := os.Args[0]
60+
subCommand := os.Args[1]
61+
62+
if subCommand == "copy" {
63+
paramName := os.Args[2]
64+
65+
decryptedParameter := paramcopy.GetDecryptedParameter(paramName)
5266

53-
fmt.Println("Hi,", name)
67+
clipboard.WriteAll(decryptedParameter)
68+
fmt.Printf("Copied %s to clipboard.\n", paramName)
69+
} else if subCommand == "list" {
70+
prefixes := os.Args[2:]
71+
72+
params := paramlist.DescribeParameters(prefixes)
73+
74+
for _, param := range params {
75+
fmt.Println(param)
76+
}
77+
}
5478
}

β€Žpkg/paramcopy/paramcopy.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package paramcopy
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"os"
7+
"path"
8+
9+
"github.com/aws/aws-sdk-go/aws"
10+
"github.com/aws/aws-sdk-go/aws/session"
11+
"github.com/aws/aws-sdk-go/service/ssm"
12+
)
13+
14+
var service = createSSMService()
15+
16+
var usage = fmt.Sprintf("Usage: \n %s paramter_name", path.Base(os.Args[0]))
17+
18+
func getName() string {
19+
if flag.NArg() < 1 {
20+
exitErrorf("Parameter name required.\n%s", usage)
21+
} else if flag.NArg() > 1 {
22+
exitErrorf("Too many parameters.\n%s", usage)
23+
}
24+
25+
return flag.Arg(0)
26+
}
27+
28+
func GetDecryptedParameter(name string) string {
29+
output, err := service.GetParameter(&ssm.GetParameterInput{
30+
Name: aws.String(name),
31+
WithDecryption: aws.Bool(true),
32+
})
33+
if err != nil {
34+
exitErrorf("Unable to describe parameters, %v", err)
35+
}
36+
return *output.Parameter.Value
37+
}
38+
39+
func createSSMService() *ssm.SSM {
40+
sess, err := session.NewSession(&aws.Config{
41+
Region: aws.String("eu-west-1")},
42+
)
43+
44+
if err != nil {
45+
exitErrorf("Unable to describe parameters, %v", err)
46+
}
47+
48+
// Create SSM service client
49+
return ssm.New(sess)
50+
}
51+
52+
func exitErrorf(msg string, args ...interface{}) {
53+
fmt.Fprintf(os.Stderr, msg+"\n", args...)
54+
os.Exit(1)
55+
}

β€Žpkg/paramlist/paramlist.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package paramlist
2+
3+
import (
4+
"fmt"
5+
"github.com/aws/aws-sdk-go/aws"
6+
"github.com/aws/aws-sdk-go/aws/session"
7+
"github.com/aws/aws-sdk-go/service/ssm"
8+
"github.com/droundy/goopt"
9+
"os"
10+
"sort"
11+
)
12+
13+
var service = createSSMService()
14+
15+
func createSSMService() *ssm.SSM {
16+
sess, err := session.NewSession(&aws.Config{
17+
Region: aws.String("eu-west-1")},
18+
)
19+
20+
if err != nil {
21+
exitErrorf("Unable to describe parameters, %v", err)
22+
}
23+
24+
// Create SSM service client
25+
return ssm.New(sess)
26+
}
27+
28+
func initGoOpt() {
29+
goopt.Description = func() string {
30+
return "Get parameter names from AWS SSM with optional prefixes."
31+
}
32+
goopt.Version = version
33+
goopt.Summary = "paramlist [prefixes]"
34+
goopt.Parse(nil)
35+
}
36+
37+
func DescribeParameters(prefixes []string) []string {
38+
paramNames := []string{}
39+
if len(prefixes) <= 0 {
40+
paramNames = getAllParamNames()
41+
} else {
42+
for _, prefix := range prefixes {
43+
for _, name := range getParamNames(prefix) {
44+
paramNames = appendIfMissing(paramNames, name)
45+
}
46+
}
47+
}
48+
sort.Strings(paramNames)
49+
return paramNames
50+
}
51+
52+
func getParamNames(prefix string) []string {
53+
// Fix passing empty string to SSM API
54+
if len(prefix) < 1 {
55+
return getAllParamNames()
56+
}
57+
58+
filters := []*ssm.ParametersFilter{&ssm.ParametersFilter{
59+
Key: aws.String("Name"),
60+
Values: []*string{aws.String(prefix)},
61+
}}
62+
paramNames := []string{}
63+
err := service.DescribeParametersPages(&ssm.DescribeParametersInput{
64+
Filters: filters},
65+
func(page *ssm.DescribeParametersOutput, lastPage bool) bool {
66+
for _, parameter := range page.Parameters {
67+
paramNames = append(paramNames, aws.StringValue(parameter.Name))
68+
}
69+
return true
70+
})
71+
72+
if err != nil {
73+
exitErrorf("Unable to describe parameters, %v", err)
74+
}
75+
76+
return paramNames
77+
}
78+
79+
func getAllParamNames() []string {
80+
return getParamNames(" ")
81+
}
82+
83+
func appendIfMissing(slice []string, s string) []string {
84+
for _, ele := range slice {
85+
if ele == s {
86+
return slice
87+
}
88+
}
89+
return append(slice, s)
90+
}
91+
92+
func exitErrorf(msg string, args ...interface{}) {
93+
fmt.Fprintf(os.Stderr, msg+"\n", args...)
94+
os.Exit(1)
95+
}
96+
97+
var version string = "πŸ˜‚πŸ‘ŒπŸ’―πŸ”₯πŸ”₯πŸ˜‚"

0 commit comments

Comments
Β (0)