1 | #!/usr/bin/env node
|
2 | var aws = require('aws-sdk')
|
3 | var async = require('async')
|
4 | var region = process.env.AWS_REGION || 'us-east-1'
|
5 | var lambda = new aws.Lambda({region:region})
|
6 | var chalk = require('chalk')
|
7 | var isUndefined = require('lodash').isUndefined
|
8 | var exists = require('path-exists').sync
|
9 | var read = require('fs').readFileSync
|
10 | var rimraf = require('rimraf').sync
|
11 | var exec = require('child_process').exec
|
12 | var join = require('path').join
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | var name = process.argv[2]
|
25 | if (isUndefined(name)) {
|
26 | console.error('Error: missing path to the lambda')
|
27 | process.exit(1)
|
28 | }
|
29 |
|
30 | var alias = process.argv[3]
|
31 | if (isUndefined(alias)) {
|
32 | console.error('Error: missing alias argument')
|
33 | process.exit(1)
|
34 | }
|
35 |
|
36 | var pkg = name + '/package.json'
|
37 | if (!exists(pkg)) {
|
38 | console.error('Error: ' + pkg + ' does not exist')
|
39 | console.error('\n')
|
40 | console.error('Create a lambda with lambda-create in an npm script.')
|
41 | console.error('\n')
|
42 | process.exit(1)
|
43 | }
|
44 |
|
45 | var package = {
|
46 | json: require(process.cwd() + '/' + pkg)
|
47 | }
|
48 |
|
49 | var actual = package.json.name
|
50 | if (isUndefined(actual)) {
|
51 | console.error('Error: package.json missing name')
|
52 | process.exit(1)
|
53 | }
|
54 |
|
55 | var config = package.json.lambda
|
56 | if (isUndefined(config)) {
|
57 |
|
58 | package.json.lambda = {
|
59 | role: "lambda_basic_execution"
|
60 | }
|
61 | }
|
62 |
|
63 | var role = package.json.lambda.role
|
64 | if (isUndefined(role)) {
|
65 | console.error('Error: package.json missing lambda.role')
|
66 | process.exit(1)
|
67 | }
|
68 |
|
69 | console.log(chalk.green('\n λ ') + chalk.underline.cyan(package.json.name) + chalk.grey(` (alias:${alias})`))
|
70 |
|
71 |
|
72 | function strip(str) {
|
73 | if(str.substr(-1) === '/') {
|
74 | return str.substr(0, str.length - 1)
|
75 | }
|
76 | return str
|
77 | }
|
78 |
|
79 | var dirname = join(process.cwd(), name)
|
80 | var zip = join(process.cwd(), strip(name) + '.zip')
|
81 |
|
82 | async.waterfall([
|
83 | function zipTmp(callback) {
|
84 | exec(`cd ${dirname} && zip -r ${zip} * --quiet`, err=> {
|
85 | if (err) {
|
86 | callback(Error(err))
|
87 | }
|
88 | else {
|
89 | console.log(chalk.green(' + ') + chalk.dim('zip the package'))
|
90 | callback()
|
91 | }
|
92 | })
|
93 | },
|
94 | function lambdaExists(callback) {
|
95 | lambda.listFunctions({}, (err, fns)=> {
|
96 | if (err) {
|
97 | callback(Error('unable to list lambdas'))
|
98 | }
|
99 | else {
|
100 | var names = fns.Functions.map(f=> f.FunctionName).sort()
|
101 | var notfound = names.indexOf(actual) === -1
|
102 | console.log(chalk.green(' + ') + chalk.dim('checking'))
|
103 | if (notfound) {
|
104 | callback(null, false)
|
105 | }
|
106 | else {
|
107 | callback(null, true)
|
108 | }
|
109 | }
|
110 | })
|
111 | },
|
112 | function create(lambdaExists, callback) {
|
113 | if (lambdaExists) {
|
114 | console.log(chalk.green(' + ') + chalk.dim('skipping create'))
|
115 | callback()
|
116 | }
|
117 | else {
|
118 | console.log(chalk.green(' + ') + chalk.dim(`create ${package.json.name}`))
|
119 | var zipfile = read(zip)
|
120 | var params = {
|
121 | Code: {
|
122 | ZipFile: zipfile
|
123 | },
|
124 | FunctionName: package.json.name,
|
125 | Handler: 'index.handler',
|
126 | Role: package.json.lambda.role,
|
127 | Runtime: 'nodejs',
|
128 | Publish: true,
|
129 | Timeout: 3
|
130 | }
|
131 | lambda.createFunction(params, (err, data)=> {
|
132 | if (err) {
|
133 | console.error(err)
|
134 | callback(Error('create failed'))
|
135 | }
|
136 | else {
|
137 | console.log(chalk.green(' + ') + chalk.dim('creating'))
|
138 | callback()
|
139 | }
|
140 | })
|
141 | }
|
142 | },
|
143 | function update(callback) {
|
144 | console.log(chalk.green(' + ') + chalk.dim('update code'))
|
145 | var zipfile = read(zip)
|
146 | var params = {
|
147 | FunctionName: package.json.name,
|
148 | Publish: true,
|
149 | ZipFile: zipfile
|
150 | }
|
151 | lambda.updateFunctionCode(params, (err, data)=> {
|
152 | if (err) {
|
153 | console.error(err)
|
154 | callback(Error('update failed'))
|
155 | }
|
156 | else {
|
157 | callback(null, data.Version)
|
158 | }
|
159 | })
|
160 | },
|
161 | function createAlias(version, callback) {
|
162 | var params = {
|
163 | FunctionName: package.json.name,
|
164 | FunctionVersion: version,
|
165 | Name: alias
|
166 | }
|
167 | lambda.createAlias(params, function(err, data) {
|
168 | console.log(chalk.green(' + ') + chalk.dim('create alias'))
|
169 | if (err) {
|
170 |
|
171 |
|
172 | callback(null, version)
|
173 | }
|
174 | else {
|
175 | callback(null, version)
|
176 | }
|
177 | })
|
178 | },
|
179 | function updateAlias(version, callback) {
|
180 | console.log(chalk.green(' + ') + chalk.dim(`alias code`))
|
181 | var params = {
|
182 | FunctionName: package.json.name,
|
183 | Name: alias,
|
184 | FunctionVersion: version
|
185 | }
|
186 | lambda.updateAlias(params, function(err, data) {
|
187 | if (err) {
|
188 | console.error(err)
|
189 | callback(Error('alias failed'))
|
190 | }
|
191 | else {
|
192 | var txt = chalk.green(' ✔︎ ')
|
193 | txt += chalk.dim('deployed ')
|
194 | txt += chalk.underline.cyan(`${package.json.name}@${version}`)
|
195 | txt += chalk.dim(` (alias:${alias})`)
|
196 | console.log(txt)
|
197 | callback()
|
198 | }
|
199 | })
|
200 | },
|
201 | function cleanupZip(callback) {
|
202 | rimraf(zip)
|
203 | callback()
|
204 | }],
|
205 | function done(err) {
|
206 | if (err) {
|
207 | console.error(err)
|
208 | process.exit(1)
|
209 | }
|
210 | else {
|
211 | console.log('\n')
|
212 | process.exit(0)
|
213 | }
|
214 | }
|
215 | )
|