Skip to content

Commit

Permalink
feat(redshift): execute resource action (#31995)
Browse files Browse the repository at this point in the history
### Issue # (if applicable)

None

### Reason for this change

We can perform various Redshift operation by specifying `ResourceAction`
prop but AWS CDK cannot do this.


<https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html#cfn-redshift-cluster-resourceaction>

### Description of changes

- Define `ResourceAction` enum
- Add `resourceAction` prop to `ClusterProps`

### Description of how you validated changes

Add both unit and integ tests.

### 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)

----

*By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache-2.0 license*
  • Loading branch information
badmintoncryer authored Dec 2, 2024
1 parent 64a0e2c commit 40835a0
Show file tree
Hide file tree
Showing 12 changed files with 1,749 additions and 1 deletion.
42 changes: 42 additions & 0 deletions packages/@aws-cdk/aws-redshift-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,48 @@ cluster.addToParameterGroup('enable_user_activity_logging', 'true');
cluster.enableRebootForParameterChanges()
```

## Resource Action

You can perform various actions on the Redshift resource by specifying the `resourceAction` property,
including [pausing and resuming the cluster](https://docs.aws.amazon.com/redshift/latest/mgmt/rs-mgmt-pause-resume-cluster.html), as well as initiating [failover for Multi-AZ clusters](https://docs.aws.amazon.com/redshift/latest/mgmt/test-cluster-multi-az.html).

```ts
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { ResourceAction } from '@aws-cdk/aws-redshift-alpha';

declare const vpc: ec2.IVpc;

// Pause the cluster
new Cluster(this, 'PausedCluster', {
masterUser: {
masterUsername: 'admin',
},
vpc,
resourceAction: ResourceAction.PAUSE,
});

// Resume the cluster
new Cluster(this, 'ResumedCluster', {
masterUser: {
masterUsername: 'admin',
},
vpc,
resourceAction: ResourceAction.RESUME,
});

// Failover the cluster
new Cluster(this, 'FailOverCluster', {
masterUser: {
masterUsername: 'admin',
},
// VPC must have 3 AZs for the cluster which executes failover action
vpc,
// Must be a multi-AZ cluster to failover
multiAz: true,
resourceAction: ResourceAction.FAILOVER_PRIMARY_COMPUTE,
});
```

## Elastic IP

If you configure your cluster to be publicly accessible, you can optionally select an *elastic IP address* to use for the external IP address. An elastic IP address is a static IP address that is associated with your AWS account. You can use an elastic IP address to connect to your cluster from outside the VPC. An elastic IP address gives you the ability to change your underlying configuration without affecting the IP address that clients use to connect to your cluster. This approach can be helpful for situations such as recovery after a failure.
Expand Down
33 changes: 33 additions & 0 deletions packages/@aws-cdk/aws-redshift-alpha/lib/cluster.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,28 @@ export enum ClusterType {
MULTI_NODE = 'multi-node',
}

/**
* The Amazon Redshift operation
*/
export enum ResourceAction {
/**
* Pause the cluster
*/
PAUSE_CLUSTER = 'pause-cluster',

/**
* Resume the cluster
*/
RESUME_CLUSTER = 'resume-cluster',

/**
* Failing over to the other availability zone
*
* @see https://docs.aws.amazon.com/redshift/latest/mgmt/test-cluster-multi-az.html
*/
FAILOVER_PRIMARY_COMPUTE = 'failover-primary-compute',
}

/**
* Username and password combination
*/
Expand Down Expand Up @@ -400,6 +422,13 @@ export interface ClusterProps {
*/
readonly multiAz?: boolean;

/**
* The Amazon Redshift operation to be performed.
*
* @default - no operation
*/
readonly resourceAction?: ResourceAction;

/**
* Whether to enable relocation for an Amazon Redshift cluster between Availability Zones after the cluster is created.
*
Expand Down Expand Up @@ -593,6 +622,9 @@ export class Cluster extends ClusterBase {
}
}

if (props.resourceAction === ResourceAction.FAILOVER_PRIMARY_COMPUTE && !props.multiAz) {
throw new Error('ResourceAction.FAILOVER_PRIMARY_COMPUTE can only be used with multi-AZ clusters.');
};
if (props.availabilityZoneRelocation && !nodeType.startsWith('ra3')) {
throw new Error(`Availability zone relocation is supported for only RA3 node types, got: ${props.nodeType}`);
}
Expand Down Expand Up @@ -626,6 +658,7 @@ export class Cluster extends ClusterBase {
elasticIp: props.elasticIp,
enhancedVpcRouting: props.enhancedVpcRouting,
multiAz: props.multiAz,
resourceAction: props.resourceAction,
availabilityZoneRelocation: props.availabilityZoneRelocation,
});

Expand Down
32 changes: 31 additions & 1 deletion packages/@aws-cdk/aws-redshift-alpha/test/cluster.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as iam from 'aws-cdk-lib/aws-iam';
import * as kms from 'aws-cdk-lib/aws-kms';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as cdk from 'aws-cdk-lib';
import { Cluster, ClusterParameterGroup, ClusterSubnetGroup, ClusterType, NodeType } from '../lib';
import { Cluster, ClusterParameterGroup, ClusterSubnetGroup, ClusterType, NodeType, ResourceAction } from '../lib';
import { CfnCluster } from 'aws-cdk-lib/aws-redshift';

let stack: cdk.Stack;
Expand Down Expand Up @@ -512,6 +512,36 @@ test('can create a cluster with logging enabled', () => {
});
});

test.each([
ResourceAction.PAUSE_CLUSTER,
ResourceAction.RESUME_CLUSTER,
ResourceAction.FAILOVER_PRIMARY_COMPUTE,
])('specify resource action %s', (resourceAction) => {
// WHEN
new Cluster(stack, 'Redshift', {
masterUser: {
masterUsername: 'admin',
},
vpc,
resourceAction,
nodeType: NodeType.RA3_XLPLUS,
multiAz: true,
});
});

test.each([false, undefined])('throw error for failover primary compute action with single AZ cluster', (multiAz) => {
expect(() => {
new Cluster(stack, 'Redshift', {
masterUser: {
masterUsername: 'admin',
},
vpc,
multiAz,
resourceAction: ResourceAction.FAILOVER_PRIMARY_COMPUTE,
});
}).toThrow('ResourceAction.FAILOVER_PRIMARY_COMPUTE can only be used with multi-AZ clusters.');
});

test('throws when trying to add rotation to a cluster without secret', () => {
// WHEN
const cluster = new Cluster(stack, 'Redshift', {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 40835a0

Please sign in to comment.