120 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#!/usr/bin/env python3
 | 
						|
import os
 | 
						|
import glob
 | 
						|
import subprocess
 | 
						|
import zipfile
 | 
						|
import boto3
 | 
						|
import click
 | 
						|
import yaml
 | 
						|
import attr
 | 
						|
import typing
 | 
						|
 | 
						|
 | 
						|
@attr.s(auto_attribs=True)
 | 
						|
class Function:
 | 
						|
    name: str
 | 
						|
    runtime: str
 | 
						|
    role_arn: str
 | 
						|
    handler: str
 | 
						|
    files: typing.List[str]
 | 
						|
    layers: typing.List[str]
 | 
						|
    environment: typing.Dict[str, str]
 | 
						|
 | 
						|
 | 
						|
def create_psycopg2_layer():
 | 
						|
    if not os.path.exists("awslambda-psycopg2"):
 | 
						|
        subprocess.run(
 | 
						|
            ["git", "clone", "git@github.com:jkehler/awslambda-psycopg2.git"],
 | 
						|
            check=True,
 | 
						|
        )
 | 
						|
    prefix = "awslambda-psycopg2/psycopg2-3.7/"
 | 
						|
    with zipfile.ZipFile("psycopg2.zip", "w") as lz:
 | 
						|
        for file in glob.glob(prefix + "*"):
 | 
						|
            arcname = file.replace(prefix, "python/psycopg2/")
 | 
						|
            lz.write(file, arcname)
 | 
						|
 | 
						|
    # upload
 | 
						|
    client = boto3.client("lambda")
 | 
						|
    client.publish_layer_version(
 | 
						|
        LayerName="py37-psycopg2",
 | 
						|
        Description="python 3.7 psycopg2 layer",
 | 
						|
        Content={"ZipFile": open("psycopg2.zip", "rb").read()},
 | 
						|
        CompatibleRuntimes=["python3.7"],
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
def do_publish(function):
 | 
						|
    zipfilename = "upload.zip"
 | 
						|
    with zipfile.ZipFile(zipfilename, "w") as zf:
 | 
						|
        for fn in function.files:
 | 
						|
            zf.write(fn)
 | 
						|
 | 
						|
    client = boto3.client("lambda")
 | 
						|
 | 
						|
    layer_arns = []
 | 
						|
    for layer in function.layers:
 | 
						|
        versions = client.list_layer_versions(LayerName=layer)
 | 
						|
        # TODO: is zero the right index?
 | 
						|
        layer_arn = versions["LayerVersions"][0]["LayerVersionArn"]
 | 
						|
        layer_arns.append(layer_arn)
 | 
						|
 | 
						|
    try:
 | 
						|
        existing_config = client.get_function_configuration(FunctionName=function.name)
 | 
						|
    except client.exceptions.ResourceNotFoundException:
 | 
						|
        existing_config = False
 | 
						|
        client.create_function(
 | 
						|
            FunctionName=function.name,
 | 
						|
            Runtime=function.runtime,
 | 
						|
            Role=function.role_arn,
 | 
						|
            Handler=function.handler,
 | 
						|
            Code={"ZipFile": open(zipfilename, "rb").read()},
 | 
						|
            Description=function.description,
 | 
						|
            Environment={"Variables": function.environment},
 | 
						|
            Publish=True,
 | 
						|
            Layers=layer_arns,
 | 
						|
        )
 | 
						|
        print(f"created function {function.name}")
 | 
						|
 | 
						|
    if existing_config:
 | 
						|
        client.update_function_code(
 | 
						|
            FunctionName=function.name, ZipFile=open(zipfilename, "rb").read()
 | 
						|
        )
 | 
						|
        client.update_function_configuration(
 | 
						|
            FunctionName=function.name,
 | 
						|
            Role=function.role_arn,
 | 
						|
            Handler=function.handler,
 | 
						|
            Description=function.description,
 | 
						|
            Environment={"Variables": function.environment},
 | 
						|
        )
 | 
						|
        client.publish_version(FunctionName=function.name)
 | 
						|
        print(f"updated function {function.name}")
 | 
						|
 | 
						|
 | 
						|
functions = {}
 | 
						|
 | 
						|
 | 
						|
@click.group()
 | 
						|
def cli():
 | 
						|
    filename = "tripod.yaml"
 | 
						|
    with open(filename) as f:
 | 
						|
        data = yaml.safe_load(f)
 | 
						|
    for function in data["functions"]:
 | 
						|
        functions[function["name"]] = Function(**function)
 | 
						|
 | 
						|
 | 
						|
@cli.command()
 | 
						|
def list():
 | 
						|
    click.echo("available functions: ")
 | 
						|
    for function in functions.values():
 | 
						|
        click.echo(f"  {function.name}")
 | 
						|
 | 
						|
 | 
						|
@cli.command()
 | 
						|
@click.argument("function")
 | 
						|
def publish(function):
 | 
						|
    click.echo(f"publishing {function}")
 | 
						|
    do_publish(functions[function])
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    cli()
 |