Awesome
lambroll
lambroll is a minimal deployment tool for AWS Lambda.
lambroll does,
- Create a function.
- Create a Zip archive from local directory.
- Update function code / configuration / tags / aliases.
- Rollback a function to previous version.
- Invoke a function with payloads.
- Manage function versions.
That's all.
lambroll does not,
- Manage resources related to the Lambda function.
- e.g. IAM Role, function triggers, API Gateway, etc.
- Build native binaries or extensions for Linux (AWS Lambda running environment).
When you hope to manage these resources, we recommend other deployment tools (AWS SAM, Serverless Framework, etc.).
Install
Homebrew (macOS and Linux)
$ brew install fujiwara/tap/lambroll
aqua
aqua is a declarative CLI Version Manager.
$ aqua g -i fujiwara/lambroll
Binary packages
CircleCI Orb
https://circleci.com/orbs/registry/orb/fujiwara/lambroll
version: 2.1
orbs:
lambroll: fujiwara/lambroll@0.0.8
jobs:
deloy:
docker:
- image: cimg/base
steps:
- checkout
- lambroll/install:
version: v0.12.2
- run:
command: |
lambroll deploy
GitHub Actions
Action fujiwara/lambroll@v0 installs lambroll binary for Linux into /usr/local/bin. This action runs install only.
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: fujiwara/lambroll@v0
with:
version: v0.12.2
- run: |
lambroll deploy
Quick start
Try migrate your existing Lambda function hello
.
$ mkdir hello
$ cd hello
$ lambroll init --function-name hello --download
2019/10/26 01:19:23 [info] function hello found
2019/10/26 01:19:23 [info] downloading function.zip
2019/10/26 01:19:23 [info] creating function.json
2019/10/26 01:19:23 [info] completed
$ unzip -l function.zip
Archive: function.zip
Length Date Time Name
--------- ---------- ----- ----
408 10-26-2019 00:30 index.js
--------- -------
408 1 file
$ unzip function.zip
Archive: function.zip
extracting: index.js
$ rm function.zip
See or edit function.json
or index.js
.
Now you can deploy hello
fuction using lambroll deploy
.
$ lambroll deploy
2019/10/26 01:24:52 [info] starting deploy function hello
2019/10/26 01:24:53 [info] creating zip archive from .
2019/10/26 01:24:53 [info] zip archive wrote 1042 bytes
2019/10/26 01:24:53 [info] updating function configuration
2019/10/26 01:24:53 [info] updating function code hello
2019/10/26 01:24:53 [info] completed
Usage
usage: lambroll [<flags>] <command> [<args> ...]
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
--log-level=info log level (trace, debug, info, warn, error)
--function="function.json" Function file path
--color enable colored output
--profile="" AWS credential profile name
--region="" AWS region
--tfstate="" URL to terraform.tfstate
--prefixed-tfstate=PREFIX=URL ...
key value pair of the prefix for template function name and URL to terraform.tfstate
--endpoint="" AWS API Lambda Endpoint
--envfile=ENVFILE ... environment files
--ext-str=EXT-STR ... external string values for Jsonnet
--ext-code=EXT-CODE ... external code values for Jsonnet
Commands:
help [<command>...]
Show help.
version
show version
init --function-name=FUNCTION-NAME [<flags>]
init function.json
list
list functions
deploy [<flags>]
deploy or create function
rollback [<flags>]
rollback function
delete [<flags>]
delete function
invoke [<flags>]
invoke function
archive [<flags>]
archive zip
logs [<flags>]
tail logs using `aws logs tail` (aws-cli v2 required)
diff [<flags>]
show display diff of function.json compared with latest function
versions [<flags>]
manage function versions
Init
lambroll init
initialize function.json by existing function.
usage: lambroll init --function-name=FUNCTION-NAME [<flags>]
init function.json
Flags:
(common flags snipped)
--function-name=FUNCTION-NAME Function name for initialize
--download Download function.zip
init
creates function.json
as a configuration file of the function.
Deploy
usage: lambroll deploy [<flags>]
deploy or create function
Flags:
(common flags snipped)
--src="." function zip archive or src dir
--exclude-file=".lambdaignore"
exclude file
--dry-run dry run
--publish publish function
--alias="current" alias name for publish
--alias-to-latest set alias to unpublished $LATEST version
--skip-archive skip to create zip archive. requires Code.S3Bucket and Code.S3Key in function definition
--keep-versions=0 Number of latest versions to keep. Older versions will be deleted. (Optional value: default 0).
deploy
works as below.
- Create a zip archive from
--src
directory.- Excludes files matched (wildcard pattern) in
--exclude-file
.
- Excludes files matched (wildcard pattern) in
- Create / Update Lambda function
- Create an alias to the published version when
--publish
(default).
Deploy container image
lambroll also support to deploy a container image for Lambda.
PackageType=Image and Code.ImageUri are required in function.json.
{
"FunctionName": "container",
"MemorySize": 128,
"Role": "arn:aws:iam::012345678912:role/test_lambda_function",
"PackageType": "Image",
"Code": {
"ImageUri": "012345678912.dkr.ecr.ap-northeast-1.amazonaws.com/lambda/test:latest"
}
}
Rollback
usage: lambroll rollback [<flags>]
rollback function
Flags:
(common flags snipped)
--delete-version Delete rolled back version
--dry-run dry run
lambroll deploy
create/update alias current
to the published function version on deploy.
lambroll rollback
works as below.
- Find previous one version of function.
- Update alias
current
to the previous version. - When
--delete-version
specified, delete old version of function.
Invoke
usage: lambroll invoke [<flags>]
invoke function
Flags:
(common flags snipped)
--async invocation type async
--log-tail output tail of log to STDERR
--qualifier=QUALIFIER version or alias to invoke
lambroll invoke
accepts multiple JSON payloads for invocations from STDIN.
Outputs from function are printed in STDOUT.
$ echo '{"foo":1}{"foo":2}' | lambroll invoke --log-tail
{"success": true, payload{"foo:1}}
2019/10/28 23:16:43 [info] StatusCode:200 ExecutionVersion:$LATEST
START RequestId: 60140e16-018e-41b1-bb46-3f021d4960c0 Version: $LATEST
END RequestId: 60140e16-018e-41b1-bb46-3f021d4960c0
REPORT RequestId: 60140e16-018e-41b1-bb46-3f021d4960c0 Duration: 561.77 ms Billed Duration: 600 ms Memory Size: 128 MB Max Memory Used: 50 MB
{"success": true, payload:{"foo":2}}
2019/10/28 23:16:43 [info] StatusCode:200 ExecutionVersion:$LATEST
START RequestId: dcc584f5-ceaf-4109-b405-8e59ca7ae92f Version: $LATEST
END RequestId: dcc584f5-ceaf-4109-b405-8e59ca7ae92f
REPORT RequestId: dcc584f5-ceaf-4109-b405-8e59ca7ae92f Duration: 597.87 ms Billed Duration: 600 ms Memory Size: 128 MB Max Memory Used: 50 MB
2019/10/28 23:16:43 [info] completed
function.json
function.json is a definition for Lambda function. JSON structure is based from CreateFunction
for Lambda API.
{
"Architectures": [
"arm64"
],
"Description": "hello function for {{ must_env `ENV` }}",
"EphemeralStorage": {
"Size": 1024
},
"Environment": {
"Variables": {
"BAR": "baz",
"FOO": "{{ env `FOO` `default for FOO` }}"
}
},
"FunctionName": "{{ must_env `ENV` }}-hello",
"FileSystemConfigs": [
{
"Arn": "arn:aws:elasticfilesystem:ap-northeast-1:123456789012:access-point/fsap-04fc0858274e7dd9a",
"LocalMountPath": "/mnt/lambda"
}
],
"Handler": "index.js",
"LoggingConfig": {
"ApplicationLogLevel": "DEBUG",
"LogFormat": "JSON",
"LogGroup": "/aws/lambda/hello_json_log",
"SystemLogLevel": "INFO"
},
"MemorySize": 128,
"Role": "arn:aws:iam::123456789012:role/hello_lambda_function",
"Runtime": "nodejs18.x",
"Tags": {
"Env": "dev"
},
"Timeout": 5,
"TracingConfig": {
"Mode": "PassThrough"
}
}
Tags
When "Tags" key exists in function.json, lambroll set / remove tags to the lambda function at deploy.
{
// ...
"Tags": {
"Env": "dev",
"Foo": "Bar"
}
}
When "Tags" key does not exist, lambroll doesn't manage tags.
If you hope to remove all tags, set "Tags": {}
expressly.
Expand enviroment variables
At reading the file, lambrol evaluates {{ env }}
and {{ must_env }}
syntax in JSON.
For example,
{{ env `FOO` `default for FOO` }}
Environment variable FOO
is expanded here. When FOO
is not defined, use default value.
{{ must_env `FOO` }}
Environment variable FOO
is expanded. When FOO
is not defined, lambroll will panic and abort.
json_escape
template function escapes JSON meta characters in string values. This is useful for inject structured values into environment variables.
{
"Environment": {
"Variables": {
"JSON": "{{ env `JSON` | json_escape }}"
}
}
}
Enviroment variables from envfile
lambroll --envfile .env1 .env2
reads files named .env1 and .env2 as environment files and export variables in these files.
These files are parsed by hashicorp/go-envparse.
FOO=foo
export BAR="bar"
Lookup resource attributes in tfstate (Terraform state)
When --tfstate
option set to an URL to terraform.tfstate
, tfstate template function enabled.
For example, define your AWS resources by terraform.
data "aws_iam_role" "lambda" {
name = "hello_lambda_function"
}
terraform apply
creates a terraform.tfstate file.
lambroll --tfstate URL ...
enables to lookup resource attributes in the tfstate URL.
{
"Description": "hello function",
"FunctionName": "hello",
"Handler": "index.js",
"MemorySize": 128,
"Role": "{{ tfstate `data.aws_iam_role.lambda.arn` }}",
"Runtime": "nodejs12.x",
"Timeout": 5,
"TracingConfig": {
"Mode": "PassThrough"
},
"VpcConfig": {
"SubnetIds": [
"{{ tfstate `aws_subnet.lambda['az-a'].id` }}",
"{{ tfstate `aws_subnet.lambda['az-b'].id` }}"
],
"SecurityGroupIds": [
"{{ tfstatef `aws_security_group.internal['%s'].id` (must_env `WORLD`) }}"
]
}
}
Likewise, if you have AWS resource definitions spread across multiple tfstate files, you can utilize --prefixed-tfstate
option:
e.g.
lambroll --prefixed-tfstate="my_first_=s3://my-bucket/first.tfstate" --prefixed-tfstate="my_second_=s3://my-bucket/second.tfstate" ...
which then exposes additional template functions available like:
{
"Description": "hello function",
"Environment": {
"Variables": {
"FIRST_VALUE": "{{ my_first_tfstate `data.aws_iam_role.lambda.arn` }}",
"SECOND_VALUE": "{{ my_second_tfstate `data.aws_iam_role.lambda.arn` }}"
}
},
"rest of the parameters": "..."
}
Jsonnet support for function configuration
lambroll also can read function.jsonnet as Jsonnet format.
{
FunctionName: 'hello',
Handler: 'index.handler',
MemorySize: std.extVar('memorySize'),
Role: 'arn:aws:iam::%s:role/lambda_role' % [ std.extVar('accountID') ],
Runtime: 'nodejs14.x',
}
$ lambroll \
--function function.jsonnet \
--ext-str accountID=0123456789012 \
--ext-code memorySize="128 * 4" \
deploy
.lambdaignore
lambroll will ignore files defined in .lambdaignore
file at creating a zip archive.
For example,
# comment
*.zip
*~
For each line in .lambdaignore
are evaluated as Go's path/filepath#Match
.
Lambda@Edge support
lambroll can deploy Lambda@Edge functions.
Edge functions require two preconditions:
--region
must set tous-east-1
.- The IAM Role must be assumed by
lambda.amazonaws.com
andedgelambda.amazonaws.com
both.
Otherwise, it works as usual.
LICENSE
MIT License
Copyright (c) 2019 FUJIWARA Shunichiro