From 9c82bcaf90a1dc2df324a72ea622c7eec729d0f5 Mon Sep 17 00:00:00 2001 From: rjjaisim-at-amazon <159363849+rjjaisim-at-amazon@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:22:24 -0600 Subject: [PATCH] feat(rds): add ability to specify PreferredMaintenanceWindow to RDS cluster database instances (#29033) ### Issue # (if applicable) Closes [#16954](https://github.com/aws/aws-cdk/issues/16954) ### Reason for this change Noticed that we were able to specify preferredMaintenanceWindow for a cluster, but unable to do so for the instances created under the cluster. Instead, AWS (semi-)randomly assigns a maintenance window ([doc](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.Maintenance.html#Concepts.DBMaintenance)) for the instances, which leads to things being out of sync b/w the cluster and its child instances There are some workarounds as mentioned in the issue above, but those are a little hacky (imo) and I figured adding the preferredMaintenanceWindow as an instance prop is a better long-term solution. Also, it might be hard for other developers to find the workarounds as they are only mentioned in the above issue and aren't available through normal channels (Stack overflow/official CDK docs) ### Description of changes Added optional preferredMaintenanceWindow field under `InstanceProps`, and passed that field in during the creation of the `CfnDBInstance`. Also added a quick unit test ### Description of how you validated changes Added a unit test, did not add integ tests. Ran `yarn build` and `yarn test` Callout: I was unable to run integration tests locally, kept getting errors with `yarn integ --directory packages/aws-cdk-lib/aws-rds` and `yarn integ-runner --directory packages/aws-cdk-lib/aws-rds` - `Error: Cannot find module './integ-runner.js'`, not sure if I'm missing something ### Checklist - [ x ] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) No breaking changes *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/aws-cdk-lib/aws-rds/README.md | 20 ++++++++++++++++ packages/aws-cdk-lib/aws-rds/lib/cluster.ts | 1 + packages/aws-cdk-lib/aws-rds/lib/props.ts | 11 +++++++++ .../aws-cdk-lib/aws-rds/test/cluster.test.ts | 24 +++++++++++++++++++ 4 files changed, 56 insertions(+) diff --git a/packages/aws-cdk-lib/aws-rds/README.md b/packages/aws-cdk-lib/aws-rds/README.md index 8106e32246807..20605a5463abd 100644 --- a/packages/aws-cdk-lib/aws-rds/README.md +++ b/packages/aws-cdk-lib/aws-rds/README.md @@ -1204,3 +1204,23 @@ The `vpc` parameter is optional. If not provided, the cluster will be created in the default VPC of the account and region. As this VPC is not deployed with AWS CDK, you can't configure the `vpcSubnets`, `subnetGroup` or `securityGroups` of the Aurora Serverless Cluster. If you want to provide one of `vpcSubnets`, `subnetGroup` or `securityGroups` parameter, please provide a `vpc`. + +### Preferred Maintenance Window + +When creating an RDS cluster, it is possible to (optionally) specify a preferred maintenance window for the cluster as well as the instances under the cluster. +See [AWS docs](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_UpgradeDBInstance.Maintenance.html#Concepts.DBMaintenance) for more information regarding maintenance windows. + +The following code snippet shows an example of setting the cluster's maintenance window to 22:15-22:45 (UTC) on Saturdays, but setting the instances' maintenance window +to 23:15-23:45 on Sundays + +```ts +declare const vpc: ec2.Vpc; +new rds.DatabaseCluster(this, 'DatabaseCluster', { + engine: rds.DatabaseClusterEngine.AURORA, + instanceProps: { + vpc: vpc, + preferredMaintenanceWindow: 'Sun:23:15-Sun:23:45', + }, + preferredMaintenanceWindow: 'Sat:22:15-Sat:22:45', +}); +``` diff --git a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts index f36a5fae6e5fa..72b4a9cb72af2 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts @@ -1415,6 +1415,7 @@ function legacyCreateInstances(cluster: DatabaseClusterNew, props: DatabaseClust autoMinorVersionUpgrade: instanceProps.autoMinorVersionUpgrade, allowMajorVersionUpgrade: instanceProps.allowMajorVersionUpgrade, deleteAutomatedBackups: instanceProps.deleteAutomatedBackups, + preferredMaintenanceWindow: instanceProps.preferredMaintenanceWindow, }); // For instances that are part of a cluster: diff --git a/packages/aws-cdk-lib/aws-rds/lib/props.ts b/packages/aws-cdk-lib/aws-rds/lib/props.ts index 4379e4d5da8b0..7b2e43b3a938f 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/props.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/props.ts @@ -101,6 +101,17 @@ export interface InstanceProps { * @default - `true` if `vpcSubnets` is `subnetType: SubnetType.PUBLIC`, `false` otherwise */ readonly publiclyAccessible?: boolean; + + /** + * A preferred maintenance window day/time range. Should be specified as a range ddd:hh24:mi-ddd:hh24:mi (24H Clock UTC). + * + * Example: 'Sun:23:45-Mon:00:15' + * + * @default - 30-minute window selected at random from an 8-hour block of time for + * each AWS Region, occurring on a random day of the week. + * @see https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_UpgradeDBInstance.Maintenance.html#Concepts.DBMaintenance + */ + readonly preferredMaintenanceWindow?: string; } /** diff --git a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts index 6122b3e0b10a5..8a21c2f744cb1 100644 --- a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts @@ -209,6 +209,30 @@ describe('cluster new api', () => { ], }); }); + + test('preferredMaintenanceWindow provided in InstanceProps', () => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + const PREFERRED_MAINTENANCE_WINDOW: string = 'Sun:12:00-Sun:13:00'; + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA, + instanceProps: { + vpc: vpc, + preferredMaintenanceWindow: PREFERRED_MAINTENANCE_WINDOW, + }, + }); + + // THEN + const template = Template.fromStack(stack); + // maintenance window is set + template.hasResourceProperties('AWS::RDS::DBInstance', Match.objectLike({ + PreferredMaintenanceWindow: PREFERRED_MAINTENANCE_WINDOW, + })); + }); }); describe('migrate from instanceProps', () => {