Skip to content

Commit 6a28b7f

Browse files
fix(opensearch): Don't throw a Az count mismatch for imported VPCs (#22654)
Solving issue #22651 Creating a domain fails for imported vpc/subnets when zone awareness is enabled and the cdk context is cleared. When the CDK context is already retrieved and the VPC is in the context, the deployment works. This is due to the fact that when there is no context yet, the subnet count is always 0. That's why I decided to disable it. If it's not correct, it will fail when applying the CloudFormation template. ---- ### All Submissions: * [X] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 813c2f1 commit 6a28b7f

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

packages/@aws-cdk/aws-opensearchservice/lib/domain.ts

+26-3
Original file line numberDiff line numberDiff line change
@@ -1235,8 +1235,11 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {
12351235
let securityGroups: ec2.ISecurityGroup[] | undefined;
12361236
let subnets: ec2.ISubnet[] | undefined;
12371237

1238+
let skipZoneAwarenessCheck: boolean = false;
12381239
if (props.vpc) {
1239-
subnets = selectSubnets(props.vpc, props.vpcSubnets ?? [{ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }]);
1240+
const subnetSelections = props.vpcSubnets ?? [{ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }];
1241+
subnets = selectSubnets(props.vpc, subnetSelections);
1242+
skipZoneAwarenessCheck = zoneAwarenessCheckShouldBeSkipped(props.vpc, subnetSelections);
12401243
securityGroups = props.securityGroups ?? [new ec2.SecurityGroup(this, 'SecurityGroup', {
12411244
vpc: props.vpc,
12421245
description: `Security group for domain ${this.node.id}`,
@@ -1248,8 +1251,12 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {
12481251
}
12491252
}
12501253

1251-
// If VPC options are supplied ensure that the number of subnets matches the number AZ
1252-
if (subnets && zoneAwarenessEnabled && new Set(subnets.map((subnet) => subnet.availabilityZone)).size < availabilityZoneCount) {
1254+
// If VPC options are supplied ensure that the number of subnets matches the number AZ (only if the vpc is not imported from another stack)
1255+
if (subnets &&
1256+
zoneAwarenessEnabled &&
1257+
!skipZoneAwarenessCheck &&
1258+
new Set(subnets.map((subnet) => subnet.availabilityZone)).size < availabilityZoneCount
1259+
) {
12531260
throw new Error('When providing vpc options you need to provide a subnet for each AZ you are using');
12541261
}
12551262

@@ -1776,6 +1783,22 @@ function selectSubnets(vpc: ec2.IVpc, vpcSubnets: ec2.SubnetSelection[]): ec2.IS
17761783
return selected;
17771784
}
17781785

1786+
/**
1787+
* Check if any of the subnets are pending lookups. If so, the zone awareness check should be skipped, otherwise it will always throw an error
1788+
*
1789+
* @param vpc The vpc to which the subnets apply
1790+
* @param vpcSubnets The vpc subnets that should be checked
1791+
* @returns true if there are pending lookups for the subnets
1792+
*/
1793+
function zoneAwarenessCheckShouldBeSkipped(vpc: ec2.IVpc, vpcSubnets: ec2.SubnetSelection[]): boolean {
1794+
for (const selection of vpcSubnets) {
1795+
if (vpc.selectSubnets(selection).isPendingLookup) {
1796+
return true;
1797+
};
1798+
}
1799+
return false;
1800+
}
1801+
17791802
/**
17801803
* Initializes an instance type.
17811804
*

packages/@aws-cdk/aws-opensearchservice/test/domain.test.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { Match, Template } from '@aws-cdk/assertions';
33
import * as acm from '@aws-cdk/aws-certificatemanager';
44
import { Metric, Statistic } from '@aws-cdk/aws-cloudwatch';
5-
import { Vpc, EbsDeviceVolumeType, Port, SecurityGroup } from '@aws-cdk/aws-ec2';
5+
import { Vpc, EbsDeviceVolumeType, Port, SecurityGroup, SubnetType } from '@aws-cdk/aws-ec2';
66
import * as iam from '@aws-cdk/aws-iam';
77
import * as kms from '@aws-cdk/aws-kms';
88
import * as logs from '@aws-cdk/aws-logs';
@@ -1406,6 +1406,27 @@ describe('custom error responses', () => {
14061406
})).toThrow(/you need to provide a subnet for each AZ you are using/);
14071407
});
14081408

1409+
test('Imported VPC with subnets that are still pending lookup won\'t throw Az count mismatch', () => {
1410+
const vpc = Vpc.fromLookup(stack, 'ExampleVpc', {
1411+
vpcId: 'vpc-123',
1412+
});
1413+
let subnets = vpc.selectSubnets({
1414+
subnetType: SubnetType.PRIVATE_WITH_EGRESS,
1415+
});
1416+
1417+
new Domain(stack, 'Domain1', {
1418+
version: defaultVersion,
1419+
vpc,
1420+
vpcSubnets: [subnets],
1421+
zoneAwareness: {
1422+
enabled: true,
1423+
availabilityZoneCount: 3,
1424+
},
1425+
});
1426+
1427+
Template.fromStack(stack).resourceCountIs('AWS::OpenSearchService::Domain', 1);
1428+
});
1429+
14091430
test('error when master, data or Ultra Warm instance types do not end with .search', () => {
14101431
const error = /instance types must end with ".search"/;
14111432
expect(() => new Domain(stack, 'Domain1', {

0 commit comments

Comments
 (0)