/blambda

Blambda! is a custom runtime for AWS Lambda that lets you write functions using Babashka

Primary LanguageClojureOtherNOASSERTION

Blambda!

Blambda! is a custom runtime for AWS Lambda that lets you write functions using Babashka. It is based on the fantastic work that Tatu Tarvainen did on taking care of the heavy lifting of interacting with the Lambda runtime API to process function invocations in bb-lambda. I'm using the bootstrap.clj from that project directly, and have just rewritten the machinery around it to remove Docker in favour of zip files, which I think are simpler (but maybe not easier).

Building

To build Blambda! with the default Babashka version and platform, run:

bb build

To see what the default Babashka version and platform are, run:

bb help

To build a custom runtime with Babashka 0.8.2 on amd64, run:

bb build --bb-version 0.8.2 --bb-arch arm64

To see what else you can do, run:

bb tasks

To see what command-line arguments are available, run:

bb help

Deploying

To deploy a custom runtime layer, run:

bb deploy

To deploy an arm64 runtime so that you can use AWS Graviton 2 lamdbas (which AWS say will give you up to "34%" better price performance), run:

bb deploy --bb-arch arm64

Note that if you do this, you must configure your lambda as follows:

  • Runtime: Custom runtime on Amazon Linux 2
  • Architecture: arm64

Using Blambda!

I'm planning on adding examples tasks for deploying layers functions, but for now, you can do it the hard way with the AWS CLI.

AWS CLI

This section assumes you have the AWS Command Line Interface version 1 installed.

To create or update a layer:

bb deploy

Assuming you're standing in the root of the Blambda! repo, you will have an example directory that contains a hello.clj that looks something like this:

(ns hello)

(defn hello [{:keys [name] :or {name "Blambda"} :as event} context]
  (prn {:msg "Invoked with event",
        :data {:event event}})
  {:greeting (str "Hello " name "!")})

You can create a function that uses Blambda! like this:

# The ARN will be printed by the `bb deploy` command
layer_arn=arn:aws:lambda:eu-west-1:123456789100:layer:blambda:1

cd example

zip hello-blambda.zip hello.clj

aws iam create-role \
  --role-name hello-blambda \
  --assume-role-policy-document file://trust.json

# Set this to the value of `Role.Arn` from the output of the previous command
role_arn=arn:aws:iam::123456789100:role/hello-blambda

aws iam create-policy \
  --policy-name hello-blambda \
  --policy-document file://policy.json

# Set this to the value of `Policy.Arn` from the output of the previous command
policy_arn=arn:aws:iam::123456789100:policy/hello-blambda

aws iam attach-role-policy \
  --role-name hello-blambda \
  --policy-arn=$policy_arn 

aws lambda create-function \
  --function-name hello-blambda \
  --runtime provided \
  --role $role_arn \
  --handler hello/hello \
  --layers $layer_arn \
  --zip-file fileb://hello-blambda.zip

You can invoke the function like this:

aws lambda invoke \
  --function-name hello-blambda \
  --payload '{}' \
  /dev/stdout

You should see something like this:

{"greeting":"Hello Blambda!"}{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}

Of course, you can also get more personal:

aws lambda invoke \
  --function-name hello-blambda \
  --payload '{"name": "Josh"}' \
  /dev/stdout
{"greeting":"Hello Josh!"}{
    "StatusCode": 200,
    "ExecutedVersion": "$LATEST"
}