lambroll is a simple deployment tool for AWS Lambda.
lambroll does,
- Create a function.
- Create a Zip archive from a local directory.
- Deploy function code / configuration / tags / aliases / function URLs.
- Rollback a function to the previous version.
- Invoke a function with payloads.
- Manage function versions.
- Show status of a function.
- Show function logs.
- Show diff of function code / configuration.
- Delete a function.
lambroll does not,
- Manage resources related to the Lambda function.
- For example, IAM Role, function triggers, API Gateway, and etc.
- Only the function URLs can be managed by lambroll if you want.
- 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.).
See docs/v0-v1.md.
$ brew install fujiwara/tap/lambroll
aqua is a declarative CLI Version Manager.
$ aqua g -i fujiwara/lambroll
https://circleci.com/orbs/registry/orb/fujiwara/lambroll
version: 2.1
orbs:
lambroll: fujiwara/lambroll@2.0.1
jobs:
deploy:
docker:
- image: cimg/base
steps:
- checkout
- lambroll/install:
version: v1.1.0
- run:
command: |
lambroll deploy
Action fujiwara/lambroll@v1 installs lambroll binary for Linux into /usr/local/bin. This action runs install only.
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: fujiwara/lambroll@v1
with:
version: v1.1.0
- run: |
lambroll deploy
Note:
version
is not required, but it is recommended that the version be specified.- The default version is not fixed and may change in the future.
os
andarch
are automatically detected. (Some previous versions useos
andarch
as inputs, but they are deprecated.)
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
function 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: lambroll <command>
Flags:
-h, --help Show context-sensitive help.
--function=STRING Function file path ($LAMBROLL_FUNCTION)
--log-level="info" log level (trace, debug, info, warn, error) ($LAMBROLL_LOGLEVEL)
--[no-]color enable colored output ($LAMBROLL_COLOR)
--region=REGION AWS region ($AWS_REGION)
--profile=PROFILE AWS credential profile name ($AWS_PROFILE)
--tfstate=TFSTATE URL to terraform.tfstate ($LAMBROLL_TFSTATE)
--prefixed-tfstate=KEY=VALUE;... key value pair of the prefix for template function name and URL to
terraform.tfstate ($LAMBROLL_PREFIXED_TFSTATE)
--endpoint=ENDPOINT AWS API Lambda Endpoint ($AWS_LAMBDA_ENDPOINT)
--envfile=ENVFILE,... environment files ($LAMBROLL_ENVFILE)
--ext-str=KEY=VALUE;... external string values for Jsonnet ($LAMBROLL_EXTSTR)
--ext-code=KEY=VALUE;... external code values for Jsonnet ($LAMBROLL_EXTCODE)
Commands:
deploy
deploy or create function
init --function-name=
init function.json
list
list functions
rollback
rollback function
invoke
invoke function
archive
archive function
logs
show logs of function
diff
show diff of function
render
render function.json
status
show status of function
delete
delete function
versions
show versions of function
version
show version
Run "lambroll <command> --help" for more information on a command.
lambroll init
initialize function.json by existing function.
Usage: lambroll init --function-name=
init function.json
Flags:
--function-name= Function name for init
--download Download function.zip
--jsonnet render function.json as jsonnet
--qualifier=QUALIFIER function version or alias
--function-url create function url definition file
init
creates function.json
as a configuration file of the function.
Usage: lambroll deploy
deploy or create function
Flags:
--src="." function zip archive or src dir
--publish publish function
--alias="current" alias name for publish
--alias-to-latest set alias to unpublished $LATEST version
--dry-run dry run
--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).
--ignore="" ignore fields by jq queries in function.json
--function-url="" path to function-url definition ($LAMBROLL_FUNCTION_URL)
--skip-function skip to deploy a function. deploy function-url only
--exclude-file=".lambdaignore" exclude file
--symlink keep symlink (same as zip --symlink,-y)
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).
When the zip archive is too large to upload directly, you can deploy via S3.
Set Code.S3Bucket
and Code.S3Key
in function.json. lambroll uploads the zip archive to the specified S3 bucket and deploys the function.
{
"Code": {
"S3Bucket": "my-bucket",
"S3Key": "function.zip"
}
}
If you want to upload the zip archive yourself, you can skip creating the zip archive by using the --skip-archive
flag.
lambroll also support to deploy a container image for Lambda.
PackageType=Image
and Code.ImageUri
are required in function.json.
ImageConfig
is optional.
{
"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"
},
"ImageConfig": {
"Command": [
"/path/to/bootstrap"
],
"WorkingDirectory": "/var/task",
"EntryPoint": [
"/path/to/entrypoint"
],
}
}
Usage: lambroll rollback
rollback function
Flags:
--dry-run dry run
--alias="current" alias to rollback
--version="" version to rollback (default: previous version auto detected)
--delete-version delete rolled back version
lambroll deploy
create/update alias to the published function version on deploy.
lambroll rollback
works as below.
- Find the previous version from the alias with no other aliases.
- Update the alias to the previous version.
- If
--version
is specified, update the alias to the specified version.
- If
- When
--delete-version
is specified, delete the old version of the function.
If you add multiple aliases to the function, lambroll rollback --alias={some-alias}
may not work as expected. Because the previous version that auto-detected may be the older version of other aliases.
So you should specify the version to rollback with --version
flag to clear the ambiguity.
Usage: lambroll invoke
invoke function
Flags:
--async invocation type async
--log-tail output tail of log to STDERR
--qualifier=QUALIFIER version or alias to invoke
--payload=PAYLOAD payload to invoke. if not specified, read from STDIN
lambroll invoke
accepts multiple JSON payloads for invocations from --payload
flag or STDIN.
If the payload is a concatenation of multiple JSON payloads, lambroll invoke
will invoke the function for each JSON payload.
Outputs from the function invoked are printed to STDOUT.
$ lambroll invoke --payload='{"foo":1} --log-tail'
{"success": true, "payload": {"foo":1}}
2019/10/28 23:16:43 [info] StatusCode:200 ExecutionVersion:$LATEST
START RequestId: aa38233f-a179-4192-8469-c86414fe463c Version: $LATEST
END RequestId: aa38233f-a179-4192-8469-c86414fe463c
REPORT RequestId: 60140e16-018e-41b1-bb46-3f021d4960c0 Duration: 561.77 ms Billed Duration: 600 ms Memory Size: 128 MB Max Memory Used: 50 MB
$ 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 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",
"MemorySize": 128,
"Role": "arn:aws:iam::123456789012:role/hello_lambda_function",
"Runtime": "nodejs18.x",
"Tags": {
"Env": "dev"
},
"Timeout": 5,
"TracingConfig": {
"Mode": "PassThrough"
}
}
The template functions is available in {{ }}
.
env
function expands environment variables.must_env
function expands environment variables. If the environment variable is not defined, lambroll will panic and abort.
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.
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"
lambroll also can read function.jsonnet as Jsonnet format instead of plain JSON.
{
FunctionName: 'hello',
Handler: 'index.handler',
MemorySize: std.extVar('memorySize'),
Role: 'arn:aws:iam::%s:role/lambda_role' % [ std.extVar('accountID') ],
Runtime: 'nodejs20.x',
}
$ lambroll \
--function function.jsonnet \
--ext-str accountID=0123456789012 \
--ext-code memorySize="128 * 4" \
deploy
--ext-str
sets external string values for Jsonnet.--ext-code
sets external code values for Jsonnet.
v1.1.0 and later, lambroll supports Jsonnet native functions. See below for details.
At reading the file, lambroll evaluates {{ ssm }}
syntax in JSON.
For example,
{{ ssm `/path/to/param` }}
SSM parameter value of /path/to/param
is expanded here.
For Jsonnet, the ssm
function is available.
local ssm = std.native('ssm');
{
Environment: {
Variables: {
FOO: ssm('/path/to/param'),
},
},
}
At reading the file, lambroll 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 }}"
}
}
}
For Jsonnet, the env
and must_env
native functions are available.
local env = std.native('env');
local must_env = std.native('must_env');
{
Environment: {
Variables: {
FOO: env('FOO', 'default for FOO'),
BAR: must_env('BAR'),
},
},
}
The caller_identity
template function resolves the AWS caller identity.
{
"Account": "{{ caller_identity.Account }}",
"Arn": "{{ caller_identity.Arn }}",
"UserId": "{{ caller_identity.UserId }}"
}
The caller_identity
native function also available in Jsonnet.
local caller = std.native('caller_identity')();
{
Account: caller.Account,
Arn: caller.Arn,
UserId: caller.UserId,
}
The caller_identity
function returns an object containing the following fields: Account
, Arn
, and UserId
.
This object is the same as the result of GetCallerIdentity API.
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": "nodejs20.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`) }}"
]
}
}
For Jsonnet, the tfstate
native function is available.
local tfstate = std.native('tfstate');
{
Description: 'hello function',
FunctionName: 'hello',
Handler: 'index.js',
MemorySize: 128,
Role: tfstate('data.aws_iam_role.lambda.arn'),
Runtime: 'nodejs20.x',
Timeout: 5,
TracingConfig: {
Mode: 'PassThrough',
},
VpcConfig: {
SubnetIds: [
tfstate('aws_subnet.lambda["az-a"].id'),
tfstate('aws_subnet.lambda["az-b"].id'),
],
SecurityGroupIds: [
tfstate('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": "..."
}
For Jsonnet, a {prefix}_tfstate
native function is generated by the --prefixed-tfstate
option.
local first_tfstate = std.native('my_first_tfstate');
local second_tfstate = std.native('my_second_tfstate');
{
Description: 'hello function',
Environment: {
Variables: {
FIRST_VALUE: first_tfstate('data.aws_iam_role.lambda.arn'),
SECOND_VALUE: second_tfstate('data.aws_iam_role.lambda.arn'),
},
},
"rest of the parameters": "...",
}
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
.
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.
lambroll can deploy Lambda function URLs.
lambroll deploy --function-url=function_url.json
deploys a function URL after the function deploied.
Even if your Lambda function already has a function URL, lambroll deploy
without --function-url
option does not touch the function URLs resources.
When you want to deploy a public (without authentication) function URL, function_url.json
is shown below.
{
"Config": {
"AuthType": "NONE"
}
}
When you want to deploy a private (requires AWS IAM authentication) function URL, function_url.json
is shown below.
{
"Config": {
"AuthType": "AWS_IAM",
"Cors": {
"AllowOrigins": [
"*"
],
"AllowMethods": [
"GET",
"POST"
]
},
},
"Permissions": [
{
"Principal": "0123456789012"
},
{
"PrincipalOrgID": "o-123456789",
"Principal": "*"
}
]
}
Config
maps to CreateFunctionUrlConfigInput in AWS SDK Go v2.Config.AuthType
must beAWS_IAM
orNONE
.Config.Qualifier
is optional. Default is$LATEST
.
Permissions
is optional.- If
Permissions
is not defined andAuthType
isNONE
,Principal
is set to*
automatically. - When
AuthType
isAWS_IAM
, you must definePermissions
to specify allowed principals. - Each elements of
Permissions
maps to AddPermissionInput in AWS SDK Go v2.
- If
function_url.jsonnet
is also supported likefunction.jsonnet
.
CloudFront provides origin access control (OAC) for restricting access to a Lambda function URL origin.
When you want to restrict access to a Lambda function URL origin by CloudFront, you can specify Principal
as cloudfront.amazonaws.com
and SourceArn
as the ARN of the CloudFront distribution.
See also Restricting access to an AWS Lambda function URL origin.
{
"Config": {
"AuthType": "AWS_IAM",
},
"Permissions": [
{
"Principal": "cloudfront.amazonaws.com",
"SourceArn": "arn:aws:cloudfront::123456789012:distribution/EXXXXXXXX"
}
]
}
If you need to allow access from any CloudFront distributions in your account, you can specify SourceArn
as arn:aws:cloudfront::123456789012:distribution/*
.
Specifying SourceArn
as *
is not recommended because it allows access from any CloudFront distribution in any AWS account.
MIT License
Copyright (c) 2019 FUJIWARA Shunichiro