はじめに
AWS-CDKで生成されるCloudformationテンプレートは<ユーザーが指定したID>A1B2C3
といった感じで末尾にランダムな文字列が付与される。
通常であれば問題ないが今回DeletionPolicyにRETAINを指定したDynamoDBを含んだStackを更新しようとしたところ、論理IDが変わって(tableA1B2C3
→tableX1Y2Z3
)別のDynamoDBのリソースとして認識された。
そのためすでにあるDynamoDBと名前が被っているのでエラーとなりStackが更新できなくなった。
TL;DR
該当のStackを定義しているClassでallocateLogicalIdをオーバライドして独自実装する
実装例
大体はallocateLogicalIdやmakeUniqueId内の処理を丸コピしたもの
ちゃんと期待通りのものになっているかはデプロイ前にSynthコマンドで要確認
import { CfnElement, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib'
import { Construct } from 'constructs'
import * as DynamoDB from 'aws-cdk-lib/aws-dynamodb'
export class TableStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props)
new DynamoDB.Table(this, `table`, {
tableName: `table`,
partitionKey: { name: 'id', type: DynamoDB.AttributeType.STRING },
billingMode: DynamoDB.BillingMode.PAY_PER_REQUEST,
removalPolicy: RemovalPolicy.RETAIN
})
}
// Class「Stack」から継承されたallocateLogicalIdメソッドを再定義
protected allocateLogicalId(cfnElement: CfnElement): string {
// allocateLogicalIdと同じ実装
const scopes = cfnElement.node.scopes
const stackIndex = scopes.indexOf(cfnElement.stack)
const pathComponents = scopes
.slice(stackIndex + 1)
// .replaceからはmakeUniqueIdを参考
.map((x) => x.node.id.replace(/[^A-Za-z0-9]|Resource/g, ''))
return pathComponents.join('')
}
}