Skip to content

Commit 80c0f84

Browse files
authored
Update readme with more up to date information (#484)
- Simplify the build and deployment sections. - Add a new section about unit tests. Signed-off-by: David Calavera <[email protected]>
1 parent bb34300 commit 80c0f84

File tree

1 file changed

+117
-34
lines changed

1 file changed

+117
-34
lines changed

README.md

Lines changed: 117 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,36 @@ This package makes it easy to run AWS Lambda Functions written in Rust. This wor
99
- [![Docs](https://docs.rs/lambda-extension/badge.svg)](https://docs.rs/lambda-extension) **`lambda-extension`** is a library that makes it easy to write Lambda Runtime Extensions in Rust.
1010
- [![Docs](https://docs.rs/lambda_runtime_api_client/badge.svg)](https://docs.rs/lambda_runtime_api_client) **`lambda-runtime-api-client`** is a shared library between the lambda runtime and lambda extension libraries that includes a common API client to talk with the AWS Lambda Runtime API.
1111

12-
## Example function
12+
## Getting started
1313

14-
The code below creates a simple function that receives an event with a `firstName` field and returns a message to the caller. Notice: this crate is tested against latest stable Rust.
14+
The easiest way to start writing Lambda functions with Rust is by using Cargo-Lambda. This Cargo subcommand provides several commands to help you in your journey with Rust on AWS Lambda.
15+
16+
You can install `cargo-lambda` with a package manager like Homebrew:
17+
18+
```bash
19+
brew tap cargo-lambda/cargo-lambda
20+
brew install cargo-lambda
21+
```
22+
23+
Or by compiling it from source:
24+
25+
```bash
26+
cargo install cargo-lambda
27+
```
28+
29+
See other installation options in [the cargo-lambda documentation](https://github.com/cargo-lambda/cargo-lambda#installation).
30+
31+
### Your first function
32+
33+
To create your first function, run `cargo-lambda` with the subcomand `new`. This command will generate a Rust package with the initial source code for your function:
34+
35+
```
36+
cargo lambda new YOUR_FUNCTION_NAME
37+
```
38+
39+
### Example function
40+
41+
If you'd like to manually create your first function, the code below shows you a simple function that receives an event with a `firstName` field and returns a message to the caller.
1542

1643
```rust,no_run
1744
use lambda_runtime::{service_fn, LambdaEvent, Error};
@@ -34,32 +61,18 @@ async fn func(event: LambdaEvent<Value>) -> Result<Value, Error> {
3461

3562
## Building and deploying your Lambda functions
3663

37-
There are currently multiple ways of building this package: manually with the AWS CLI, with [AWS SAM](https://github.com/aws/aws-sam-cli), and with the [Serverless framework](https://serverless.com/framework/).
64+
If you already have `cargo-lambda` installed in your machine, run the next command to build your function:
3865

39-
### 1. Cross-compiling your Lambda functions
40-
41-
At the time of writing, the ability to cross compile to a different architecture is limited. For example, you might experience issues if you are compiling from a MacOS machine, or from a Linux machine with a different architecture (e.g. compiling to Arm64 from x86_64). The most robust way we've found is using [`cargo-zigbuild`](https://github.com/messense/cargo-zigbuild) to compile for the target architecture.
42-
43-
#### 1.1. Setup the cross-compilation environment
44-
45-
_You can skip this step if you are compiling for the same target as your host architecture (e.g. x86_64 Linux to x86_64 Linux), unless you're building for an Amazon Linux 1 runtime._
46-
47-
Run this script once to add your desired target:
48-
49-
```bash
50-
# For Arm64 Lambda functions
51-
rustup target add aarch64-unknown-linux-gnu
52-
# For x86_64 Lambda functions
53-
rustup target add x86_64-unknown-linux-gnu
66+
```
67+
cargo lambda build --release
5468
```
5569

56-
Once this is done, install `cargo-lambda`:
70+
There are other ways of building your function: manually with the AWS CLI, with [AWS SAM](https://github.com/aws/aws-sam-cli), and with the [Serverless framework](https://serverless.com/framework/).
5771

58-
```bash
59-
cargo install cargo-lambda
60-
```
6172

62-
This Cargo subcommand will give you the option to install [Zig](https://ziglang.org/) to use as the linker. You can also install [Zig](https://ziglang.org/) using the instructions in their [installation guide](https://ziglang.org/learn/getting-started/#installing-zig).
73+
### 1. Cross-compiling your Lambda functions
74+
75+
By default, `cargo-lambda` builds your functions to run on x86_64 architectures. If you'd like to use a different architecture, use the options described below.
6376

6477
#### 1.2. Build your Lambda functions
6578

@@ -68,13 +81,12 @@ __Amazon Linux 2__
6881
We recommend you to use Amazon Linux 2 runtimes (such as `provided.al2`) as much as possible for building Lambda functions in Rust. To build your Lambda functions for Amazon Linux 2 runtimes, run:
6982

7083
```bash
71-
# Note: replace "aarch64" with "x86_64" if you are building for x86_64
72-
cargo lambda build --release --target aarch64-unknown-linux-gnu
84+
cargo lambda build --release --arm64
7385
```
7486

7587
__Amazon Linux 1__
7688

77-
Amazon Linux 1 uses glibc version 2.17, while Rust binaries need glibc version 2.18 or later by default. However, with `cargo-zigbuild`, you can specify a different version of glibc.
89+
Amazon Linux 1 uses glibc version 2.17, while Rust binaries need glibc version 2.18 or later by default. However, with `cargo-lambda`, you can specify a different version of glibc.
7890

7991
If you are building for Amazon Linux 1, or you want to support both Amazon Linux 2 and 1, run:
8092

@@ -89,15 +101,50 @@ For [a custom runtime](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-cus
89101

90102
You can find the `bootstrap` binary for your function under the `target/lambda` directory.
91103

92-
#### 2.1. Deploying with the AWS CLI
104+
#### 2.2. Deploying with cargo-lambda
93105

94-
First, you will need to create a ZIP archive of your Lambda function. Cargo-lambda can do that for you automatically when it builds your binary if you add the `output-format` flag. For example, if you are using the `basic` example and aarch64-unknown-linux-gnu as your target, you can run:
106+
You can use `cargo-lambda` for simple function deployments. Once you've built your code with one of the options described earlier, use the `deploy` subcommand to upload your function to AWS:
95107

96108
```bash
97-
cargo lambda build --release --target aarch64-unknown-linux-gnu --output-format zip
109+
cargo lambda deploy \
110+
--iam-role arn:aws:iam::XXXXXXXXXXXXX:role/your_lambda_execution_role
98111
```
99112

100-
Now that we have a deployment package (`target/lambda/basic/bootstrap.zip`), we can use the [AWS CLI](https://aws.amazon.com/cli/) to create a new Lambda function. Make sure to replace the execution role with an existing role in your account!
113+
> **warning**
114+
> Make sure to replace the execution role with an existing role in your account!
115+
116+
This command will create a Lambda function with the same name of your rust package. You can change the name
117+
of the function by adding the argument at the end of the command:
118+
119+
120+
```bash
121+
cargo lambda deploy \
122+
--iam-role arn:aws:iam::XXXXXXXXXXXXX:role/your_lambda_execution_role \
123+
my-first-lambda-function
124+
```
125+
126+
> **info**
127+
> See other deployment options in [the cargo-lambda documentation](https://github.com/cargo-lambda/cargo-lambda#deploy).
128+
129+
You can test the function with `cargo-lambda`'s invoke subcommand:
130+
131+
```bash
132+
cargo lambda invoke --remote \
133+
--data-ascii '{"command": "hi"}' \
134+
--output-format json \
135+
my-first-lambda-function
136+
```
137+
138+
#### 2.2. Deploying with the AWS CLI
139+
140+
You can also use the AWS CLI to deploy your Rust functions. First, you will need to create a ZIP archive of your function. Cargo-lambda can do that for you automatically when it builds your binary if you add the `output-format` flag:
141+
142+
```bash
143+
cargo lambda build --release --arm64 --output-format zip
144+
```
145+
146+
You can find the resulting zip file in `target/lambda/YOUR_PACKAGE/bootstrap.zip`. Use that file path to deploy your function with the [AWS CLI](https://aws.amazon.com/cli/):
147+
101148

102149
```bash
103150
$ aws lambda create-function --function-name rustTest \
@@ -109,6 +156,9 @@ $ aws lambda create-function --function-name rustTest \
109156
--tracing-config Mode=Active
110157
```
111158

159+
> **warning**
160+
> Make sure to replace the execution role with an existing role in your account!
161+
112162
You can now test the function using the AWS CLI or the AWS Lambda console
113163

114164
```bash
@@ -123,7 +173,7 @@ $ cat output.json # Prints: {"msg": "Command Say Hi! executed."}
123173
**Note:** `--cli-binary-format raw-in-base64-out` is a required
124174
argument when using the AWS CLI version 2. [More Information](https://docs.aws.amazon.com/cli/latest/userguide/cliv2-migration.html#cliv2-migration-binaryparam)
125175

126-
#### 2.2. AWS Serverless Application Model (SAM)
176+
#### 2.3. AWS Serverless Application Model (SAM)
127177

128178
You can use Lambda functions built in Rust with the [AWS Serverless Application Model (SAM)](https://aws.amazon.com/serverless/sam/). To do so, you will need to install the [AWS SAM CLI](https://github.com/aws/aws-sam-cli), which will help you package and deploy your Lambda functions in your AWS account.
129179

@@ -167,7 +217,7 @@ $ aws lambda invoke
167217
$ cat output.json # Prints: {"msg": "Command Say Hi! executed."}
168218
```
169219

170-
#### 2.3. Serverless Framework
220+
#### 2.4. Serverless Framework
171221

172222
Alternatively, you can build a Rust-based Lambda function declaratively using the [Serverless framework Rust plugin](https://github.com/softprops/serverless-rust).
173223

@@ -201,7 +251,7 @@ Invoke it using serverless framework or a configured AWS integrated trigger sour
201251
$ npx serverless invoke -f hello -d '{"foo":"bar"}'
202252
```
203253

204-
### Docker
254+
#### 2.5. Docker
205255

206256
Alternatively, you can build a Rust-based Lambda function in a [docker mirror of the AWS Lambda provided runtime with the Rust toolchain preinstalled](https://github.com/rust-serverless/lambda-rust).
207257

@@ -237,6 +287,39 @@ $ unzip -o \
237287

238288
## Local development and testing
239289

290+
### Testing your code with unit and integration tests
291+
292+
AWS Lambda events are plain structures deserialized from JSON objects.
293+
If your function handler uses the standard runtime, you can use `serde` to deserialize
294+
your text fixtures into the structures, and call your handler directly:
295+
296+
```rust,no_run
297+
#[test]
298+
fn test_my_lambda_handler() {
299+
let input = serde_json::from_str("{\"command\": \"Say Hi!\"}").expect("failed to parse event");
300+
let context = lambda_runtime::types::Context::default();
301+
302+
let event = lambda_runtime::types::LambdaEvent::new(input, context);
303+
304+
my_lambda_handler(event).expect("failed to handle event");
305+
}
306+
```
307+
308+
If you're using `lambda_http` to receive HTTP events, you can also create `http_lambda::Request`
309+
structures from plain text fixtures:
310+
311+
```rust,no_run
312+
#[test]
313+
fn test_my_lambda_handler() {
314+
let input = include_str!("apigw_proxy_request.json");
315+
316+
let request = lambda_http::request::from_str(input)
317+
.expect("failed to create request");
318+
319+
let response = my_lambda_handler(request).expect("failed to handle request");
320+
}
321+
```
322+
240323
### Cargo Lambda
241324

242325
[Cargo Lambda](https://crates.io/crates/cargo-lambda) provides a local server that emulates the AWS Lambda control plane. This server works on Windows, Linux, and MacOS. In the root of your Lambda project, run the subcommand `cargo lambda start` to start the server. Your function will be compiled when the server receives the first request to process. Use the subcommand `cargo lambda invoke` to send requests to your function. The `start` subcommand will watch your function's code for changes, and it will compile it every time you save the source after making changes.
@@ -261,7 +344,7 @@ This project does not currently include Lambda event struct definitions. Instead
261344

262345
To serialize and deserialize events and responses, we suggest using the [`serde`](https://github.com/serde-rs/serde) library. To receive custom events, annotate your structure with Serde's macros:
263346

264-
```rust
347+
```rust,no_run
265348
use serde::{Serialize, Deserialize};
266349
use serde_json::json;
267350
use std::error::Error;

0 commit comments

Comments
 (0)