Rust Serverless

Page content

Getting started

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 :)

Hello world code

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 })
}

Build for Lambda environment

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

Deploy on AWS Lambda

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!

Test

$ 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

  • New event
  • Template: hello-world
  • Name: MyEventTest
  • Data: {"fullName": "Im atlex00", "message": "See you Lambda!"}

Review

Note: Failed 2018 post

https://aws.amazon.com/blogs/opensource/rust-runtime-for-aws-lambda/

error: linker `x86_64-linux-musl-gcc` not found