Skip to content

Commit 6d04fb9

Browse files
- add support for a dependsOn option proposed by #158
1 parent 6915022 commit 6d04fb9

File tree

3 files changed

+130
-12
lines changed

3 files changed

+130
-12
lines changed

README.md

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ stepFunctions:
4747
Type: Task
4848
Resource: arn:aws:lambda:#{AWS::Region}:#{AWS::AccountId}:function:${self:service}-${opt:stage}-hello
4949
End: true
50+
dependsOn:
51+
Ref: DynamoDBTable
5052
hellostepfunc2:
5153
definition:
5254
StartAt: HelloWorld2
@@ -55,6 +57,10 @@ stepFunctions:
5557
Type: Task
5658
Resource: arn:aws:states:#{AWS::Region}:#{AWS::AccountId}:activity:myTask
5759
End: true
60+
dependsOn:
61+
- Ref: DynamoDBTable
62+
- Ref: KinesisStream
63+
- Ref: CUstomIamRole
5864
activities:
5965
- myTask
6066
- yourTask
@@ -110,6 +116,23 @@ plugins:
110116

111117
You can then `Ref: SendMessageStateMachine` in various parts of CloudFormation or serverless.yml
112118

119+
#### Depending on another logical id
120+
If your state machine depends on another resource defined in your `serverless.yml` then you can add a `dependsOn` field to the state machine `definition`. This would add the `DependsOn`clause to the generated CloudFormation template.
121+
122+
This `dependsOn` field can be either a string, or an array of strings.
123+
124+
```yaml
125+
stepFunctions:
126+
stateMachines:
127+
myStateMachine:
128+
dependsOn: myDB
129+
130+
myOtherStateMachine:
131+
dependsOn:
132+
- myOtherDB
133+
- myStream
134+
```
135+
113136
#### Current Gotcha
114137
Please keep this gotcha in mind if you want to reference the `name` from the `resources` section. To generate Logical ID for CloudFormation, the plugin transforms the specified name in serverless.yml based on the following scheme.
115138

@@ -329,11 +352,11 @@ stepFunctions:
329352
events:
330353
- http:
331354
path: /users
332-
...
355+
...
333356
authorizer:
334357
# Provide both type and authorizerId
335358
type: COGNITO_USER_POOLS # TOKEN, CUSTOM or COGNITO_USER_POOLS, same as AWS Cloudformation documentation
336-
authorizerId:
359+
authorizerId:
337360
Ref: ApiGatewayAuthorizer # or hard-code Authorizer ID
338361
```
339362

@@ -581,7 +604,7 @@ stepFunctions:
581604
state:
582605
- pending
583606
definition:
584-
...
607+
...
585608
```
586609

587610
## Specifying a Name
@@ -654,7 +677,7 @@ resources:
654677
Resources:
655678
StateMachineRole:
656679
Type: AWS::IAM::Role
657-
Properties:
680+
Properties:
658681
...
659682
```
660683

lib/deploy/stepFunctions/compileStateMachines.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ module.exports = {
1515
const stateMachineObj = this.getStateMachine(stateMachineName);
1616
let DefinitionString;
1717
let RoleArn;
18-
let DependsOn;
18+
let DependsOn = [];
1919

2020
if (stateMachineObj.definition) {
2121
if (typeof stateMachineObj.definition === 'string') {
@@ -63,7 +63,24 @@ module.exports = {
6363
'Arn',
6464
],
6565
};
66-
DependsOn = 'IamRoleStateMachineExecution';
66+
DependsOn.push('IamRoleStateMachineExecution');
67+
}
68+
69+
if (stateMachineObj.dependsOn) {
70+
const dependsOn = stateMachineObj.dependsOn;
71+
72+
if (_.isArray(dependsOn) && _.every(dependsOn, _.isString)) {
73+
DependsOn = _.concat(DependsOn, dependsOn);
74+
} else if (_.isString(dependsOn)) {
75+
DependsOn.push(dependsOn);
76+
} else {
77+
const errorMessage = [
78+
`dependsOn property in stateMachine "${stateMachineName}" is neither a string`,
79+
' nor an array of strings',
80+
].join('');
81+
throw new this.serverless.classes
82+
.Error(errorMessage);
83+
}
6784
}
6885

6986
const stateMachineLogicalId = this.getStateMachineLogicalId(stateMachineName,

lib/deploy/stepFunctions/compileStateMachines.test.js

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ describe('#compileStateMachines', () => {
6464
expect(serverlessStepFunctions.serverless.service
6565
.provider.compiledCloudFormationTemplate.Resources
6666
.StateMachineBeta1.DependsOn
67-
).to.equal('IamRoleStateMachineExecution');
67+
).to.deep.eq(['IamRoleStateMachineExecution']);
6868
expect(serverlessStepFunctions.serverless.service
6969
.provider.compiledCloudFormationTemplate.Resources
7070
.StateMachineBeta2.DependsOn
71-
).to.equal('IamRoleStateMachineExecution');
71+
).to.deep.eq(['IamRoleStateMachineExecution']);
7272
expect(serverlessStepFunctions.serverless.service
7373
.provider.compiledCloudFormationTemplate.Outputs
7474
.StateMachineBeta1Arn.Value.Ref
@@ -119,11 +119,11 @@ describe('#compileStateMachines', () => {
119119
expect(serverlessStepFunctions.serverless.service
120120
.provider.compiledCloudFormationTemplate.Resources
121121
.MyStateMachine1StepFunctionsStateMachine.DependsOn
122-
).to.equal('IamRoleStateMachineExecution');
122+
).to.deep.eq(['IamRoleStateMachineExecution']);
123123
expect(serverlessStepFunctions.serverless.service
124124
.provider.compiledCloudFormationTemplate.Resources
125125
.MyStateMachine2StepFunctionsStateMachine.DependsOn
126-
).to.equal('IamRoleStateMachineExecution');
126+
).to.deep.eq(['IamRoleStateMachineExecution']);
127127
expect(serverlessStepFunctions.serverless.service
128128
.provider.compiledCloudFormationTemplate.Outputs
129129
.MyStateMachine1StepFunctionsStateMachineArn.Value.Ref
@@ -176,11 +176,11 @@ describe('#compileStateMachines', () => {
176176
expect(serverlessStepFunctions.serverless.service
177177
.provider.compiledCloudFormationTemplate.Resources
178178
.StateMachineBeta1.DependsOn
179-
).to.equal('IamRoleStateMachineExecution');
179+
).to.deep.eq(['IamRoleStateMachineExecution']);
180180
expect(serverlessStepFunctions.serverless.service
181181
.provider.compiledCloudFormationTemplate.Resources
182182
.StateMachineBeta2.DependsOn
183-
).to.equal('IamRoleStateMachineExecution');
183+
).to.deep.eq(['IamRoleStateMachineExecution']);
184184
});
185185

186186
it('should create corresponding resources when definition and role property are given', () => {
@@ -405,4 +405,82 @@ describe('#compileStateMachines', () => {
405405

406406
expect(actual).to.equal(JSON.stringify(definition, undefined, 2));
407407
});
408+
409+
it('should add dependsOn resources', () => {
410+
serverless.service.stepFunctions = {
411+
stateMachines: {
412+
myStateMachine1: {
413+
definition: 'definition1',
414+
name: 'stateMachineBeta1',
415+
dependsOn: 'DynamoDBTable',
416+
},
417+
myStateMachine2: {
418+
definition: 'definition2',
419+
name: 'stateMachineBeta2',
420+
dependsOn: [
421+
'DynamoDBTable',
422+
'KinesisStream',
423+
],
424+
},
425+
},
426+
};
427+
428+
serverlessStepFunctions.compileStateMachines();
429+
expect(serverlessStepFunctions.serverless.service
430+
.provider.compiledCloudFormationTemplate.Resources
431+
.StateMachineBeta1.Type
432+
).to.equal('AWS::StepFunctions::StateMachine');
433+
expect(serverlessStepFunctions.serverless.service
434+
.provider.compiledCloudFormationTemplate.Resources
435+
.StateMachineBeta2.Type
436+
).to.equal('AWS::StepFunctions::StateMachine');
437+
expect(serverlessStepFunctions.serverless.service
438+
.provider.compiledCloudFormationTemplate.Resources
439+
.StateMachineBeta1.Properties.DefinitionString
440+
).to.equal('"definition1"');
441+
expect(serverlessStepFunctions.serverless.service
442+
.provider.compiledCloudFormationTemplate.Resources
443+
.StateMachineBeta2.Properties.DefinitionString
444+
).to.equal('"definition2"');
445+
expect(serverlessStepFunctions.serverless.service
446+
.provider.compiledCloudFormationTemplate.Resources
447+
.StateMachineBeta1.Properties.RoleArn['Fn::GetAtt'][0]
448+
).to.equal('IamRoleStateMachineExecution');
449+
expect(serverlessStepFunctions.serverless.service
450+
.provider.compiledCloudFormationTemplate.Resources
451+
.StateMachineBeta2.Properties.RoleArn['Fn::GetAtt'][0]
452+
).to.equal('IamRoleStateMachineExecution');
453+
expect(serverlessStepFunctions.serverless.service
454+
.provider.compiledCloudFormationTemplate.Resources
455+
.StateMachineBeta1.DependsOn
456+
).to.deep.eq(['IamRoleStateMachineExecution', 'DynamoDBTable']);
457+
expect(serverlessStepFunctions.serverless.service
458+
.provider.compiledCloudFormationTemplate.Resources
459+
.StateMachineBeta2.DependsOn
460+
).to.deep.eq(['IamRoleStateMachineExecution', 'DynamoDBTable', 'KinesisStream']);
461+
});
462+
463+
it('should throw error when dependsOn property is neither string nor [string]', () => {
464+
serverless.service.stepFunctions = {
465+
stateMachines: {
466+
myStateMachine1: {
467+
definition: 'definition1',
468+
name: 'stateMachineBeta1',
469+
dependsOn: { Ref: 'ss' },
470+
},
471+
},
472+
};
473+
expect(() => serverlessStepFunctions.compileStateMachines()).to.throw(Error);
474+
475+
serverless.service.stepFunctions = {
476+
stateMachines: {
477+
myStateMachine1: {
478+
definition: 'definition1',
479+
name: 'stateMachineBeta1',
480+
dependsOn: [{ Ref: 'ss' }],
481+
},
482+
},
483+
};
484+
expect(() => serverlessStepFunctions.compileStateMachines()).to.throw(Error);
485+
});
408486
});

0 commit comments

Comments
 (0)