Skip to content

Commit 9f1d65d

Browse files
authored
fix(allow ITable for dynamodb stream patterns) (#214)
* fix(allow ITable for dynamodb stream patterns) * fix(allow ITable for dynamodb stream patterns) * fixing the cfn nag issues * PR feedback
1 parent 074b820 commit 9f1d65d

File tree

9 files changed

+540
-24
lines changed

9 files changed

+540
-24
lines changed

source/patterns/@aws-solutions-constructs/aws-dynamodb-stream-lambda-elasticsearch-kibana/README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ _Parameters_
6363
|existingLambdaObj?|[`lambda.Function`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.Function.html)|Existing instance of Lambda Function object, providing both this and `lambdaFunctionProps` will cause an error.|
6464
|lambdaFunctionProps?|[`lambda.FunctionProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.FunctionProps.html)|User provided props to override the default props for the Lambda function.|
6565
|dynamoTableProps?|[`dynamodb.TableProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.TableProps.html)|Optional user provided props to override the default props for DynamoDB Table|
66-
|existingTableObj?|[`dynamodb.Table`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.Table.html)|Existing instance of DynamoDB table object, providing both this and `dynamoTableProps` will cause an error.|
66+
|existingTableInterface?|[`dynamodb.ITable`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.ITable.html)|Existing instance of DynamoDB table object or interface, providing both this and `dynamoTableProps` will cause an error.|
6767
|dynamoEventSourceProps?|[`aws-lambda-event-sources.DynamoEventSourceProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda-event-sources.DynamoEventSourceProps.html)|Optional user provided props to override the default props for DynamoDB Event Source|
6868
|esDomainProps?|[`elasticsearch.CfnDomainProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-elasticsearch.CfnDomainProps.html)|Optional user provided props to override the default props for the Elasticsearch Service|
6969
|domainName|`string`|Domain name for the Cognito and the Elasticsearch Service|
@@ -73,7 +73,8 @@ _Parameters_
7373

7474
| **Name** | **Type** | **Description** |
7575
|:-------------|:----------------|-----------------|
76-
|dynamoTable|[`dynamodb.Table`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.Table.html)|Returns an instance of dynamodb.Table created by the construct|
76+
|dynamoTableInterface|[`dynamodb.ITable`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.ITable.html)|Returns an instance of dynamodb.ITable created by the construct|
77+
|dynamoTable?|[`dynamodb.Table`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.Table.html)|Returns an instance of dynamodb.Table created by the construct. IMPORTANT: If existingTableInterface was provided in Pattern Construct Props, this property will be `undefined`|
7778
|lambdaFunction|[`lambda.Function`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.Function.html)|Returns an instance of lambda.Function created by the construct|
7879
|userPool|[`cognito.UserPool`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-cognito.UserPool.html)|Returns an instance of cognito.UserPool created by the construct|
7980
|userPoolClient|[`cognito.UserPoolClient`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-cognito.UserPoolClient.html)|Returns an instance of cognito.UserPoolClient created by the construct|

source/patterns/@aws-solutions-constructs/aws-dynamodb-stream-lambda-elasticsearch-kibana/lib/index.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export interface DynamoDBStreamToLambdaToElasticSearchAndKibanaProps {
5151
*
5252
* @default - None
5353
*/
54-
readonly existingTableObj?: dynamodb.Table,
54+
readonly existingTableInterface?: dynamodb.ITable,
5555
/**
5656
* Optional user provided props to override the default props
5757
*
@@ -101,7 +101,8 @@ export class DynamoDBStreamToLambdaToElasticSearchAndKibana extends Construct {
101101
private dynamoDBStreamToLambda: DynamoDBStreamToLambda;
102102
private lambdaToElasticSearchAndKibana: LambdaToElasticSearchAndKibana;
103103
public readonly lambdaFunction: lambda.Function;
104-
public readonly dynamoTable: dynamodb.Table;
104+
public readonly dynamoTableInterface: dynamodb.ITable;
105+
public readonly dynamoTable?: dynamodb.Table;
105106
public readonly userPool: cognito.UserPool;
106107
public readonly userPoolClient: cognito.UserPoolClient;
107108
public readonly identityPool: cognito.CfnIdentityPool;
@@ -126,7 +127,7 @@ export class DynamoDBStreamToLambdaToElasticSearchAndKibana extends Construct {
126127
lambdaFunctionProps: props.lambdaFunctionProps,
127128
dynamoEventSourceProps: props.dynamoEventSourceProps,
128129
dynamoTableProps: props.dynamoTableProps,
129-
existingTableObj: props.existingTableObj,
130+
existingTableInterface: props.existingTableInterface,
130131
deploySqsDlqQueue: props.deploySqsDlqQueue,
131132
sqsDlqQueueProps: props.sqsDlqQueueProps
132133
};
@@ -146,6 +147,7 @@ export class DynamoDBStreamToLambdaToElasticSearchAndKibana extends Construct {
146147
this.lambdaToElasticSearchAndKibana = new LambdaToElasticSearchAndKibana(this, 'LambdaToElasticSearch', _props2);
147148

148149
this.dynamoTable = this.dynamoDBStreamToLambda.dynamoTable;
150+
this.dynamoTableInterface = this.dynamoDBStreamToLambda.dynamoTableInterface;
149151
this.userPool = this.lambdaToElasticSearchAndKibana.userPool;
150152
this.userPoolClient = this.lambdaToElasticSearchAndKibana.userPoolClient;
151153
this.identityPool = this.lambdaToElasticSearchAndKibana.identityPool;

source/patterns/@aws-solutions-constructs/aws-dynamodb-stream-lambda/README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,15 @@ _Parameters_
5858
|existingLambdaObj?|[`lambda.Function`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.Function.html)|Existing instance of Lambda Function object, providing both this and `lambdaFunctionProps` will cause an error.|
5959
|lambdaFunctionProps?|[`lambda.FunctionProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.FunctionProps.html)|User provided props to override the default props for the Lambda function.|
6060
|dynamoTableProps?|[`dynamodb.TableProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.TableProps.html)|Optional user provided props to override the default props for DynamoDB Table|
61-
|existingTableObj?|[`dynamodb.Table`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.Table.html)|Existing instance of DynamoDB table object, providing both this and `dynamoTableProps` will cause an error.|
61+
|existingTableInterface?|[`dynamodb.ITable`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.ITable.html)|Existing instance of DynamoDB table object or interface, providing both this and `dynamoTableProps` will cause an error.|
6262
|dynamoEventSourceProps?|[`aws-lambda-event-sources.DynamoEventSourceProps`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda-event-sources.DynamoEventSourceProps.html)|Optional user provided props to override the default props for DynamoDB Event Source|
6363

6464
## Pattern Properties
6565

6666
| **Name** | **Type** | **Description** |
6767
|:-------------|:----------------|-----------------|
68-
|dynamoTable|[`dynamodb.Table`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.Table.html)|Returns an instance of dynamodb.Table created by the construct|
68+
|dynamoTableInterface|[`dynamodb.ITable`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.ITable.html)|Returns an instance of dynamodb.ITable created by the construct|
69+
|dynamoTable?|[`dynamodb.Table`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-dynamodb.Table.html)|Returns an instance of dynamodb.Table created by the construct. IMPORTANT: If existingTableInterface was provided in Pattern Construct Props, this property will be `undefined`|
6970
|lambdaFunction|[`lambda.Function`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.Function.html)|Returns an instance of lambda.Function created by the construct|
7071

7172
## Lambda Function

source/patterns/@aws-solutions-constructs/aws-dynamodb-stream-lambda/lib/index.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export interface DynamoDBStreamToLambdaProps {
4545
*
4646
* @default - None
4747
*/
48-
readonly existingTableObj?: dynamodb.Table,
48+
readonly existingTableInterface?: dynamodb.ITable,
4949
/**
5050
* Optional user provided props to override the default props
5151
*
@@ -69,7 +69,8 @@ export interface DynamoDBStreamToLambdaProps {
6969

7070
export class DynamoDBStreamToLambda extends Construct {
7171
public readonly lambdaFunction: lambda.Function;
72-
public readonly dynamoTable: dynamodb.Table;
72+
public readonly dynamoTableInterface: dynamodb.ITable;
73+
public readonly dynamoTable?: dynamodb.Table;
7374

7475
/**
7576
* @summary Constructs a new instance of the LambdaToDynamoDB class.
@@ -88,20 +89,20 @@ export class DynamoDBStreamToLambda extends Construct {
8889
lambdaFunctionProps: props.lambdaFunctionProps
8990
});
9091

91-
this.dynamoTable = defaults.buildDynamoDBTableWithStream(this, {
92+
[this.dynamoTableInterface, this.dynamoTable] = defaults.buildDynamoDBTableWithStream(this, {
9293
dynamoTableProps: props.dynamoTableProps,
93-
existingTableObj: props.existingTableObj
94+
existingTableInterface: props.existingTableInterface
9495
});
9596

9697
// Grant DynamoDB Stream read perimssion for lambda function
97-
this.dynamoTable.grantStreamRead(this.lambdaFunction.grantPrincipal);
98+
this.dynamoTableInterface.grantStreamRead(this.lambdaFunction.grantPrincipal);
9899

99100
// Add the Lambda event source mapping
100101
const eventSourceProps = defaults.DynamoEventSourceProps(this, {
101102
eventSourceProps: props.dynamoEventSourceProps,
102103
deploySqsDlqQueue: props.deploySqsDlqQueue,
103104
sqsDlqQueueProps: props.sqsDlqQueueProps
104105
});
105-
this.lambdaFunction.addEventSource(new DynamoEventSource(this.dynamoTable, eventSourceProps));
106+
this.lambdaFunction.addEventSource(new DynamoEventSource(this.dynamoTableInterface, eventSourceProps));
106107
}
107108
}

source/patterns/@aws-solutions-constructs/aws-dynamodb-stream-lambda/test/dynamodb-stream-lambda.test.ts

+94-4
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,37 @@ test('check dynamodb table stream override', () => {
185185

186186
});
187187

188-
test('check getter methods', () => {
188+
test('check getter methods without existingTableInterface', () => {
189189
const stack = new cdk.Stack();
190190

191191
const construct: DynamoDBStreamToLambda = deployNewFunc(stack);
192192

193-
expect(construct.lambdaFunction !== null);
194-
expect(construct.dynamoTable !== null);
193+
expect(construct.lambdaFunction).toBeInstanceOf(lambda.Function);
194+
expect(construct.dynamoTableInterface).toHaveProperty('tableName');
195+
expect(construct.dynamoTable).toBeInstanceOf(dynamodb.Table);
196+
expect(construct.dynamoTable).toHaveProperty('addGlobalSecondaryIndex');
197+
});
198+
199+
test('check getter methods with existingTableInterface', () => {
200+
const stack = new cdk.Stack();
201+
202+
const construct: DynamoDBStreamToLambda = new DynamoDBStreamToLambda(stack, 'test', {
203+
existingTableInterface: new dynamodb.Table(stack, 'table', {
204+
partitionKey: {
205+
name: 'id',
206+
type: dynamodb.AttributeType.STRING
207+
},
208+
stream: dynamodb.StreamViewType.NEW_AND_OLD_IMAGES
209+
}),
210+
lambdaFunctionProps: {
211+
code: lambda.Code.fromAsset(`${__dirname}/lambda`),
212+
runtime: lambda.Runtime.NODEJS_12_X,
213+
handler: 'index.handler'
214+
},
215+
});
216+
217+
expect(construct.lambdaFunction).toBeInstanceOf(lambda.Function);
218+
expect(construct.dynamoTable).toBeUndefined();
195219
});
196220

197221
test('check exception for Missing existingObj from props', () => {
@@ -205,4 +229,70 @@ test('check exception for Missing existingObj from props', () => {
205229
} catch (e) {
206230
expect(e).toBeInstanceOf(Error);
207231
}
208-
});
232+
});
233+
234+
test('check dynamodb table stream override with ITable', () => {
235+
const stack = new cdk.Stack();
236+
const existingTableInterface = dynamodb.Table.fromTableAttributes(stack, 'existingtable', {
237+
tableArn: 'arn:aws:dynamodb:us-east-1:xxxxxxxxxxxxx:table/existing-table',
238+
tableStreamArn: 'arn:aws:dynamodb:us-east-1:xxxxxxxxxxxxx:table/existing-table/stream/2020-06-22T18:34:05.824'
239+
});
240+
const props: DynamoDBStreamToLambdaProps = {
241+
lambdaFunctionProps: {
242+
code: lambda.Code.fromAsset(`${__dirname}/lambda`),
243+
runtime: lambda.Runtime.NODEJS_12_X,
244+
handler: 'index.handler'
245+
},
246+
existingTableInterface
247+
};
248+
249+
new DynamoDBStreamToLambda(stack, 'test-lambda-dynamodb-stack', props);
250+
251+
expect(stack).toHaveResource('AWS::Lambda::EventSourceMapping', {
252+
EventSourceArn: "arn:aws:dynamodb:us-east-1:xxxxxxxxxxxxx:table/existing-table/stream/2020-06-22T18:34:05.824",
253+
});
254+
255+
expect(stack).toHaveResource('AWS::IAM::Policy', {
256+
PolicyDocument: {
257+
Statement: [
258+
{
259+
Action: [
260+
"xray:PutTraceSegments",
261+
"xray:PutTelemetryRecords"
262+
],
263+
Effect: "Allow",
264+
Resource: "*"
265+
},
266+
{
267+
Action: "dynamodb:ListStreams",
268+
Effect: "Allow",
269+
Resource: "*"
270+
},
271+
{
272+
Action: [
273+
"dynamodb:DescribeStream",
274+
"dynamodb:GetRecords",
275+
"dynamodb:GetShardIterator"
276+
],
277+
Effect: "Allow",
278+
Resource: "arn:aws:dynamodb:us-east-1:xxxxxxxxxxxxx:table/existing-table/stream/2020-06-22T18:34:05.824"
279+
},
280+
{
281+
Action: [
282+
"sqs:SendMessage",
283+
"sqs:GetQueueAttributes",
284+
"sqs:GetQueueUrl"
285+
],
286+
Effect: "Allow",
287+
Resource: {
288+
"Fn::GetAtt": [
289+
"testlambdadynamodbstackSqsDlqQueue4CC9868B",
290+
"Arn"
291+
]
292+
}
293+
}
294+
],
295+
Version: "2012-10-17"
296+
}
297+
});
298+
});

0 commit comments

Comments
 (0)