Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 72 additions & 158 deletions docs/src/main/asciidoc/amazon-lambda.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,10 @@ If you look at the two generated handler classes in the project, you'll see that
----
@Named("test")
public class TestLambda implements RequestHandler<InputObject, OutputObject> {

}

@Named("unused")
public class UnusedLambda implements RequestHandler<InputObject, OutputObject> {

}
----

Expand All @@ -88,7 +86,7 @@ The CDI name of the handler class must match the value specified within the `qua

== Deploy to AWS Lambda Java Runtime

There are a few steps to get your lambda running on AWS. The generated maven project contains some helpful scripts to
There are a few steps to get your lambda running on AWS. The generated maven project contains a helpful script to
create, update, delete, and invoke your lambdas for pure Java and native deployments.

== Build and Deploy
Expand All @@ -106,228 +104,144 @@ This will compile and package your code.

View the https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-awscli.html[Getting Started Guide] for deploying
a lambda with AWS CLI. Specifically, make sure you have created an `Execution Role`. You will need to copy and
paste the `Role Arn` into the scripts generated by the maven archetype.
paste the `Role Arn` into the scripts generated by the maven archetype. To use the provided scripts, you will either
need to define a `LAMBDA_ROLE_ARN` environment variable in your profile or define it prior to executing the scripts like
this:

== Edit Script Files

Edit the `create.sh` and `create-native.sh` scripts included with the generated project. After the `--role` switch
replace the dummy `Role Arn` with the Arn of the `Execution Role` you created in the Amazon IAM console.
[source]
----
LAMBDA_ROLE_ARN="arn:aws:iam::1234567890:role/lambda-role"
----

== Create the function

The `create.sh` script is for deploying your lambda using the AWS Lambda Java runtime.
The `manage.sh` script is for managing your lambda using the AWS Lambda Java runtime. This script is provided only for
your convenience. Should you choose to use Amazon provided tools, you can freely skip these sections and consult the
appropriate Amazon documentation.

`manage.sh` supports four operation: `create`, `delete`, `update`, and `invoke`. You can create your function using
the following command:

.create.sh
[source, subs=attributes+]
----
aws lambda create-function --function-name my-function \
--zip-file fileb://target/my-function-1.0-SNAPSHOT-runner.jar \
--handler io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest \
--runtime java8 \
--role arn:aws:iam::1234567:role/lambda-cli-role
sh manage.sh create
----

Don't forget to replace the `--role` flag with the Arn of your `Execution Role`.
or if you do not have `LAMBDA_ROLE_ARN` already defined in this shell:

[source]
----
LAMBDA_ROLE_ARN="arn:aws:iam::1234567890:role/lambda-role" sh manage.sh create
----

WARNING: Do not change the handler switch. This must be hardcoded to `io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest`. This
handler bootstraps Quarkus and wraps your actual handler so that injection can be performed.

If there are any problems creating the function, you must delete it with the `delete.sh` script before re-running
the `create.sh` script.

== Invoke the Lambda

Use the `invoke.sh` script to invoke your function.
If there are any problems creating the function, you must delete it with the `delete` function before re-running
the `create` command.

.invoke.sh
[source, subs=attributes+]
----
aws lambda invoke --function-name my-function
--payload file://payload.json out
--log-type Tail --query 'LogResult' --output text | base64 -d
sh manage.sh delete
----

The example lambda takes input passed in via the `--payload` switch which points to a json file
in the root directory of the project. If you want to see the return output of the lambda, open the `out` file.
This script will also write the log output to the console.

== Update the Lambda

You can update the Java code as you see fit. Once you've rebuilt, you can redeploy your lambda by executing the
`update.sh` script.

.update.sh
Commands may also be stacked:
[source, subs=attributes+]
----
aws lambda update-function-code --function-name my-function \
--zip-file fileb://target/my-function-1.0-SNAPSHOT-runner.jar
sh manage.sh delete create
----

== Deploy to AWS Lambda Custom (native) Runtime

If you want a lower memory footprint and faster initialization times for your lambda, you can compile your Java
code to a native executable. Just make sure to rebuild your project with the `-Dnative` switch.

== Build and Deploy (native)
== Invoke the Lambda

Build the native executable.
Use the `invoke` command to invoke your function.

[source, subs=attributes+]
----
mvn clean install -Dnative
sh manage.sh invoke
----

This will compile and create a native executable image. It also generates a zip file `target/function.zip`.
This zip file contains your native executable image renamed to `bootstrap`. This is a requirement of Amazon Lambda
Custom Runtime.


== Create an Execution Role

View the https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-awscli.html[Getting Started Guide] for deploying
a lambda with AWS CLI. Specifically make sure you have created an `Execution Role`. You will need the `Role Arn` to copy/paste
into the scripts generated by the maven archetype.
The example lambda takes input passed in via the `--payload` switch which points to a json file
in the root directory of the project. If you want to see the output of the lambda, open the `response.txt` file.
The lambda can also be invoked locally like this:

== Edit native script files
[source]
----
sam local invoke --template sam.jvm.yaml --event payload.json
----

Edit the `create-native.sh` scripts included with the generated project. After the `--role` switch
replace the dummy `Role Arn` with the Arn of the `Execution Role` you created in the Amazon IAM console.
If you are working with your native image build, simply replace the template name above with the native version.

== Create the Native Lambda
== Update the Lambda

The `create-native.sh` script is for deploying your lambda using the AWS Lambda Custom runtime.
You can update the Java code as you see fit. Once you've rebuilt, you can redeploy your lambda by executing the
`update` command.

.create-native.sh
[source, subs=attributes+]
----
aws lambda create-function --function-name my-native-function \
--zip-file fileb://target/function.zip --handler any.name.not.used \
--runtime provided --role arn:aws:iam::1234567:role/lambda-cli-role \
--environment Variables="{DISABLE_SIGNAL_HANDLERS=true}"
sh manage.sh update
----

Don't forget to replace the `--role` flag with the Arn of your `Execution Role`.

Notice that the `--zip-file` flag points to the `function.zip` file generated by the build.
The handler switch is not used, but must be set. It can be any value. Finally, notice that an environment variable
must be set: `DISABLE_SIGNAL_HANDLERS`. This resolves certain incompatibilities with the Amazon Lambda Custom Runtime container
and Quarkus.

If there are any problems creating the function, you must delete it with the `delete-native.sh` script before re-running
the `create-native.sh` script.

== Invoke the Native Lambda
== Deploy to AWS Lambda Custom (native) Runtime

Use the `invoke-native.sh` script to invoke your function.
If you want a lower memory footprint and faster initialization times for your lambda, you can compile your Java
code to a native executable. Just make sure to rebuild your project with the `-Pnative` switch. If you are building
on a non-linux system, you will need to also pass in a property instructing quarkus to use a docker build as Amazon
Lambda requires linux binaries. You can do this by passing this property to your maven build:
`-Dnative-image.docker-build=true`. This requires you to have docker installed locally, however.

.invoke-native.sh
[source, subs=attributes+]
----
aws lambda invoke --function-name my-native-function
--payload file://payload.json out
--log-type Tail --query 'LogResult' --output text | base64 -d
mvn clean install -Pnative -Dnative-image.docker-build=true
----

The example lambda takes input. This input is passed in via the `--payload` switch which points to a json file
in the root directory of the project. If you want to see the return output of the lambda, open the `out` file.
This script will also write the log output to the console.

== Update the Native Lambda
This will compile and create a native executable image. It also generates a zip file `target/function.zip`.
This zip file contains your native executable image renamed to `bootstrap`. This is a requirement of Amazon Lambda
Custom Runtime. If you are building on Linux, the `native-image.docker-build` property is mildly redundant but its primary
cost is a slightly longer build cycle.

You can update the Java code as you see fit. Once you've rebuilt, you can redeploy your lambda by executing the
`update-native.sh` script.
The instructions here are exactly as above with one change: you'll need to add `native` as the first parameter to the
`manage.sh` script:

.update-native.sh
[source, subs=attributes+]
----
aws lambda update-function-code --function-name my-native-function \
--zip-file fileb://target/function.zip
sh manage.sh native create
----

As above, commands can be stacked. The only requirement is that `native` be the first parameter should you wish
to work with native image builds. The script will take care of the rest of the details necessary to manage your native
image function deployments.

== Examine the POM

If you want to adapt an existing project to use Quarkus's Amazon Lambda extension, there's a couple
If you want to adapt an existing project to use Quarkus's Amazon Lambda extension, there are a couple
of things you need to do. Take a look at the generated example project to get an example of what you need to adapt.

1. Include the `quarkus-amazon-lambda` extension as a pom dependency
2. Configure Quarkus to build an `uber-jar` (via quarkus.package.uber-jar=true in the application.properties)
3. If you are doing a native image build, Amazon requires you to rename your executable to `bootstrap` and zip it up. Notice that the `pom.xml` uses the `maven-assembly-plugin` to perform this requirement.
3. If you are doing a native image build, Amazon requires you to rename your executable to `bootstrap` and zip it up.
Notice that the `pom.xml` uses the `maven-assembly-plugin` to perform this requirement.

NB: With gradle, to build the uber-jar execute: ./gradlew quarkusBuild --uber-jar

== Testing with the SAM CLI

The https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html[AWS SAM CLI] allows you to run your lambdas locally on your laptop in a simulated Lambda environment. This requires https://www.docker.com/products/docker-desktop[docker] to be installed.
The https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html[AWS SAM CLI]
allows you to run your lambdas locally on your laptop in a simulated Lambda environment. This requires
https://www.docker.com/products/docker-desktop[docker] to be installed. This is an optional approach should you choose
to take advantage of it. Otherwise, dev mode should be sufficient for most of your needs.

To execute your lambda function with the
`java8` runtime, create a `sam.jvm.yaml` template as below:
----
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
Function:
Timeout: 5
Resources:
QuarkusSam:
Type: AWS::Serverless::Function
Properties:
Handler: io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest
Runtime: java8
CodeUri: {path to *-runner.jar}
MemorySize: 128
Policies: AWSLambdaBasicExecutionRole
----

Run the following SAM CLI command to test your lambda function with the `Java8` runtime and `sam.jvm.yaml` template:
----
sam local invoke --template sam.jvm.yaml --event {json test file}
----

The native executable can be tested via the `provided` runtime defined in a `sam.native.yaml` template:
----
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
Function:
Timeout: 5
Resources:
QuarkusSam:
Type: AWS::Serverless::Function
Properties:
Handler: not.used.in.provided.runtimei
Runtime: provided
CodeUri: {path to function.zip}
MemorySize: 128
Policies: AWSLambdaBasicExecutionRole
Timeout: 15
Environment:
Variables:
DISABLE_SIGNAL_HANDLERS: true
----


When using the `provided` runtime, AWS requires a bootstrap script to trigger the native executable. Bundle the `bootstrap` script along with the *-runner executable.
A starter template has been generated for both JVM and native execution modes.

i.e., create a zip file called `function.zip` with:
Run the following SAM CLI command to locally test your lambda function:

* bootstrap
* {projectname-version}-runner

Example `bootstrap` script to load the native executable:
[source]
----
#!/usr/bin/env bash

RUNNER=$( find . -maxdepth 1 -name '*-runner' )
if [[ ! -z "$RUNNER" ]]
then
$RUNNER
fi
sam local invoke --template sam.jvm.yaml --event {json test file}
----

To invoke the native `provided` runtime with the `sam.native.yaml` template, use the following command:
The native image can also be locally tested using the `sam.native.yaml` template:

[source]
----
sam local invoke --template sam.native.yaml --event {json test file}
----
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ under the License.
<includes>
<include>*.sh</include>
<include>*.json</include>
<include>sam.jvm.yaml</include>
<include>sam.native.yaml</include>
</includes>
</fileSet>
</fileSets>
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
function cmd_create() {
echo Creating function
aws lambda create-function \
--function-name ${FUNCTION_NAME} \
--zip-file ${ZIP_FILE} \
--handler ${HANDLER} \
--runtime ${RUNTIME} \
--role ${LAMBDA_ROLE_ARN} \
${LAMBDA_META}
}

function cmd_delete() {
echo Deleting function
aws lambda delete-function --function-name ${FUNCTION_NAME}
}

function cmd_invoke() {
echo Invoking function
aws lambda invoke response.txt \
--function-name ${FUNCTION_NAME} \
--payload file://payload.json
}

function cmd_update() {
echo Updating function
aws lambda update-function-code \
--function-name ${FUNCTION_NAME} \
--zip-file ${ZIP_FILE}
}

FUNCTION_NAME=${resourceName}Function
HANDLER=io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest
RUNTIME=java8
ZIP_FILE=fileb://target/${artifactId}-${version}-runner.jar

if [ "$1" == "native" ]
then
RUNTIME=provided
ZIP_FILE=fileb://target/function.zip
FUNCTION_NAME=${resourceName}NativeFunction
LAMBDA_META="--environment Variables={DISABLE_SIGNAL_HANDLERS=true}"
shift
fi

while [ "$1" ]
do
eval cmd_${1}
shift
done

Loading