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 setting Events on input and exit for State #19249

Merged
merged 3 commits into from
Mar 8, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@
}
]
},
"OnInput": {},
"StateName": "MyState"
}
]
Expand Down
10 changes: 9 additions & 1 deletion packages/@aws-cdk/aws-iotevents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,18 @@ const input = new iotevents.Input(this, 'MyInput', {
const warmState = new iotevents.State({
stateName: 'warm',
onEnter: [{
eventName: 'test-event',
eventName: 'test-enter-event',
condition: iotevents.Expression.currentInput(input),
actions: [new actions.LambdaInvokeAction(func)], // optional
}],
onInput: [{ // optional
eventName: 'test-input-event',
actions: [new actions.LambdaInvokeAction(func)],
}],
onExit: [{ // optional
eventName: 'test-exit-event',
actions: [new actions.LambdaInvokeAction(func)],
}],
});
const coldState = new iotevents.State({
stateName: 'cold',
Expand Down
40 changes: 31 additions & 9 deletions packages/@aws-cdk/aws-iotevents/lib/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,28 @@ export interface StateProps {
readonly stateName: string;

/**
* Specifies the events on enter. the conditions of the events are evaluated when the state is entered.
* If the condition is `TRUE`, the actions of the event are performed.
* Specifies the events on enter. The conditions of the events will be evaluated when entering this state.
* If the condition of the event evaluates to `true`, the actions of the event will be executed.
*
* @default - events on enter will not be set
* @default - no events will trigger on entering this state
skinny85 marked this conversation as resolved.
Show resolved Hide resolved
*/
readonly onEnter?: Event[];

/**
* Specifies the events on input. The conditions of the events will be evaluated when any input is received.
* If the condition of the event evaluates to `true`, the actions of the event will be executed.
*
* @default - no events will trigger on input in this state
*/
readonly onInput?: Event[];

/**
* Specifies the events on exit. The conditions of the events are evaluated when an exiting this state.
* If the condition evaluates to `true`, the actions of the event will be executed.
*
* @default - no events will trigger on exiting this state
*/
readonly onExit?: Event[];
}

/**
Expand Down Expand Up @@ -141,12 +157,18 @@ export class State {
}

private toStateJson(scope: Construct, actionBindOptions: ActionBindOptions): CfnDetectorModel.StateProperty {
const { onEnter } = this.props;
const { onEnter, onInput, onExit } = this.props;
return {
stateName: this.stateName,
onEnter: onEnter && { events: toEventsJson(scope, actionBindOptions, onEnter) },
yamatatsu marked this conversation as resolved.
Show resolved Hide resolved
onInput: {
onEnter: onEnter && {
events: toEventsJson(scope, actionBindOptions, onEnter),
},
onInput: (onInput || this.transitionEvents.length !== 0) ? {
events: toEventsJson(scope, actionBindOptions, onInput),
transitionEvents: toTransitionEventsJson(scope, actionBindOptions, this.transitionEvents),
} : undefined,
onExit: onExit && {
events: toEventsJson(scope, actionBindOptions, onExit),
},
};
}
Expand All @@ -155,9 +177,9 @@ export class State {
function toEventsJson(
scope: Construct,
actionBindOptions: ActionBindOptions,
events: Event[],
): CfnDetectorModel.EventProperty[] {
return events.map(event => ({
events?: Event[],
): CfnDetectorModel.EventProperty[] | undefined {
return events?.map(event => ({
eventName: event.eventName,
condition: event.condition?.evaluate(),
actions: event.actions?.map(action => action.bind(scope, actionBindOptions).configuration),
Expand Down
20 changes: 20 additions & 0 deletions packages/@aws-cdk/aws-iotevents/test/detector-model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,26 @@ test('can set actions to events', () => {
});
});

test.each([
['onInput', { onInput: [{ eventName: 'test-eventName1' }] }, { OnInput: { Events: [{ EventName: 'test-eventName1' }] } }],
['onExit', { onExit: [{ eventName: 'test-eventName1' }] }, { OnExit: { Events: [{ EventName: 'test-eventName1' }] } }],
])('can set %s to State', (_, events, expected) => {
// WHEN
new iotevents.DetectorModel(stack, 'MyDetectorModel', {
initialState: new iotevents.State({
stateName: 'test-state',
onEnter: [{ eventName: 'test-eventName1', condition: iotevents.Expression.currentInput(input) }],
...events,
}),
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::IoTEvents::DetectorModel', {
DetectorModelDefinition: {
States: [Match.objectLike(expected)],
},
});
});

test('can set an action to multiple detector models', () => {
// GIVEN an action
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,43 @@
}
]
},
"OnExit": {
"Events": [
{
"Condition": {
"Fn::Join": [
"",
[
"$input.",
{
"Ref": "MyInput08947B23"
},
".payload.temperature == 31.7"
]
]
},
"EventName": "test-exit-event"
}
]
},
"OnInput": {
"Events": [
{
"Condition": {
"Fn::Join": [
"",
[
"$input.",
{
"Ref": "MyInput08947B23"
},
".payload.temperature == 31.6"
]
]
},
"EventName": "test-input-event"
}
],
"TransitionEvents": [
{
"Condition": {
Expand Down
14 changes: 14 additions & 0 deletions packages/@aws-cdk/aws-iotevents/test/integ.detector-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ class TestStack extends cdk.Stack {
),
),
}],
onInput: [{
eventName: 'test-input-event',
condition: iotevents.Expression.eq(
iotevents.Expression.inputAttribute(input, 'payload.temperature'),
iotevents.Expression.fromString('31.6'),
),
}],
onExit: [{
eventName: 'test-exit-event',
condition: iotevents.Expression.eq(
iotevents.Expression.inputAttribute(input, 'payload.temperature'),
iotevents.Expression.fromString('31.7'),
),
}],
});
const offlineState = new iotevents.State({
stateName: 'offline',
Expand Down