aws-ec2: cdk ignores ReplaceAndDelete always policy in the diff output
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 4.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 83
Description
### Describe the bug
Bear with me, as I'm not sure whether this is actually on CloudFormation or CDK side - or in the middle.
I have a `Vpc-Stack` that is defined as follows, that was previously deployed successfully:
```
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
export class VpcStack extends cdk.Stack {
readonly vpc: ec2.Vpc;
readonly dbSecurityGroup: ec2.SecurityGroup;
readonly egressSubnets: ec2.SubnetSelection;
readonly isolatedSubnets: ec2.SubnetSelection;
readonly publicSubnets: ec2.SubnetSelection;
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);
this.vpc = new ec2.Vpc(this, 'Vpc', {
maxAzs: 2,
subnetConfiguration: [
{ cidrMask: 24, name: 'Isolated', subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
{ cidrMask: 24, name: 'Public', subnetType: ec2.SubnetType.PUBLIC },
{ cidrMask: 24, name: 'Egress', subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
],
gatewayEndpoints: {
S3: {
service: ec2.GatewayVpcEndpointAwsService.S3,
},
},
});
this.isolatedSubnets = this.vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_ISOLATED });
this.egressSubnets = this.vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS });
this.publicSubnets = this.vpc.selectSubnets({ subnetType: ec2.SubnetType.PUBLIC });
// Create a Security Group for the db subnet
this.dbSecurityGroup = new ec2.SecurityGroup(this, 'DbSecurityGroup', {
// securityGroupName: 'DbSecurityGroup',
vpc: this.vpc,
description: 'Security group for DB subnet',
});
const bastionHostSG = new ec2.SecurityGroup(this, 'BastionHostSG', {
securityGroupName: 'BastionSecurityGroup',
vpc: this.vpc,
description: 'Security group for BastionHosts',
});
new ec2.BastionHostLinux(this, 'BastionHost', {
vpc: this.vpc,
requireImdsv2: true,
securityGroup: bastionHostSG,
});
// Allow application traffic to DB subnets
this.egressSubnets.subnets!.forEach((subnet) => {
this.dbSecurityGroup.addIngressRule(ec2.Peer.ipv4(subnet.ipv4CidrBlock), ec2.Port.tcp(5432), 'Allow internal PostgreSQL traffic');
this.dbSecurityGroup.addIngressRule(ec2.Peer.ipv4(subnet.ipv4CidrBlock), ec2.Port.tcp(6379), 'Allow internal Redis traffic');
});
}
}
```
Now, today, `cdk diff` showed only CDK metadata that would need a REPLACE:
```
Stack Vpc-Stack
Conditions
[~] Condition CDKMetadata/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"},"il-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"sa-east-1"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-east-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-2"]}]}]} to {"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-northeast-3"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-south-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-3"]}]},{"Fn::Or":[{"Fn::Equals":[{"Ref":"AWS::Region"},"ap-southeast-4"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ca-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"ca-west-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"cn-northwest-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-central-2"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-north-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-south-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"eu-south-2"]}]},{"Fn::Or":[{"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"},"il-central-1"]},{"Fn::Equals":[{"Ref":"AWS::Region"},"me-central-1"]},{"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::Equals":[{"Ref":"AWS::Region"},"us-west-1"]}]},{"Fn::Equals":[{"Ref":"AWS::Region"},"us-west-2"]}]}
start: Building 2575bd4cf5e3931a406f6c71ad10f7e7989285d82ef405e8f330cdc868196e97:current_account-current_region
success: Built 2575bd4cf5e3931a406f6c71ad10f7e7989285d82ef405e8f330cdc868196e97:current_account-current_region
start: Publishing 2575bd4cf5e3931a406f6c71ad10f7e7989285d82ef405e8f330cdc868196e97:current_account-current_region
success: Published 2575bd4cf5e3931a406f6c71ad10f7e7989285d82ef405e8f330cdc868196e97:current_account-current_region
```
However, when doing a subsequent `cdk deploy`, CloudFormation suddenly started to replace an EC2 instance:
```
Vpc-Stack
Vpc-Stack: deploying... [1/5]
Vpc-Stack: creating CloudFormation changeset...
Vpc-Stack | 0/4 | 12:41:01 PM | UPDATE_IN_PROGRESS | AWS::CloudFormation::Stack | Vpc-Stack User Initiated
Vpc-Stack | 0/4 | 12:41:05 PM | UPDATE_IN_PROGRESS | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata)
Vpc-Stack | 1/4 | 12:41:06 PM | UPDATE_COMPLETE | AWS::CDK::Metadata | CDKMetadata/Default (CDKMetadata)
Vpc-Stack | 1/4 | 12:41:07 PM | UPDATE_IN_PROGRESS | AWS::EC2::Instance | BastionHost/Resource (BastionHost30F9ED05) Requested update requires the creation of a new physical resource; hence creating one.
Vpc-Stack | 1/4 | 12:41:08 PM | UPDATE_IN_PROGRESS | AWS::EC2::Instance | BastionHost/Resource (BastionHost30F9ED05) Resource creation Initiated
Vpc-Stack | 2/4 | 12:41:29 PM | UPDATE_COMPLETE | AWS::EC2::Instance | BastionHost/Resource (BastionHost30F9ED05)
Vpc-Stack | 3/4 | 12:41:31 PM | UPDATE_COMPLETE_CLEA | AWS::CloudFormation::Stack | Vpc-Stack
Vpc-Stack | 3/4 | 12:41:32 PM | DELETE_IN_PROGRESS | AWS::EC2::Instance | BastionHost/Resource (BastionHost30F9ED05)
3/4 Currently in progress: Vpc-Stack, BastionHost30F9ED05
Vpc-Stack | 2/4 | 12:42:54 PM | DELETE_COMPLETE | AWS::EC2::Instance | BastionHost/Resource (BastionHost30F9ED05)
Vpc-Stack | 3/4 | 12:42:54 PM | UPDATE_COMPLETE | AWS::CloudFormation::Stack | Vpc-Stack
✅ Vpc-Stack
```
### Regression Issue
- [ ] Select this option if this issue appears to be a regression.
### Last Known Working CDK Version
_No response_
### Expected Behavior
cdk diff should show accurate resource re-creation information.
### Current Behavior
`cdk diff` did not show that an EC2 would be replaced during deployment.
### Reproduction Steps
Code above.
### Possible Solution
_No response_
### Additional Information/Context
```
npm list
cdk@0.1.0
├── @eslint/js@9.16.0
├── @stylistic/eslint-plugin@2.12.0
├── @types/babel__traverse@7.20.6
├── @types/eslint__js@8.42.3
├── @types/js-yaml@4.0.9
├── @types/node@20.17.9
├── @typescript-eslint/eslint-plugin@8.18.0
├── @typescript-eslint/parser@8.18.0
├── aws-cdk-lib@2.172.0
├── aws-cdk@2.172.0
├── cdk-nag@2.34.21
├── cloudwatch-retention-setter@0.0.15
├── constructs@10.4.2
├── eslint-import-resolver-typescript@3.7.0
├── eslint-plugin-import@2.31.0
├── eslint@9.16.0
├── js-yaml@4.1.0
├── source-map-support@0.5.21
├── typescript-eslint@8.18.0
└── typescript@5.7.2
```
### CDK CLI Version
2.172.0 (build 0f666c5)
### Framework Version
_No response_
### Node.js Version
v22.11.0
### OS
MacOS
### Language
TypeScript
### Language Version
_No response_
### Other information
_No response_
Contributor guide
Research direction
Start by reproducing the VpcStack example with CDK CLI and aws-cdk-lib 2.172.0, then compare the cdk diff output with the CloudFormation changeset and deployment events for BastionHost/Resource. Done means cdk diff accurately reports the EC2 instance replacement that deployment performs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, typescript
- Domain
- cloud, infrastructure
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100