Skip to content
This repository has been archived by the owner on Oct 21, 2024. It is now read-only.

rust function url example #960

Merged
merged 7 commits into from
Oct 7, 2024
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
7 changes: 7 additions & 0 deletions examples/aws-rust-api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

# sst
.sst

# rust
Cargo.lock
target/
23 changes: 23 additions & 0 deletions examples/aws-rust-api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "aws_rust_cluster"
version = "0.1.0"
edition = "2021"

[profile.release]
debug = 0
incremental = false
panic = "abort"
opt-level = 3 # 0-3
strip = 'symbols' # strip symbols from binary
lto = true # enable link time optimization

[dependencies]
axum = "0.7.5"
lambda_http = "0.13.0"
lambda_runtime = "0.13.0"
serde = { version = "1.0.209", features = ["derive"] }
tokio = { version = ">=1.x", features = ["macros", "rt-multi-thread"] }

[[bin]]
name = "api"
path = "src/bin/handlers/api.rs"
133 changes: 133 additions & 0 deletions examples/aws-rust-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Rust Function Url Example

This example uses [cargo lambda](https://www.cargo-lambda.info/) to build rust binaries and deploy them on a provided AL2 runtime

NOTE: (cargo lambda relies on [zig](https://ziglang.org/), which it will prompt to install on first running a cargo lambda command)

```sh
cargo lambda build --release
```

you can also provide the architecture of choice

```sh
cargo lambda build --release --arm64
# or
cargo lambda build --release --x86-64
```

which can then be reflected in the `sst.config.ts`

```ts
const api = new sst.aws.Function("rust-api", {
architecture: "arm64", // or x86_64
...
});
```

by default, cargo lambda will build to a folder in `target/` called `lambda/`. The binary build will be called `bootstrap`, and it will be built in a sub folder which is the name of your binary.

For example, a rust binary `src/bin/handlers/api.rs` will be built to `target/lambda/api/bootstrap`

After building the binary, deploys can be done normally via `sst deploy --stage production`

Other services can be orchestrated in a similar manner with cargo lambda, for example a cron:
```ts
new sst.aws.Cron('MyCron', {
schedule: 'cron(0 0 * * ? *)',
job: {
architecture: 'arm64',
runtime: 'provided.al2023',
handler: 'bootstrap',
bundle: 'target/lambda/my-cron',
}
});
```

# GHA

An example to deploy using github actions with `arm64` architecture, feel free to configure as needed

```yml
name: Deploy Prod

on:
push:
branches:
- main

jobs:
deploy-prod:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pguyot/arm-runner-action@v2

- name: use Node.js
uses: actions/setup-node@v3
with:
node-version: latest

- name: use pnpm
uses: pnpm/action-setup@v4
with:
version: latest

- name: get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV

- name: setup pnpm cache
uses: actions/cache@v3
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-

- name: use Rust
uses: actions-rs/toolchain@v1

- name: use Rust cache
uses: Swatinem/rust-cache@v2

- name: use Zig
uses: korandoru/setup-zig@v1
with:
zig-version: master

- name: use Cargo Lambda
uses: jaxxstorm/[email protected]
with:
repo: cargo-lambda/cargo-lambda
platform: linux
arch: aarch64 # | x86_64

- name: cargo lint
run: cargo lint

- name: pnpm install
run: pnpm install --frozen-lockfile

- name: sst install providers
run: |
set -euxo pipefail
pnpm sst install

- name: build lambdas
run: |
set -euxo pipefail
cargo lambda build --release --arm64

- name: sst deploy
run: |
set -euxo pipefail
pnpm sst deploy --stage prod

env:
STAGE: prod
LOG_LEVEL: info
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
```
17 changes: 17 additions & 0 deletions examples/aws-rust-api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "aws-rust-cluster",
"version": "1.0.0",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"sst": "3.0.68",
"sst-linux-x64": "^3.0.66"
},
"devDependencies": {
"@types/aws-lambda": "8.10.143"
}
}
23 changes: 23 additions & 0 deletions examples/aws-rust-api/src/bin/handlers/api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use axum::{http::StatusCode, response::IntoResponse, routing::get, Json};
use lambda_http::Error;
use serde::Serialize;

#[derive(Serialize)]
pub struct Ping {
message: &'static str,
}

pub async fn ping() -> impl IntoResponse {
(
StatusCode::IM_A_TEAPOT,
Json(Ping {
message: "hello from rust :)",
}),
)
}

#[tokio::main]
pub async fn main() -> Result<(), Error> {
let app = axum::Router::new().route("/", get(ping));
lambda_http::run(app).await
}
8 changes: 8 additions & 0 deletions examples/aws-rust-api/sst-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* tslint:disable */
/* eslint-disable */
import "sst"
declare module "sst" {
export interface Resource {
}
}
export {}
33 changes: 33 additions & 0 deletions examples/aws-rust-api/sst.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/// <reference path="./.sst/platform/config.d.ts" />

export default $config({
app(input) {
return {
name: "aws-rust-function-url",
removal: input?.stage === "production" ? "retain" : "remove",
home: "aws",
providers: {
aws: { region: 'us-east-1' }
},
};
},
async run() {
const api = new sst.aws.Function("rust-api", {
handler: "bootstrap",
architecture: "arm64", // or x86_64
bundle: "target/lambda/api",
runtime: 'provided.al2023',
url: true,
});
const router = new sst.aws.Router("MyRouter", {
routes: {
"/*": api.url,
},
domain: "rust.dev.sst.dev",
});
return {
function: api.url,
domain: router.url
}
}
});
1 change: 1 addition & 0 deletions examples/aws-rust-api/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}