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): add the TopicRule L2 construct #16681

Merged
merged 23 commits into from
Oct 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e6c26f5
feat(iot): support the TopicRule L2 construct
yamatatsu Sep 28, 2021
259ca2e
Merge branch 'master' into aws-iot
yamatatsu Oct 6, 2021
61c9d70
Merge branch 'master' into aws-iot
yamatatsu Oct 8, 2021
5b3f786
Update packages/@aws-cdk/aws-iot/lib/action.ts
yamatatsu Oct 13, 2021
84001cd
Update packages/@aws-cdk/aws-iot/lib/topic-rule.ts
yamatatsu Oct 13, 2021
94dcbbe
fix(iot): be a small PR
yamatatsu Oct 13, 2021
f969810
Merge branch 'master' into aws-iot
yamatatsu Oct 13, 2021
e2b78f5
Update packages/@aws-cdk/aws-iot/lib/topic-rule.ts
yamatatsu Oct 15, 2021
4023a08
Update packages/@aws-cdk/aws-iot/lib/topic-rule.ts
yamatatsu Oct 15, 2021
912fdaf
Update packages/@aws-cdk/aws-iot/test/topic-rule.test.ts
yamatatsu Oct 15, 2021
1562ac6
Update packages/@aws-cdk/aws-iot/test/topic-rule.test.ts
yamatatsu Oct 15, 2021
1ada690
fix(iot): about feedbacks
yamatatsu Oct 16, 2021
9e7256b
feat(iot): modeling AWS IoT SQL
yamatatsu Oct 18, 2021
59815ad
Update packages/@aws-cdk/aws-iot/test/iot-sql.test.ts
yamatatsu Oct 19, 2021
89a8571
Update packages/@aws-cdk/aws-iot/test/topic-rule.test.ts
yamatatsu Oct 19, 2021
8a94620
Update packages/@aws-cdk/aws-iot/test/topic-rule.test.ts
yamatatsu Oct 19, 2021
a252d75
Update packages/@aws-cdk/aws-iot/test/topic-rule.test.ts
yamatatsu Oct 19, 2021
30d0fa6
Update packages/@aws-cdk/aws-iot/test/topic-rule.test.ts
yamatatsu Oct 19, 2021
f21567e
Update packages/@aws-cdk/aws-iot/test/topic-rule.test.ts
yamatatsu Oct 19, 2021
e150499
Update packages/@aws-cdk/aws-iot/lib/topic-rule.ts
yamatatsu Oct 19, 2021
13b4701
fix(iot): about feedbacks
yamatatsu Oct 19, 2021
1bcb870
feat(iot): remove IAction
yamatatsu Oct 21, 2021
f2c0a38
Merge branch 'master' into aws-iot
mergify[bot] Oct 21, 2021
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
41 changes: 40 additions & 1 deletion packages/@aws-cdk/aws-iot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,47 @@
>
> [CFN Resources]: https://docs.aws.amazon.com/cdk/latest/guide/constructs.html#constructs_lib

![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge)

> The APIs of higher level constructs in this module are experimental and under active development.
> They are subject to non-backward compatible changes or removal in any future version. These are
> not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be
> announced in the release notes. This means that while you may use them, you may need to update
> your source code when upgrading to a newer version of this package.

---

<!--END STABILITY BANNER-->

This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.
AWS IoT Core lets you connect billions of IoT devices and route trillions of
messages to AWS services without managing infrastructure.

## Installation

Install the module:

```console
$ npm i @aws-cdk/aws-iot
```

Import it into your code:

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

## `TopicRule`

The `TopicRule` construct defined Rules that give your devices the ability to
interact with AWS services.

For example, to define a rule:

```ts
new iot.TopicRule(stack, 'MyTopicRule', {
topicRuleName: 'MyRuleName', // optional property
sql: iot.IotSql.fromStringAsVer20160323(
"SELECT topic(2) as device_id, temperature FROM 'device/+/data'",
),
});
```
skinny85 marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 3 additions & 0 deletions packages/@aws-cdk/aws-iot/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export * from './iot-sql';
export * from './topic-rule';

// AWS::IoT CloudFormation Resources:
export * from './iot.generated';
75 changes: 75 additions & 0 deletions packages/@aws-cdk/aws-iot/lib/iot-sql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Construct } from 'constructs';

/**
* The type returned from the `bind()` method in {@link IotSql}.
*/
export interface IotSqlConfig {
/**
* The version of the SQL rules engine to use when evaluating the rule.
*/
readonly awsIotSqlVersion: string;

/**
* The SQL statement used to query the topic.
*/
readonly sql: string;
}

/**
* Defines AWS IoT SQL.
*/
export abstract class IotSql {
/**
* Uses the original SQL version built on 2015-10-08.
*
* @param sql The actual SQL-like syntax query
* @returns Instance of IotSql
*/
public static fromStringAsVer20151008(sql: string): IotSql {
return new IotSqlImpl('2015-10-08', sql);
}

/**
* Uses the SQL version built on 2016-03-23.
*
* @param sql The actual SQL-like syntax query
* @returns Instance of IotSql
*/
public static fromStringAsVer20160323(sql: string): IotSql {
return new IotSqlImpl('2016-03-23', sql);
}

/**
* Uses the most recent beta SQL version. If you use this version, it might
* introduce breaking changes to your rules.
*
* @param sql The actual SQL-like syntax query
* @returns Instance of IotSql
*/
public static fromStringAsVerNewestUnstable(sql: string): IotSql {
return new IotSqlImpl('beta', sql);
}

/**
* Returns the IoT SQL configuration.
*/
public abstract bind(scope: Construct): IotSqlConfig;
}


class IotSqlImpl extends IotSql {
constructor(private readonly version: string, private readonly sql: string) {
super();

if (sql === '') {
throw new Error('IoT SQL string cannot be empty');
}
}

bind(_scope: Construct): IotSqlConfig {
return {
awsIotSqlVersion: this.version,
sql: this.sql,
};
}
}
106 changes: 106 additions & 0 deletions packages/@aws-cdk/aws-iot/lib/topic-rule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { ArnFormat, Resource, Stack, IResource } from '@aws-cdk/core';
import { Construct } from 'constructs';
import { IotSql } from './iot-sql';
import { CfnTopicRule } from './iot.generated';

/**
* Represents an AWS IoT Rule
*/
export interface ITopicRule extends IResource {
/**
* The value of the topic rule Amazon Resource Name (ARN), such as
* arn:aws:iot:us-east-2:123456789012:rule/rule_name
*
* @attribute
*/
readonly topicRuleArn: string;

/**
* The name topic rule
*
* @attribute
*/
readonly topicRuleName: string;
}

/**
* Properties for defining an AWS IoT Rule
*/
export interface TopicRuleProps {
/**
* The name of the rule.
* @default None
*/
readonly topicRuleName?: string;

/**
* A simplified SQL syntax to filter messages received on an MQTT topic and push the data elsewhere.
*
* @see https://docs.aws.amazon.com/iot/latest/developerguide/iot-sql-reference.html
*/
readonly sql: IotSql;
}

/**
* Defines an AWS IoT Rule in this stack.
*/
export class TopicRule extends Resource implements ITopicRule {
/**
* Import an existing AWS IoT Rule provided an ARN
*
* @param scope The parent creating construct (usually `this`).
* @param id The construct's name.
* @param topicRuleArn AWS IoT Rule ARN (i.e. arn:aws:iot:<region>:<account-id>:rule/MyRule).
*/
public static fromTopicRuleArn(scope: Construct, id: string, topicRuleArn: string): ITopicRule {
const parts = Stack.of(scope).splitArn(topicRuleArn, ArnFormat.SLASH_RESOURCE_NAME);
if (!parts.resourceName) {
throw new Error(`Missing topic rule name in ARN: '${topicRuleArn}'`);
}
const resourceName = parts.resourceName;

class Import extends Resource implements ITopicRule {
public readonly topicRuleArn = topicRuleArn;
public readonly topicRuleName = resourceName;
}
return new Import(scope, id, {
environmentFromArn: topicRuleArn,
});
}

/**
* Arn of this rule
* @attribute
*/
public readonly topicRuleArn: string;

/**
* Name of this rule
* @attribute
*/
public readonly topicRuleName: string;

constructor(scope: Construct, id: string, props: TopicRuleProps) {
super(scope, id, {
physicalName: props.topicRuleName,
});

const sqlConfig = props.sql.bind(this);

const resource = new CfnTopicRule(this, 'Resource', {
ruleName: this.physicalName,
topicRulePayload: {
actions: [],
awsIotSqlVersion: sqlConfig.awsIotSqlVersion,
sql: sqlConfig.sql,
},
});

this.topicRuleArn = this.getResourceArnAttribute(resource.attrArn, {
service: 'iot',
resource: 'rule',
resourceName: this.physicalName,
});
this.topicRuleName = this.getResourceNameAttribute(resource.ref);
}
}
6 changes: 4 additions & 2 deletions packages/@aws-cdk/aws-iot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,11 @@
"devDependencies": {
"@aws-cdk/assertions": "0.0.0",
"@aws-cdk/cdk-build-tools": "0.0.0",
"@aws-cdk/cdk-integ-tools": "0.0.0",
"@aws-cdk/cfn2ts": "0.0.0",
"@aws-cdk/pkglint": "0.0.0",
"@types/jest": "^26.0.24"
"@types/jest": "^26.0.24",
"jest": "^26.6.3"
},
"dependencies": {
"@aws-cdk/core": "0.0.0",
Expand All @@ -91,7 +93,7 @@
"node": ">= 10.13.0 <13 || >=13.7.0"
},
"stability": "experimental",
"maturity": "cfn-only",
"maturity": "experimental",
"awscdkio": {
"announce": false
},
Expand Down
14 changes: 14 additions & 0 deletions packages/@aws-cdk/aws-iot/test/integ.topic-rule.expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"Resources": {
"TopicRule40A4EA44": {
"Type": "AWS::IoT::TopicRule",
"Properties": {
"TopicRulePayload": {
"Actions": [],
"AwsIotSqlVersion": "2015-10-08",
"Sql": "SELECT topic(2) as device_id FROM 'device/+/data'"
}
}
}
}
}
18 changes: 18 additions & 0 deletions packages/@aws-cdk/aws-iot/test/integ.topic-rule.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// !cdk-integ pragma:ignore-assets
import * as cdk from '@aws-cdk/core';
import * as iot from '../lib';

const app = new cdk.App();

class TestStack extends cdk.Stack {
constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
super(scope, id, props);

new iot.TopicRule(this, 'TopicRule', {
sql: iot.IotSql.fromStringAsVer20151008("SELECT topic(2) as device_id FROM 'device/+/data'"),
});
}
}

new TestStack(app, 'test-stack');
app.synth();
6 changes: 0 additions & 6 deletions packages/@aws-cdk/aws-iot/test/iot.test.ts

This file was deleted.

Loading