Rust + AWS Lambda + Windows Part 2

In the previous section of this tutorial, we set up a WSL build environment in Windows for Rust, adapted code, and compiled + packaged a binary ready for upload to AWS Lambda. Now, it’s time to get our code up and running.

AWS Account

If you already have an account with AWS, skip this part. Included in the free tier of AWS are 1 million requests per month and 3.2 million seconds of compute time of Lambda. What’s neat about using the Lambda product is that no environment is needed meaning no setting up of a virtual machine or other container system; the user uploads code then can immediately send data to and receive data from their application.

AWS Lambda

Once logged into your AWS Management Console, not to be confused with a console running AWS CLI, you’ll want to take note of the region your account is set to. As of the date of this post, that information is at the top-right of the page. I set mine to US East (N. Virginia) us-east-1 for this tutorial, but it’s only important to note this down for use later.

Under All Services > Compute, you’ll find Lambda. Here, we should find a big button labeled: Create function.

The options we want are:

  • Author from scratch
  • Basic information
    • Function name: rustTest
    • Runtime: Provide your own bootstrap on Amazon Linux 2
    • Architecture: x86_64
  • Permissions
    • Execution role: Create a new role with basic Lambda permissions

Press the Create function

rustTest

Within this Lambda, look for Upload from > .zip file, and upload the lambda.zip file we created in the previous section. Below the Function overview section, we find some tabs: Code, Test, Monitor, etc. Select the Test tab. Here, we’ll want to create a New event with some name, perhaps HelloName is suitable? What should we pass the test, and how should it be formatted? Let’s open up C:\aws-lambda-rust-runtime\lambda-runtime\examples\basic.rs and take a peek around.

use serde::{Deserialize, Serialize};

#[derive(Deserialize)]
struct Request {
    test_name: String,
}

Out of the box, the serde package converts Rust data structures into JSON-formatted strings for transmission across HTTP APIs. Also note that we specially named the data member test_name. This is the second part of what we need to write our test.

{
  "test_name": "Macsimum"
}

Press Save changes then Test. A green box should appear with the text Execution result: succeeded. Expand the Details section. A response JSON string should be there.

{
  "req_id": "some id string unique to your session",
  "msg": "Hello Macsimum!"
}

Recall from our code that these match the members found here:

#[derive(Serialize)]
struct Response {
    req_id: String,
    msg: String,
}

The response also matches the code we edited:

let resp = Response {
    req_id: event.context.request_id,
    msg: format!("Hello {}!", output_name),
};

Let’s see what a bad test looks like. Make a New event using the HelloName template but named HelloNameBad.

{
"command": "Macsimum"
}

Press Save changes then Test. This time, a red box should appear with the text Execution result: failed. Expand the Details section. A response JSON string should be there.

{
  "errorMessage": "RequestId: some id string unique to your session Error: Runtime exited with error: exit status 1",
  "errorType": "Runtime.ExitError"
}

Below, in Log output, you’ll find:

Error: Error("missing field `test_name`", line: 1, column: 22)

Logging

You may have noticed (logs) next to Execution result: succeeded and Execution result: failed. Clicking the link will take you to CloudWatch > Log Groups > rustTest. From the AWS Console, CloudWatch can be found at All Services > Management & Governance > CloudWatch. Perusing these entries will yield insights into time and memory usage. The unsuccessful test we ran should have logged the error message noted above.

Cleanup?

There is at least one other lesson to learn, but it’s outside the scope of this section and involves using the AWS CLI mentioned previously. I do wish to point out that the AWS CLI under Windows has some unique formatting quirks which took me some time to get right. If you are not interested in learning the CLI and testing Lambdas, you can go ahead and delete the function in Lambda and the logs in CloudWatch. In All services > Security, Identity, & Compliance > IAM, you’ll find a section called Roles. For the function we created, AWS created a role named rustTest-role-something. Delete this as well. Also in IAM, we need to go into Policies and delete the AWSLambdaBasicExecutionRole-some-long-hex-number which was created for us.