Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(opensearch): correctly validate ebs configuration against instance types #16911

Merged
7 changes: 3 additions & 4 deletions packages/@aws-cdk/aws-elasticsearch/lib/domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1403,9 +1403,8 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {
return instanceTypes.some(isInstanceType);
};

function isEveryInstanceType(...instanceTypes: string[]): Boolean {
return instanceTypes.some(t => dedicatedMasterType.startsWith(t))
&& instanceTypes.some(t => instanceType.startsWith(t));
function isEveryDatanodeInstanceType(...instanceTypes: string[]): Boolean {
return instanceTypes.some(t => instanceType.startsWith(t));
};

// Validate feature support for the given Elasticsearch version, per
Expand Down Expand Up @@ -1464,7 +1463,7 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {

// Only R3, I3 and r6gd support instance storage, per
// https://aws.amazon.com/elasticsearch-service/pricing/
if (!ebsEnabled && !isEveryInstanceType('r3', 'i3', 'r6gd')) {
if (!ebsEnabled && !isEveryDatanodeInstanceType('r3', 'i3', 'r6gd')) {
throw new Error('EBS volumes are required when using instance types other than r3, i3 or r6gd.');
}

Expand Down
47 changes: 46 additions & 1 deletion packages/@aws-cdk/aws-elasticsearch/test/domain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1437,7 +1437,7 @@ describe('custom error responses', () => {
})).toThrow(/Node-to-node encryption requires Elasticsearch version 6.0 or later/);
});

test('error when i3 instance types are specified with EBS enabled', () => {
test('error when i3 or r6g instance types are specified with EBS enabled', () => {
expect(() => new Domain(stack, 'Domain1', {
version: ElasticsearchVersion.V7_4,
capacity: {
Expand All @@ -1448,6 +1448,16 @@ describe('custom error responses', () => {
volumeType: EbsDeviceVolumeType.GENERAL_PURPOSE_SSD,
},
})).toThrow(/I3 and R6GD instance types do not support EBS storage volumes/);
expect(() => new Domain(stack, 'Domain2', {
version: ElasticsearchVersion.V7_4,
capacity: {
dataNodeInstanceType: 'r6gd.large.elasticsearch',
},
ebs: {
volumeSize: 100,
volumeType: EbsDeviceVolumeType.GENERAL_PURPOSE_SSD,
},
})).toThrow(/I3 and R6GD instance types do not support EBS storage volumes/);
});

test('error when m3, r3, or t2 instance types are specified with encryption at rest enabled', () => {
Expand Down Expand Up @@ -1500,6 +1510,41 @@ describe('custom error responses', () => {
masterNodeInstanceType: 'm5.large.elasticsearch',
},
})).toThrow(/EBS volumes are required when using instance types other than r3, i3 or r6gd/);
expect(() => new Domain(stack, 'Domain2', {
version: ElasticsearchVersion.V7_4,
ebs: {
enabled: false,
},
capacity: {
dataNodeInstanceType: 'm5.large.elasticsearch',
},
})).toThrow(/EBS volumes are required when using instance types other than r3, i3 or r6gd/);
});

test('can use compatible master instance types that does not have local storage when data node type is i3 or r6gd', () => {
new Domain(stack, 'Domain1', {
version: ElasticsearchVersion.V7_4,
ebs: {
enabled: false,
},
capacity: {
masterNodeInstanceType: 'c5.2xlarge.elasticsearch',
dataNodeInstanceType: 'i3.2xlarge.elasticsearch',
},
});
new Domain(stack, 'Domain2', {
version: ElasticsearchVersion.V7_4,
ebs: {
enabled: false,
},
capacity: {
masterNodes: 3,
masterNodeInstanceType: 'c6g.large.elasticsearch',
dataNodeInstanceType: 'r6gd.large.elasticsearch',
},
});
// both configurations pass synth-time validation
expect(stack).toCountResources('AWS::Elasticsearch::Domain', 2);
kaizencc marked this conversation as resolved.
Show resolved Hide resolved
});

test('error when availabilityZoneCount is not 2 or 3', () => {
Expand Down
7 changes: 3 additions & 4 deletions packages/@aws-cdk/aws-opensearchservice/lib/domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1320,9 +1320,8 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {
return instanceTypes.some(isInstanceType);
};

function isEveryInstanceType(...instanceTypes: string[]): Boolean {
return instanceTypes.some(t => dedicatedMasterType.startsWith(t))
&& instanceTypes.some(t => instanceType.startsWith(t));
function isEveryDatanodeInstanceType(...instanceTypes: string[]): Boolean {
return instanceTypes.some(t => instanceType.startsWith(t));
};

// Validate feature support for the given Elasticsearch/OpenSearch version, per
Expand Down Expand Up @@ -1396,7 +1395,7 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {

// Only R3, I3 and r6gd support instance storage, per
// https://aws.amazon.com/opensearch-service/pricing/
if (!ebsEnabled && !isEveryInstanceType('r3', 'i3', 'r6gd')) {
if (!ebsEnabled && !isEveryDatanodeInstanceType('r3', 'i3', 'r6gd')) {
throw new Error('EBS volumes are required when using instance types other than r3, i3 or r6gd.');
}

Expand Down
47 changes: 46 additions & 1 deletion packages/@aws-cdk/aws-opensearchservice/test/domain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1439,7 +1439,7 @@ describe('custom error responses', () => {
})).toThrow(/Node-to-node encryption requires Elasticsearch version 6.0 or later or OpenSearch version 1.0 or later/);
});

test('error when i3 instance types are specified with EBS enabled', () => {
test('error when i3 or r6g instance types are specified with EBS enabled', () => {
expect(() => new Domain(stack, 'Domain1', {
version: defaultVersion,
capacity: {
Expand All @@ -1450,6 +1450,16 @@ describe('custom error responses', () => {
volumeType: EbsDeviceVolumeType.GENERAL_PURPOSE_SSD,
},
})).toThrow(/I3 and R6GD instance types do not support EBS storage volumes/);
expect(() => new Domain(stack, 'Domain2', {
version: defaultVersion,
capacity: {
dataNodeInstanceType: 'r6gd.large.search',
},
ebs: {
volumeSize: 100,
volumeType: EbsDeviceVolumeType.GENERAL_PURPOSE_SSD,
},
})).toThrow(/I3 and R6GD instance types do not support EBS storage volumes/);
});

test('error when m3, r3, or t2 instance types are specified with encryption at rest enabled', () => {
Expand Down Expand Up @@ -1502,6 +1512,41 @@ describe('custom error responses', () => {
masterNodeInstanceType: 'm5.large.search',
},
})).toThrow(/EBS volumes are required when using instance types other than r3, i3 or r6gd/);
expect(() => new Domain(stack, 'Domain2', {
version: defaultVersion,
ebs: {
enabled: false,
},
capacity: {
dataNodeInstanceType: 'm5.large.search',
},
})).toThrow(/EBS volumes are required when using instance types other than r3, i3 or r6gd/);
});

test('can use compatible master instance types that does not have local storage when data node type is i3 or r6gd', () => {
new Domain(stack, 'Domain1', {
version: defaultVersion,
ebs: {
enabled: false,
},
capacity: {
masterNodeInstanceType: 'c5.2xlarge.search',
dataNodeInstanceType: 'i3.2xlarge.search',
},
});
new Domain(stack, 'Domain2', {
version: defaultVersion,
ebs: {
enabled: false,
},
capacity: {
masterNodes: 3,
masterNodeInstanceType: 'c6g.large.search',
dataNodeInstanceType: 'r6gd.large.search',
},
});
// both configurations pass synth-time validation
expect(stack).toCountResources('AWS::OpenSearchService::Domain', 2);
kaizencc marked this conversation as resolved.
Show resolved Hide resolved
});

test('error when availabilityZoneCount is not 2 or 3', () => {
Expand Down