tripod-lambda/tripod.py
2020-05-28 14:25:23 -04:00

121 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()