/
init.go
212 lines (192 loc) · 4.88 KB
/
init.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
package main
import "github.com/hopkinsth/lambda-phage/Godeps/_workspace/src/github.com/spf13/cobra"
import "github.com/hopkinsth/lambda-phage/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/iam"
import "github.com/hopkinsth/lambda-phage/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws"
import "github.com/hopkinsth/lambda-phage/Godeps/_workspace/src/github.com/tj/go-debug"
import "strings"
import "fmt"
import "os"
func init() {
initCmd := &cobra.Command{
Use: "init",
Short: "initializes a config for your function",
Run: initPhage,
}
cmds = append(cmds, initCmd)
}
// helps you build a config file
func initPhage(c *cobra.Command, _ []string) {
var err error
fmt.Println(`
HELLO AND WELCOME
This command will help you set up your code for deployment to Lambda!
But we need some information from you, like what you want to name
your function and a few other things!
Please answer the prompts as they appear below:
`)
iCfg := new(Config)
iCfg.IamRole = new(IamRole)
iCfg.Location = new(Location)
prompts := getPrompts(iCfg)
err = prompts.run()
// merge in any existing properties from the config object
var wCfg *Config
if cfg != nil {
// if there's a config object, merge these two together
cfg.merge(iCfg)
wCfg = cfg
} else {
wCfg = iCfg
}
cfgFile, _ := c.Flags().GetString("config")
err = wCfg.writeToFile(cfgFile)
if err != nil {
panic(err)
}
fmt.Printf("Setup complete; saved config to %s\n", cfgFile)
}
// returns all the prompts needed for the `init` command
func getPrompts(cfg *Config) prompter {
wd, _ := os.Getwd()
st, _ := os.Stat(wd)
iamRoles, roleMap := getIamRoles()
ps := new(promptSet)
return ps.add().
withString(&cfg.Name).
isRequired().
setText("Enter a project name").
setDef(st.Name()).
done().
add().
withString(&cfg.Description).
setText("Enter a project description if you'd like").
setDef("").
done().
add().
withString(&cfg.Archive).
setText("Enter a archive name if you'd like").
setDef(st.Name() + ".zip").
done().
add().
withString(&cfg.Runtime).
isRequired().
setText("What runtime are you using: nodejs, java8, or python 2.7?").
setDef("nodejs").
withCompleter(
func(l string) []string {
// there can only be one
r := make([]string, 1)
if len(l) == 0 {
r[0] = ""
} else {
switch string(l[0]) {
case "n":
r[0] = "nodejs"
case "j":
r[0] = "java8"
case "p":
r[0] = "python2.7"
}
}
return r
},
).
done().
add().
withString(&cfg.EntryPoint).
isRequired().
setText("Enter an entry point or handler name").
setDef("index.handler").
done().
add().
withInt(&cfg.MemorySize).
setText("Enter memory size").
setDef("128").
done().
add().
withInt(&cfg.Timeout).
setText("Enter timeout").
setDef("5").
done().
add().
withStringSet(&cfg.Regions).
setText("Enter AWS regions where this function will run").
setDef("us-east-1").
done().
add().
withFunc(
func(s string) {
// if this looks like an ARN,
// we'll assume it is... for now
if strings.Index(s, "arn:aws:iam::") == 0 {
cfg.IamRole.Arn = &s
} else {
// check to see if this name is inside the role map
if arn, ok := roleMap[s]; ok {
cfg.IamRole.Arn = arn
} else {
// if not in role map, set the name
cfg.IamRole.Name = &s
}
}
},
).
isRequired().
setText("IAM Role").
setDescription(
"\nAll Lambda functions must run with an IAM role, which gives them access\n" +
"to various resources in AWS. What role do you want to assign this function?\n" +
"Type a name and we'll try to auto-complete it if you press the tab key\n",
).
setDef("").
withCompleter(
func(l string) []string {
c := make([]string, 0)
for _, role := range iamRoles {
if strings.HasPrefix(*role.Name, l) {
c = append(c, *role.Name)
}
}
return c
},
).
done().
add().
withString(&cfg.Location.S3Bucket).
setText("s3 bucket you want to upload your code to (if any)").
setDef("").
done().
add().
withString(&cfg.Location.S3Key).
setText("s3 folder your code should be stored inside (if any)").
setDef("").
done().
add().
withString(&cfg.Location.S3Region).
setText("s3 region where your bucket is (if any)").
setDef("").
done()
}
// pulls all the IAM roles from your account
func getIamRoles() ([]*IamRole, map[string]*string) {
debug := debug.Debug("core.getIamRoles")
i := iam.New(nil)
r, err := i.ListRoles(&iam.ListRolesInput{
// try loading up to 1000 roles now
MaxItems: aws.Int64(1000),
})
if err != nil {
debug("getting IAM roles failed! maybe you don't have permission to do that?")
return []*IamRole{}, map[string]*string{}
}
roles := make([]*IamRole, len(r.Roles))
roleMap := make(map[string]*string)
for i, r := range r.Roles {
roles[i] = &IamRole{
Arn: r.Arn,
Name: r.RoleName,
}
roleMap[*r.RoleName] = r.Arn
}
return roles, roleMap
}