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(iotevents): support actions #18869

Merged
merged 32 commits into from
Mar 4, 2022
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
61a4bae
feat(iotevents): support actions
yamatatsu Feb 8, 2022
f3bdd56
fix code comments
yamatatsu Feb 8, 2022
940e1c7
remove redundant comments
yamatatsu Feb 8, 2022
5b86fa8
Update packages/@aws-cdk/aws-iotevents/README.md
yamatatsu Feb 9, 2022
7ad0532
Update packages/@aws-cdk/aws-iotevents/README.md
yamatatsu Feb 9, 2022
a021c79
Update packages/@aws-cdk/aws-iotevents/README.md
yamatatsu Feb 9, 2022
814e352
Update packages/@aws-cdk/aws-iotevents/README.md
yamatatsu Feb 9, 2022
2e9bca1
Update packages/@aws-cdk/aws-iotevents/README.md
yamatatsu Feb 9, 2022
a430030
address comments about README
yamatatsu Feb 9, 2022
31d3516
Update packages/@aws-cdk/aws-iotevents/lib/event.ts
yamatatsu Feb 9, 2022
7bd8f97
Update packages/@aws-cdk/aws-iotevents/lib/state.ts
yamatatsu Feb 9, 2022
ebfeeb2
Update packages/@aws-cdk/aws-iotevents/lib/state.ts
yamatatsu Feb 9, 2022
a123666
Update packages/@aws-cdk/aws-iotevents/lib/state.ts
yamatatsu Feb 9, 2022
20c47d2
Update packages/@aws-cdk/aws-iotevents/lib/state.ts
yamatatsu Feb 9, 2022
9e67025
Update packages/@aws-cdk/aws-iotevents/lib/state.ts
yamatatsu Feb 9, 2022
9a62326
Update packages/@aws-cdk/aws-iotevents/lib/state.ts
yamatatsu Feb 9, 2022
9cc9794
address comments
yamatatsu Feb 10, 2022
218b91e
address comments about tests
yamatatsu Feb 10, 2022
c7e142d
fix readme
yamatatsu Feb 12, 2022
9d7abc3
Merge branch 'master' into iotevents-actions
yamatatsu Feb 17, 2022
297e3b1
add sns action
yamatatsu Feb 21, 2022
8e4452b
lambda actions
yamatatsu Feb 28, 2022
6d80f69
write readme
yamatatsu Feb 28, 2022
011f1eb
add test for coverage
yamatatsu Feb 28, 2022
a8e6fd0
Merge branch 'master' into iotevents-actions
yamatatsu Feb 28, 2022
b686021
write readme
yamatatsu Mar 1, 2022
369562d
address comments
yamatatsu Mar 3, 2022
9f7ddf7
documentation
yamatatsu Mar 3, 2022
c0ccdf8
address commits
yamatatsu Mar 4, 2022
f9b8d8c
add link of actions to README
yamatatsu Mar 4, 2022
ea3059d
test behavior of action
yamatatsu Mar 4, 2022
de801e0
Merge branch 'master' into iotevents-actions
mergify[bot] Mar 4, 2022
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
30 changes: 30 additions & 0 deletions packages/@aws-cdk/aws-iotevents-actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,33 @@
This library contains integration classes to specify actions of state events of Detector Model in `@aws-cdk/aws-iotevents`.
Instances of these classes should be passed to `State` defined in `@aws-cdk/aws-iotevents`
You can define built-in actions to use a timer or set a variable, or send data to other AWS resources.

This library contains integration classes to use a timer or set a variable, or send data to other AWS resources.
AWS IoT Events can trigger actions when it detects a specified event or transition event.

Currently supported are:

- Invoke a Lambda function

## Invoke a Lambda function

The code snippet below creates an Action that invoke a Lambda function
when it is triggered.

```ts
import * as iotevents from '@aws-cdk/aws-iotevents';
import * as actions from '@aws-cdk/aws-iotevents-actions';
import * as lambda from '@aws-cdk/aws-lambda';

declare const input: iotevents.IInput;
declare const func: lambda.IFunction;

const state = new iotevents.State({
stateName: 'MyState',
onEnter: [{
eventName: 'test-event',
condition: iotevents.Expression.currentInput(input),
actions: [new actions.LambdaInvokeAction(func)],
}],
});
```
3 changes: 1 addition & 2 deletions packages/@aws-cdk/aws-iotevents-actions/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
// this is placeholder for monocdk
export const dummy = true;
export * from './lambda-invoke-action';
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as iotevents from '@aws-cdk/aws-iotevents';
import * as lambda from '@aws-cdk/aws-lambda';
import { Construct } from 'constructs';

/**
* The action to write the data to an AWS Lambda function.
*/
export class LambdaInvokeAction implements iotevents.IAction {
/**
* @param func the AWS Lambda function to be invoked by this action
*/
constructor(private readonly func: lambda.IFunction) {
}

bind(_scope: Construct, options: iotevents.ActionBindOptions): iotevents.ActionConfig {
this.func.grantInvoke(options.role);
return {
configuration: {
lambda: {
functionArn: this.func.functionArn,
},
},
};
}
}
12 changes: 10 additions & 2 deletions packages/@aws-cdk/aws-iotevents-actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,19 @@
"jest": "^27.5.1"
},
"dependencies": {
"@aws-cdk/core": "0.0.0"
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-iotevents": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/core": "0.0.0",
"constructs": "^3.3.69"
},
"homepage": "https://github.com/aws/aws-cdk",
"peerDependencies": {
"@aws-cdk/core": "0.0.0"
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-iotevents": "0.0.0",
"@aws-cdk/aws-lambda": "0.0.0",
"@aws-cdk/core": "0.0.0",
"constructs": "^3.3.69"
},
"engines": {
"node": ">= 10.13.0 <13 || >=13.7.0"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
{
"Resources": {
"MyInput08947B23": {
"Type": "AWS::IoTEvents::Input",
"Properties": {
"InputDefinition": {
"Attributes": [
{
"JsonPath": "payload.deviceId"
}
]
},
"InputName": "test_input"
}
},
"MyFunctionServiceRole3C357FF2": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"ManagedPolicyArns": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
]
]
}
]
}
},
"MyFunction3BAA72D1": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile": "\n exports.handler = (event) => {\n console.log(\"It is test for lambda action of AWS IoT Rule.\", event);\n };"
},
"Role": {
"Fn::GetAtt": [
"MyFunctionServiceRole3C357FF2",
"Arn"
]
},
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"MyFunctionServiceRole3C357FF2"
]
},
"MyDetectorModelDetectorModelRoleF2FB4D88": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "iotevents.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"MyDetectorModelDetectorModelRoleDefaultPolicy82887422": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "lambda:InvokeFunction",
"Effect": "Allow",
"Resource": {
"Fn::GetAtt": [
"MyFunction3BAA72D1",
"Arn"
]
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "MyDetectorModelDetectorModelRoleDefaultPolicy82887422",
"Roles": [
{
"Ref": "MyDetectorModelDetectorModelRoleF2FB4D88"
}
]
}
},
"MyDetectorModel559C0B0E": {
"Type": "AWS::IoTEvents::DetectorModel",
"Properties": {
"DetectorModelDefinition": {
"InitialStateName": "MyState",
"States": [
{
"OnEnter": {
"Events": [
{
"Actions": [
{
"Lambda": {
"FunctionArn": {
"Fn::GetAtt": [
"MyFunction3BAA72D1",
"Arn"
]
}
}
}
],
"Condition": {
"Fn::Join": [
"",
[
"currentInput(\"",
{
"Ref": "MyInput08947B23"
},
"\")"
]
]
},
"EventName": "test-event"
}
]
},
"OnInput": {},
"StateName": "MyState"
}
]
},
"RoleArn": {
"Fn::GetAtt": [
"MyDetectorModelDetectorModelRoleF2FB4D88",
"Arn"
]
},
"Key": "payload.deviceId"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Stack verification steps:
* * put a message
* * aws iotevents-data batch-put-message --messages=messageId=(date | md5),inputName=test_input,payload=(echo '{"payload":{"temperature":31.9,"deviceId":"000"}}' | base64)
* * verify that the lambda logs be put
*/
import * as iotevents from '@aws-cdk/aws-iotevents';
import * as lambda from '@aws-cdk/aws-lambda';
import * as cdk from '@aws-cdk/core';
import * as actions from '../../lib';

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

const input = new iotevents.Input(this, 'MyInput', {
inputName: 'test_input',
attributeJsonPaths: ['payload.deviceId'],
});
const func = new lambda.Function(this, 'MyFunction', {
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromInline(`
exports.handler = (event) => {
console.log("It is test for lambda action of AWS IoT Rule.", event);
};`,
),
});

const state = new iotevents.State({
stateName: 'MyState',
onEnter: [{
eventName: 'test-event',
condition: iotevents.Expression.currentInput(input),
actions: [new actions.LambdaInvokeAction(func)],
}],
});

new iotevents.DetectorModel(this, 'MyDetectorModel', {
detectorKey: 'payload.deviceId',
initialState: state,
});
}
}

const app = new cdk.App();
new TestStack(app, 'lambda-invoke-action-test-stack');
app.synth();
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Template } from '@aws-cdk/assertions';
import * as iotevents from '@aws-cdk/aws-iotevents';
import * as lambda from '@aws-cdk/aws-lambda';
import * as cdk from '@aws-cdk/core';
import * as actions from '../../lib';

let stack: cdk.Stack;
let input: iotevents.IInput;
let func: lambda.IFunction;
beforeEach(() => {
stack = new cdk.Stack();
input = iotevents.Input.fromInputName(stack, 'MyInput', 'test-input');
func = lambda.Function.fromFunctionAttributes(stack, 'MyFunction', {
functionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn',
sameEnvironment: true,
});
});

test('Default property', () => {
// WHEN
new iotevents.DetectorModel(stack, 'MyDetectorModel', {
initialState: new iotevents.State({
stateName: 'test-state',
onEnter: [{
eventName: 'test-eventName',
condition: iotevents.Expression.currentInput(input),
actions: [new actions.LambdaInvokeAction(func)],
}],
}),
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', {
DetectorModelDefinition: {
States: [{
OnEnter: {
Events: [{
Actions: [{
Lambda: {
FunctionArn: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn',
},
}],
}],
},
}],
},
RoleArn: {
'Fn::GetAtt': ['MyDetectorModelDetectorModelRoleF2FB4D88', 'Arn'],
},
});

Template.fromStack(stack).hasResourceProperties('AWS::IAM::Policy', {
PolicyDocument: {
Statement: [{
Action: 'lambda:InvokeFunction',
Effect: 'Allow',
Resource: 'arn:aws:lambda:us-east-1:123456789012:function:MyFn',
}],
},
Roles: [{
Ref: 'MyDetectorModelDetectorModelRoleF2FB4D88',
}],
});
});
6 changes: 6 additions & 0 deletions packages/@aws-cdk/aws-iotevents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ AWS IoT Events inputs enable the detector to get MQTT payload values from IoT Co

```ts
import * as iotevents from '@aws-cdk/aws-iotevents';
import * as actions from '@aws-cdk/aws-iotevents-actions';
import * as lambda from '@aws-cdk/aws-lambda';

declare const func: lambda.IFunction;

const input = new iotevents.Input(this, 'MyInput', {
inputName: 'my_input', // optional
yamatatsu marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -59,6 +63,7 @@ const warmState = new iotevents.State({
onEnter: [{
eventName: 'test-event',
condition: iotevents.Expression.currentInput(input),
actions: [new actions.LambdaInvokeAction(func)], // optional
}],
});
const coldState = new iotevents.State({
Expand All @@ -72,6 +77,7 @@ warmState.transitionTo(coldState, {
iotevents.Expression.inputAttribute(input, 'payload.temperature'),
iotevents.Expression.fromString('10'),
),
executing: [new actions.LambdaInvokeAction(func)], // optional
});
// transit to warmState when temperature is 20
coldState.transitionTo(warmState, {
Expand Down
Loading