Skip to content

Conversation

@gravitylow
Copy link

@gravitylow gravitylow commented Apr 1, 2025

Issue # (if applicable)

Closes #32451

Reason for this change

When creating a Vpc construct and specifying a list of availability zones to use for creating subnets with, passing an empty list causing misleading and confusing errors to happen with other Vpc features. See #32451 for further details and examples.

Description of changes

I added a simple check to throw an error when at least one subnet is going to be created, but the provided availabilityZones to use is empty.

Describe any new or updated permissions being added

N/A

Description of how you validated changes

Added a unit test and confirm it fails with the misleading error message prior to fixing the issue:

% yarn test aws-ec2
...
Summary of all failing tests
 FAIL  aws-ec2/test/vpc.test.ts
  ● vpc › When creating a VPC › throws an error when availabilityZones is empty

    expect(received).toThrow(expected)

    Expected pattern: /At least one availability zone must be configured to create subnets/
    Received message: "There are no 'Private' subnet groups in this VPC. Available types: "

          644 |     if (subnets.length === 0 && !this.incompleteSubnetDefinition) {
          645 |       const availableTypes = Object.entries(allSubnets).filter(([_, subs]) => subs.length > 0).map(([typeName, _]) => typeName);
        > 646 |       throw new Error(`There are no '${subnetType}' subnet groups in this VPC. Available types: ${availableTypes}`);
              |             ^
          647 |     }
          648 |
          649 |     return subnets;

          at Vpc.selectSubnetObjectsByType (aws-ec2/lib/vpc.ts:646:13)
          at Vpc.selectSubnetObjectsByType [as selectSubnetObjects] (aws-ec2/lib/vpc.ts:599:22)
          at Vpc.selectSubnetObjects [as selectSubnets] (aws-ec2/lib/vpc.ts:475:26)
          at selectSubnets (aws-ec2/lib/vpc-endpoint.ts:210:50)
              at Array.map (<anonymous>)
          at new map (aws-ec2/lib/vpc-endpoint.ts:210:31)
          at Vpc.addGatewayEndpoint (aws-ec2/lib/vpc.ts:560:12)
          at new addGatewayEndpoint (aws-ec2/lib/vpc.ts:1692:14)
          at aws-ec2/test/vpc.test.ts:1407:9
          at Object.<anonymous> (../../node_modules/expect/build/toThrowMatchers.js:74:11)
          at Object.throwingMatcher [as toThrow] (../../node_modules/expect/build/index.js:320:21)
          at Object.<anonymous> (aws-ec2/test/vpc.test.ts:1416:10)

      1414 |           },
      1415 |         });
    > 1416 |       }).toThrow(/At least one availability zone must be configured to create subnets/);
           |          ^
      1417 |     });
      1418 |   });
      1419 |

      at Object.<anonymous> (aws-ec2/test/vpc.test.ts:1416:10)


Test Suites: 1 failed, 27 passed, 28 total
Tests:       1 failed, 882 passed, 883 total
Snapshots:   0 total
Time:        6.635 s

Fixed the issue and confirm the test now passes, along with others:

% yarn test aws-ec2
...
Test Suites: 28 passed, 28 total
Tests:       883 passed, 883 total
Snapshots:   0 total
Time:        6.17 s
Ran all test suites matching /aws-ec2/i.
✨  Done in 7.34s.

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@aws-cdk-automation aws-cdk-automation requested a review from a team April 1, 2025 02:35
@github-actions github-actions bot added beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK bug This issue is a bug. effort/small Small work item – less than a day of effort p2 labels Apr 1, 2025
Copy link
Collaborator

@aws-cdk-automation aws-cdk-automation left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pull request linter fails with the following errors:

❌ Fixes must contain a change to an integration test file and the resulting snapshot.

If you believe this pull request should receive an exemption, please comment and provide a justification. A comment requesting an exemption should contain the text Exemption Request. Additionally, if clarification is needed, add Clarification Request to a comment.

✅ A exemption request has been requested. Please wait for a maintainer's review.

@codecov
Copy link

codecov bot commented Apr 1, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 82.39%. Comparing base (be383a9) to head (73ae970).

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #33993   +/-   ##
=======================================
  Coverage   82.39%   82.39%           
=======================================
  Files         120      120           
  Lines        6960     6960           
  Branches     1175     1175           
=======================================
  Hits         5735     5735           
  Misses       1120     1120           
  Partials      105      105           
Flag Coverage Δ
suite.unit 82.39% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
packages/aws-cdk ∅ <ø> (∅)
packages/aws-cdk-lib/core 82.39% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gravitylow gravitylow force-pushed the 32451 branch 2 times, most recently from b34a1b9 to 73ae970 Compare April 1, 2025 02:55
@gravitylow
Copy link
Author

Exemption Request for "Fixes must contain a change to an integration test file and the resulting snapshot." -- the fix involves throwing an error at build time and won't end up deploying a stack. A unit test exercising the behavior of the fix was added.

@aws-cdk-automation aws-cdk-automation added pr-linter/exemption-requested The contributor has requested an exemption to the PR Linter feedback. pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. labels Apr 1, 2025
@shikha372 shikha372 self-assigned this Apr 1, 2025
@shikha372
Copy link
Contributor

shikha372 commented Apr 1, 2025

Thank you @gravitylow for submitting this, while i agree that there should be a validation to check whether the availabilty zones is an empty array or not, i also think it is not a good definition of setting an availability zone as '[]' in the Vpc definition, few concerns that I have to add this validation and if we can verify that this doesn't affect those existing implementations will be good to go:

  1. Case where we have a looked up VPC and in DummyVPC we pass this parameter as [] to import the asymmetric subnets, would like to validate that with throwing error here doesn't impact those implementations.
  2. Same concern to verify this with fromVpcAttributes.
  3. This can break customers who are passing this value as an empty array right now in their stacks and maybe initializing it later, so throwing a warning instead of error would be safest to reduce the impact on such customers. Please let me know if you disagree on any of these concerns.

For the exemption request, we can try running the existing integration test just to confirm that these are working fine along with additional unit tests for the scenario's mentioned above.

@shikha372 shikha372 removed the pr-linter/exemption-requested The contributor has requested an exemption to the PR Linter feedback. label Apr 1, 2025
@aws-cdk-automation aws-cdk-automation removed the pr/needs-community-review This PR needs a review from a Trusted Community Member or Core Team Member. label Apr 1, 2025
@gravitylow
Copy link
Author

gravitylow commented Apr 21, 2025

Hey @shikha372 thanks for your review and feedback. Addressing specific points below:

  1. Vpc.fromLookup does not support availabilityZones as a parameter, but after a VPC has been looked up one can do vpc.selectSubnets to import asymmetric subnets as you indicated. I have added a test to vpc.from-lookup.test.ts to cover this scenario but let me know if I misunderstood your concern.
  2. Vpc.fromAttributes does support availabilityZones, however setting availabilityZones: [] is already not allowed, see the bottom for the exact test case and error message seen when attempting to do this. As a result I did not include this test case in my changes, but can or can include something different again if I misunderstood your concern.
  3. I've changed the error into a warning but feel free to critique the message as I'm not super familiar with the etiquette for warning messages. It would also be great to know if there is an telemetry on warning messages, so that we know if it's safe (and desirable) to change this from a warning to an error in a later release.
  4. I followed the instructions that I could find to run the integ tests, and while the output was happy it was a bit unsatisfying because it seemed nothing changed. I'm not sure if I missed a step, the instructions here were a bit hard for me to follow in terms of what exact steps needed to be taken to run an existing integ test against updated construct code. Let me know if I missed something you were looking for, although now that this has been changed to a warning rather than an error I definitely would not expect any issues here:
adam@Adams-MacBook-Pro framework-integ % yarn integ --directory test/aws-ec2/test
yarn run v1.22.22
$ integ-runner --language javascript --directory test/aws-ec2/test

Verifying integration test snapshots...

  UNCHANGED  integ.import-default-vpc.lit 0.886s
  UNCHANGED  integ.graviton3 1.053s
  UNCHANGED  integ.bastion-host 1.086s
  UNCHANGED  integ.bastion-host-userdatacausesreplacement 1.182s
  UNCHANGED  integ.core-cross-stack-string-list-references 1.178s
  UNCHANGED  integ.instance-ipv6-address-count 1.33s
  UNCHANGED  integ.bastion-host-disable-al2023-feature-flag 1.381s
  UNCHANGED  integ.instance-credit 1.387s
  UNCHANGED  integ.instance-iam-profile 1.383s
  UNCHANGED  integ.instance-ebs-optimized 1.446s
  UNCHANGED  integ.enable-sum-timeout-instance-init 1.485s
  UNCHANGED  integ.instance-init-multiple 1.531s
  UNCHANGED  integ.instance-init 1.596s
  UNCHANGED  integ.instance-disable-api-termination 1.591s
  UNCHANGED  integ.instance-multipart-userdata 1.281s
  UNCHANGED  integ.instance-public 1.063s
  UNCHANGED  integ.instance-public-and-privateip 1.181s
  UNCHANGED  integ.instance 1.122s
  UNCHANGED  integ.instance-placement-group 1.399s
  UNCHANGED  integ.bastion-host-arm-support 2.518s
  UNCHANGED  integ.instance-nitro-enclaves-hibernation 1.54s
  UNCHANGED  integ.launch-template 1.206s
  UNCHANGED  integ.machine-image 1.222s
  UNCHANGED  integ.nat-gateway-provider 1.273s
  UNCHANGED  integ.client-vpn-endpoint 2.823s
  UNCHANGED  integ.key-pair 1.51s
  UNCHANGED  integ.nat-instance-credit 1.505s
  UNCHANGED  integ.placement-group 0.671s
  UNCHANGED  integ.prefix-list-lookup 0.565s
  UNCHANGED  integ.prefix-list 0.676s
  UNCHANGED  integ.nat-instances-v2 1.694s
  UNCHANGED  integ.nat-instances-v2-arm 1.811s
  UNCHANGED  integ.nat-instances-with-public-ip 1.234s
  UNCHANGED  integ.ports 1.066s
  UNCHANGED  integ.share-vpcs.lit 0.915s
  UNCHANGED  integ.nat-instances-v2-custom 1.93s
  UNCHANGED  integ.volume 0.792s
  UNCHANGED  integ.nat-instances.lit 1.379s
  UNCHANGED  integ.reserved-public-subnet 1.114s
  UNCHANGED  integ.vpc-filter-subnets 0.823s
  UNCHANGED  integ.vpc-endpoint-service 1.267s
  UNCHANGED  integ.vpc-global-endpoint 0.797s
  UNCHANGED  integ.vpc-dual-stack 1.405s
  UNCHANGED  integ.reserved-private-subnet 2.013s
  UNCHANGED  integ.vpc-dual-stack-ec2 1.669s
  UNCHANGED  integ.vpc-flow-logs-from-transit-gateway 1.436s
  UNCHANGED  integ.vpc-ipam 1.145s
  UNCHANGED  integ.vpc-azs 2.077s
  UNCHANGED  integ.vpc-flow-logs-customformat 1.603s
  UNCHANGED  integ.vpc-flow-logs-interval 1.528s
  UNCHANGED  integ.vpc-flow-logs-kinesis 1.566s
  UNCHANGED  integ.userdata 2.459s
  UNCHANGED  integ.vpc-flow-logs 1.847s
  UNCHANGED  integ.vpc-reserved-azs 0.844s
  UNCHANGED  integ.vpc-lookup 1.121s
  UNCHANGED  integ.vpc-ipv6 1.344s
  UNCHANGED  integ.vpc-no-default-igw 1.037s
  UNCHANGED  integ.vpc-gateway 1.928s
  UNCHANGED  integ.vpc-endpoint.lit 2.357s
  UNCHANGED  integ.vpc-restrict-default-sg 0.96s
  UNCHANGED  integ.vpn-two-tunnels 0.726s
  UNCHANGED  integ.vpc-networkacl 1.547s
  UNCHANGED  integ.vpn-pre-shared-key-token 1.212s
  UNCHANGED  integ.vpc 1.255s
  UNCHANGED  integ.vpn 1.178s

Snapshot Results:

Tests:    65 passed, 65 total
✨  Done in 6.46s.

For the Vpc.fromAttributes case, I added this test locally:

    test('allows fromVpcAttributes with empty availabilityZones', () => {
      const stack = new Stack();

      Vpc.fromVpcAttributes(stack, 'Vpc', {
        vpcId: 'vpc-1234',
        availabilityZones: [],
      });

      Annotations.fromStack(stack).hasNoWarning('/TestStack/VPC', 'An empty list of availabilityZones was provided. This is probably not intended and may cause errors when configuring subnets (More info: https://github.com/aws/aws-cdk/pull/33993) [ack: @aws-cdk/aws-ec2:emptyVpcAvailabilityZones]');
    });

The unrelated error which is thrown from this test case is:

 FAIL  aws-ec2/test/vpc.test.ts
  ● vpc › fromVpcAttributes › allows fromVpcAttributes with empty availabilityZones

    Number of publicSubnetIds (0) must be a multiple of availability zones (0).

      68 |     if (Math.floor(this.groups) !== this.groups) {
      69 |       // eslint-disable-next-line max-len
    > 70 |       throw new Error(`Number of ${idField} (${this.subnetIds.length}) must be a multiple of availability zones (${this.availabilityZones.length}).`);
         |             ^
      71 |     }

(I am actually not immediately sure if this is desirable behavior, it's a bit of a buggy message since of course 0 is a multiple of 0. But seems to handle the concerning case anyway...)

@shikha372
Copy link
Contributor

Hey @shikha372 thanks for your review and feedback. Addressing specific points below:

  1. Vpc.fromLookup does not support availabilityZones as a parameter, but after a VPC has been looked up one can do vpc.selectSubnets to import asymmetric subnets as you indicated. I have added a test to vpc.from-lookup.test.ts to cover this scenario but let me know if I misunderstood your concern.
  2. Vpc.fromAttributes does support availabilityZones, however setting availabilityZones: [] is already not allowed, see the bottom for the exact test case and error message seen when attempting to do this. As a result I did not include this test case in my changes, but can or can include something different again if I misunderstood your concern.
  3. I've changed the error into a warning but feel free to critique the message as I'm not super familiar with the etiquette for warning messages. It would also be great to know if there is an telemetry on warning messages, so that we know if it's safe (and desirable) to change this from a warning to an error in a later release.
  4. I followed the instructions that I could find to run the integ tests, and while the output was happy it was a bit unsatisfying because it seemed nothing changed. I'm not sure if I missed a step, the instructions here were a bit hard for me to follow in terms of what exact steps needed to be taken to run an existing integ test against updated construct code. Let me know if I missed something you were looking for, although now that this has been changed to a warning rather than an error I definitely would not expect any issues here:
adam@Adams-MacBook-Pro framework-integ % yarn integ --directory test/aws-ec2/test
yarn run v1.22.22
$ integ-runner --language javascript --directory test/aws-ec2/test

Verifying integration test snapshots...

  UNCHANGED  integ.import-default-vpc.lit 0.886s
  UNCHANGED  integ.graviton3 1.053s
  UNCHANGED  integ.bastion-host 1.086s
  UNCHANGED  integ.bastion-host-userdatacausesreplacement 1.182s
  UNCHANGED  integ.core-cross-stack-string-list-references 1.178s
  UNCHANGED  integ.instance-ipv6-address-count 1.33s
  UNCHANGED  integ.bastion-host-disable-al2023-feature-flag 1.381s
  UNCHANGED  integ.instance-credit 1.387s
  UNCHANGED  integ.instance-iam-profile 1.383s
  UNCHANGED  integ.instance-ebs-optimized 1.446s
  UNCHANGED  integ.enable-sum-timeout-instance-init 1.485s
  UNCHANGED  integ.instance-init-multiple 1.531s
  UNCHANGED  integ.instance-init 1.596s
  UNCHANGED  integ.instance-disable-api-termination 1.591s
  UNCHANGED  integ.instance-multipart-userdata 1.281s
  UNCHANGED  integ.instance-public 1.063s
  UNCHANGED  integ.instance-public-and-privateip 1.181s
  UNCHANGED  integ.instance 1.122s
  UNCHANGED  integ.instance-placement-group 1.399s
  UNCHANGED  integ.bastion-host-arm-support 2.518s
  UNCHANGED  integ.instance-nitro-enclaves-hibernation 1.54s
  UNCHANGED  integ.launch-template 1.206s
  UNCHANGED  integ.machine-image 1.222s
  UNCHANGED  integ.nat-gateway-provider 1.273s
  UNCHANGED  integ.client-vpn-endpoint 2.823s
  UNCHANGED  integ.key-pair 1.51s
  UNCHANGED  integ.nat-instance-credit 1.505s
  UNCHANGED  integ.placement-group 0.671s
  UNCHANGED  integ.prefix-list-lookup 0.565s
  UNCHANGED  integ.prefix-list 0.676s
  UNCHANGED  integ.nat-instances-v2 1.694s
  UNCHANGED  integ.nat-instances-v2-arm 1.811s
  UNCHANGED  integ.nat-instances-with-public-ip 1.234s
  UNCHANGED  integ.ports 1.066s
  UNCHANGED  integ.share-vpcs.lit 0.915s
  UNCHANGED  integ.nat-instances-v2-custom 1.93s
  UNCHANGED  integ.volume 0.792s
  UNCHANGED  integ.nat-instances.lit 1.379s
  UNCHANGED  integ.reserved-public-subnet 1.114s
  UNCHANGED  integ.vpc-filter-subnets 0.823s
  UNCHANGED  integ.vpc-endpoint-service 1.267s
  UNCHANGED  integ.vpc-global-endpoint 0.797s
  UNCHANGED  integ.vpc-dual-stack 1.405s
  UNCHANGED  integ.reserved-private-subnet 2.013s
  UNCHANGED  integ.vpc-dual-stack-ec2 1.669s
  UNCHANGED  integ.vpc-flow-logs-from-transit-gateway 1.436s
  UNCHANGED  integ.vpc-ipam 1.145s
  UNCHANGED  integ.vpc-azs 2.077s
  UNCHANGED  integ.vpc-flow-logs-customformat 1.603s
  UNCHANGED  integ.vpc-flow-logs-interval 1.528s
  UNCHANGED  integ.vpc-flow-logs-kinesis 1.566s
  UNCHANGED  integ.userdata 2.459s
  UNCHANGED  integ.vpc-flow-logs 1.847s
  UNCHANGED  integ.vpc-reserved-azs 0.844s
  UNCHANGED  integ.vpc-lookup 1.121s
  UNCHANGED  integ.vpc-ipv6 1.344s
  UNCHANGED  integ.vpc-no-default-igw 1.037s
  UNCHANGED  integ.vpc-gateway 1.928s
  UNCHANGED  integ.vpc-endpoint.lit 2.357s
  UNCHANGED  integ.vpc-restrict-default-sg 0.96s
  UNCHANGED  integ.vpn-two-tunnels 0.726s
  UNCHANGED  integ.vpc-networkacl 1.547s
  UNCHANGED  integ.vpn-pre-shared-key-token 1.212s
  UNCHANGED  integ.vpc 1.255s
  UNCHANGED  integ.vpn 1.178s

Snapshot Results:

Tests:    65 passed, 65 total
✨  Done in 6.46s.

For the Vpc.fromAttributes case, I added this test locally:

    test('allows fromVpcAttributes with empty availabilityZones', () => {
      const stack = new Stack();

      Vpc.fromVpcAttributes(stack, 'Vpc', {
        vpcId: 'vpc-1234',
        availabilityZones: [],
      });

      Annotations.fromStack(stack).hasNoWarning('/TestStack/VPC', 'An empty list of availabilityZones was provided. This is probably not intended and may cause errors when configuring subnets (More info: [https://github.com/aws/aws-cdk/pull/33993
    
        
            
                
                
                
            
        
        
    ](https://github.com/aws/aws-cdk/pull/33993)) [ack: @aws-cdk/aws-ec2:emptyVpcAvailabilityZones]');
    });

The unrelated error which is thrown from this test case is:

 FAIL  aws-ec2/test/vpc.test.ts
  ● vpc › fromVpcAttributes › allows fromVpcAttributes with empty availabilityZones

    Number of publicSubnetIds (0) must be a multiple of availability zones (0).

      68 |     if (Math.floor(this.groups) !== this.groups) {
      69 |       // eslint-disable-next-line max-len
    > 70 |       throw new Error(`Number of ${idField} (${this.subnetIds.length}) must be a multiple of availability zones (${this.availabilityZones.length}).`);
         |             ^
      71 |     }

(I am actually not immediately sure if this is desirable behavior, it's a bit of a buggy message since of course 0 is a multiple of 0. But seems to handle the concerning case anyway...)

Thank you @gravitylow , changing this to a warning should not result in any snapshot changes and is least intrusive as well,
you got my concern right i just wanted to make sure that this is a non-breaking change for the two cases vpc.fromLookup which returns an empty AZ value during first synthesis (i'll double check at my end as well) and for Vpc.fromAttributes which makes sense that it is already not allowed.

@aws-cdk-automation
Copy link
Collaborator

This PR has been in the CHANGES REQUESTED state for 3 weeks, and looks abandoned. Note that PRs with failing linting check or builds are not reviewed, please ensure your build is passing

To prevent automatic closure:

  • Resume work on the PR
  • OR request an exemption by adding a comment containing 'Exemption Request' with justification e.x "Exemption Request: "
  • OR request clarification by adding a comment containing 'Clarification Request' with a question e.x "Clarification Request: "

This PR will automatically close in 14 days if no action is taken.

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildv2Project1C6BFA3F-wQm2hXv2jqQv
  • Commit ID: fec5289
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@gravitylow
Copy link
Author

Thanks for making the requested change to the warning message. Please let me know if there are any outstanding actions on my side and I'll be happy to address them.

@aws-cdk-automation
Copy link
Collaborator

This PR has been deemed to be abandoned, and will be automatically closed. Please create a new PR for these changes if you think this decision has been made in error.

@aws-cdk-automation aws-cdk-automation added the closed-for-staleness This issue was automatically closed because it hadn't received any attention in a while. label May 8, 2025
@github-actions
Copy link
Contributor

github-actions bot commented May 8, 2025

Comments on closed issues and PRs are hard for our team to see.
If you need help, please open a new issue that references this one.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 8, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK bug This issue is a bug. closed-for-staleness This issue was automatically closed because it hadn't received any attention in a while. effort/small Small work item – less than a day of effort p2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(aws-cdk-lib/aws-ec2): Misleading error "There are no <SubnetType> subnet groups in this VPC. Available types:" when no availability zones are provided

3 participants