diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md index 6665cc4196b23..239c943674c2e 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/README.md +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/README.md @@ -164,25 +164,22 @@ Use the `EvaluateExpression` to perform simple operations referencing state path Example: convert a wait time from milliseconds to seconds, concat this in a message and wait: ```ts -const convertToSeconds = new sfn.Task(this, 'Convert to seconds', { - task: new tasks.EvaluateExpression({ expression: '$.waitMilliseconds / 1000' }), - resultPath: '$.waitSeconds' +const convertToSeconds = new tasks.EvaluateExpression(this, 'Convert to seconds', { + expression: '$.waitMilliseconds / 1000', + resultPath: '$.waitSeconds', }); -const createMessage = new sfn.Task(this, 'Create message', { +const createMessage = new tasks.EvaluateExpression(this, 'Create message', { // Note: this is a string inside a string. - task: new tasks.EvaluateExpression({ expression: '`Now waiting ${$.waitSeconds} seconds...`', runtime: lambda.Runtime.NODEJS_10_X, - }), - resultPath: '$.message' + resultPath: '$.message', }); -const publishMessage = new sfn.Task(this, 'Publish message', { - task: new tasks.PublishToTopic(topic, { - message: sfn.TaskInput.fromDataAt('$.message'), - }), - resultPath: '$.sns' +const publishMessage = new tasks.SnsPublish(this, 'Publish message', { + topic, + message: sfn.TaskInput.fromDataAt('$.message'), + resultPath: '$.sns', }); const wait = new sfn.Wait(this, 'Wait', { diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/evaluate-expression.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/evaluate-expression.ts index 0e13d9d90c1e3..e07da1a16493b 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/lib/evaluate-expression.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/lib/evaluate-expression.ts @@ -9,7 +9,7 @@ import * as path from 'path'; * * @experimental */ -export interface EvaluateExpressionProps { +export interface EvaluateExpressionProps extends sfn.TaskStateBaseProps { /** * The expression to evaluate. The expression may contain state paths. * @@ -49,11 +49,29 @@ export interface Event { * * @experimental */ -export class EvaluateExpression implements sfn.IStepFunctionsTask { - constructor(private readonly props: EvaluateExpressionProps) { +export class EvaluateExpression extends sfn.TaskStateBase { + protected readonly taskMetrics?: sfn.TaskMetricsConfig; + protected readonly taskPolicies?: iam.PolicyStatement[]; + + private readonly evalFn: lambda.SingletonFunction; + + constructor(scope: cdk.Construct, id: string, private readonly props: EvaluateExpressionProps) { + super(scope, id, props); + + this.evalFn = createEvalFn(this.props.runtime || lambda.Runtime.NODEJS_10_X, this); + + this.taskPolicies = [ + new iam.PolicyStatement({ + resources: [this.evalFn.functionArn], + actions: ['lambda:InvokeFunction'], + }), + ]; } - public bind(task: sfn.Task): sfn.StepFunctionsTaskConfig { + /** + * @internal + */ + protected _renderTask(): any { const matches = this.props.expression.match(/\$[.\[][.a-zA-Z[\]0-9]+/g); let expressionAttributeValues = {}; @@ -67,19 +85,13 @@ export class EvaluateExpression implements sfn.IStepFunctionsTask { ); } - 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, + Resource: this.evalFn.functionArn, + Parameters: sfn.FieldUtils.renderObject(parameters), }; } } diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/evaluate-expression.test.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/evaluate-expression.test.ts index d1235d66a16aa..0bcc3cc3e98c3 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/evaluate-expression.test.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/evaluate-expression.test.ts @@ -10,10 +10,8 @@ beforeEach(() => { test('Eval with Node.js', () => { // WHEN - const task = new sfn.Task(stack, 'Task', { - task: new tasks.EvaluateExpression({ - expression: '$.a + $.b', - }), + const task = new tasks.EvaluateExpression(stack, 'Task', { + expression: '$.a + $.b', }); new sfn.StateMachine(stack, 'SM', { definition: task, @@ -25,14 +23,11 @@ test('Eval with Node.js', () => { 'Fn::Join': [ '', [ - '{"StartAt":"Task","States":{"Task":{"End":true,"Parameters":{"expression":"$.a + $.b","expressionAttributeValues":{"$.a.$":"$.a","$.b.$":"$.b"}},"Type":"Task","Resource":"', + '{"StartAt":"Task","States":{"Task":{"End":true,"Type":"Task","Resource":"', { - 'Fn::GetAtt': [ - 'Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1', - 'Arn', - ], + 'Fn::GetAtt': ['Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1', 'Arn'], }, - '"}}}', + '","Parameters":{"expression":"$.a + $.b","expressionAttributeValues":{"$.a.$":"$.a","$.b.$":"$.b"}}}}}', ], ], }, @@ -45,10 +40,8 @@ test('Eval with Node.js', () => { test('expression does not contain paths', () => { // WHEN - const task = new sfn.Task(stack, 'Task', { - task: new tasks.EvaluateExpression({ - expression: '2 + 2', - }), + const task = new tasks.EvaluateExpression(stack, 'Task', { + expression: '2 + 2', }); new sfn.StateMachine(stack, 'SM', { definition: task, @@ -59,14 +52,11 @@ test('expression does not contain paths', () => { 'Fn::Join': [ '', [ - '{"StartAt":"Task","States":{"Task":{"End":true,"Parameters":{"expression":"2 + 2",\"expressionAttributeValues\":{}},"Type":"Task","Resource":"', + '{"StartAt":"Task","States":{"Task":{"End":true,"Type":"Task","Resource":"', { - 'Fn::GetAtt': [ - 'Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1', - 'Arn', - ], + 'Fn::GetAtt': ['Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1', 'Arn'], }, - '"}}}', + '","Parameters":{"expression":"2 + 2","expressionAttributeValues":{}}}}}', ], ], }, diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/integ.evaluate-expression.expected.json b/packages/@aws-cdk/aws-stepfunctions-tasks/test/integ.evaluate-expression.expected.json index 7c44d5f356e85..efdf3878e67e2 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/integ.evaluate-expression.expected.json +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/integ.evaluate-expression.expected.json @@ -142,40 +142,40 @@ "StateMachine2E01A3A5": { "Type": "AWS::StepFunctions::StateMachine", "Properties": { + "RoleArn": { + "Fn::GetAtt": [ + "StateMachineRoleB840431D", + "Arn" + ] + }, "DefinitionString": { "Fn::Join": [ "", [ - "{\"StartAt\":\"Sum\",\"States\":{\"Sum\":{\"Next\":\"Multiply\",\"Parameters\":{\"expression\":\"$.a + $.b\",\"expressionAttributeValues\":{\"$.a.$\":\"$.a\",\"$.b.$\":\"$.b\"}},\"Type\":\"Task\",\"Resource\":\"", + "{\"StartAt\":\"Sum\",\"States\":{\"Sum\":{\"Next\":\"Multiply\",\"Type\":\"Task\",\"ResultPath\":\"$.c\",\"Resource\":\"", { "Fn::GetAtt": [ "Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1", "Arn" ] }, - "\",\"ResultPath\":\"$.c\"},\"Multiply\":{\"Next\":\"Wait\",\"Parameters\":{\"expression\":\"$.c * 2\",\"expressionAttributeValues\":{\"$.c.$\":\"$.c\"}},\"Type\":\"Task\",\"Resource\":\"", + "\",\"Parameters\":{\"expression\":\"$.a + $.b\",\"expressionAttributeValues\":{\"$.a.$\":\"$.a\",\"$.b.$\":\"$.b\"}}},\"Multiply\":{\"Next\":\"Wait\",\"Type\":\"Task\",\"ResultPath\":\"$.d\",\"Resource\":\"", { "Fn::GetAtt": [ "Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1", "Arn" ] }, - "\",\"ResultPath\":\"$.d\"},\"Wait\":{\"Type\":\"Wait\",\"SecondsPath\":\"$.d\",\"Next\":\"Now\"},\"Now\":{\"End\":true,\"Parameters\":{\"expression\":\"(new Date()).toUTCString()\",\"expressionAttributeValues\":{}},\"Type\":\"Task\",\"Resource\":\"", + "\",\"Parameters\":{\"expression\":\"$.c * 2\",\"expressionAttributeValues\":{\"$.c.$\":\"$.c\"}}},\"Wait\":{\"Type\":\"Wait\",\"SecondsPath\":\"$.d\",\"Next\":\"Now\"},\"Now\":{\"End\":true,\"Type\":\"Task\",\"ResultPath\":\"$.now\",\"Resource\":\"", { "Fn::GetAtt": [ "Evala0d2ce44871b4e7487a1f5e63d7c3bdc4DAC06E1", "Arn" ] }, - "\",\"ResultPath\":\"$.now\"}}}" + "\",\"Parameters\":{\"expression\":\"(new Date()).toUTCString()\",\"expressionAttributeValues\":{}}}}}" ] ] - }, - "RoleArn": { - "Fn::GetAtt": [ - "StateMachineRoleB840431D", - "Arn" - ] } }, "DependsOn": [ diff --git a/packages/@aws-cdk/aws-stepfunctions-tasks/test/integ.evaluate-expression.ts b/packages/@aws-cdk/aws-stepfunctions-tasks/test/integ.evaluate-expression.ts index 0dac6789aeb7c..8034635352b32 100644 --- a/packages/@aws-cdk/aws-stepfunctions-tasks/test/integ.evaluate-expression.ts +++ b/packages/@aws-cdk/aws-stepfunctions-tasks/test/integ.evaluate-expression.ts @@ -12,33 +12,29 @@ import * as tasks from '../lib'; const app = new cdk.App(); const stack = new cdk.Stack(app, 'aws-stepfunctions-integ'); -const sum = new sfn.Task(stack, 'Sum', { - task: new tasks.EvaluateExpression({ - expression: '$.a + $.b', - }), +const sum = new tasks.EvaluateExpression(stack, 'Sum', { + expression: '$.a + $.b', resultPath: '$.c', }); -const multiply = new sfn.Task(stack, 'Multiply', { - task: new tasks.EvaluateExpression({ - expression: '$.c * 2', - }), +const multiply = new tasks.EvaluateExpression(stack, 'Multiply', { + expression: '$.c * 2', resultPath: '$.d', }); -const now = new sfn.Task(stack, 'Now', { - task: new tasks.EvaluateExpression({ - expression: '(new Date()).toUTCString()', - }), +const now = new tasks.EvaluateExpression(stack, 'Now', { + 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('$.d'), - })) + .next( + new sfn.Wait(stack, 'Wait', { + time: sfn.WaitTime.secondsPath('$.d'), + }), + ) .next(now), });