Skip to content

Commit 059ad93

Browse files
committed
Merge branch 'master' of github.com:knihit/aws-solutions-constructs
2 parents 3c0b58f + 1629501 commit 059ad93

File tree

7 files changed

+122
-19
lines changed

7 files changed

+122
-19
lines changed

CONTRIBUTING.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,11 @@ Additional scripts that take part in the versioning mechanism:
218218
```console
219219
$ cd <root-of-aws-solutions-constructs-repo>
220220
$ docker run -u root --rm --net=host -it -v $PWD:$PWD -w $PWD jsii/superchain:1-buster-slim-node14
221+
# The build-patterns.sh command can take along time, be sure to allocate enough resources in the Docker dashboard
222+
# (6 CPUs is good)
221223
docker$ ./deployment/build-patterns.sh
222-
docker$ exit
224+
# At this point the container is configured and ready to work on.
225+
# To work on a specific construct, execute the Partial Build steps below
223226
```
224227

225228
### Partial Build
@@ -235,7 +238,6 @@ docker$ export PATH=$(npm bin):$PATH
235238
docker$ cd patterns/@aws-solutions-constructs/my-module
236239
docker$ npm run build+lint+test
237240
docker$ ../../../../deployment/align-version.sh revert
238-
docker$ exit
239241
```
240242

241243
## Code of Conduct

source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/README.md

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -97,53 +97,69 @@ _Parameters_
9797
| tableProps? | [`CfnTableProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-glue.TableProps.html) | User provided AWS Glue Table props to override default props used to create a Glue Table. |
9898
| fieldSchema? | [`CfnTable.ColumnProperty[]`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-glue.CfnTable.ColumnProperty.html) | User provided schema structure to create an AWS Glue Table. |
9999
| outputDataStore? | [`SinkDataStoreProps`](#sinkdatastoreprops) | User provided properties for S3 bucket that stores Glue Job output. Current datastore types suported is only S3. |
100+
|createCloudWatchAlarms?|`boolean`|Whether to create recommended CloudWatch alarms for Kinesis Data Stream. Default value is set to `true`|
100101

101-
## SinkDataStoreProps
102+
### SinkDataStoreProps
102103

103104
| **Name** | **Type** | **Description** |
104105
| :---------------------- | :------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
105106
| existingS3OutputBucket? | [`Bucket`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.Bucket.html) | Existing instance of S3 bucket where the data should be written. Providing both this and `outputBucketProps` will cause an error. |
106107
| outputBucketProps | [`BucketProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-s3.BucketProps.html) | User provided bucket properties to create the S3 bucket to store the output from the AWS Glue Job. |
107108
| datastoreType | [`SinkStoreType`](#sinkstoretype) | Sink data store type. |
108109

109-
## SinkStoreType
110+
### SinkStoreType
110111

111112
Enumeration of data store types that could include S3, DynamoDB, DocumentDB, RDS or Redshift. Current construct implementation only supports S3, but potential to add other output types in the future.
112113

113114
| **Name** | **Type** | **Description** |
114115
| :------- | :------- | --------------- |
115116
| S3 | `string` | S3 storage type |
116117

117-
# Default settings
118+
## Pattern Properties
119+
120+
| **Name** | **Type** | **Description** |
121+
|:-------------|:----------------|-----------------|
122+
|cloudwatchAlarms?|[`cloudwatch.Alarm[]`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-cloudwatch.Alarm.html)|Returns an array of recommended CloudWatch Alarms created by the construct for Kinesis Data stream|
123+
|glueJob|[`CfnJob`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-glue.CfnJob.html)|Returns an instance of AWS Glue Job created by the construct|
124+
|glueJobRole|[`iam.Role`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-iam.Role.html)|Returns an instance of the IAM Role created by the construct for the Glue Job|
125+
|database|[`CfnDatabase`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-glue.CfnDatabase.html)|Returns an instance of AWS Glue Database created by the construct|
126+
|table|[`CfnTable`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-glue.CfnTable.html)|Returns an instance of the AWS Glue Table created by the construct|
127+
128+
## Default settings
118129

119130
Out of the box implementation of the Construct without any override will set the following defaults:
120131

121132
### Amazon Kinesis Stream
122133

123-
- Configure least privilege access IAM role for Kinesis Stream
124-
- Enable server-side encryption for Kinesis Stream using AWS Managed KMS Key
125-
- Deploy best practices CloudWatch Alarms for the Kinesis Stream
134+
- Configure least privilege access IAM role for Kinesis Stream
135+
- Enable server-side encryption for Kinesis Stream using AWS Managed KMS Key
136+
- Deploy best practices CloudWatch Alarms for the Kinesis Stream
126137

127138
### Glue Job
128139

129-
- Create a Glue Security Config that configures encryption for CloudWatch, Job Bookmarks, and S3. CloudWatch and Job Bookmarks are encrypted using AWS Managed KMS Key created for AWS Glue Service. The S3 bucket is configured with SSE-S3 encryption mode
130-
- Configure service role policies that allow AWS Glue to read from Kinesis Data Streams
140+
- Create a Glue Security Config that configures encryption for CloudWatch, Job Bookmarks, and S3. CloudWatch and Job Bookmarks are encrypted using AWS Managed KMS Key created for AWS Glue Service. The S3 bucket is configured with SSE-S3 encryption mode
141+
- Configure service role policies that allow AWS Glue to read from Kinesis Data Streams
131142

132143
### Glue Database
133144

134-
- Create an AWS Glue database. An AWS Glue Table will be added to the database. This table defines the schema for the records buffered in the Amazon Kinesis Data Streams
145+
- Create an AWS Glue database. An AWS Glue Table will be added to the database. This table defines the schema for the records buffered in the Amazon Kinesis Data Streams
135146

136147
### Glue Table
137148

138-
- Create an AWS Glue table. The table schema definition is based on the JSON structure of the records buffered in the Amazon Kinesis Data Streams
149+
- Create an AWS Glue table. The table schema definition is based on the JSON structure of the records buffered in the Amazon Kinesis Data Streams
139150

140151
### IAM Role
141152

142-
- A job execution role that has privileges to 1) read the ETL script from the S3 bucket location, 2) read records from the Kinesis Stream, and 3) execute the Glue Job
153+
- A job execution role that has privileges to 1) read the ETL script from the S3 bucket location, 2) read records from the Kinesis Stream, and 3) execute the Glue Job
143154

144155
### Output S3 Bucket
145156

146-
- An S3 bucket to store the output of the ETL transformation. This bucket will be passed as an argument to the created glue job so that it can be used in the ETL script to write data into it
157+
- An S3 bucket to store the output of the ETL transformation. This bucket will be passed as an argument to the created glue job so that it can be used in the ETL script to write data into it
158+
159+
### Cloudwatch Alarms
160+
161+
- A CloudWatch Alarm to report when consumer application is reading data slower than expected
162+
- A CloudWatch Alarm to report when consumer record processing is falling behind (to avoid risk of data loss due to record expiration)
147163

148164
## Architecture
149165

@@ -153,4 +169,4 @@ Out of the box implementation of the Construct without any override will set the
153169

154170
A sample use case which uses this pattern is available under [`use_cases/aws-custom-glue-etl`](https://github.com/awslabs/aws-solutions-constructs/tree/master/source/use_cases/aws-custom-glue-etl).
155171

156-
&copy; Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
172+
&copy; Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.

source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/lib/index.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Effect, IRole, Policy, PolicyStatement } from '@aws-cdk/aws-iam';
1616
import { Stream, StreamProps } from '@aws-cdk/aws-kinesis';
1717
import { Bucket } from '@aws-cdk/aws-s3';
1818
import { Aws, Construct } from '@aws-cdk/core';
19+
import * as cloudwatch from '@aws-cdk/aws-cloudwatch';
1920
import * as defaults from '@aws-solutions-constructs/core';
2021

2122
export interface KinesisstreamsToGluejobProps {
@@ -100,6 +101,12 @@ export interface KinesisstreamsToGluejobProps {
100101
* include only S3, other potential stores may be added in the future.
101102
*/
102103
readonly outputDataStore?: defaults.SinkDataStoreProps;
104+
/**
105+
* Whether to create recommended CloudWatch alarms
106+
*
107+
* @default - Alarms are created
108+
*/
109+
readonly createCloudWatchAlarms?: boolean;
103110
}
104111

105112
/**
@@ -125,6 +132,7 @@ export class KinesisstreamsToGluejob extends Construct {
125132
* property is undefined
126133
*/
127134
public readonly outputBucket?: [Bucket, (Bucket | undefined)?];
135+
public readonly cloudwatchAlarms?: cloudwatch.Alarm[];
128136

129137
/**
130138
* Constructs a new instance of KinesisstreamsToGluejob.Based on the values set in the @props
@@ -165,6 +173,11 @@ export class KinesisstreamsToGluejob extends Construct {
165173
});
166174

167175
this.glueJobRole = this.buildRolePolicy(scope, id, this.database, this.table, this.glueJob, this.glueJobRole);
176+
177+
if (props.createCloudWatchAlarms === undefined || props.createCloudWatchAlarms) {
178+
// Deploy best practices CW Alarms for Kinesis Stream
179+
this.cloudwatchAlarms = defaults.buildKinesisStreamCWAlarms(this);
180+
}
168181
}
169182

170183
/**

source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"@aws-cdk/core": "0.0.0",
6262
"@aws-cdk/aws-logs": "0.0.0",
6363
"@aws-solutions-constructs/core": "0.0.0",
64+
"@aws-cdk/aws-cloudwatch": "0.0.0",
6465
"constructs": "^3.2.0"
6566
},
6667
"devDependencies": {
@@ -90,6 +91,7 @@
9091
"@aws-cdk/aws-s3-assets": "0.0.0",
9192
"@aws-cdk/core": "0.0.0",
9293
"@aws-solutions-constructs/core": "0.0.0",
94+
"@aws-cdk/aws-cloudwatch": "0.0.0",
9395
"constructs": "^3.2.0",
9496
"@aws-cdk/aws-logs": "0.0.0"
9597
},

source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.existing-job.expected.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,32 @@
8383
}
8484
}
8585
},
86+
"testkinesisstreamslambdaKinesisStreamGetRecordsIteratorAgeAlarmFB74C363": {
87+
"Type": "AWS::CloudWatch::Alarm",
88+
"Properties": {
89+
"ComparisonOperator": "GreaterThanOrEqualToThreshold",
90+
"EvaluationPeriods": 1,
91+
"AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.",
92+
"MetricName": "GetRecords.IteratorAgeMilliseconds",
93+
"Namespace": "AWS/Kinesis",
94+
"Period": 300,
95+
"Statistic": "Maximum",
96+
"Threshold": 2592000
97+
}
98+
},
99+
"testkinesisstreamslambdaKinesisStreamReadProvisionedThroughputExceededAlarm5ABF4346": {
100+
"Type": "AWS::CloudWatch::Alarm",
101+
"Properties": {
102+
"ComparisonOperator": "GreaterThanThreshold",
103+
"EvaluationPeriods": 1,
104+
"AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.",
105+
"MetricName": "ReadProvisionedThroughputExceeded",
106+
"Namespace": "AWS/Kinesis",
107+
"Period": 300,
108+
"Statistic": "Average",
109+
"Threshold": 0
110+
}
111+
},
86112
"GlueDatabase": {
87113
"Type": "AWS::Glue::Database",
88114
"Properties": {

source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/integ.no-arguments.expected.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,32 @@
410410
"WorkerType": "G.1X"
411411
}
412412
},
413+
"testkinesisstreamslambdaKinesisStreamGetRecordsIteratorAgeAlarmFB74C363": {
414+
"Type": "AWS::CloudWatch::Alarm",
415+
"Properties": {
416+
"ComparisonOperator": "GreaterThanOrEqualToThreshold",
417+
"EvaluationPeriods": 1,
418+
"AlarmDescription": "Consumer Record Processing Falling Behind, there is risk for data loss due to record expiration.",
419+
"MetricName": "GetRecords.IteratorAgeMilliseconds",
420+
"Namespace": "AWS/Kinesis",
421+
"Period": 300,
422+
"Statistic": "Maximum",
423+
"Threshold": 2592000
424+
}
425+
},
426+
"testkinesisstreamslambdaKinesisStreamReadProvisionedThroughputExceededAlarm5ABF4346": {
427+
"Type": "AWS::CloudWatch::Alarm",
428+
"Properties": {
429+
"ComparisonOperator": "GreaterThanThreshold",
430+
"EvaluationPeriods": 1,
431+
"AlarmDescription": "Consumer Application is Reading at a Slower Rate Than Expected.",
432+
"MetricName": "ReadProvisionedThroughputExceeded",
433+
"Namespace": "AWS/Kinesis",
434+
"Period": 300,
435+
"Statistic": "Average",
436+
"Threshold": 0
437+
}
438+
},
413439
"GlueDatabase": {
414440
"Type": "AWS::Glue::Database",
415441
"Properties": {

source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/test.kinesisstream-gluejob.test.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ test('Pattern minimal deployment', () => {
5555

5656
const id = 'test-kinesisstreams-lambda';
5757

58-
new KinesisstreamsToGluejob(stack, id, props);
58+
const construct = new KinesisstreamsToGluejob(stack, id, props);
5959

6060
// check for role creation
6161
expect(stack).toHaveResourceLike('AWS::IAM::Role', {
@@ -253,6 +253,17 @@ test('Pattern minimal deployment', () => {
253253
}
254254
}
255255
}, ResourcePart.CompleteDefinition);
256+
257+
// Check for cloudwatch alarm
258+
expect(stack).toCountResources('AWS::CloudWatch::Alarm', 2);
259+
260+
// Check for properties
261+
expect(construct.database).toBeDefined();
262+
expect(construct.glueJob).toBeDefined();
263+
expect(construct.table).toBeDefined();
264+
expect(construct.kinesisStream).toBeDefined();
265+
expect(construct.glueJobRole).toBeDefined();
266+
expect(construct.cloudwatchAlarms).toBeDefined();
256267
});
257268

258269
// --------------------------------------------------------------
@@ -527,12 +538,13 @@ test('When database and table are provided', () => {
527538
});
528539

529540
// --------------------------------------------------------------
530-
// When database and table are not provided
541+
// When database and table are not provided & cloudwatch alarms set to false
531542
// --------------------------------------------------------------
532-
test('When database and table are not provided', () => {
543+
test('When database and table are not provided & cloudwatch alarms set to false', () => {
533544
// Initial setup
534545
const stack = new Stack();
535546
const props: KinesisstreamsToGluejobProps = {
547+
createCloudWatchAlarms: false,
536548
glueJobProps: {
537549
command: {
538550
name: 'glueetl',
@@ -558,7 +570,7 @@ test('When database and table are not provided', () => {
558570
comment: "Some value associated with the record"
559571
}]
560572
};
561-
new KinesisstreamsToGluejob(stack, 'test-kinesisstreams-lambda', props);
573+
const construct = new KinesisstreamsToGluejob(stack, 'test-kinesisstreams-lambda', props);
562574
expect(stack).toHaveResourceLike('AWS::Glue::Database', {
563575
Type: "AWS::Glue::Database",
564576
Properties: {
@@ -655,4 +667,10 @@ test('When database and table are not provided', () => {
655667
}
656668
}
657669
}, ResourcePart.CompleteDefinition);
670+
671+
// Cloudwatch alarms is set to false, no CFN def should exist
672+
expect(stack).not.toHaveResource('AWS::CloudWatch::Alarm');
673+
674+
// Since alarms is set to false, cloudwatch alarms property should be undefined
675+
expect(construct.cloudwatchAlarms).toBeUndefined();
658676
});

0 commit comments

Comments
 (0)