Skip to content

Commit

Permalink
feat(opensearchservice): L2 properties for offPeakWindowOptions and s…
Browse files Browse the repository at this point in the history
…oftwareUpdateOptions (#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*
  • Loading branch information
lpizzinidev committed Jul 27, 2023
1 parent 7ddb305 commit 02e8d58
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@
},
"NodeToNodeEncryptionOptions": {
"Enabled": true
},
"OffPeakWindowOptions": {
"Enabled": true,
"OffPeakWindow": {
"WindowStartTime": {
"Hours": 20,
"Minutes": 0
}
}
},
"SoftwareUpdateOptions": {
"AutoSoftwareUpdateEnabled": true
}
},
"DependsOn": [
Expand Down Expand Up @@ -458,6 +470,18 @@
},
"NodeToNodeEncryptionOptions": {
"Enabled": true
},
"OffPeakWindowOptions": {
"Enabled": true,
"OffPeakWindow": {
"WindowStartTime": {
"Hours": 20,
"Minutes": 0
}
}
},
"SoftwareUpdateOptions": {
"AutoSoftwareUpdateEnabled": true
}
},
"DependsOn": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ class TestStack extends Stack {
capacity: {
multiAzWithStandbyEnabled: false,
},
offPeakWindowEnabled: true,
offPeakWindowStart: {
hours: 20,
minutes: 0,
},
enableAutoSoftwareUpdate: true,
};

// create 2 domains to ensure that Cloudwatch Log Group policy names dont conflict
Expand Down
36 changes: 36 additions & 0 deletions packages/aws-cdk-lib/aws-opensearchservice/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -396,4 +396,40 @@ const domain = new Domain(this, 'Domain', {
dataNodes: 3,
},
});
```

## Define off-peak windows

The domain can be configured to use a daily 10-hour window considered as off-peak hours.

Off-peak windows were introduced on February 16, 2023.
All domains created before this date have the off-peak window disabled by default.
You must manually enable and configure the off-peak window for these domains.
All domains created after this date will have the off-peak window enabled by default.
You can't disable the off-peak window for a domain after it's enabled.

> Visit [Defining off-peak windows for Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/off-peak.html) for more details.
```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,
},
});
```

## Configuring service software updates

The domain can be configured to use service software updates.

> Visit [Service software updates in Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/service-software.html) for more details.
```ts
const domain = new Domain(this, 'Domain', {
version: EngineVersion.OPENSEARCH_1_3,
enableAutoSoftwareUpdate: true,
});
```
84 changes: 83 additions & 1 deletion packages/aws-cdk-lib/aws-opensearchservice/lib/domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,22 @@ export interface CustomEndpointOptions {
readonly hostedZone?: route53.IHostedZone;
}

export interface WindowStartTime {
/**
* The start hour of the window in Coordinated Universal Time (UTC), using 24-hour time.
* For example, 17 refers to 5:00 P.M. UTC.
*
* @default - 22
*/
readonly hours: number;
/**
* The start minute of the window, in UTC.
*
* @default - 0
*/
readonly minutes: number;
}

/**
* Properties for an Amazon OpenSearch Service domain.
*/
Expand Down Expand Up @@ -493,6 +509,7 @@ export interface DomainProps {
* domain resource, use the EnableVersionUpgrade update policy.
*
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-updatepolicy.html#cfn-attributes-updatepolicy-upgradeopensearchdomain
*
* @default - false
*/
readonly enableVersionUpgrade?: boolean;
Expand All @@ -508,9 +525,44 @@ export interface DomainProps {
* To configure a custom domain configure these options
*
* If you specify a Route53 hosted zone it will create a CNAME record and use DNS validation for the certificate
*
* @default - no custom domain endpoint will be configured
*/
readonly customEndpoint?: CustomEndpointOptions;

/**
* Options for enabling a domain's off-peak window, during which OpenSearch Service can perform mandatory
* configuration changes on the domain.
*
* Off-peak windows were introduced on February 16, 2023.
* All domains created before this date have the off-peak window disabled by default.
* You must manually enable and configure the off-peak window for these domains.
* All domains created after this date will have the off-peak window enabled by default.
* You can't disable the off-peak window for a domain after it's enabled.
*
* @see https://docs.aws.amazon.com/it_it/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchservice-domain-offpeakwindow.html
*
* @default - Disabled for domains created before February 16, 2023. Enabled for domains created after. Enabled if `offPeakWindowStart` is set.
*/
readonly offPeakWindowEnabled?: boolean;

/**
* Start time for the off-peak window, in Coordinated Universal Time (UTC).
* The window length will always be 10 hours, so you can't specify an end time.
* 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.
*
* @default - 10:00 P.M. local time
*/
readonly offPeakWindowStart?: WindowStartTime;

/**
* Specifies whether automatic service software updates are enabled for the domain.
*
* @see https://docs.aws.amazon.com/it_it/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchservice-domain-softwareupdateoptions.html
*
* @default - false
*/
readonly enableAutoSoftwareUpdate?: boolean;
}

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

return grant;
}

}

/**
Expand Down Expand Up @@ -1558,6 +1609,11 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {
}
}

const offPeakWindowEnabled = props.offPeakWindowEnabled ?? props.offPeakWindowStart !== undefined;
if (offPeakWindowEnabled) {
this.validateWindowStartTime(props.offPeakWindowStart);
}

// Create the domain
this.domain = new CfnDomain(this, 'Resource', {
domainName: this.physicalName,
Expand Down Expand Up @@ -1632,6 +1688,18 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {
}
: undefined,
advancedOptions: props.advancedOptions,
offPeakWindowOptions: offPeakWindowEnabled ? {
enabled: offPeakWindowEnabled,
offPeakWindow: {
windowStartTime: props.offPeakWindowStart ?? {
hours: 22,
minutes: 0,
},
},
} : undefined,
softwareUpdateOptions: props.enableAutoSoftwareUpdate ? {
autoSoftwareUpdateEnabled: props.enableAutoSoftwareUpdate,
} : undefined,
});
this.domain.applyRemovalPolicy(props.removalPolicy);

Expand Down Expand Up @@ -1689,6 +1757,20 @@ export class Domain extends DomainBase implements IDomain, ec2.IConnectable {
}
}

/**
* Validate windowStartTime property according to
* https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-opensearchservice-domain-windowstarttime.html
*/
private validateWindowStartTime(windowStartTime?: WindowStartTime) {
if (!windowStartTime) return;
if (windowStartTime.hours < 0 || windowStartTime.hours > 23) {
throw new Error(`Hours must be a value between 0 and 23, but got ${windowStartTime.hours}.`);
}
if (windowStartTime.minutes < 0 || windowStartTime.minutes > 59) {
throw new Error(`Minutes must be a value between 0 and 59, but got ${windowStartTime.minutes}.`);
}
}

/**
* Manages network connections to the domain. This will throw an error in case the domain
* is not placed inside a VPC.
Expand Down
107 changes: 107 additions & 0 deletions packages/aws-cdk-lib/aws-opensearchservice/test/domain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1980,6 +1980,113 @@ each(testedOpenSearchVersions).describe('cognito dashboards auth', (engineVersio
});
});

each(testedOpenSearchVersions).describe('offPeakWindow and softwareUpdateOptions', (engineVersion) => {
test('with offPeakWindowStart and offPeakWindowEnabled', () => {
new Domain(stack, 'Domain', {
version: engineVersion,
offPeakWindowEnabled: true,
offPeakWindowStart: {
hours: 10,
minutes: 30,
},
});

Template.fromStack(stack).hasResourceProperties('AWS::OpenSearchService::Domain', {
OffPeakWindowOptions: {
Enabled: true,
OffPeakWindow: {
WindowStartTime: {
Hours: 10,
Minutes: 30,
},
},
},
});
});

test('with offPeakWindowStart only', () => {
new Domain(stack, 'Domain', {
version: engineVersion,
offPeakWindowStart: {
hours: 10,
minutes: 30,
},
});

Template.fromStack(stack).hasResourceProperties('AWS::OpenSearchService::Domain', {
OffPeakWindowOptions: {
Enabled: true,
OffPeakWindow: {
WindowStartTime: {
Hours: 10,
Minutes: 30,
},
},
},
});
});

test('with offPeakWindowOptions default start time', () => {
new Domain(stack, 'Domain', {
version: engineVersion,
offPeakWindowEnabled: true,
});

Template.fromStack(stack).hasResourceProperties('AWS::OpenSearchService::Domain', {
OffPeakWindowOptions: {
Enabled: true,
OffPeakWindow: {
WindowStartTime: {
Hours: 22,
Minutes: 0,
},
},
},
});
});

test('with autoSoftwareUpdateEnabled', () => {
new Domain(stack, 'Domain', {
version: engineVersion,
enableAutoSoftwareUpdate: true,
});

Template.fromStack(stack).hasResourceProperties('AWS::OpenSearchService::Domain', {
SoftwareUpdateOptions: {
AutoSoftwareUpdateEnabled: true,
},
});
});

test('with invalid offPeakWindowStart', () => {
expect(() => {
new Domain(stack, 'Domain1', {
version: engineVersion,
offPeakWindowEnabled: true,
offPeakWindowStart: {
hours: 50,
minutes: 0,
},
});
}).toThrow(
/Hours must be a value between 0 and 23/,
);

expect(() => {
new Domain(stack, 'Domain2', {
version: engineVersion,
offPeakWindowEnabled: true,
offPeakWindowStart: {
hours: 10,
minutes: 90,
},
});
}).toThrow(
/Minutes must be a value between 0 and 59/,
);
});
});

function testGrant(
expectedActions: string[],
invocation: (user: iam.IPrincipal, domain: Domain) => void,
Expand Down

0 comments on commit 02e8d58

Please sign in to comment.