|
8 | 8 | from shutil import copy, copyfile |
9 | 9 | from tempfile import mkdtemp |
10 | 10 |
|
| 11 | +import botocore |
11 | 12 | import boto3 |
12 | 13 | import pip |
13 | 14 | import yaml |
14 | | -from . import project_template |
| 15 | + |
15 | 16 | from .helpers import mkdir, read, archive, timestamp |
16 | 17 |
|
17 | 18 |
|
18 | 19 | log = logging.getLogger(__name__) |
19 | 20 |
|
20 | 21 |
|
| 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 | + |
21 | 65 | def deploy(src, local_package=None): |
22 | 66 | """Deploys a new function to AWS Lambda. |
23 | 67 |
|
@@ -93,15 +137,13 @@ def init(src, minimal=False): |
93 | 137 | Minimal possible template files (excludes event.json). |
94 | 138 | """ |
95 | 139 |
|
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'): |
100 | 144 | 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) |
105 | 147 |
|
106 | 148 |
|
107 | 149 | def build(src, local_package=None): |
@@ -232,9 +274,9 @@ def get_role_name(account_id, role): |
232 | 274 |
|
233 | 275 |
|
234 | 276 | 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') |
238 | 280 |
|
239 | 281 |
|
240 | 282 | 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): |
262 | 304 | client = get_client('lambda', aws_access_key_id, aws_secret_access_key, |
263 | 305 | cfg.get('region')) |
264 | 306 |
|
| 307 | + function_name = os.environ.get('LAMBDA_FUNCTION_NAME') or cfg.get('function_name') |
| 308 | + print('Creating lambda function with name: {}'.format(function_name)) |
265 | 309 | client.create_function( |
266 | | - FunctionName=cfg.get('function_name'), |
| 310 | + FunctionName=function_name, |
267 | 311 | Runtime=cfg.get('runtime', 'python2.7'), |
268 | 312 | Role=role, |
269 | 313 | Handler=cfg.get('handler'), |
270 | 314 | Code={'ZipFile': byte_stream}, |
271 | 315 | Description=cfg.get('description'), |
272 | 316 | Timeout=cfg.get('timeout', 15), |
273 | 317 | 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 | + }, |
274 | 325 | Publish=True |
275 | 326 | ) |
276 | 327 |
|
@@ -301,7 +352,11 @@ def update_function(cfg, path_to_zip_file): |
301 | 352 | Handler=cfg.get('handler'), |
302 | 353 | Description=cfg.get('description'), |
303 | 354 | 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 | + } |
305 | 360 | ) |
306 | 361 |
|
307 | 362 |
|
|
0 commit comments