-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdeploy_scribrbot.py
More file actions
executable file
·257 lines (194 loc) · 7.5 KB
/
deploy_scribrbot.py
File metadata and controls
executable file
·257 lines (194 loc) · 7.5 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
#!venv/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2017 Shreepad Shukla
"""
deploy_scribrbot
~~~~~~~~~~~~~~~~~~
This module deploys ScribrBot on AWS and registers the corresponding webhook.
It uses a CloudFormation template (stored in resources/) and AWS credentials
of an IAM user with the appropriate permissions.
The CloudFormation template creates the API Gateway, Lambda Function and
DynamoDB table for ScribrBot.
"""
import argparse
import subprocess
import platform
import boto3
import requests
def package_deploy(s3bucket, bot_name):
"""
Package the ScribrBot lambda function and deploy to the given S3 bucket
using the bot_name as the key.
"""
zip_tld_files = 'scribrbot.py' # files from the top level directory
zip_package_list = 'requests urllib3 certifi chardet idna jinja2 ' \
'markupsafe' # folders from site-packages
# Construct platform specific zip commands
zip_command = None
if (platform.system().lower() == 'linux'):
zip_command = '/bin/zip -9 {}.zip {} && ' \
'cd venv/lib/python2.7/site-packages/ && ' \
'/bin/zip -9r ../../../../{}.zip {}'.format(
bot_name, zip_tld_files, bot_name, zip_package_list
)
#TODO Windows specific zip command
if (platform.system().lower() == 'windows'):
pass
if (not zip_command):
raise Exception
# Execute ZIP command to create package file
zip_output = None
try:
zip_output = subprocess.Popen(zip_command,
stdout=subprocess.PIPE, shell=True).stdout.read().decode('utf-8')
except subprocess.SubprocessError as e:
print('SubprocessError: %s' % e)
raise e
print('zip_output: %s' % zip_output)
# Upload created ZIP package to S3
print('Uploading ZIP package to S3')
zip_filename = '{}.zip'.format(bot_name)
s3_key = 'resources/code/{}'.format(zip_filename)
s3bucket.put_object(Key=s3_key, Body=open(zip_filename, 'rb'))
print('Uploaded ZIP package to S3 with key: %s' % s3_key)
return s3_key
def uploadresources(s3bucket):
"""
Upload the neceassary /resources to the bucket with the appropriate
permissions.
"""
s3bucket.upload_file('resources/jinja2templates/summary.html',
'resources/jinja2templates/summary.html')
s3bucket.upload_file('resources/css/summary.css',
'resources/css/summary.css',
ExtraArgs={
'ACL': 'public-read',
'ContentType' : 'text/css'
}
)
def createstack(stackname, bot_name, telegram_token, lambda_s3bucket,
s3bucket_key, templatedata):
"""
Creates a ScribrBot stack for the given bot_name using the
CloudFormation templatedata.
Returns URL of the REST ApiGateway endpoint
"""
print('Creating stack: %s' % stackname)
# Get the low level client
cfclient = boto3.client('cloudformation')
cfresponse = cfclient.create_stack(
StackName=stackname,
TemplateBody=templatedata,
Parameters=[
{
'ParameterKey': 'TelegramBotName',
'ParameterValue': bot_name
},
{
'ParameterKey': 'TelegramBotToken',
'ParameterValue': telegram_token
},
{
'ParameterKey': 'LambdaFunctionS3Bucket',
'ParameterValue': lambda_s3bucket
},
{
'ParameterKey': 'LambdaFunctionS3Key',
'ParameterValue': s3bucket_key
}
],
Capabilities=['CAPABILITY_IAM'],
Tags=[
{
'Key': 'BotName',
'Value': bot_name
},
]
)
print('cfresponse: %r' % cfresponse)
# Wait for stack formation
print('Waiting for stack creation...')
cfcreatewaiter = cfclient.get_waiter('stack_create_complete')
cfcreatewaiter.wait(StackName=stackname)
print('Stack creation complete!')
# Pick up the Response Values
descstack = cfclient.describe_stacks(StackName=stackname)
print('Stack creation outputs: %r' % (descstack['Stacks'][0]['Outputs']) )
# Return ApiGateway URL
apig_url = descstack['Stacks'][0]['Outputs'][0]['OutputValue']
print('API Gateway URL: %r' % apig_url)
return apig_url
def registerWebhook(telegram_token, url):
"""
Register the Telegram webhook for the given token using the url given
"""
register_webhook_url = \
"https://api.telegram.org/bot{0}/setWebhook?url={1}".format(
telegram_token,
url
)
response = requests.get(register_webhook_url)
if response.status_code == 200:
print("Webhook registered succesfully!")
else:
print("Webhook registration failed")
print("Response: %r" % response)
def main():
"""
Parses command line arguments and environment variables and triggers the
core agent function.
"""
# Get environment variables - TODO
# Parse command line variables
parser = argparse.ArgumentParser()
parser.add_argument('--bot_name',
help='Name of the bot to be deployed (default TestScribrBotv3). Must be ' \
'unique, 6 to 10 chars long and only contain numbers and uppercase/ ' \
'lowercase letters',
default='TestScribrBotv3')
parser.add_argument('--telegram_token',
help='Telegram API token for the bot. The webhook will be registered '\
'and response messages sent using this. The API token for at least ' \
'one messaging platform is required')
parser.add_argument('--templatefile',
help='Filename of the CloudFormation template file. Default is ' \
'./resources/cloudformtemplates/CloudForm-ScribrBot.yaml',
default='./resources/cloudformtemplates/CloudForm-ScribrBot.yaml')
parser.add_argument('--s3bucket',
help='Name of the S3 bucket where the resources, including the bot ' \
'lamdba function, must be uploaded and the generated summaries stored ' \
' (default testscribrbot)',
default='testscribrbot')
parser.add_argument('--s3bucket_key',
help='S3 bucket key where the bot lamdba function has already been ' \
'uploaded. If provided, will use this and not package and deploy')
args = parser.parse_args()
# Check for telegram token
if (not args.telegram_token):
print("Telegram bot token is required to proceed. See deploy_scribrbot.py --help for details")
return
# Get the s3 bucket resource
s3 = boto3.resource('s3')
s3bucket = s3.Bucket(args.s3bucket)
# Package the bot lamdba function and deploy to S3 if s3bucket_key not provided
s3bucket_key = None
if (args.s3bucket_key):
s3bucket_key = args.s3bucket_key
else:
s3bucket_key = package_deploy(s3bucket, args.bot_name)
# Upload the ncessary /resources to the bucket
uploadresources(s3bucket)
# Create the stack
# Load the template data
f = open(args.templatefile)
templatedata = f.read()
f.close()
stackname = 'ScribrBotStack-' + args.bot_name
apig_url = createstack(stackname, args.bot_name, args.telegram_token, args.s3bucket,
s3bucket_key, templatedata)
# Register the webhook
registerWebhook(args.telegram_token, apig_url)
return
if __name__ == '__main__':
main()