Skip to content
This repository was archived by the owner on Mar 15, 2026. It is now read-only.

Commit e1297fb

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents d08efe2 + fc32da5 commit e1297fb

File tree

11 files changed

+106
-25
lines changed

11 files changed

+106
-25
lines changed

README.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,20 @@ Under API endpoint type select "API Gateway".
121121

122122
Next change Method to ``POST`` and Security to "Open" and click submit (NOTE: you should secure this for use in production, open security is used for demo purposes).
123123

124+
At last you need to change the return value of the function to comply with the standard defined for the API Gateway endpoint, the function should now look like this:
125+
126+
.. code:: python
127+
128+
def handler(event, context):
129+
# Your code goes here!
130+
e = event.get('e')
131+
pi = event.get('pi')
132+
return {
133+
"statusCode": 200,
134+
"headers": { "Content-Type": "application/json"},
135+
"body": e + pi
136+
}
137+
124138
Now try and run:
125139

126140
.. code:: bash

aws_lambda/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
# flake8: noqa
33
__author__ = 'Nick Ficano'
44
__email__ = 'nficano@gmail.com'
5-
__version__ = '0.4.0'
5+
__version__ = '0.5.0'
66

7-
from .aws_lambda import deploy, invoke, init, build
7+
from .aws_lambda import deploy, invoke, init, build, 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: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,60 @@
88
from shutil import copy, copyfile
99
from tempfile import mkdtemp
1010

11+
import botocore
1112
import boto3
1213
import pip
1314
import yaml
14-
from . import project_template
15+
1516
from .helpers import mkdir, read, archive, timestamp
1617

1718

1819
log = logging.getLogger(__name__)
1920

2021

22+
def cleanup_old_versions(src, keep_last_versions):
23+
"""Deletes old deployed versions of the function in AWS Lambda.
24+
25+
Won't delete $Latest and any aliased version
26+
27+
:param str src:
28+
The path to your Lambda ready project (folder must contain a valid
29+
config.yaml and handler module (e.g.: service.py).
30+
:param int keep_last_versions:
31+
The number of recent versions to keep and not delete
32+
"""
33+
if keep_last_versions <= 0:
34+
print("Won't delete all versions. Please do this manually")
35+
else:
36+
path_to_config_file = os.path.join(src, 'config.yaml')
37+
cfg = read(path_to_config_file, loader=yaml.load)
38+
39+
aws_access_key_id = cfg.get('aws_access_key_id')
40+
aws_secret_access_key = cfg.get('aws_secret_access_key')
41+
42+
client = get_client('lambda', aws_access_key_id, aws_secret_access_key,
43+
cfg.get('region'))
44+
45+
response = client.list_versions_by_function(
46+
FunctionName=cfg.get("function_name")
47+
)
48+
versions = response.get("Versions")
49+
if len(response.get("Versions")) < keep_last_versions:
50+
print("Nothing to delete. (Too few versions published)")
51+
else:
52+
version_numbers = [elem.get("Version") for elem in
53+
versions[1:-keep_last_versions]]
54+
for version_number in version_numbers:
55+
try:
56+
client.delete_function(
57+
FunctionName=cfg.get("function_name"),
58+
Qualifier=version_number
59+
)
60+
except botocore.exceptions.ClientError as e:
61+
print("Skipping Version {}: {}".format(version_number,
62+
e.message))
63+
64+
2165
def deploy(src, local_package=None):
2266
"""Deploys a new function to AWS Lambda.
2367
@@ -93,15 +137,13 @@ def init(src, minimal=False):
93137
Minimal possible template files (excludes event.json).
94138
"""
95139

96-
path_to_project_template = project_template.__path__[0]
97-
for f in os.listdir(path_to_project_template):
98-
path_to_file = os.path.join(path_to_project_template, f)
99-
if minimal and f == 'event.json':
140+
templates_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
141+
"project_templates")
142+
for filename in os.listdir(templates_path):
143+
if (minimal and filename == 'event.json') or filename.endswith('.pyc'):
100144
continue
101-
if f.endswith('.pyc'):
102-
# We don't need the compiled files.
103-
continue
104-
copy(path_to_file, src)
145+
destination = os.path.join(templates_path, filename)
146+
copy(destination, src)
105147

106148

107149
def build(src, local_package=None):
@@ -232,9 +274,9 @@ def get_role_name(account_id, role):
232274

233275

234276
def get_account_id(aws_access_key_id, aws_secret_access_key):
235-
"""Query IAM for a users' account_id"""
236-
client = get_client('iam', aws_access_key_id, aws_secret_access_key)
237-
return client.get_user()['User']['Arn'].split(':')[4]
277+
"""Query STS for a users' account_id"""
278+
client = get_client('sts', aws_access_key_id, aws_secret_access_key)
279+
return client.get_caller_identity().get('Account')
238280

239281

240282
def get_client(client, aws_access_key_id, aws_secret_access_key, region=None):
@@ -262,15 +304,24 @@ def create_function(cfg, path_to_zip_file):
262304
client = get_client('lambda', aws_access_key_id, aws_secret_access_key,
263305
cfg.get('region'))
264306

307+
function_name = os.environ.get('LAMBDA_FUNCTION_NAME') or cfg.get('function_name')
308+
print('Creating lambda function with name: {}'.format(function_name))
265309
client.create_function(
266-
FunctionName=cfg.get('function_name'),
310+
FunctionName=function_name,
267311
Runtime=cfg.get('runtime', 'python2.7'),
268312
Role=role,
269313
Handler=cfg.get('handler'),
270314
Code={'ZipFile': byte_stream},
271315
Description=cfg.get('description'),
272316
Timeout=cfg.get('timeout', 15),
273317
MemorySize=cfg.get('memory_size', 512),
318+
Environment={
319+
'Variables': {
320+
key.strip('LAMBDA_'): value
321+
for key, value in os.environ.items()
322+
if key.startswith('LAMBDA_')
323+
}
324+
},
274325
Publish=True
275326
)
276327

@@ -301,7 +352,11 @@ def update_function(cfg, path_to_zip_file):
301352
Handler=cfg.get('handler'),
302353
Description=cfg.get('description'),
303354
Timeout=cfg.get('timeout', 15),
304-
MemorySize=cfg.get('memory_size', 512)
355+
MemorySize=cfg.get('memory_size', 512),
356+
VpcConfig={
357+
'SubnetIds': cfg.get('subnet_ids', []),
358+
'SecurityGroupIds': cfg.get('security_group_ids', [])
359+
}
305360
)
306361

307362

aws_lambda/project_template/__init__.py

Whitespace-only changes.

requirements.txt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
boto3==1.3.1
2-
botocore==1.4.32
1+
boto3==1.4.1
2+
botocore==1.4.61
33
click==6.6
44
docutils==0.12
55
futures==3.0.5
66
jmespath==0.9.0
77
pyaml==15.8.2
88
python-dateutil==2.5.3
9-
python-lambda==0.4.0
109
PyYAML==3.11
11-
six==1.10.0
10+
six==1.10.0

scripts/lambda

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@ def cli():
1616

1717

1818
@click.command(help="Create a new function for Lambda.")
19-
def init():
20-
aws_lambda.init(CURRENT_DIR)
19+
@click.argument('folder', nargs=-1, type=click.Path(file_okay=False, writable=True))
20+
def init(folder):
21+
path = CURRENT_DIR
22+
if len(folder) > 0:
23+
path = "{}/{}".format(CURRENT_DIR, folder[0])
24+
if not os.path.exists(path):
25+
os.makedirs(path)
26+
aws_lambda.init(path)
2127

2228

2329
@click.command(help="Bundles package for deployment.")
@@ -38,9 +44,16 @@ def invoke(event_file, verbose):
3844
def deploy(local_package):
3945
aws_lambda.deploy(CURRENT_DIR, local_package)
4046

47+
48+
@click.command(help="Delete old versions of your functions")
49+
@click.option("--keep-last", type=int, prompt="Please enter the number of recent versions to keep")
50+
def cleanup(keep_last):
51+
aws_lambda.cleanup_old_versions(CURRENT_DIR, keep_last)
52+
4153
if __name__ == '__main__':
4254
cli.add_command(init)
4355
cli.add_command(invoke)
4456
cli.add_command(deploy)
4557
cli.add_command(build)
58+
cli.add_command(cleanup)
4659
cli()

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.4.0
2+
current_version = 0.5.0
33
commit = True
44
tag = True
55

0 commit comments

Comments
 (0)