こんにちは、ちゃりおです。
CDKの自動で追加されるクロススタック参照で以下のエラーがでました。
Export <アウトプット> cannot be deleted as it is in use by <スタック名>
Outputしている側は特に変更せず、Importしている側で取得する値を変えました。
Import側を変えた影響で、CDKが自動生成しているOutputを消してしまってスタックを変更できず困りました。
結論から書くと、exportValueで自動生成されるOutputを保持することで解決しました。
CDKのクロススタック参照がロックされてしまう
事象
ロググループとECSのタスク定義を別スタックにして、クロススタックする場合を例にします。
#!/usr/bin/env node
import "source-map-support/register"
import * as cdk from "@aws-cdk/core"
import * as logs from "@aws-cdk/aws-logs"
import * as ecs from "@aws-cdk/aws-ecs"
export class LogsStack extends cdk.Stack {
logGroup: {
sample: logs.LogGroup,
sample2: logs.LogGroup
}
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const sampleLog = new logs.LogGroup(this, "sample-logGroup", {
removalPolicy: cdk.RemovalPolicy.DESTROY
})
const sample2Log = new logs.LogGroup(this, "sample2-logGroup", {
removalPolicy: cdk.RemovalPolicy.DESTROY
})
this.logGroup = {
sample: sampleLog,
sample2: sample2Log
}
}
}
interface ecsProps extends cdk.StackProps {
log: LogsStack
}
export class EcsStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props: ecsProps ) {
super(scope, id)
const taskDef = new ecs.FargateTaskDefinition(this, "app-task")
taskDef.addContainer("nginx", {
image: ecs.ContainerImage.fromRegistry("amazon/amazon-ecs-sample"),
logging: new ecs.AwsLogDriver({
streamPrefix: "fargate",
logGroup: props.log.logGroup.sample
})
})
}
}
const app = new cdk.App();
const logsStack = new LogsStack(app, "logs-stack")
new EcsStack(app, "ecs-stack", { log: logsStack })
上記がデプロイ済みの状態で、タスク定義のロググループを変更しようとするとエラーがでます。
// sample2に変更
// logGroup: props.log.logGroup.sample
logGroup: props.log.logGroup.sample2
% cdk deploy "*" (git)-[master]
logs-stack
logs-stack: deploying...
logs-stack: creating CloudFormation changeset...
17:17:12 | UPDATE_ROLLBACK_IN_P | AWS::CloudFormation::Stack | logs-stack
Export logs-stack:ExportsOutputRefsamplelogGroupA6FE7BF7B332FB07 cannot be deleted as it is in use by ecs-stack
17:17:12 | UPDATE_ROLLBACK_IN_P | AWS::CloudFormation::Stack | logs-stack
Export logs-stack:ExportsOutputRefsamplelogGroupA6FE7BF7B332FB07 cannot be deleted as it is in use by ecs-stack
スタック作り直せば、ロググループ変更できますが作り直すのは面倒です。
どうやら「logs-stack」側のOutputを消そうとしているが、他のスタックで使っていて消せない旨のエラーがでます。
diffを見ると「logs-stack」は変更していないにも関わらず、Outputの変更がでてきます。
% cdk diff logs-stack (git)-[master]
Stack logs-stack
Outputs
[-] Output ExportsOutputRefsamplelogGroupA6FE7BF7B332FB07: {"Value":{"Ref":"samplelogGroupA6FE7BF7"},"Export":{"Name":"logs-stack:ExportsOutputRefsamplelogGroupA6FE7BF7B332FB07"}}
[-] Output ExportsOutputFnGetAttsamplelogGroupA6FE7BF7Arn1ECF63B5: {"Value":{"Fn::GetAtt":["samplelogGroupA6FE7BF7","Arn"]},"Export":{"Name":"logs-stack:ExportsOutputFnGetAttsamplelogGroupA6FE7BF7Arn1ECF63B5"}}
[+] Output Exports/Output{"Ref":"sample2logGroup2B304774"} ExportsOutputRefsample2logGroup2B3047744874A5FB: {"Value":{"Ref":"sample2logGroup2B304774"},"Export":{"Name":"logs-stack:ExportsOutputRefsample2logGroup2B3047744874A5FB"}}
[+] Output Exports/Output{"Fn::GetAtt":["sample2logGroup2B304774","Arn"]} ExportsOutputFnGetAttsample2logGroup2B304774Arn2624143A: {"Value":{"Fn::GetAtt":["sample2logGroup2B304774","Arn"]},"Export":{"Name":"logs-stack:ExportsOutputFnGetAttsample2logGroup2B304774Arn2624143A"}}
対策
自動で生成されるOutputを削除しようとするのが原因です。
保持するようにすれば解決します。
exportValueを使って明示的に定義すれば、変更時にOutputが自動で削除されなくなります。
this.logGroup = {
sample: sampleLog,
sample2: sample2Log
}
// 追加
this.exportValue(sampleLog.logGroupArn)
this.exportValue(sampleLog.logGroupName)
this.exportValue(sample2Log.logGroupArn)
this.exportValue(sample2Log.logGroupName)
上記追加してデプロイしたところ、logGroupを変更できました。
参考 CDK tips, part 3 – how to unblock cross-stack references

AWS CDKのADVANCED WORKSHOPやってみたこんにちは、ちゃりおです。
CDK Pipelineをざっくり試したいと思っていて、なにかいいチュートリアルないかと探していたら。「A...

Github Actionsを使ってCDKを自動デプロイするこんにちは、ちゃりおです。
CDK手動反映だと反映漏れが発生することもあり、今回はGithub Actionsを使ってCDKを自動デプ...

【書評】ITエンジニア的論理思考テクニック!こんにちは、ちゃりおです。
今回紹介する本は、ITエンジニア向けの論理的思考の本です。
論理的思考について書かれた本は山のようにある...