From a462ea25211c8e43c58d7b2eaeed80474175ae00 Mon Sep 17 00:00:00 2001 From: Richard Boyd Date: Tue, 28 Aug 2018 02:02:55 -0400 Subject: [PATCH 1/3] added the ability to specify a stream type, default behavior is no stream to maintain backwards compatibility --- CHANGELOG.md | 1 + packages/@aws-cdk/aws-dynamodb/lib/table.ts | 12 +- .../aws-dynamodb/test/test.dynamodb.ts | 139 +++++++++++++++++- 3 files changed, 147 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d151afe1e9dc6..30421ebfac4f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ + **Property Changes** - AWS::AppSync::DataSource HttpConfig (__added__) - AWS::DAX::Cluster SSESpecification (__added__) + - AWS::DynamoDB::Table Stream (__added__) - AWS::EC2::VPCEndpoint IsPrivateDnsEnabled (__added__) - AWS::EC2::VPCEndpoint SecurityGroupIds (__added__) - AWS::EC2::VPCEndpoint SubnetIds (__added__) diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index d6a3ff419a6f4..fec85fa3e2495 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -23,6 +23,12 @@ export interface TableProps { * @default */ tableName?: string; + + /** + * The Type of Stream to create. + * @default '' + */ + streamSpecification?: cloudformation.TableResource.StreamSpecificationProperty; } /** @@ -43,12 +49,14 @@ export class Table extends Construct { const readCapacityUnits = props.readCapacity || 5; const writeCapacityUnits = props.writeCapacity || 5; + const streamViewType = props.streamSpecification; this.table = new cloudformation.TableResource(this, 'Resource', { tableName: props.tableName, keySchema: this.keySchema, attributeDefinitions: this.attributeDefinitions, - provisionedThroughput: { readCapacityUnits, writeCapacityUnits } + provisionedThroughput: { readCapacityUnits, writeCapacityUnits }, + streamSpecification: streamViewType }); if (props.tableName) { this.addMetadata('aws:cdk:hasPhysicalName', props.tableName); } @@ -111,4 +119,4 @@ export enum KeyAttributeType { Binary = 'B', Number = 'N', String = 'S', -} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts b/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts index de6142177eba1..d03f5f42acfca 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts +++ b/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts @@ -24,7 +24,7 @@ export = { Properties: { AttributeDefinitions: [{ AttributeName: 'hashKey', AttributeType: 'B' }], KeySchema: [{ AttributeName: 'hashKey', KeyType: 'HASH' }], - ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 } + ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 }, } } } @@ -52,7 +52,7 @@ export = { { AttributeName: 'hashKey', KeyType: 'HASH' }, { AttributeName: 'sortKey', KeyType: 'RANGE' } ], - ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 } + ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 }, } } } @@ -60,6 +60,139 @@ export = { test.done(); }, + 'stream is not enabled by default'(test: Test) { + const app = new TestApp(); + new Table(app.stack, 'MyTable') + .addPartitionKey('partitionKey', KeyAttributeType.Binary) + .addSortKey('sortKey', KeyAttributeType.Number); + const template = app.synthesizeTemplate(); + + test.deepEqual(template, { + Resources: { + MyTable794EDED1: { + Type: 'AWS::DynamoDB::Table', + Properties: { + AttributeDefinitions: [ + { AttributeName: 'partitionKey', AttributeType: 'B' }, + { AttributeName: 'sortKey', AttributeType: 'N' } + ], + KeySchema: [ + { AttributeName: 'partitionKey', KeyType: 'HASH' }, + { AttributeName: 'sortKey', KeyType: 'RANGE' } + ], + ProvisionedThroughput: { ReadCapacityUnits: 5, WriteCapacityUnits: 5 }, + } + } + } + }); + + test.done(); + }, + 'can specify new and old images'(test: Test) { + const app = new TestApp(); + const table = new Table(app.stack, 'MyTable', { + tableName: 'MyTable', + readCapacity: 42, + writeCapacity: 1337, + streamSpecification: {streamViewType: 'NEW_AND_OLD_IMAGES'} + }); + table.addPartitionKey('partitionKey', KeyAttributeType.String); + table.addSortKey('sortKey', KeyAttributeType.Binary); + const template = app.synthesizeTemplate(); + + test.deepEqual(template, { + Resources: { + MyTable794EDED1: { + Type: 'AWS::DynamoDB::Table', + Properties: { + AttributeDefinitions: [ + { AttributeName: 'partitionKey', AttributeType: 'S' }, + { AttributeName: 'sortKey', AttributeType: 'B' } + ], + StreamSpecification: { StreamViewType: 'NEW_AND_OLD_IMAGES' }, + KeySchema: [ + { AttributeName: 'partitionKey', KeyType: 'HASH' }, + { AttributeName: 'sortKey', KeyType: 'RANGE' } + ], + ProvisionedThroughput: { ReadCapacityUnits: 42, WriteCapacityUnits: 1337 }, + TableName: 'MyTable' + } + } + } + }); + + test.done(); + }, + 'can specify new images only'(test: Test) { + const app = new TestApp(); + const table = new Table(app.stack, 'MyTable', { + tableName: 'MyTable', + readCapacity: 42, + writeCapacity: 1337, + streamSpecification: {streamViewType: 'NEW_IMAGE'} + }); + table.addPartitionKey('partitionKey', KeyAttributeType.String); + table.addSortKey('sortKey', KeyAttributeType.Binary); + const template = app.synthesizeTemplate(); + + test.deepEqual(template, { + Resources: { + MyTable794EDED1: { + Type: 'AWS::DynamoDB::Table', + Properties: { + KeySchema: [ + { AttributeName: 'partitionKey', KeyType: 'HASH' }, + { AttributeName: 'sortKey', KeyType: 'RANGE' } + ], + ProvisionedThroughput: { ReadCapacityUnits: 42, WriteCapacityUnits: 1337 }, + AttributeDefinitions: [ + { AttributeName: 'partitionKey', AttributeType: 'S' }, + { AttributeName: 'sortKey', AttributeType: 'B' } + ], + StreamSpecification: { StreamViewType: 'NEW_IMAGE' }, + TableName: 'MyTable' + } + } + } + }); + + test.done(); + }, + 'can specify old images only'(test: Test) { + const app = new TestApp(); + const table = new Table(app.stack, 'MyTable', { + tableName: 'MyTable', + readCapacity: 42, + writeCapacity: 1337, + streamSpecification: {streamViewType: 'OLD_IMAGE'} + }); + table.addPartitionKey('partitionKey', KeyAttributeType.String); + table.addSortKey('sortKey', KeyAttributeType.Binary); + const template = app.synthesizeTemplate(); + + test.deepEqual(template, { + Resources: { + MyTable794EDED1: { + Type: 'AWS::DynamoDB::Table', + Properties: { + KeySchema: [ + { AttributeName: 'partitionKey', KeyType: 'HASH' }, + { AttributeName: 'sortKey', KeyType: 'RANGE' } + ], + ProvisionedThroughput: { ReadCapacityUnits: 42, WriteCapacityUnits: 1337 }, + AttributeDefinitions: [ + { AttributeName: 'partitionKey', AttributeType: 'S' }, + { AttributeName: 'sortKey', AttributeType: 'B' } + ], + StreamSpecification: { StreamViewType: 'OLD_IMAGE' }, + TableName: 'MyTable' + } + } + } + }); + + test.done(); + } }, 'when specifying every property'(test: Test) { @@ -90,7 +223,7 @@ export = { ReadCapacityUnits: 42, WriteCapacityUnits: 1337 }, - TableName: 'MyTable' + TableName: 'MyTable', } } } From 27a483c229a405c1f431dfb3a5178586518ce8df Mon Sep 17 00:00:00 2001 From: Richard Boyd Date: Tue, 28 Aug 2018 10:06:11 -0400 Subject: [PATCH 2/3] incorporated @eladb's feedback --- packages/@aws-cdk/aws-dynamodb/lib/table.ts | 29 +++++++++++++++---- .../aws-dynamodb/test/test.dynamodb.ts | 8 ++--- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index fec85fa3e2495..f2089a735deec 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -25,10 +25,11 @@ export interface TableProps { tableName?: string; /** - * The Type of Stream to create. - * @default '' + * When an item in the table is modified, StreamViewType determines what information + * is written to the stream for this table. Valid values for StreamViewType are: + * @default undefined */ - streamSpecification?: cloudformation.TableResource.StreamSpecificationProperty; + streamSpecification?: StreamViewType; } /** @@ -49,14 +50,13 @@ export class Table extends Construct { const readCapacityUnits = props.readCapacity || 5; const writeCapacityUnits = props.writeCapacity || 5; - const streamViewType = props.streamSpecification; this.table = new cloudformation.TableResource(this, 'Resource', { tableName: props.tableName, keySchema: this.keySchema, attributeDefinitions: this.attributeDefinitions, provisionedThroughput: { readCapacityUnits, writeCapacityUnits }, - streamSpecification: streamViewType + streamSpecification: props.streamSpecification ? {streamViewType: props.streamSpecification} : undefined }); if (props.tableName) { this.addMetadata('aws:cdk:hasPhysicalName', props.tableName); } @@ -119,4 +119,21 @@ export enum KeyAttributeType { Binary = 'B', Number = 'N', String = 'S', -} \ No newline at end of file +} + +/** + * When an item in the table is modified, StreamViewType determines what information + * is written to the stream for this table. Valid values for StreamViewType are: + * @link https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_StreamSpecification.html + * @enum {string} + */ +export enum StreamViewType { + /** The entire item, as it appears after it was modified, is written to the stream. */ + NewImage = 'NEW_IMAGE', + /** The entire item, as it appeared before it was modified, is written to the stream. */ + OldImage = 'OLD_IMAGE', + /** Both the new and the old item images of the item are written to the stream. */ + NewAndOldImages = 'NEW_AND_OLD_IMAGES', + /** Only the key attributes of the modified item are written to the stream. */ + KeysOnly = 'KEYS_ONLY' + } diff --git a/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts b/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts index d03f5f42acfca..3fda4c4e7bbcf 100644 --- a/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts +++ b/packages/@aws-cdk/aws-dynamodb/test/test.dynamodb.ts @@ -1,6 +1,6 @@ import { App, Stack } from '@aws-cdk/cdk'; import { Test } from 'nodeunit'; -import { KeyAttributeType, Table } from '../lib'; +import { KeyAttributeType, StreamViewType, Table } from '../lib'; export = { 'default properties': { @@ -94,7 +94,7 @@ export = { tableName: 'MyTable', readCapacity: 42, writeCapacity: 1337, - streamSpecification: {streamViewType: 'NEW_AND_OLD_IMAGES'} + streamSpecification: StreamViewType.NewAndOldImages }); table.addPartitionKey('partitionKey', KeyAttributeType.String); table.addSortKey('sortKey', KeyAttributeType.Binary); @@ -129,7 +129,7 @@ export = { tableName: 'MyTable', readCapacity: 42, writeCapacity: 1337, - streamSpecification: {streamViewType: 'NEW_IMAGE'} + streamSpecification: StreamViewType.NewImage }); table.addPartitionKey('partitionKey', KeyAttributeType.String); table.addSortKey('sortKey', KeyAttributeType.Binary); @@ -164,7 +164,7 @@ export = { tableName: 'MyTable', readCapacity: 42, writeCapacity: 1337, - streamSpecification: {streamViewType: 'OLD_IMAGE'} + streamSpecification: StreamViewType.OldImage }); table.addPartitionKey('partitionKey', KeyAttributeType.String); table.addSortKey('sortKey', KeyAttributeType.Binary); From b41eff34a8ca3e6d1006706a71f8f0759ce40541 Mon Sep 17 00:00:00 2001 From: Richard Boyd Date: Tue, 28 Aug 2018 10:11:46 -0400 Subject: [PATCH 3/3] clarified the default behavior --- packages/@aws-cdk/aws-dynamodb/lib/table.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-dynamodb/lib/table.ts b/packages/@aws-cdk/aws-dynamodb/lib/table.ts index f2089a735deec..d5fdf087c0074 100644 --- a/packages/@aws-cdk/aws-dynamodb/lib/table.ts +++ b/packages/@aws-cdk/aws-dynamodb/lib/table.ts @@ -27,7 +27,7 @@ export interface TableProps { /** * When an item in the table is modified, StreamViewType determines what information * is written to the stream for this table. Valid values for StreamViewType are: - * @default undefined + * @default undefined, streams are disbaled */ streamSpecification?: StreamViewType; }