emahiro/b.log

日々の勉強の記録とか育児の記録とか。

AWS Go SDK V2 を使ってみる

Overview

AWS Go SDK の V2 が GA になったので早速業務の中で使ってみてハマったところ、V1 との違いでつまづいたところを中心にまとめます。

基本的には https://aws.github.io/aws-sdk-go-v2/docs/migrating/ にまとまっていますが、色々わからないところがあったので補足しながら記載します。

AWS SDK for Go V2 について

1月に GA になっています。

aws.amazon.com

github.com

AWS の設定をロードする

一番最初からなんですが、一番ハマったのはここでした。

AWS SDK for Go を利用する場合、AWS の認証情報をとって設定をロードし、それを各サービスのクライアントに当てはめて AWS の各サービスの API を Call することになります。

単純な Configuration のロードと V1 → V2 へのマイグレーションについては https://aws.github.io/aws-sdk-go-v2/docs/migrating/#configuration-loading に記載されている通りです。 特に独自に環境変数を持っていないケース(AWS Lambda とか?)ではここのマイグレーションドキュメントの通りに実装すると良さそうです。 (Lambda ではまだ実装してないので多分ですが。そのうち Lambda でも使おうと思います。)

独自で環境変数を持ってる場合

自前で AWS環境変数を設定してるケースでは、https://aws.github.io/aws-sdk-go-v2/docs/migrating/#credentials--credential-providers に書かれている Credentials を取り出してから Config を Credentials 付きで Load します。

id := os.Getenv("$YourAccessKeyID")
secret := os.Getenv("$YourSecretKey")
// AWS_SESSION_TOKEN はそのまま取り出してOK
cred := aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(id, secret, os.Getenv("AWS_SESSION_TOKEN")))
if cred == nil {
    panic("failed to fetch credentials provider")
}
cfg, err := config.LoadDefaultConfig(ctx, config.WithCredentialsProvider(cred))
if err != nil {
    panic(err)
}
// => ここで load した config を AWS の各サービスに入れて使います。

DynamoDB を使う

仕事で使ったのは DynamoDB だったので DynamoDB を例にとって V2 を使った DynamoDB の操作方法について記載します。

DynamoDB の使い方のサンプルは公式が以下のドキュメントを公開しています。

aws.github.io

DynamoDB クライアントを Load する

これは割と簡単で上記で取り出した config 情報を DynamoDB のクライアントに差し込みます。

dynamodb.NewFromConfig(cfg)

リソースを更新する

サンプルとしてリソースの更新する実装は以下です。

update := expression.Set(expression.Name("key"), expression.IfNotExists(expression.Name("key"), expression.Value("val")))
// SET a = :a, b = :b のように複数 key を更新したい場合は以下のように Set を追加します。
update = update.Set(...)

expr, err := expression.NewBuilder().WithUpdate(update).Build()
if err != nil {
    return err
}

input := dynamodb.UpdateItemInput{
    TableName: tableName,
    Key: map[string]types.AttributeValue{
        "$PK": &types.AttributeValueMemberS{ 
            Value: "$PKValue",
        },
    },
    UpdateExpression:          expr.Update(),
    ExpressionAttributeValues: expr.Values(),
    ExpressionAttributeNames:  expr.Names(),
    ConditionExpression:       expr.Condition(),
}

これに対応する aws dynamodb のクエリは以下です。

aws dynamodb update-item \
--table-name $tableName \
--key '{"$PK":{"S":"$PKValue"}}' \
--update-expression "SET key = :val" \
--expression-attribute-values '{":val":{"N":"1"}}' \
--return-value ALL_NEW

ちなみに --key に GSI を指定できないことに気づかずだいぶ時間を溶かしました。ドキュメント読んでて Id を指定しているのをみて気づきました。

※ クエリの表現は以下に大体書いてあります。

docs.aws.amazon.com

expression はまだ feature だった

V1 で存在していた dyanmodb/expression が V2 だと最初見つからずに、愚直に expression を書くしかないのかなーと思ってたのですが、feature package の中にいました。

余談: 毎回めんどいなーところと思うところ

DynamoDB のクライアントの実装してて毎回 aws コマンドぽちぽちしながら一個一個 expression のフィールドに当てはめて実装していくのが結構めんどいなーと思ってます。

毎回こんな感じでちまちま aws dynamodb コマンドを叩いて少しずつ実装をしてます。

aws dynamodb query \
--index-name $indexName \
--table-name $tableTame \
--key-condition-expression "key = :val" \
--expression-attribute-values '{":val":{"S":"$Value"}}'

Transaction について

DynamoDB のトランザクションについてまだちゃんと見てないですが使う機会がありそうなのでその時に調べようと思います。

ざっと調べた感じ例えば Put の処理に対して Transaction を貼る場合はhttps://github.com/aws/aws-sdk-go-v2/blob/67f74949e4831edc2d0a8da2aba8c4b356b27fff/service/dynamodb/api_op_TransactWriteItems.go#L95 の TransactionItems に Put したいテーブルの Attributes を突っ込んでいって一括で処理するっぽいですね。

Put の中身自体は https://github.com/aws/aws-sdk-go-v2/blob/67f74949e4831edc2d0a8da2aba8c4b356b27fff/service/dynamodb/types/types.go#L1876-L1905 の構造体に定義があるのでこれを一個一個作って突っ込んでいくのが良さそうです。

以下で仕様周りのことは記載してあります。

docs.aws.amazon.com

ここはまた実装してみた後にまとめたいと思います。

See Also