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(iot-actions): add support for DynamoDBv2 rule #20171

Merged
merged 21 commits into from
Aug 2, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
38 changes: 38 additions & 0 deletions packages/@aws-cdk/aws-iot-actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Currently supported are:
- Put records to Kinesis Data Firehose stream
- Send messages to SQS queues
- Publish messages on SNS topics
- Write messages into columns of DynamoDB

## Republish a message to another MQTT topic

Expand Down Expand Up @@ -278,3 +279,40 @@ const topicRule = new iot.TopicRule(this, 'TopicRule', {
],
});
```

## Write attributes of a message to DynamoDB

The code snippet below creates an AWS IoT rule that writes all or part of an
MQTT message to DynamoDB using the DynamoDBv2 action.

```ts
import * as dynamodb from '@aws-cdk/aws-dynamodb';

const tablePartitionKey: dynamodb.Attribute = {
name: 'hashKey',
type: dynamodb.AttributeType.STRING,
};

const tableSortKey: dynamodb.Attribute = {
name: 'sortKey',
type: dynamodb.AttributeType.NUMBER,
};

const table = new dynamodb.Table(this, 'MyTable', {
tableName: 'MyTable',
readCapacity: 1,
writeCapacity: 1,
partitionKey: tablePartitionKey,
sortKey: tableSortKey,
});
bobveringa marked this conversation as resolved.
Show resolved Hide resolved

const topicRule = new iot.TopicRule(this, 'TopicRule', {
sql: iot.IotSql.fromStringAsVer20160323(
"SELECT * FROM 'device/+/data'",
),
actions: [
new actions.DynamoDBv2PutItemAction(table)
],
});

bobveringa marked this conversation as resolved.
Show resolved Hide resolved
```
45 changes: 45 additions & 0 deletions packages/@aws-cdk/aws-iot-actions/lib/dynamo-db-v2-put-item.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as dynamodb from '@aws-cdk/aws-dynamodb';
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is better to rename this file to dynamodb-v2-put-item.ts because existing files for DynamoDB in this repository are named dynamodb-xxx instead of dynamo-db-xxx.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would actually go with dynamodbv2-put-item-action.ts

import * as iam from '@aws-cdk/aws-iam';
import * as iot from '@aws-cdk/aws-iot';
import { CommonActionProps } from './common-action-props';
import { singletonActionRole } from './private/role';

/**
* Configuration properties of an action for the dynamodb table.
*/
export interface DynamoDBv2PutItemActionProps extends CommonActionProps {
}

bobveringa marked this conversation as resolved.
Show resolved Hide resolved

/**
* The action to put the record from an MQTT message to the Kinesis Data Firehose stream.
bobveringa marked this conversation as resolved.
Show resolved Hide resolved
*/
export class DynamoDBv2PutItemAction implements iot.IAction {
private readonly role?: iam.IRole;

/**
* @param table the DynamoDB table in which to put the items.
* @param props Optional properties to not use default
*/
constructor(private readonly table: dynamodb.ITable, props: DynamoDBv2PutItemActionProps = {}) {
this.role = props.role;
}

bind(rule: iot.ITopicRule): iot.ActionConfig {
const role = this.role ?? singletonActionRole(rule);
role.addToPrincipalPolicy(new iam.PolicyStatement({
actions: ['dynamodb:PutItem'],
resources: [this.table.tableArn],
}));
return {
configuration: {
dynamoDBv2: {
putItem: {
tableName: this.table.tableName,
},
roleArn: role.roleArn,
},
},
};
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-iot-actions/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './cloudwatch-logs-action';
export * from './cloudwatch-put-metric-action';
export * from './cloudwatch-set-alarm-state-action';
export * from './common-action-props';
export * from './dynamo-db-v2-put-item';
export * from './firehose-put-record-action';
export * from './iot-republish-action';
export * from './kinesis-put-record-action';
Expand Down
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-iot-actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
},
"dependencies": {
"@aws-cdk/aws-cloudwatch": "0.0.0",
"@aws-cdk/aws-dynamodb": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-iot": "0.0.0",
"@aws-cdk/aws-kinesis": "0.0.0",
Expand All @@ -104,6 +105,7 @@
"homepage": "https://github.com/aws/aws-cdk",
"peerDependencies": {
"@aws-cdk/aws-cloudwatch": "0.0.0",
"@aws-cdk/aws-dynamodb": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-iot": "0.0.0",
"@aws-cdk/aws-kinesis": "0.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"version":"18.0.0"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"version": "18.0.0",
"testCases": {
"dynamodb-v2/integ.dynamodb-v2-put-item-action": {
"stacks": [
"test-dynamo-d-bv2-put-item-action-stack"
],
"diffAssets": false,
"stackUpdateWorkflow": true
}
},
"synthContext": {},
"enableLookups": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"version": "18.0.0",
"artifacts": {
"Tree": {
"type": "cdk:tree",
"properties": {
"file": "tree.json"
}
},
"test-dynamo-d-bv2-put-item-action-stack": {
"type": "aws:cloudformation:stack",
"environment": "aws://unknown-account/unknown-region",
"properties": {
"templateFile": "test-dynamo-d-bv2-put-item-action-stack.template.json",
"validateOnSynth": false
},
"metadata": {
"/test-dynamo-d-bv2-put-item-action-stack/TopicRule/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "TopicRule40A4EA44"
}
],
"/test-dynamo-d-bv2-put-item-action-stack/TopicRule/TopicRuleActionRole/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "TopicRuleTopicRuleActionRole246C4F77"
}
],
"/test-dynamo-d-bv2-put-item-action-stack/TopicRule/TopicRuleActionRole/DefaultPolicy/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "TopicRuleTopicRuleActionRoleDefaultPolicy99ADD687"
}
],
"/test-dynamo-d-bv2-put-item-action-stack/MyTable": [
{
"type": "aws:cdk:hasPhysicalName",
"data": {
"Ref": "MyTable794EDED1"
}
}
],
"/test-dynamo-d-bv2-put-item-action-stack/MyTable/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "MyTable794EDED1"
}
]
},
"displayName": "test-dynamo-d-bv2-put-item-action-stack"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
{
"Resources": {
"TopicRule40A4EA44": {
"Type": "AWS::IoT::TopicRule",
"Properties": {
"TopicRulePayload": {
"Actions": [
{
"DynamoDBv2": {
"PutItem": {
"TableName": {
"Ref": "MyTable794EDED1"
}
},
"RoleArn": {
"Fn::GetAtt": [
"TopicRuleTopicRuleActionRole246C4F77",
"Arn"
]
}
}
}
],
"AwsIotSqlVersion": "2016-03-23",
"Sql": "SELECT * FROM 'device/+/data'"
}
}
},
"TopicRuleTopicRuleActionRole246C4F77": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "iot.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"TopicRuleTopicRuleActionRoleDefaultPolicy99ADD687": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "dynamodb:PutItem",
"Effect": "Allow",
"Resource": {
"Fn::GetAtt": [
"MyTable794EDED1",
"Arn"
]
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "TopicRuleTopicRuleActionRoleDefaultPolicy99ADD687",
"Roles": [
{
"Ref": "TopicRuleTopicRuleActionRole246C4F77"
}
]
}
},
"MyTable794EDED1": {
"Type": "AWS::DynamoDB::Table",
"Properties": {
"KeySchema": [
{
"AttributeName": "hashKey",
"KeyType": "HASH"
},
{
"AttributeName": "sortKey",
"KeyType": "RANGE"
}
],
"AttributeDefinitions": [
{
"AttributeName": "hashKey",
"AttributeType": "S"
},
{
"AttributeName": "sortKey",
"AttributeType": "N"
}
],
"ProvisionedThroughput": {
"ReadCapacityUnits": 1,
"WriteCapacityUnits": 1
},
"TableName": "MyTable"
},
"UpdateReplacePolicy": "Delete",
"DeletionPolicy": "Delete"
}
}
}
Loading