Skip to content

Commit 1c0b347

Browse files
authored
Merge pull request #546 from akshaydk/distributed_map_support
feat: add IAM role to distributed_map to start the state machine
2 parents b1cb3b6 + c7d22ba commit 1c0b347

File tree

2 files changed

+79
-7
lines changed

2 files changed

+79
-7
lines changed

lib/deploy/stepFunctions/compileIamRole.js

+22-7
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,27 @@ const { getArnPartition } = require('../../utils/arn');
88

99
const logger = require('../../utils/logger');
1010

11-
function getTaskStates(states) {
11+
function getTaskStates(states, stateMachineName) {
1212
return _.flatMap(states, (state) => {
1313
switch (state.Type) {
1414
case 'Task': {
1515
return [state];
1616
}
1717
case 'Parallel': {
1818
const parallelStates = _.flatMap(state.Branches, branch => _.values(branch.States));
19-
return getTaskStates(parallelStates);
19+
return getTaskStates(parallelStates, stateMachineName);
2020
}
2121
case 'Map': {
2222
const mapStates = state.ItemProcessor ? state.ItemProcessor.States : state.Iterator.States;
23-
const taskStates = getTaskStates(mapStates);
23+
const taskStates = getTaskStates(mapStates, stateMachineName);
24+
if (state.ItemProcessor && state.ItemProcessor.ProcessorConfig
25+
&& state.ItemProcessor.ProcessorConfig.Mode === 'DISTRIBUTED') {
26+
taskStates.push({
27+
Resource: 'arn:aws:states:::states:startExecution',
28+
Mode: 'DISTRIBUTED',
29+
StateMachineName: stateMachineName,
30+
});
31+
}
2432
if (state.ItemReader) {
2533
taskStates.push(state.ItemReader);
2634
}
@@ -303,9 +311,16 @@ function getLambdaPermissions(state) {
303311
}
304312

305313
function getStepFunctionsPermissions(state) {
306-
const stateMachineArn = state.Parameters['StateMachineArn.$']
307-
? '*'
308-
: state.Parameters.StateMachineArn;
314+
let stateMachineArn = state.Mode === 'DISTRIBUTED' ? {
315+
'Fn::Sub': [
316+
`arn:aws:states:\${AWS::Region}:\${AWS::AccountId}:stateMachine:${state.StateMachineName}`,
317+
],
318+
} : null;
319+
320+
if (!stateMachineArn) {
321+
stateMachineArn = state.Parameters['StateMachineArn.$'] ? '*'
322+
: state.Parameters.StateMachineArn;
323+
}
309324

310325
return [{
311326
action: 'states:StartExecution',
@@ -591,7 +606,7 @@ module.exports = {
591606
throw new Error(`Missing "definition" for state machine ${stateMachineName}`);
592607
}
593608

594-
const taskStates = getTaskStates(stateMachineObj.definition.States);
609+
const taskStates = getTaskStates(stateMachineObj.definition.States, stateMachineName);
595610
let iamPermissions = getIamPermissions.bind(this)(taskStates);
596611

597612
if (stateMachineObj.loggingConfig) {

lib/deploy/stepFunctions/compileIamRole.test.js

+57
Original file line numberDiff line numberDiff line change
@@ -2286,6 +2286,63 @@ describe('#compileIamRole', () => {
22862286
expect(lambdaPermissions[0].Resource).to.deep.equal(lambdaArns);
22872287
});
22882288

2289+
it('should support Distributed Map state type', () => {
2290+
const getStateMachine = (id, lambdaArn) => ({
2291+
id,
2292+
definition: {
2293+
StartAt: 'A',
2294+
States: {
2295+
A: {
2296+
Type: 'Map',
2297+
ItemProcessor: {
2298+
ProcessorConfig: {
2299+
Mode: 'DISTRIBUTED',
2300+
},
2301+
StartAt: 'B',
2302+
States: {
2303+
B: {
2304+
Type: 'Task',
2305+
Resource: lambdaArn,
2306+
End: true,
2307+
},
2308+
},
2309+
},
2310+
End: true,
2311+
},
2312+
},
2313+
},
2314+
});
2315+
2316+
serverless.service.stepFunctions = {
2317+
stateMachines: {
2318+
myStateMachine: getStateMachine('StateMachine1', 'arn:aws:lambda:us-west-2:1234567890:function:foo'),
2319+
},
2320+
};
2321+
2322+
serverlessStepFunctions.compileIamRole();
2323+
const statements = serverlessStepFunctions.serverless.service
2324+
.provider.compiledCloudFormationTemplate.Resources.StateMachine1Role
2325+
.Properties.Policies[0].PolicyDocument.Statement;
2326+
2327+
const lambdaPermissions = statements.filter(s => _.isEqual(s.Action, ['lambda:InvokeFunction']));
2328+
expect(lambdaPermissions).to.have.lengthOf(1);
2329+
2330+
const lambdaArns = [
2331+
'arn:aws:lambda:us-west-2:1234567890:function:foo',
2332+
getAlias('arn:aws:lambda:us-west-2:1234567890:function:foo'),
2333+
];
2334+
expect(lambdaPermissions[0].Resource).to.deep.equal(lambdaArns);
2335+
2336+
const stepFunctionPermission = statements.filter(s => _.isEqual(s.Action, ['states:StartExecution']));
2337+
expect(stepFunctionPermission).to.have.lengthOf(1);
2338+
expect(stepFunctionPermission[0].Resource).to.deep.eq([{
2339+
'Fn::Sub': [
2340+
'arn:aws:states:${AWS::Region}:${AWS::AccountId}:stateMachine:myStateMachine',
2341+
],
2342+
},
2343+
]);
2344+
});
2345+
22892346
it('should support nested Map state type', () => {
22902347
const getStateMachine = (id, lambdaArn1, lambdaArn2) => ({
22912348
id,

0 commit comments

Comments
 (0)