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

feat(redshift): execute resource action #31995

Merged
merged 7 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -448,6 +448,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
34 changes: 34 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 @@ -399,6 +421,13 @@ export interface ClusterProps {
* @default - false
*/
readonly multiAz?: boolean;

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

/**
Expand Down Expand Up @@ -584,6 +613,10 @@ 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.');
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to execute failover for the single AZ cluster but I got a deployment error.

    const singleAzCluster = new redshiftAlpha.Cluster(this, 'SingleAzCluster', {
      vpc,
      vpcSubnets: {
        subnetType: ec2.SubnetType.PUBLIC,
      },
      masterUser: {
        masterUsername: 'admin',
      },
      nodeType: redshiftAlpha.NodeType.RA3_XLPLUS,
      publiclyAccessible: true,
    });

    const cfnSingleAzCluster = singleAzCluster.node.defaultChild as redshift.CfnCluster;
    cfnSingleAzCluster.addPropertyOverride('ResourceAction', 'failover-primary-compute');

Results:

8:50:18 | UPDATE_FAILED        | AWS::Redshift::Cluster                      | SingleAzCluster885C9BDD
Resource handler returned message: "Cannot invoke "java.lang.Boolean.booleanValue()" because the return value of "software.amazon.redshift
.cluster.ResourceModel.getMultiAZ()" is null" (RequestToken: d865c8ea-217c-ff00-0c71-1b659fdf6233, HandlerErrorCode: InternalFailure)

I also confirmed we can execute failover operation for a multi-AZ cluster.


this.cluster = new CfnCluster(this, 'Resource', {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommendation generated by Amazon CodeGuru Reviewer. Leave feedback on this recommendation by replying to the comment or by reacting to the comment using emoji.

Ensure that user activity logging is enabled for the Redshift cluster. This feature logs each query before it is executed on the cluster's database. To activate this, associate a Redshift Cluster Parameter Group with the enable_user_activity_logging parameter set to true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this feedback is inappropriate. This implementation is for existing L2 code, and to avoid breaking changes, we should not forcefully enable enable_user_activity_logging.

// Basic
allowVersionUpgrade: true,
Expand Down Expand Up @@ -613,6 +646,7 @@ export class Cluster extends ClusterBase {
elasticIp: props.elasticIp,
enhancedVpcRouting: props.enhancedVpcRouting,
multiAz: props.multiAz,
resourceAction: props.resourceAction,
});

this.cluster.applyRemovalPolicy(removalPolicy, {
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 @@ -479,6 +479,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