Skip to content

Commit 01cf641

Browse files
committed
Adding function to deploy using S3 as source
1 parent 9ebf9e7 commit 01cf641

File tree

4 files changed

+99
-24
lines changed

4 files changed

+99
-24
lines changed

README.rst

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,20 @@ This would create environment variables in the lambda instance upon deploy. If y
167167

168168
Uploading to S3
169169
===============
170-
You may find that you do not need the toolkit to fully deploy your Lambda or that your code bundle is too large to upload via the API. You can use the `upload` command to send the bundle to an S3 bucket of your choosing.
171-
Before doing this, you will need to set the following variables in `config.yaml`:
172-
```
170+
You may find that you do not need the toolkit to fully deploy your Lambda or that your code bundle is too large to upload via the API. You can use the ``upload`` command to send the bundle to an S3 bucket of your choosing.
171+
Before doing this, you will need to set the following variables in ``config.yaml`:
172+
173+
.. code:: yaml
174+
173175
role: basic_s3_upload
174176
bucket_name: 'example-bucket'
175177
s3_key_prefix: 'path/to/file/'
176-
```
177-
Your role must have `s3:PutObject` permission on the bucket/key that you specify for the upload to work properly. Once you have that set, you can execute `lambda upload` to initiate the transfer.
178+
179+
Your role must have ``s3:PutObject`` permission on the bucket/key that you specify for the upload to work properly. Once you have that set, you can execute ``lambda upload`` to initiate the transfer.
180+
181+
Deploying via S3
182+
===============
183+
You can also choose to use S3 as your source for Lambda deployments. This can be done by issuing ``lambda deploy_s3`` with the same variables/AWS permissions you'd set for executing the ``upload`` command.
178184

179185
Development
180186
===========

aws_lambda/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
__email__ = '[email protected]'
55
__version__ = '1.0.1'
66

7-
from .aws_lambda import deploy, invoke, init, build, upload, cleanup_old_versions
7+
from .aws_lambda import deploy, deploy_s3, invoke, init, build, upload, cleanup_old_versions
88

99
# Set default logging handler to avoid "No handler found" warnings.
1010
import logging

aws_lambda/aws_lambda.py

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,33 @@ def deploy(src, requirements=False, local_package=None):
9595
else:
9696
create_function(cfg, path_to_zip_file)
9797

98+
def deploy_s3(src, requirements=False, local_package=None):
99+
"""Deploys a new function via AWS S3.
100+
101+
:param str src:
102+
The path to your Lambda ready project (folder must contain a valid
103+
config.yaml and handler module (e.g.: service.py).
104+
:param str local_package:
105+
The path to a local package with should be included in the deploy as
106+
well (and/or is not available on PyPi)
107+
"""
108+
# Load and parse the config file.
109+
path_to_config_file = os.path.join(src, 'config.yaml')
110+
cfg = read(path_to_config_file, loader=yaml.load)
111+
112+
# Copy all the pip dependencies required to run your code into a temporary
113+
# folder then add the handler file in the root of this directory.
114+
# Zip the contents of this folder into a single file and output to the dist
115+
# directory.
116+
path_to_zip_file = build(src, requirements, local_package)
117+
118+
use_s3 = True
119+
s3_file = upload_s3(cfg, path_to_zip_file, use_s3)
120+
if function_exists(cfg, cfg.get('function_name')):
121+
update_function(cfg, path_to_zip_file, use_s3, s3_file)
122+
else:
123+
create_function(cfg, path_to_zip_file, use_s3, s3_file)
124+
98125
def upload(src, requirements=False, local_package=None):
99126
"""Uploads a new function to AWS S3.
100127
@@ -363,7 +390,7 @@ def get_client(client, aws_access_key_id, aws_secret_access_key, region=None):
363390
)
364391

365392

366-
def create_function(cfg, path_to_zip_file):
393+
def create_function(cfg, path_to_zip_file, *use_s3, **s3_file):
367394
"""Register and upload a function to AWS Lambda."""
368395

369396
print('Creating your new Lambda function')
@@ -378,21 +405,41 @@ def create_function(cfg, path_to_zip_file):
378405
cfg.get('region'))
379406

380407
# Do we prefer development variable over config?
408+
buck_name = (
409+
os.environ.get('S3_BUCKET_NAME') or cfg.get('bucket_name')
410+
)
381411
func_name = (
382412
os.environ.get('LAMBDA_FUNCTION_NAME') or cfg.get('function_name')
383413
)
384414
print('Creating lambda function with name: {}'.format(func_name))
385-
kwargs = {
386-
'FunctionName': func_name,
387-
'Runtime': cfg.get('runtime', 'python2.7'),
388-
'Role': role,
389-
'Handler': cfg.get('handler'),
390-
'Code': {'ZipFile': byte_stream},
391-
'Description': cfg.get('description'),
392-
'Timeout': cfg.get('timeout', 15),
393-
'MemorySize': cfg.get('memory_size', 512),
394-
'Publish': True
395-
}
415+
416+
if use_s3 == True:
417+
kwargs = {
418+
'FunctionName': func_name,
419+
'Runtime': cfg.get('runtime', 'python2.7'),
420+
'Role': role,
421+
'Handler': cfg.get('handler'),
422+
'Code': {
423+
'S3Bucket': '{}'.format(buck_name),
424+
'S3Key': '{}'.format(s3_file)
425+
},
426+
'Description': cfg.get('description'),
427+
'Timeout': cfg.get('timeout', 15),
428+
'MemorySize': cfg.get('memory_size', 512),
429+
'Publish': True
430+
}
431+
else:
432+
kwargs = {
433+
'FunctionName': func_name,
434+
'Runtime': cfg.get('runtime', 'python2.7'),
435+
'Role': role,
436+
'Handler': cfg.get('handler'),
437+
'Code': {'ZipFile': byte_stream},
438+
'Description': cfg.get('description'),
439+
'Timeout': cfg.get('timeout', 15),
440+
'MemorySize': cfg.get('memory_size', 512),
441+
'Publish': True
442+
}
396443

397444
if 'environment_variables' in cfg:
398445
kwargs.update(
@@ -408,7 +455,7 @@ def create_function(cfg, path_to_zip_file):
408455
client.create_function(**kwargs)
409456

410457

411-
def update_function(cfg, path_to_zip_file):
458+
def update_function(cfg, path_to_zip_file, *use_s3, **s3_file):
412459
"""Updates the code of an existing Lambda function"""
413460

414461
print('Updating your Lambda function')
@@ -422,12 +469,25 @@ def update_function(cfg, path_to_zip_file):
422469
client = get_client('lambda', aws_access_key_id, aws_secret_access_key,
423470
cfg.get('region'))
424471

425-
client.update_function_code(
426-
FunctionName=cfg.get('function_name'),
427-
ZipFile=byte_stream,
428-
Publish=True
472+
# Do we prefer development variable over config?
473+
buck_name = (
474+
os.environ.get('S3_BUCKET_NAME') or cfg.get('bucket_name')
429475
)
430476

477+
if use_s3 == True:
478+
client.update_function_code(
479+
FunctionName=cfg.get('function_name'),
480+
S3Bucket='{}'.format(buck_name),
481+
S3Key='{}'.format(s3_file),
482+
Publish=True
483+
)
484+
else:
485+
client.update_function_code(
486+
FunctionName=cfg.get('function_name'),
487+
ZipFile=byte_stream,
488+
Publish=True
489+
)
490+
431491
kwargs = {
432492
'FunctionName': cfg.get('function_name'),
433493
'Role': role,
@@ -454,7 +514,7 @@ def update_function(cfg, path_to_zip_file):
454514

455515
client.update_function_configuration(**kwargs)
456516

457-
def upload_s3(cfg, path_to_zip_file):
517+
def upload_s3(cfg, path_to_zip_file, *use_s3):
458518
"""Upload a function to AWS S3."""
459519

460520
print('Uploading your new Lambda function')
@@ -487,6 +547,8 @@ def upload_s3(cfg, path_to_zip_file):
487547

488548
client.put_object(**kwargs)
489549
print('Finished uploading {} to S3 bucket {}'.format(func_name, buck_name))
550+
if use_s3 == True:
551+
return filename
490552

491553
def function_exists(cfg, function_name):
492554
"""Check whether a function exists or not"""

scripts/lambda

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ def deploy(use_requirements, local_package):
5252
def upload(use_requirements, local_package):
5353
aws_lambda.upload(CURRENT_DIR, use_requirements, local_package)
5454

55+
@click.command(help="Deploy your lambda via S3.")
56+
@click.option('--use-requirements', default=False, is_flag=True, help='Install all packages defined in requirements.txt')
57+
@click.option('--local-package', default=None, help='Install local package as well.', type=click.Path(), multiple=True)
58+
def deploy_s3(use_requirements, local_package):
59+
aws_lambda.deploy_s3(CURRENT_DIR, use_requirements, local_package)
60+
5561
@click.command(help="Delete old versions of your functions")
5662
@click.option("--keep-last", type=int, prompt="Please enter the number of recent versions to keep")
5763
def cleanup(keep_last):
@@ -62,6 +68,7 @@ if __name__ == '__main__':
6268
cli.add_command(invoke)
6369
cli.add_command(deploy)
6470
cli.add_command(upload)
71+
cli.add_command(deploy_s3)
6572
cli.add_command(build)
6673
cli.add_command(cleanup)
6774
cli()

0 commit comments

Comments
 (0)