Skip to content

Commit

Permalink
fix(stepfunctions-tasks): EvaluateExpression is limited to expression…
Browse files Browse the repository at this point in the history
…s that contain state paths (aws#7774)

fixes aws#7655
  • Loading branch information
Niranjan Jayakar authored May 12, 2020
1 parent cb3c184 commit 97f4f01
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as path from 'path';
*/
export interface EvaluateExpressionProps {
/**
* The expression to evaluate. It must contain state paths.
* The expression to evaluate. The expression may contain state paths.
*
* @example '$.a + $.b'
*/
Expand Down Expand Up @@ -56,30 +56,30 @@ export class EvaluateExpression implements sfn.IStepFunctionsTask {
public bind(task: sfn.Task): sfn.StepFunctionsTaskConfig {
const matches = this.props.expression.match(/\$[.\[][.a-zA-Z[\]0-9]+/g);

if (!matches) {
throw new Error('No paths found in expression');
let expressionAttributeValues = {};
if (matches) {
expressionAttributeValues = matches.reduce(
(acc, m) => ({
...acc,
[m]: sfn.Data.stringAt(m), // It's okay to always use `stringAt` here
}),
{},
);
}

const expressionAttributeValues = matches.reduce(
(acc, m) => ({
...acc,
[m]: sfn.Data.stringAt(m), // It's okay to always use `stringAt` here
}),
{},
);

const evalFn = createEvalFn(this.props.runtime || lambda.Runtime.NODEJS_10_X, task);

const parameters: Event = {
expression: this.props.expression,
expressionAttributeValues,
};
return {
resourceArn: evalFn.functionArn,
policyStatements: [new iam.PolicyStatement({
resources: [evalFn.functionArn],
actions: ['lambda:InvokeFunction'],
})],
parameters: {
expression: this.props.expression,
expressionAttributeValues,
} as Event,
parameters,
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,32 @@ test('Eval with Node.js', () => {
});
});

test('Throws when expression does not contain paths', () => {
test('expression does not contain paths', () => {
// WHEN
expect(() => new sfn.Task(stack, 'Task', {
const task = new sfn.Task(stack, 'Task', {
task: new tasks.EvaluateExpression({
expression: '2 + 2',
}),
})).toThrow(/No paths found in expression/);
});
new sfn.StateMachine(stack, 'SM', {
definition: task,
});

expect(stack).toHaveResource('AWS::StepFunctions::StateMachine', {
DefinitionString: {
'Fn::Join': [
'',
[
'{"StartAt":"Task","States":{"Task":{"End":true,"Parameters":{"expression":"2 + 2",\"expressionAttributeValues\":{}},"Type":"Task","Resource":"',
{
'Fn::GetAtt': [
'Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1',
'Arn',
],
},
'"}}}',
],
],
},
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,14 @@
"Arn"
]
},
"\",\"ResultPath\":\"$.waitSeconds\"},\"Wait\":{\"Type\":\"Wait\",\"SecondsPath\":\"$.waitSeconds\",\"End\":true}}}"
"\",\"ResultPath\":\"$.d\"},\"Wait\":{\"Type\":\"Wait\",\"SecondsPath\":\"$.d\",\"Next\":\"Now\"},\"Now\":{\"End\":true,\"Parameters\":{\"expression\":\"(new Date()).toUTCString()\",\"expressionAttributeValues\":{}},\"Type\":\"Task\",\"Resource\":\"",
{
"Fn::GetAtt": [
"Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1",
"Arn"
]
},
"\",\"ResultPath\":\"$.now\"}}}"
]
]
},
Expand Down Expand Up @@ -190,5 +197,12 @@
"Type": "String",
"Description": "Artifact hash for asset \"26ff0ffbfcb72e0fa136547addc06082857c59c734b1dd8c4294b58f03f1d26c\""
}
},
"Outputs": {
"StateMachineARN": {
"Value": {
"Ref": "StateMachine2E01A3A5"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ import * as sfn from '@aws-cdk/aws-stepfunctions';
import * as cdk from '@aws-cdk/core';
import * as tasks from '../lib';

/*
* Stack verification steps:
* * aws stepfunctions start-execution --input '{"a": 3, "b": 4}' --state-machine-arn <StateMachineARN>
* * aws stepfunctions describe-execution --execution-arn <execution-arn>
* * The output here should contain `status: "SUCCEEDED"` and `output: "{ a: 3, b: 4, c: 7, d: 14, now: <current date> }"
*/

const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-stepfunctions-integ');

Expand All @@ -16,15 +23,27 @@ const multiply = new sfn.Task(stack, 'Multiply', {
task: new tasks.EvaluateExpression({
expression: '$.c * 2',
}),
resultPath: '$.waitSeconds',
resultPath: '$.d',
});

new sfn.StateMachine(stack, 'StateMachine', {
const now = new sfn.Task(stack, 'Now', {
task: new tasks.EvaluateExpression({
expression: '(new Date()).toUTCString()',
}),
resultPath: '$.now',
});

const statemachine = new sfn.StateMachine(stack, 'StateMachine', {
definition: sum
.next(multiply)
.next(new sfn.Wait(stack, 'Wait', {
time: sfn.WaitTime.secondsPath('$.waitSeconds'),
})),
time: sfn.WaitTime.secondsPath('$.d'),
}))
.next(now),
});

new cdk.CfnOutput(stack, 'StateMachineARN', {
value: statemachine.stateMachineArn,
});

app.synth();

0 comments on commit 97f4f01

Please sign in to comment.