-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdeploy-wrapper.py
More file actions
310 lines (249 loc) · 9.46 KB
/
Copy pathdeploy-wrapper.py
File metadata and controls
310 lines (249 loc) · 9.46 KB
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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
#!/usr/local/bin/python
'''
Deployment and build script to manage build and deploy lamda functions
Author: Jason Witting
Version: 0.1
'''
import argparse
import json
import logging
import subprocess
import sys
import boto3
BASE_DIR = subprocess.check_output(['pwd']).strip('\n')
BUILD_SCRIPT = BASE_DIR + '/' + 'build.sh'
CONFIG_FILE = 'config/deployment-config.json'
# setup logger
LOGGER = logging.getLogger('DEPLOY')
LOGGER.setLevel(logging.DEBUG)
STDOUT_LOG_HANDLER = logging.StreamHandler(sys.stdout)
STDOUT_LOG_HANDLER.setLevel(logging.INFO)
FORMATTER = logging.Formatter('\
[%(asctime)s] \
[%(levelname)s] \
[%(name)s] %(message)s')
STDOUT_LOG_HANDLER.setFormatter(FORMATTER)
LOGGER.addHandler(STDOUT_LOG_HANDLER)
def load_config(filename):
'''loads the script config variables'''
config = ''
with open(filename) as f:
config = json.load(f)
return config
def create_deployment_bundle():
'''create lambda deployment zip file and return name'''
pkg = subprocess.check_output([BUILD_SCRIPT, '-b']).strip('\n')
LOGGER.info("Created deployment bundle: " + pkg)
return pkg
def publish_s3(filename, bucket, key):
'''
push files to s3
args:
filename - (string) the file to publish to s3
bucket - (string) s3 bucket
key - (string) s3 object key
'''
s3 = boto3.client('s3')
with open(filename, 'rb') as data:
s3.upload_fileobj(data, bucket, key)
LOGGER.info("Uploaded " + filename + " as "+key+ " to S3://" + bucket)
def upate_config(env, lambda_config_file, config):
'''
push config file to specific env folder on s3
args:
env - (string) the enviroment to push to i.e DEV, STAGE, PROD
file - (string) the config.json file which contains the lambda
config
'''
print ("FILE: " + lambda_config_file +
" BUCKET: " + config['S3_CONFIG_BUCKET'] +
" KEY: " + env + '/' +
config['CONFIG_FILE'])
return publish_s3(lambda_config_file,
config['S3_CONFIG_BUCKET'],
env + '/' +
config['CONFIG_FILE'])
def create_lamda_function(function_name, role_arn, handler, bucket, key, timeout, memory_size, description=''):
'''
create a lambda function
returns the entire response as a JSON string
args:
function_name - (string) name of the lambda function to create
role_arn - (string) the role for lambda function to assume
handler - (string) the lamda function within the package to invoke
bucket - (string) the s3 bucket where the deployment package resides
key - (string) the s3 object key AKA lamda deployment package filename
timeout - (string) the timeout value for the lambda function
memory_size - (string) the memory size of the lambda function
opt args:
description - description of the function
'''
aws_lambda = boto3.client('lambda')
resp = aws_lambda.create_function(
FunctionName=function_name,
Runtime='python2.7',
Role=role_arn,
Handler=handler,
Code={
'S3Bucket': bucket,
'S3Key': key,
},
Description=description,
Timeout=int(timeout),
MemorySize=int(memory_size),
Publish=True
)
LOGGER.info("Created Lambda function: " + function_name)
return resp
def update_lamda_alias(alias, version, function_name, description=''):
'''
update lambda alias to specified version
returns the entire response as a JSON string
args:
alias - (string) name of the lambda alias to update
version - (string) version number of lambda alias to point to
function_name - the lamda function name
opt args:
description - description of the function
'''
aws_lambda = boto3.client('lambda')
resp = aws_lambda.update_alias(
FunctionName=function_name,
Name=alias,
FunctionVersion=version,
Description=description
)
LOGGER.info("Updated Alias: " +
alias +
" to version: " +
version)
return resp
def publish_lambda(function_name, bucket, key):
'''
publish lambda function and return version number
returns a version number as a string
args:
function_name - (string) the function name
bucket - (string) the s3 bucket NameError
key - (string) the s3 object key
'''
aws_lambda = boto3.client('lambda')
resp = aws_lambda.update_function_code(
FunctionName=function_name,
S3Bucket=bucket,
S3Key=key,
Publish=True
)
LOGGER.info("Published verison: " + resp['Version'])
return resp['Version']
def get_alias_version(alias, function_name):
'''
version number associated with alias
returns the version number as a string
args:
alias - (string) the lambda alias to query
function_name - (string) the lambda function name
'''
aws_lambda = boto3.client('lambda')
response = aws_lambda.get_alias(
FunctionName=function_name,
Name=alias
)
return response['FunctionVersion']
def promote_version(source, target, config):
'''
promote version tied to an alias to another enviroment(alias)
returns the entire reponse as JSON string
args:
source - (string) the source alias from which to get version
target - (string) the target alias to set the version to
'''
resp = ''
version = get_alias_version(source, config['LAMBDA_FUNC_NAME'])
print("promote " + source +
" version: " + version + " to " +
target + " (Y/N):")
reply = raw_input().strip('\n').upper()
if reply == 'Y':
LOGGER.info('Updating Alias: ' + source +
' to version: ' + version)
resp = update_lamda_alias(target, version, config['LAMBDA_FUNC_NAME'])
LOGGER.debug(resp)
return resp
def main():
'''
main method
'''
config = load_config(CONFIG_FILE)
parser = argparse.ArgumentParser(
description='Deploy and manipulate lambda function')
subparsers = parser.add_subparsers(
dest='subparsers_name', help="[CMDS...]")
parser_promote = subparsers.add_parser(
'promote', help='promote <source enviroment> \
version to <target enviroment>')
parser_promote.add_argument('source', choices=['DEV', 'STAGE', 'PROD'],
help='the source enviroment')
parser_promote.add_argument('target', choices=['DEV', 'STAGE', 'PROD'],
help='the target enviroment')
parser_deploy = subparsers.add_parser(
'deploy', help='deploy function to s3')
parser_deploy.add_argument(
'--env', choices=['DEV', 'STAGE', 'PROD', 'LATEST'],
help='the target enviroment')
parser_config = subparsers.add_parser('config',
help='deploy config to s3')
parser_config.add_argument('env',
choices=['DEV', 'STAGE', 'PROD', 'LATEST'],
help='set config for specific enviroment')
subparsers.add_parser(
'init', help='creates the base lambda function')
subparsers.add_parser(
'clean', help='clean local build enviroment')
subparsers.add_parser(
'setup', help='create local build enviroment')
args = parser.parse_args()
deploy_env = args.env
if args.env == 'LATEST':
deploy_env = '$LATEST'
# deploy
if args.subparsers_name == 'deploy':
pkg = create_deployment_bundle()
publish_s3(pkg, config['LAMBDA_DEPLOY_BUCKET'], pkg.split('/').pop())
LOGGER.info("Uploaded lambda zip:" + pkg.split('/').pop() +
" to S3://" + config['LAMBDA_DEPLOY_BUCKET'])
version = publish_lambda(config['LAMBDA_FUNC_NAME'],
config['LAMBDA_DEPLOY_BUCKET'],
pkg.split('/').pop())
if args.env:
LOGGER.debug(update_lamda_alias(deploy_env, version,
config['LAMBDA_FUNC_NAME'], description=''))
# promote
if args.subparsers_name == 'promote':
LOGGER.debug(promote_version(args.source, args.target, config))
# deploy
if args.subparsers_name == 'config':
LOGGER.debug(upate_config(deploy_env, BASE_DIR +
"/config/" + config['CONFIG_FILE'], config))
if args.subparsers_name == 'init':
pkg = create_deployment_bundle()
publish_s3(pkg, config['LAMBDA_DEPLOY_BUCKET'], pkg.split('/').pop())
LOGGER.info("Uploaded lambda zip:" + pkg.split('/').pop() +
" to S3://" + config['LAMBDA_DEPLOY_BUCKET'])
LOGGER.debug(create_lamda_function(config['LAMBDA_FUNC_NAME'],
config['LAMBDA_ROLE_ARN'], config[
'LAMBDA_HANDLER'],
config['LAMBDA_DEPLOY_BUCKET'],
pkg.split('/').pop(),
config['LAMBDA_TIMEOUT'],
config['LAMBDA_MEMORY_SIZE']))
# clean
if args.subparsers_name == 'clean':
LOGGER.info(subprocess.check_output([BUILD_SCRIPT, '-c']).strip('\n'))
# setup
if args.subparsers_name == 'setup':
LOGGER.info("creating build enviroment" +
subprocess.check_output([BUILD_SCRIPT, '-s']).strip('\n'))
# launch main
if __name__ == "__main__":
main()