The first virsion of this post was created in Apri 2021, but as of 2022, AWS officially released their SDK. This post (note) should be updated.
Still there is no native run environment for Rust on AWS Lambda as of Jan.18.2022, so we still need to create a bootstrap
executable.
I followed the link. In this page, the author wrote details and it’s very educational. To remind the procedure, I left memo.
I really appreciate you, Chuma Umenze :)
cargo new rust_lambda
Cargo.toml
:
[package]
// --- snip ---
autobins = false
[dependencies]
lambda_runtime = "0.2.1"
serde = { version = "^1.0", features = ["derive"] }
[[bin]]
name = "bootstrap"
path = "src/main.rs"
src/main.rs
:
use lambda_runtime::{error::HandlerError, lambda, Context};
use serde::{Deserialize, Serialize};
use std::error::Error;
#[derive(Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
struct LambdaRequest {
full_name: String,
message: Option<String>,
}
#[derive(Deserialize, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
struct LambdaResponse {
lambda_request: LambdaRequest,
}
fn main() -> Result<(), Box<dyn Error>> {
lambda!(lambda_handler);
Ok(())
}
fn lambda_handler(e: LambdaRequest, _c: Context) -> Result<LambdaResponse, HandlerError> {
let mut e = e.clone();
e.full_name = format!("Hello {name}!", name = e.full_name);
let msg = match e.message {
Some(msg) => format!("Your message is '{msg}'.", msg = msg),
None => format!("You have no message."),
};
e.message = Some(msg);
Ok(LambdaResponse { lambda_request: e })
}
rustup target add x86_64-unknown-linux-musl
cargo install cross
echo '
[target.x86_64-unknown-linux-gnu]
image = "lambci/lambda:build-provided"
[target.x86_64-unknown-linux-musl]
image = "lambci/lambda:build-provided"
' >> Cross.toml
cross build --target x86_64-unknown-linux-musl --release
cross build --target x86_64-unknown-linux-gnu --release
zip -r9 -j bootstrap.zip ./target/x86_64-unknown-linux-gnu/release/bootstrap
aws iam create-role \
--role-name lambda-basic-execution \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}'
aws iam attach-role-policy \
--role-name lambda-basic-execution \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
AWS_ACCOUNT_ID=`aws sts get-caller-identity --query Account --output text` && \
aws lambda create-function \
--function-name rust_lambda \
--runtime provided \
--role arn:aws:iam::$AWS_ACCOUNT_ID:role/lambda-basic-execution \
--zip-file fileb://bootstrap.zip \
--description "Simple Rust function" \
--timeout 5 \
--handler main
Done!
$ aws lambda invoke \
--function-name=rust_lambda \
--invocation-type=RequestResponse \
--payload $(echo '{"fullName": "Martin Luther", "message": null}' | base64 ) \
output.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
The response is saved as output.json
.
$ cat output.json
{"lambdaRequest":{"fullName":"Hello Martin Luther!","message":"You have no message."}}
At AWS Lambda console, go the function rust_lambda
and Test with
{"fullName": "Im atlex00", "message": "See you Lambda!"}
bootstrap
. This is described in [[bin]]
section in Cargo.toml
.cross
will provide all the ingredients needed for cross compilation without touching your system installation. The trick is, cross
uses Docker container for compile environment.bootstrap
.bootstrap
use dynamic link, and the destination is somewhere in Lambda default execution environment. cross
create proper link paths. Awsome…https://aws.amazon.com/blogs/opensource/rust-runtime-for-aws-lambda/
error: linker `x86_64-linux-musl-gcc` not found