Skip to content

Commit 02e8d58

Browse files
authored
feat(opensearchservice): L2 properties for offPeakWindowOptions and softwareUpdateOptions (#26403)
The [`OffPeakWindowOptions`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_opensearchservice.CfnDomain.OffPeakWindowOptionsProperty.html) and [`SoftwareUpdateOptions`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_opensearchservice.CfnDomain.SoftwareUpdateOptionsProperty.html) are supported by OpenSearch Domain, but not by the CDK high-level construct. This change adds the corresponding properties to the `Domain` construct: ```ts const domain = new Domain(this, 'Domain', { version: EngineVersion.OPENSEARCH_1_3, offPeakWindowEnabled: true, // can be omitted if offPeakWindowStart is set offPeakWindowStart: { hours: 20, minutes: 0, }, enableAutoSoftwareUpdate: true, }); ``` Closes #26388. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 7ddb305 commit 02e8d58

File tree

5 files changed

+256
-1
lines changed

5 files changed

+256
-1
lines changed

Diff for: packages/@aws-cdk-testing/framework-integ/test/aws-opensearchservice/test/integ.opensearch.js.snapshot/cdk-integ-opensearch.template.json

+24
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,18 @@
152152
},
153153
"NodeToNodeEncryptionOptions": {
154154
"Enabled": true
155+
},
156+
"OffPeakWindowOptions": {
157+
"Enabled": true,
158+
"OffPeakWindow": {
159+
"WindowStartTime": {
160+
"Hours": 20,
161+
"Minutes": 0
162+
}
163+
}
164+
},
165+
"SoftwareUpdateOptions": {
166+
"AutoSoftwareUpdateEnabled": true
155167
}
156168
},
157169
"DependsOn": [
@@ -458,6 +470,18 @@
458470
},
459471
"NodeToNodeEncryptionOptions": {
460472
"Enabled": true
473+
},
474+
"OffPeakWindowOptions": {
475+
"Enabled": true,
476+
"OffPeakWindow": {
477+
"WindowStartTime": {
478+
"Hours": 20,
479+
"Minutes": 0
480+
}
481+
}
482+
},
483+
"SoftwareUpdateOptions": {
484+
"AutoSoftwareUpdateEnabled": true
461485
}
462486
},
463487
"DependsOn": [

Diff for: packages/@aws-cdk-testing/framework-integ/test/aws-opensearchservice/test/integ.opensearch.ts

+6
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ class TestStack extends Stack {
4141
capacity: {
4242
multiAzWithStandbyEnabled: false,
4343
},
44+
offPeakWindowEnabled: true,
45+
offPeakWindowStart: {
46+
hours: 20,
47+
minutes: 0,
48+
},
49+
enableAutoSoftwareUpdate: true,
4450
};
4551

4652
// create 2 domains to ensure that Cloudwatch Log Group policy names dont conflict

Diff for: packages/aws-cdk-lib/aws-opensearchservice/README.md

+36
Original file line numberDiff line numberDiff line change
@@ -396,4 +396,40 @@ const domain = new Domain(this, 'Domain', {
396396
dataNodes: 3,
397397
},
398398
});
399+
```
400+
401+
## Define off-peak windows
402+
403+
The domain can be configured to use a daily 10-hour window considered as off-peak hours.
404+
405+
Off-peak windows were introduced on February 16, 2023.
406+
All domains created before this date have the off-peak window disabled by default.
407+
You must manually enable and configure the off-peak window for these domains.
408+
All domains created after this date will have the off-peak window enabled by default.
409+
You can't disable the off-peak window for a domain after it's enabled.
410+
411+
> Visit [Defining off-peak windows for Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/off-peak.html) for more details.
412+
413+
```ts
414+
const domain = new Domain(this, 'Domain', {
415+
version: EngineVersion.OPENSEARCH_1_3,
416+
offPeakWindowEnabled: true, // can be omitted if offPeakWindowStart is set
417+
offPeakWindowStart: {
418+
hours: 20,
419+
minutes: 0,
420+
},
421+
});
422+
```
423+
424+
## Configuring service software updates
425+
426+
The domain can be configured to use service software updates.
427+
428+
> Visit [Service software updates in Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/service-software.html) for more details.
429+
430+
```ts
431+
const domain = new Domain(this, 'Domain', {
432+
version: EngineVersion.OPENSEARCH_1_3,
433+
enableAutoSoftwareUpdate: true,
434+
});
399435
```

Diff for: packages/aws-cdk-lib/aws-opensearchservice/lib/domain.ts

+83-1
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,22 @@ export interface CustomEndpointOptions {
328328
readonly hostedZone?: route53.IHostedZone;
329329
}
330330

331+
export interface WindowStartTime {
332+
/**
333+
* The start hour of the window in Coordinated Universal Time (UTC), using 24-hour time.
334+
* For example, 17 refers to 5:00 P.M. UTC.
335+
*
336+
* @default - 22
337+
*/
338+
readonly hours: number;
339+
/**
340+
* The start minute of the window, in UTC.
341+
*
342+
* @default - 0
343+
*/
344+
readonly minutes: number;
345+
}
346+
331347
/**
332348
* Properties for an Amazon OpenSearch Service domain.
333349
*/
@@ -493,6 +509,7 @@ export interface DomainProps {
493509
* domain resource, use the EnableVersionUpgrade update policy.
494510
*
495511
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html#cfn-attributes-updatepolicy-upgradeopensearchdomain
512+
*
496513
* @default - false
497514
*/
498515
readonly enableVersionUpgrade?: boolean;
@@ -508,9 +525,44 @@ export interface DomainProps {
508525
* To configure a custom domain configure these options
509526
*
510527
* If you specify a Route53 hosted zone it will create a CNAME record and use DNS validation for the certificate
528+
*
511529
* @default - no custom domain endpoint will be configured
512530
*/
513531
readonly customEndpoint?: CustomEndpointOptions;
532+
533+
/**
534+
* Options for enabling a domain's off-peak window, during which OpenSearch Service can perform mandatory
535+
* configuration changes on the domain.
536+
*
537+
* Off-peak windows were introduced on February 16, 2023.
538+
* All domains created before this date have the off-peak window disabled by default.
539+
* You must manually enable and configure the off-peak window for these domains.
540+
* All domains created after this date will have the off-peak window enabled by default.
541+
* You can't disable the off-peak window for a domain after it's enabled.
542+
*
543+
* @see https://docs.aws.amazon.com/it_it/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchservice-domain-offpeakwindow.html
544+
*
545+
* @default - Disabled for domains created before February 16, 2023. Enabled for domains created after. Enabled if `offPeakWindowStart` is set.
546+
*/
547+
readonly offPeakWindowEnabled?: boolean;
548+
549+
/**
550+
* Start time for the off-peak window, in Coordinated Universal Time (UTC).
551+
* The window length will always be 10 hours, so you can't specify an end time.
552+
* For example, if you specify 11:00 P.M. UTC as a start time, the end time will automatically be set to 9:00 A.M.
553+
*
554+
* @default - 10:00 P.M. local time
555+
*/
556+
readonly offPeakWindowStart?: WindowStartTime;
557+
558+
/**
559+
* Specifies whether automatic service software updates are enabled for the domain.
560+
*
561+
* @see https://docs.aws.amazon.com/it_it/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchservice-domain-softwareupdateoptions.html
562+
*
563+
* @default - false
564+
*/
565+
readonly enableAutoSoftwareUpdate?: boolean;
514566
}
515567

516568
/**
@@ -1089,7 +1141,6 @@ abstract class DomainBase extends cdk.Resource implements IDomain {
10891141

10901142
return grant;
10911143
}
1092-
10931144
}
10941145

10951146
/**
@@ -1558,6 +1609,11 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {
15581609
}
15591610
}
15601611

1612+
const offPeakWindowEnabled = props.offPeakWindowEnabled ?? props.offPeakWindowStart !== undefined;
1613+
if (offPeakWindowEnabled) {
1614+
this.validateWindowStartTime(props.offPeakWindowStart);
1615+
}
1616+
15611617
// Create the domain
15621618
this.domain = new CfnDomain(this, 'Resource', {
15631619
domainName: this.physicalName,
@@ -1632,6 +1688,18 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {
16321688
}
16331689
: undefined,
16341690
advancedOptions: props.advancedOptions,
1691+
offPeakWindowOptions: offPeakWindowEnabled ? {
1692+
enabled: offPeakWindowEnabled,
1693+
offPeakWindow: {
1694+
windowStartTime: props.offPeakWindowStart ?? {
1695+
hours: 22,
1696+
minutes: 0,
1697+
},
1698+
},
1699+
} : undefined,
1700+
softwareUpdateOptions: props.enableAutoSoftwareUpdate ? {
1701+
autoSoftwareUpdateEnabled: props.enableAutoSoftwareUpdate,
1702+
} : undefined,
16351703
});
16361704
this.domain.applyRemovalPolicy(props.removalPolicy);
16371705

@@ -1689,6 +1757,20 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {
16891757
}
16901758
}
16911759

1760+
/**
1761+
* Validate windowStartTime property according to
1762+
* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchservice-domain-windowstarttime.html
1763+
*/
1764+
private validateWindowStartTime(windowStartTime?: WindowStartTime) {
1765+
if (!windowStartTime) return;
1766+
if (windowStartTime.hours < 0 || windowStartTime.hours > 23) {
1767+
throw new Error(`Hours must be a value between 0 and 23, but got ${windowStartTime.hours}.`);
1768+
}
1769+
if (windowStartTime.minutes < 0 || windowStartTime.minutes > 59) {
1770+
throw new Error(`Minutes must be a value between 0 and 59, but got ${windowStartTime.minutes}.`);
1771+
}
1772+
}
1773+
16921774
/**
16931775
* Manages network connections to the domain. This will throw an error in case the domain
16941776
* is not placed inside a VPC.

Diff for: packages/aws-cdk-lib/aws-opensearchservice/test/domain.test.ts

+107
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,113 @@ each(testedOpenSearchVersions).describe('cognito dashboards auth', (engineVersio
19801980
});
19811981
});
19821982

1983+
each(testedOpenSearchVersions).describe('offPeakWindow and softwareUpdateOptions', (engineVersion) => {
1984+
test('with offPeakWindowStart and offPeakWindowEnabled', () => {
1985+
new Domain(stack, 'Domain', {
1986+
version: engineVersion,
1987+
offPeakWindowEnabled: true,
1988+
offPeakWindowStart: {
1989+
hours: 10,
1990+
minutes: 30,
1991+
},
1992+
});
1993+
1994+
Template.fromStack(stack).hasResourceProperties('AWS::OpenSearchService::Domain', {
1995+
OffPeakWindowOptions: {
1996+
Enabled: true,
1997+
OffPeakWindow: {
1998+
WindowStartTime: {
1999+
Hours: 10,
2000+
Minutes: 30,
2001+
},
2002+
},
2003+
},
2004+
});
2005+
});
2006+
2007+
test('with offPeakWindowStart only', () => {
2008+
new Domain(stack, 'Domain', {
2009+
version: engineVersion,
2010+
offPeakWindowStart: {
2011+
hours: 10,
2012+
minutes: 30,
2013+
},
2014+
});
2015+
2016+
Template.fromStack(stack).hasResourceProperties('AWS::OpenSearchService::Domain', {
2017+
OffPeakWindowOptions: {
2018+
Enabled: true,
2019+
OffPeakWindow: {
2020+
WindowStartTime: {
2021+
Hours: 10,
2022+
Minutes: 30,
2023+
},
2024+
},
2025+
},
2026+
});
2027+
});
2028+
2029+
test('with offPeakWindowOptions default start time', () => {
2030+
new Domain(stack, 'Domain', {
2031+
version: engineVersion,
2032+
offPeakWindowEnabled: true,
2033+
});
2034+
2035+
Template.fromStack(stack).hasResourceProperties('AWS::OpenSearchService::Domain', {
2036+
OffPeakWindowOptions: {
2037+
Enabled: true,
2038+
OffPeakWindow: {
2039+
WindowStartTime: {
2040+
Hours: 22,
2041+
Minutes: 0,
2042+
},
2043+
},
2044+
},
2045+
});
2046+
});
2047+
2048+
test('with autoSoftwareUpdateEnabled', () => {
2049+
new Domain(stack, 'Domain', {
2050+
version: engineVersion,
2051+
enableAutoSoftwareUpdate: true,
2052+
});
2053+
2054+
Template.fromStack(stack).hasResourceProperties('AWS::OpenSearchService::Domain', {
2055+
SoftwareUpdateOptions: {
2056+
AutoSoftwareUpdateEnabled: true,
2057+
},
2058+
});
2059+
});
2060+
2061+
test('with invalid offPeakWindowStart', () => {
2062+
expect(() => {
2063+
new Domain(stack, 'Domain1', {
2064+
version: engineVersion,
2065+
offPeakWindowEnabled: true,
2066+
offPeakWindowStart: {
2067+
hours: 50,
2068+
minutes: 0,
2069+
},
2070+
});
2071+
}).toThrow(
2072+
/Hours must be a value between 0 and 23/,
2073+
);
2074+
2075+
expect(() => {
2076+
new Domain(stack, 'Domain2', {
2077+
version: engineVersion,
2078+
offPeakWindowEnabled: true,
2079+
offPeakWindowStart: {
2080+
hours: 10,
2081+
minutes: 90,
2082+
},
2083+
});
2084+
}).toThrow(
2085+
/Minutes must be a value between 0 and 59/,
2086+
);
2087+
});
2088+
});
2089+
19832090
function testGrant(
19842091
expectedActions: string[],
19852092
invocation: (user: iam.IPrincipal, domain: Domain) => void,

0 commit comments

Comments
 (0)