Skip to content

Introduce Skeptic for testing the README.md #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 23, 2018
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/target
lambda-runtime/libtest.rmeta
106 changes: 106 additions & 0 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
members = [
"lambda-runtime-client",
"lambda-runtime"
]
]
96 changes: 60 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,56 @@
# Rust runtime for AWS Lambda
# Rust Runtime for AWS Lambda

This package makes it easy to run AWS Lambda Functions written in Rust. This workspace includes multiple crates:
* **`lambda-runtime-client`** is a client SDK for the Lambda runtime APIs
* **`lambda-runtime`** is a library that makes it easy to write Lambda functions in rust as executables
This package makes it easy to run AWS Lambda Functions written in Rust. This workspace includes two crates:

* **`lambda-runtime-client`** is a client SDK for the Lambda Runtime APIs. You probably don't need to use this crate directly!
* **`lambda-runtime`** is a library that makes it easy to write Lambda functions in Rust.

## Example function
The code below creates a simple function that receives an event with a `firstName` property and returns a hello world message for the given first name.

```rust
#[macro_use]
The code below creates a simple function that receives an event with a `greeting` and `name` field and returns a `GreetingResponse` message for the given name and greeting. Notice: to run these examples, we require a minimum Rust version of 1.30.

```rust,no_run
extern crate lambda_runtime as lambda;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate log;
extern crate simple_logger;

use lambda::error::HandlerError;

use serde_derive::{Serialize, Deserialize};
use lambda::{lambda, Context, error::HandlerError};
use log::error;
use std::error::Error;

#[derive(Deserialize, Clone)]
struct CustomEvent {
#[serde(rename = "firstName")]
first_name: String,
#[derive(Serialize, Deserialize)]
struct GreetingEvent {
greeting: String,
name: String,
}

#[derive(Serialize, Clone)]
struct CustomOutput {
#[derive(Serialize, Deserialize)]
struct GreetingResponse {
message: String,
}

fn main() -> Result<(), Box<dyn Error>> {
simple_logger::init_with_level(log::Level::Info)?;
simple_logger::init_with_level(log::Level::Debug).unwrap();
lambda!(my_handler);

Ok(())
}

fn my_handler(e: CustomEvent, c: lambda::Context) -> Result<CustomOutput, HandlerError> {
if e.first_name == "" {
error!("Empty first name in request {}", c.aws_request_id);
return Err(c.new_error("Empty first name"));
fn my_handler(event: GreetingEvent, ctx: Context) -> Result<GreetingResponse, HandlerError> {
if event.name == "" {
error!("Empty name in request {}", ctx.aws_request_id);
return Err(ctx.new_error("Empty name"));
}

Ok(CustomOutput {
message: format!("Hello, {}!", e.first_name),
Ok(GreetingResponse {
message: format!("{}, {}!", event.greeting, event.name),
})
}
```

The code above is the same as the [basic example](https://github.com/awslabs/aws-lambda-rust-runtime/tree/master/lambda-runtime/examples/basic.rs) in the `lambda-runtime` crate. To deploy the basic sample as a Lambda function, we first build it with `cargo`. Remember that AWS Lambda uses Amazon Linux so you need to target your executable for an `x86_64-linux` platform.
The code above is the same as the [basic example](https://github.com/awslabs/aws-lambda-rust-runtime/tree/master/lambda-runtime/examples/basic.rs) in the `lambda-runtime` crate. To deploy the basic sample as a Lambda function, we first build it with `cargo`. Since Lambda uses Amazon Linux, you'll need to target your executable for an `x86_64-linux` platform.

```bash
$ cargo build -p lambda_runtime --example basic --release
Expand All @@ -59,10 +59,10 @@ $ cargo build -p lambda_runtime --example basic --release
For a custom runtime, AWS Lambda looks for an executable called `boostrap` in the deployment package zip. Rename the generated `basic` executable to `bootstrap` and add it to a zip archive.

```bash
$ cp ./target/release/examples/basic ./bootstrap && zip rust.zip bootstrap && rm bootstrap
$ cp ./target/release/examples/basic ./bootstrap && zip lambda.zip bootstrap && rm bootstrap
```

Now that we have a deployment package (`rust.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.
Now that we have a deployment package (`lambda.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!

```bash
$ aws lambda create-function --function-name rustTest \
Expand All @@ -84,35 +84,59 @@ $ cat output.json # Prints: {"message":"Hello, world!"}
```

## lambda-runtime-client

Defines the `RuntimeClient` trait and provides its `HttpRuntimeClient` implementation. The client fetches events and returns output as `Vec<u8>`.

For error reporting to the runtime APIs the library defines the `RuntimeApiError` trait and the `ErrorResponse` object. Custom errors for the APIs should implement the `to_response() -> ErrorResponse` method of the `RuntimeApiError` trait.

## lambda-runtime

This library makes it easy to create Rust executables for AWS lambda. The library defines a `lambda!()` macro. Call the `lambda!()` macro from your main method with a function that matches the `Handler` type:
```rust

```rust,ignore
pub type Handler<E, O> = fn(E, Context) -> Result<O, error::HandlerError>;
```

Optionally, you can pass your own instance of Tokio runtime to the `lambda!()` macro. See our [`with_custom_runtime.rs` example](https://github.com/awslabs/aws-lambda-rust-runtime/tree/master/lambda-runtime/examples/with_custom_runtime.rs)

## Custom event objects

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

```rust
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

#[derive(Deserialize)]
pub struct MyEvent {
pub records: Vec<String>,
use serde_derive::{Serialize, Deserialize};
use serde_json::json;
use std::error::Error;

#[derive(Serialize, Deserialize)]
pub struct NewIceCreamEvent {
pub flavors: Vec<String>,
}

#[derive(Serialize)]
pub struct MyEventResponse {
pub message: String,
#[derive(Serialize, Deserialize)]
pub struct NewIceCreamResponse {
pub flavors_added_count: usize,
}

fn main() -> Result<(), Box<Error>> {
let flavors = json!({
"flavors": [
"Nocciola",
"抹茶",
"आम"
]
});

let event: NewIceCreamEvent = serde_json::from_value(flavors)?;
let response = NewIceCreamResponse {
flavors_added_count: event.flavors.len(),
};
serde_json::to_string(&response)?;

Ok(())
}
```
7 changes: 6 additions & 1 deletion lambda-runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ authors = ["Stefano Buliani", "David Barsky"]
description = "Rust runtime for AWS Lambda"
keywords = ["AWS", "Lambda", "Runtime", "Rust"]
license = "Apache-2.0"
build = "build.rs"

[dependencies]
serde = "^1"
Expand All @@ -21,4 +22,8 @@ simple_logger = "^1"
[dev-dependencies]
hyper-tls = "^0.3"
rusoto_core = "^0.35"
rusoto_dynamodb = "^0.35"
rusoto_dynamodb = "^0.35"
skeptic = "^0.13"

[build-dependencies]
skeptic = "^0.13"
6 changes: 6 additions & 0 deletions lambda-runtime/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
extern crate skeptic;

fn main() {
// generates doc tests for `README.md`.
skeptic::generate_doc_tests(&["./../README.md"]);
}
12 changes: 5 additions & 7 deletions lambda-runtime/examples/basic.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
#[macro_use]
extern crate lambda_runtime as lambda;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate log;
extern crate simple_logger;

use lambda::error::HandlerError;

use serde_derive::{Serialize, Deserialize};
use lambda::{lambda, error::HandlerError};
use log::error;
use std::error::Error;

#[derive(Deserialize, Clone)]
#[derive(Deserialize)]
struct CustomEvent {
#[serde(rename = "firstName")]
first_name: String,
}

#[derive(Serialize, Clone)]
#[derive(Serialize)]
struct CustomOutput {
message: String,
}
Expand Down
8 changes: 3 additions & 5 deletions lambda-runtime/examples/with_custom_runtime.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
#[macro_use]
extern crate lambda_runtime as lambda;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate log;
extern crate simple_logger;
extern crate tokio;

use lambda::error::HandlerError;
use lambda::{lambda, error::HandlerError};
use tokio::runtime::Runtime;

use serde_derive::{Serialize, Deserialize};
use log::error;
use std::error::Error;

#[derive(Deserialize, Clone)]
Expand Down
1 change: 1 addition & 0 deletions lambda-runtime/tests/skeptic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include!(concat!(env!("OUT_DIR"), "/skeptic-tests.rs"));