Skip to content

Commit 29c85e0

Browse files
authored
fix(redshift): add Redshift SLR creation (#725)
* add Redshift service linked role creation in RedshiftServerlessNamespace * add service linked role factory in RedshiftServerlessNamespace props
1 parent 3880167 commit 29c85e0

10 files changed

Lines changed: 405 additions & 5 deletions

File tree

framework/API.md

Lines changed: 355 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

framework/src/consumption/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ A [Redshift Serverless Workgroup](https://docs.aws.amazon.com/redshift/latest/mg
3737
- Provide helper methods for running SQL commands via the Redshift Data API. Commands can be custom or predefined for common administration tasks like creating and granting roles.
3838
- Initialize a Glue Data Catalog integration with auto crawling via Glue Crawlers. This would allow tables in Redshift Serverless to appear in the [Glue Data Catalog](https://docs.aws.amazon.com/glue/latest/dg/catalog-and-crawler.html) for the purposes of discovery and integration.
3939

40+
:::warning
41+
The default VPC created by the construct follows the [standard implementation of the VPC L2 CDK Construct](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#control-over-availability-zones). As a result, if no account ID and no region are configured in the CDK Stack, the VPC will only contain 2 AZ and the [Redshift Serverless Workgroup will fail to deploy](https://docs.aws.amazon.com/redshift/latest/mgmt/serverless-usage-considerations.html). Be sure to configure the account ID and region to create a 3 AZ VPC.
42+
:::
43+
4044
## Usage
4145

4246
[example default usage](./examples/redshift-serverless-workgroup-default.lit.ts)

framework/src/consumption/lib/redshift/redshift-serverless/redshift-serverless-namespace-props.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { RemovalPolicy } from 'aws-cdk-lib';
44
import { IRole } from 'aws-cdk-lib/aws-iam';
55
import { Key } from 'aws-cdk-lib/aws-kms';
6+
import { CreateServiceLinkedRole } from '../../../../utils';
67

78
/**
89
* Namespace log export types
@@ -83,4 +84,10 @@ export interface RedshiftServerlessNamespaceProps {
8384
* @default Indefinite final snapshot retention
8485
*/
8586
readonly finalSnapshotRetentionPeriod?: number;
87+
88+
/**
89+
* The Factory for creating Redshift service linked role
90+
* @default - A factory is created
91+
*/
92+
readonly serviceLinkedRoleFactory?: CreateServiceLinkedRole;
8693
}

framework/src/consumption/lib/redshift/redshift-serverless/redshift-serverless-namespace.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import { ILogGroup } from 'aws-cdk-lib/aws-logs';
99
import { ISecret, Secret } from 'aws-cdk-lib/aws-secretsmanager';
1010
import { Construct } from 'constructs';
1111
import { RedshiftServerlessNamespaceProps } from './redshift-serverless-namespace-props';
12-
import { Context, TrackedConstruct, TrackedConstructProps, Utils } from '../../../../utils';
12+
import { Context, CreateServiceLinkedRole, TrackedConstruct, TrackedConstructProps, Utils } from '../../../../utils';
1313
import { DsfProvider } from '../../../../utils/lib/dsf-provider';
14+
import { ServiceLinkedRoleService } from '../../../../utils/lib/service-linked-role-service';
1415

1516
/**
1617
* Create a Redshift Serverless Namespace with the admin credentials stored in Secrets Manager
@@ -113,8 +114,14 @@ export class RedshiftServerlessNamespace extends TrackedConstruct {
113114
this.roles[props.defaultIAMRole.roleArn] = props.defaultIAMRole;
114115
}
115116

116-
this.dbName = props.dbName;
117117
this.removalPolicy = Context.revertRemovalPolicy(scope, props.removalPolicy);
118+
119+
const slr = props.serviceLinkedRoleFactory || new CreateServiceLinkedRole(this, 'CreateSLR', {
120+
removalPolicy: this.removalPolicy,
121+
});
122+
slr.create(ServiceLinkedRoleService.REDSHIFT);
123+
124+
this.dbName = props.dbName;
118125
const logExports: string[] = props.logExports || [];
119126
this.namespaceName = `${props.name}-${Utils.generateUniqueHash(this)}`;
120127
this.dataKey = props.dataKey ?? new Key(this, 'DefaultNamespaceKey', { enableKeyRotation: true, removalPolicy: this.removalPolicy });

framework/src/utils/lib/create-service-linked-role.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@ import { DsfProvider } from './dsf-provider';
1010
import { ServiceLinkedRoleService } from './service-linked-role-service';
1111

1212
/**
13-
* @internal
1413
* Create service linked role for the indicated service if it doesn't exists
1514
*
1615
* @example
1716
* const slr = new dsf.utils.CreateServiceLinkedRole(this, 'CreateSLR')
18-
* slr.create('redshift.amazonaws.com')
17+
* slr.create(ServiceLinkedRoleService.REDSHIFT)
1918
*/
2019
export class CreateServiceLinkedRole extends Construct {
2120

framework/src/utils/lib/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@ export * from './s3-data-copy-props';
1717
export * from './architecture';
1818
export * from './client-vpn-endpoint-props';
1919
export * from './create-service-linked-role';
20+
export * from './create-service-linked-role-props';
21+
export * from './service-linked-role-service';
2022

2123

framework/test/unit/nag/consumption/nag-redshift-data-sharing.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@ NagSuppressions.addResourceSuppressionsByPath(stack, [
100100
],
101101
true);
102102

103+
NagSuppressions.addResourceSuppressionsByPath(stack,
104+
'Stack/DefaultNamespace/CreateSLR',
105+
[
106+
{ id: 'AwsSolutions-IAM5', reason: 'Inherited from another DSF construct, not in the scope of this test' },
107+
{ id: 'AwsSolutions-IAM4', reason: 'Inherited from another DSF construct, not in the scope of this test' },
108+
{ id: 'AwsSolutions-L1', reason: 'Inherited from another DSF construct, not in the scope of this test' },
109+
],
110+
true,
111+
);
112+
103113
test('No unsuppressed Warnings', () => {
104114
const warnings = Annotations.fromStack(stack).findWarning('*', Match.stringLikeRegexp('AwsSolutions-.*'));
105115
console.log(warnings);

framework/test/unit/nag/consumption/nag-redshift-serverless.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ NagSuppressions.addResourceSuppressionsByPath(stack,
8181
],
8282
);
8383

84+
NagSuppressions.addResourceSuppressionsByPath(stack,
85+
'Stack/DefaultNamespace/CreateSLR',
86+
[
87+
{ id: 'AwsSolutions-IAM5', reason: 'Inherited from another DSF construct, not in the scope of this test' },
88+
{ id: 'AwsSolutions-IAM4', reason: 'Inherited from another DSF construct, not in the scope of this test' },
89+
{ id: 'AwsSolutions-L1', reason: 'Inherited from another DSF construct, not in the scope of this test' },
90+
],
91+
true,
92+
);
93+
8494
NagSuppressions.addResourceSuppressionsByPath(stack, [
8595
'Stack/RedshiftWorkgroup/DataApiCheckAccessData',
8696
'Stack/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a',

website/docs/constructs/library/generated/_consumption-redshift-serverless-workgroup.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ A [Redshift Serverless Workgroup](https://docs.aws.amazon.com/redshift/latest/mg
1212
- Provide helper methods for running SQL commands via the Redshift Data API. Commands can be custom or predefined for common administration tasks like creating and granting roles.
1313
- Initialize a Glue Data Catalog integration with auto crawling via Glue Crawlers. This would allow tables in Redshift Serverless to appear in the [Glue Data Catalog](https://docs.aws.amazon.com/glue/latest/dg/catalog-and-crawler.html) for the purposes of discovery and integration.
1414

15+
:::warning
16+
The default VPC created by the construct follows the [standard implementation of the VPC L2 CDK Construct](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#control-over-availability-zones). As a result, if no account ID and no region are configured in the CDK Stack, the VPC will only contain 2 AZ and the [Redshift Serverless Workgroup will fail to deploy](https://docs.aws.amazon.com/redshift/latest/mgmt/serverless-usage-considerations.html). Be sure to configure the account ID and region to create a 3 AZ VPC.
17+
:::
18+
1519
## Usage
1620

1721
<Tabs>

website/docs/intro.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import TabItem from '@theme/TabItem';
88

99
# Quick start
1010

11-
> :heavy_exclamation_mark: If you're new to AWS CDK, we recommend going through a [few basic examples first](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html).
11+
:::warning
12+
If you're new to AWS CDK, we recommend going through a [few basic examples first](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html).
13+
:::
1214

1315
The DSF on AWS library is available in Typescript or Python, select the right tab for code examples in your preferred language.
1416

0 commit comments

Comments
 (0)