-
Notifications
You must be signed in to change notification settings - Fork 3.9k
/
start-execution.ts
159 lines (140 loc) · 6.06 KB
/
start-execution.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import { Construct } from 'constructs';
import * as iam from '../../../aws-iam';
import * as sfn from '../../../aws-stepfunctions';
import { ArnFormat, Stack } from '../../../core';
import { integrationResourceArn, validatePatternSupported } from '../private/task-utils';
/**
* Properties for StartExecution
*/
export interface StepFunctionsStartExecutionProps extends sfn.TaskStateBaseProps {
/**
* The Step Functions state machine to start the execution on.
*/
readonly stateMachine: sfn.IStateMachine;
/**
* The JSON input for the execution, same as that of StartExecution.
*
* @see https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html
*
* @default - The state input (JSON path '$')
*/
readonly input?: sfn.TaskInput;
/**
* The name of the execution, same as that of StartExecution.
*
* @see https://docs.aws.amazon.com/step-functions/latest/apireference/API_StartExecution.html
*
* @default - None
*/
readonly name?: string;
/**
* Pass the execution ID from the context object to the execution input.
* This allows the Step Functions UI to link child executions from parent executions, making it easier to trace execution flow across state machines.
*
* If you set this property to `true`, the `input` property must be an object (provided by `sfn.TaskInput.fromObject`) or omitted entirely.
*
* @see https://docs.aws.amazon.com/step-functions/latest/dg/concepts-nested-workflows.html#nested-execution-startid
*
* @default - false
*/
readonly associateWithParent?: boolean;
}
/**
* A Step Functions Task to call StartExecution on another state machine.
*
* It supports three service integration patterns: REQUEST_RESPONSE, RUN_JOB, and WAIT_FOR_TASK_TOKEN.
*/
export class StepFunctionsStartExecution extends sfn.TaskStateBase {
private static readonly SUPPORTED_INTEGRATION_PATTERNS = [
sfn.IntegrationPattern.REQUEST_RESPONSE,
sfn.IntegrationPattern.RUN_JOB,
sfn.IntegrationPattern.WAIT_FOR_TASK_TOKEN,
];
protected readonly taskMetrics?: sfn.TaskMetricsConfig;
protected readonly taskPolicies?: iam.PolicyStatement[];
private readonly integrationPattern: sfn.IntegrationPattern;
constructor(scope: Construct, id: string, private readonly props: StepFunctionsStartExecutionProps) {
super(scope, id, props);
this.integrationPattern = props.integrationPattern || sfn.IntegrationPattern.REQUEST_RESPONSE;
validatePatternSupported(this.integrationPattern, StepFunctionsStartExecution.SUPPORTED_INTEGRATION_PATTERNS);
if (this.integrationPattern === sfn.IntegrationPattern.WAIT_FOR_TASK_TOKEN && !sfn.FieldUtils.containsTaskToken(props.input)) {
throw new Error('Task Token is required in `input` for callback. Use JsonPath.taskToken to set the token.');
}
if (this.props.associateWithParent && props.input && props.input.type !== sfn.InputType.OBJECT) {
throw new Error('Could not enable `associateWithParent` because `input` is taken directly from a JSON path. Use `sfn.TaskInput.fromObject` instead.');
}
this.taskPolicies = this.createScopedAccessPolicy();
}
/**
* @internal
*/
protected _renderTask(): any {
// suffix of ':2' indicates that the output of the nested state machine should be JSON
// suffix is only applicable when waiting for a nested state machine to complete (RUN_JOB)
// https://docs.aws.amazon.com/step-functions/latest/dg/connect-stepfunctions.html
const suffix = this.integrationPattern === sfn.IntegrationPattern.RUN_JOB ? ':2' : '';
let input: any;
if (this.props.associateWithParent) {
const associateWithParentEntry = {
AWS_STEP_FUNCTIONS_STARTED_BY_EXECUTION_ID: sfn.JsonPath.stringAt('$$.Execution.Id'),
};
input = this.props.input ? { ...this.props.input.value, ...associateWithParentEntry } : associateWithParentEntry;
} else {
input = this.props.input ? this.props.input.value: sfn.TaskInput.fromJsonPathAt('$').value;
}
return {
Resource: `${integrationResourceArn('states', 'startExecution', this.integrationPattern)}${suffix}`,
Parameters: sfn.FieldUtils.renderObject({
Input: input,
StateMachineArn: this.props.stateMachine.stateMachineArn,
Name: this.props.name,
}),
};
}
/**
* As StateMachineArn is extracted automatically from the state machine object included in the constructor,
*
* the scoped access policy should be generated accordingly.
*
* This means the action of StartExecution should be restricted on the given state machine, instead of being granted to all the resources (*).
*/
private createScopedAccessPolicy(): iam.PolicyStatement[] {
const stack = Stack.of(this);
const policyStatements = [
new iam.PolicyStatement({
actions: ['states:StartExecution'],
resources: [this.props.stateMachine.stateMachineArn],
}),
];
// Step Functions use Cloud Watch managed rules to deal with synchronous tasks.
if (this.integrationPattern === sfn.IntegrationPattern.RUN_JOB) {
policyStatements.push(
new iam.PolicyStatement({
actions: ['states:DescribeExecution', 'states:StopExecution'],
// https://docs.aws.amazon.com/step-functions/latest/dg/concept-create-iam-advanced.html#concept-create-iam-advanced-execution
resources: [
stack.formatArn({
service: 'states',
resource: 'execution',
arnFormat: ArnFormat.COLON_RESOURCE_NAME,
resourceName: `${stack.splitArn(this.props.stateMachine.stateMachineArn, ArnFormat.COLON_RESOURCE_NAME).resourceName}*`,
}),
],
}),
);
policyStatements.push(
new iam.PolicyStatement({
actions: ['events:PutTargets', 'events:PutRule', 'events:DescribeRule'],
resources: [
stack.formatArn({
service: 'events',
resource: 'rule',
resourceName: 'StepFunctionsGetEventsForStepFunctionsExecutionRule',
}),
],
}),
);
}
return policyStatements;
}
}