I've been using CDK for some long time, and I'm upgrading all my stacks from version 1 to version 2
I have base stacks with network, subnets, etc. and then on top of that, I have other stacks with different resources, rds, ec2, ecs, etc.
On CDK 1, the cloudformation template generated with CDK was:
"AvailabilityZone": {
"Fn::Select": [
0,
{
"Fn::GetAZs": ""
}
]
},
On CDK2, it changed to:
"AvailabilityZone": "us-east-1a",
on the cdk diff the change is easily visible:
[~] AWS::EC2::Subnet RodAccountDBVPC/RodSubnet1/Subnet
MySubnetAAAAA02A replace
└─ [~] AvailabilityZone (requires replacement)
└─ @@ -1,8 +1,1 @@
[-] {
[-] "Fn::Select": [
[-] 0,
[-] {
[-] "Fn::GetAZs": ""
[-] }
[-] ]
[-] }
[+] "us-east-1a"
and on deploy it fails, because it is trying to replace the already existant Subnets that already have a lot of resources on them:
10:38:55 PM | CREATE_FAILED | AWS::EC2::Subnet | RodAccount...net3SubnetBBBBBBBB
Resource handler returned message: "The CIDR '172.10.16.0/26' conflicts with another subnet (Service: Ec2, Status Code: 400, Request ID: 2caaaa4e-a141-43f0-bb18-aaab745872d5)"
(RequestToken: 9baaaaa0-9488-2cd7-6ed0-aaa521b8417c, HandlerErrorCode: AlreadyExists)
so the question is, on CDK 2, is there a way I can set the availability zone to use a cloudformation Fn::Select
function, instead of the hardcoded string zone that it is trying to set now?
the code where I defined the VPC:
const vpc = new ec2.Vpc(this, 'RodAccountDBVPC', {
ipAddresses: ec2.IpAddresses.cidr(this.config['172.10.0.0/20']),
subnetConfiguration: [
{
cidrMask: 26,
name: 'RDS',
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
},
{
cidrMask: 26,
name: 'PublicNetwork',
subnetType: ec2.SubnetType.PUBLIC,
}
],
natGateways: 1,
});
We had the same issue during our upgrade from CDKv1 to CDKv2. The stack was initially created without a specific region and the region was later added, but the stack was never deployed since then.
You'll probably see something like this after running cdk diff
:
Conditions
[-] Condition CDKMetadataAvailable: {"Fn::Or":[{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"af-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-northeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ca-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-northwest-1"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-west-3"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"sa-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-2"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-2"]}]}]}
You need to remove the hardcoded region
from the env
in your bin/stack.ts
file
env: { account: "1234567890", region: "eu-central-1" }
Thanks to gshpychka and a colleague who pointed me in the right direction.