さて、今回は第一回でDynamoDBを設計したので、それに基づいてcdkで構築していきたいと思います。
まずはcdkの初期化から始めていきます。詳しくは上記で説明しているのであまり分からない方は参考にしてください。
mkdir task-management-app
cd task-management-app
cdk init --language go
上記を実行するとファイルが色々と作成されますが、cdkディレクトリを作成し、main.goを作成します。
mkdir cdk && cd cdk && touch main.go
で、ちょっと面倒ですが、cdkディレクトリにcdk.jsonを移動し、2行目を以下のように変更してください。
cdk initで作成される際には、go run task-management-app.goとなっているので、このままだとデプロイするファイルがこのファイルになってしまいます。
{
"app": "go mod download && go run main.go",
続いて、作成したcdk/main.goにDynamoDBをデプロイするためのコードを記述していく。
若干雑な設定がありますがご容赦ください🙇
package main
import (
"log"
"os"
"github.com/aws/aws-cdk-go/awscdk/v2"
"github.com/aws/aws-cdk-go/awscdk/v2/awsdynamodb"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/constructs-go/constructs/v10"
"github.com/aws/jsii-runtime-go"
"github.com/joho/godotenv"
)
type DynamoDBStackProps struct {
awscdk.StackProps
}
func NewDynamoDBStack(scope constructs.Construct, id string, props *DynamoDBStackProps) awscdk.Stack {
var sprops awscdk.StackProps
if props != nil {
sprops = props.StackProps
}
readCapacity := float64(2)
writeCapacity := float64(2)
stack := awscdk.NewStack(scope, &id, &sprops)
table := awsdynamodb.NewTable(stack, jsii.String("TaskManagement"), &awsdynamodb.TableProps{
TableName: jsii.String("TaskManagement"),
PartitionKey: &awsdynamodb.Attribute{
Name: jsii.String("id"),
Type: awsdynamodb.AttributeType_STRING},
SortKey: &awsdynamodb.Attribute{
Name: jsii.String("DataType"),
Type: awsdynamodb.AttributeType_STRING},
DeletionProtection: aws.Bool(true),
ReadCapacity: &readCapacity,
WriteCapacity: &writeCapacity,
})
table.AddGlobalSecondaryIndex(&awsdynamodb.GlobalSecondaryIndexProps{
IndexName: jsii.String("GSI1"),
PartitionKey: &awsdynamodb.Attribute{
Name: jsii.String("DataValue"),
Type: awsdynamodb.AttributeType_STRING,
},
SortKey: &awsdynamodb.Attribute{
Name: jsii.String("id"),
Type: awsdynamodb.AttributeType_STRING,
},
ReadCapacity: &readCapacity,
WriteCapacity: &writeCapacity,
})
return stack
}
func main(){
err := godotenv.Load()
if err != nil {
log.Fatalf("Error loading .env file")
}
app := awscdk.NewApp(nil)
NewDynamoDBStack(app, "taskManagementStack", &DynamoDBStackProps{
awscdk.StackProps{
Env: env(),
},
})
app.Synth(nil)
}
func env() *awscdk.Environment {
awsAccountId := os.Getenv("AWS_ACCOUNT_ID")
awsRegion := os.Getenv("AWS_REGION")
return &awscdk.Environment{
Account: jsii.String(awsAccountId),
Region: jsii.String(awsRegion),
}
}
awsdynamodb.NewTablbeで作成したテーブルにAddGlbalSecondaryIndexを使用して追加します。
AddGlbalSecondaryIndexの引数には(props *GlobalSecondaryIndexProps)の以下の項目を渡します。
もちろん、以下に GlobalSecondaryIndexProps 構造体の各フィールドとその説明を表形式でまとめました。
| フィールド名 | 必須/オプション | 説明 |
|---|---|---|
IndexName |
必須 | セカンダリインデックスの名前。 |
NonKeyAttributes |
オプション | セカンダリインデックスに投影される非キー属性。デフォルトは追加属性なし。 |
ProjectionType |
オプション | セカンダリインデックスに投影される属性のセット。デフォルトは ALL。 |
PartitionKey |
必須 | パーティションキーの属性定義。 |
SortKey |
オプション | ソートキーの属性定義。デフォルトはソートキーなし。 |
ReadCapacity |
オプション | グローバルセカンダリインデックスのリードキャパシティ。テーブルの billingMode が Provisioned または未定義の場合のみ設定可能。デフォルトは5。 |
WriteCapacity |
オプション | グローバルセカンダリインデックスのライトキャパシティ。テーブルの billingMode が Provisioned または未定義の場合のみ設定可能。デフォルトは5。 |
上の表の項目はよくある設定なので大体分かったのですが、ProjectionTypeがイマイチ分からないので調べてみると、SQLで言うと以下のような感じみたいです。
ProjectionType.INCLUDEの場合のみ、パーティションキーとソートキーに加えてどの属性を取得するかNonKeyAttributesで指定する必要があります。
今回は全属性欲しいのでデフォルトのALLのまま使用します。
| DynamoDBのProjectionType | SQLのクエリ |
|---|---|
| ProjectionType.ALL | SELECT * |
| ProjectionType.KEYS_ONLY | SELECT partition_key, sort_key |
| ProjectionType.INCLUDE | SELECT partion_key, sort_key, designated_attribute |
これで以下を実行すればデプロイ完了です!(初回の場合はbootstrapが必要です。)
cdk synth
cdk deploy
今回、No Bucket Nameというエラーでデプロイに失敗しました。。。
以下の記事が全く同じ状況で試したところ別のエラーが発生したのでbootstrapし直したところ、無事デプロイできました。
ありがとうございます🙌
https://qiita.com/ryome/items/6ae0ec1c2ae894954059
次回は、lambdaをスタックに追加して、lambda関数の中で読み込みや書き込みを行えるように実装していきます。

