[速報] AWS SDK for RustがGAになりました! #AWSreInvent

2023.11.28

福岡オフィスのyoshihitohです。

本日からAWS SDK for RustがGA(一般利用可能)になりました! What's new ブログはこちらです。

よくよく見てみると、GitHubのIssue#1692 SDK Production Readiness で着々と準備が進んでいたようですね!

以前、α版の開発者プレビューがリリースされたときに試した内容をGA版のSDKで試してみます。

検証環境

  • macOS: Ventura 13.14
  • Rust: 1.74.0
  • AWS SDK for Rust : TBA

試すこと

α版のときと比較しやすいように、DynamoDBで以下の操作を試してみます

  • CreateTable (テーブル作成)
  • PutItem (アイテム追加)
  • GetItem (アイテム取得)

やってみる

プロジェクト作成

前回試したGitリポジトリはアップロードせずに破棄してしまったので、最初からやりなおしていきます。 まず、cargoプロジェクトを作成します

cargo new aws-sdk-for-rust-example

次に、 READMEの内容 に従って依存ライブラリを追加します。以前はCargo.tomlを直接編集しましたが、今回はcargo-addで追加してみます。 (Cargo.tomlの直接編集でも問題ありません)

cargo add aws-config@1.0.1 --features behavior-version-latest
cargo add aws-sdk-dynamodb@1.3.0
cargo add tokio@1 --features full

ここまででプロジェクトの作成は完了です。

クライアント作成

α版のアナウンス時点では from_env() でクライアントを作成できましたが、aws_configクレートを利用する設計に変わったようです。

環境変数の内容でクライアントを作成する場合は以下のようにします。

use aws_sdk_dynamodb as dynamodb;

#[tokio::main]
async fn main() -> Result<(), dynamodb::Error> {
    let config = aws_config::from_env().load().await;
    let client = aws_sdk_dynamodb::Client::new(&config);
    Ok(())
}

AWS認証情報を設定して実行します。 aws-valut などのツールを利用している場合は、そのツールの使い方に合わせてコマンドを変更してください。 ドキュメントのExamples ではRegionProviderを利用していますが、 AWS_DEFAULT_REGION 環境変数を設定する場合は不要のようです。

export AWS_DEFAULT_REGION=ap-northeast-1
export AWS_ACCESS_KEY_ID=xxxx
export AWS_SECRET_ACCESS_KEY=xxxx
export AWS_SESSION_TOKEN=xxxx
cargo run

コマンド実行時にエラー終了しなければ準備完了です。 その他にもクライアントを作成する方法が用意されているようなので、ぜひ ドキュメント を確認してみてください

テーブル作成

以下の内容でテーブルを作成します。

  • テーブル名: hello-rust-sdk
  • パティションキー: title (String)
  • ソートキー: なし
  • キャパシティ: オンデマンド
async fn create_table(client: &dynamodb::Client) -> Result<(), dynamodb::Error> {
    client
        .create_table()
        .table_name("hello-rust-sdk")
        .attribute_definitions(
            dynamodb::types::builders::AttributeDefinitionBuilder::default()
                .attribute_name("title")
                .attribute_type(dynamodb::types::ScalarAttributeType::S)
                .build()?,
        )
        .key_schema(
            dynamodb::types::builders::KeySchemaElementBuilder::default()
                .attribute_name("title")
                .key_type(dynamodb::types::KeyType::Hash)
                .build()?,
        )
        .billing_mode(dynamodb::types::BillingMode::PayPerRequest)
        .send()
        .await?;

    // NOTE:
    // テーブル作成直後はアイテム追加などの操作を行えないため待機処理が必要です。
    // 本来はDescribeTableで `TableStatus` が `ACTIVE` になるまで待機するべきですが、今回はsleepで代用しています。
    std::thread::sleep(std::time::Duration::from_secs(5));

    Ok(())
}

テーブル作成時に利用する型は dynamodb::typesdynamodb::types::builders に移動したようです。

アイテム追加 (PutItem)

title と content を文字列として登録します。

async fn put_item(
    client: &dynamodb::Client,
    title: &str,
    content: &str,
) -> Result<(), dynamodb::Error> {
    client
        .put_item()
        .table_name("hello-rust-sdk")
        .item(
            "title",
            dynamodb::types::AttributeValue::S(title.to_string()),
        )
        .item(
            "content",
            dynamodb::types::AttributeValue::S(content.to_string()),
        )
        .send()
        .await?;
    Ok(())
}

こちらも同様に参照先を変えるだけでした。

アイテム取得 (GetItem)

テーブルをスキャンして、 title と content を表示します。今回は1件だけしか登録していませんが、Limit指定も試してみます。

async fn show_items(client: &dynamodb::Client) -> Result<(), dynamodb::Error> {
    let res = client
        .scan()
        .table_name("hello-rust-sdk")
        .limit(10)
        .send()
        .await?;

    for item in res.items.unwrap_or_default() {
        if let (
            Some(dynamodb::types::AttributeValue::S(title)),
            Some(dynamodb::types::AttributeValue::S(content)),
        ) = (item.get("title"), item.get("content"))
        {
            println!("title: '{}', content: '{}'", title, content)
        }
    }

    Ok(())
}

それぞれの操作を呼び出す

最後にmain関数を実装して、ここまでに実装した操作を動かしてみます。

async fn main() -> Result<(), dynamodb::Error> {
    let config = aws_config::from_env().load().await;
    let client = aws_sdk_dynamodb::Client::new(&config);

    // テーブルを作る
    create_table(&client).await?;

    // アイテムを追加する
    put_item(&client, "Rust SDK", "is Generally available from today!").await?;

    // アイテムを表示する
    show_items(&client).await?;

    Ok(())
}

以上で実装は完了です。

動作確認

早速試してみましょう! 先の手順で環境変数設定済みの場合はそのまま実行すればOKです。まだの場合は クライアント作成 の手順で設定してみてください。

cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.08s
     Running `target/debug/aws-sdk-for-rust-example`
title: 'Rust SDK', content: 'is Generally available from today!'

問題なく動きましたね!

終わりに

ついにAWS SDK for RustがGAとなりました! 今までは開発者プレビューということもありプロダクション環境での利用を泣く泣く見送るケースもあったかもしれません。 これからRustでAWS環境向けのアプリケーションを開発する際には積極的に活用していきたいですね!