Skip to content

Commit 6415b35

Browse files
authored
Merge pull request #124 from dougmoscrop/master
Support custom logicalId separate from name
2 parents 5c4c01e + 3756f9c commit 6415b35

File tree

8 files changed

+109
-36
lines changed

8 files changed

+109
-36
lines changed

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,30 @@ plugins:
8686
- serverless-step-functions
8787
```
8888

89+
### Adding a custom logical id for a stateMachine
90+
You can use a custom logical id that is only unique within the stack as opposed to the name that needs to be unique globally. This can make referencing the state machine easier/simpler because you don't have to duplicate the interpolation logic everywhere you reference the state machine.
91+
92+
```yml
93+
service: messager
94+
95+
functions:
96+
sendMessage:
97+
handler: handler.sendMessage
98+
99+
stepFunctions:
100+
stateMachines:
101+
sendMessageFunc:
102+
id: SendMessageStateMachine
103+
name: sendMessageFunc-${self:custom.service}-${opt:stage}
104+
definition:
105+
<your definition>
106+
107+
plugins:
108+
- serverless-step-functions
109+
```
110+
111+
You can then `Ref: SendMessageStateMachine` in various parts of CloudFormation or serverless.yml
112+
89113
#### Current Gotcha
90114
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.
91115

lib/deploy/events/apiGateway/methods.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module.exports = {
2525
};
2626

2727
_.merge(template,
28-
this.getMethodIntegration(event.stateMachineName, stateMachineObj.name, event.http),
28+
this.getMethodIntegration(event.stateMachineName, stateMachineObj, event.http),
2929
this.getMethodResponses(event.http)
3030
);
3131

@@ -42,7 +42,7 @@ module.exports = {
4242
return BbPromise.resolve();
4343
},
4444

45-
getMethodIntegration(stateMachineName, customName, http) {
45+
getMethodIntegration(stateMachineName, stateMachineObj, http) {
4646
const apiToStepFunctionsIamRoleLogicalId = this.getApiToStepFunctionsIamRoleLogicalId();
4747
const integration = {
4848
IntegrationHttpMethod: 'POST',
@@ -66,7 +66,11 @@ module.exports = {
6666
],
6767
},
6868
PassthroughBehavior: 'NEVER',
69-
RequestTemplates: this.getIntegrationRequestTemplates(stateMachineName, customName, http),
69+
RequestTemplates: this.getIntegrationRequestTemplates(
70+
stateMachineName,
71+
stateMachineObj,
72+
http
73+
),
7074
};
7175

7276
const integrationResponse = {
@@ -108,16 +112,19 @@ module.exports = {
108112
};
109113
},
110114

111-
getIntegrationRequestTemplates(stateMachineName, customName, http) {
112-
const defaultRequestTemplates = this.getDefaultRequestTemplates(stateMachineName, customName);
115+
getIntegrationRequestTemplates(stateMachineName, stateMachineObj, http) {
116+
const defaultRequestTemplates = this.getDefaultRequestTemplates(
117+
stateMachineName,
118+
stateMachineObj
119+
);
113120
return Object.assign(
114121
defaultRequestTemplates,
115122
_.get(http, ['request', 'template'])
116123
);
117124
},
118125

119-
getDefaultRequestTemplates(stateMachineName, customName) {
120-
const stateMachineLogicalId = this.getStateMachineLogicalId(stateMachineName, customName);
126+
getDefaultRequestTemplates(stateMachineName, stateMachineObj) {
127+
const stateMachineLogicalId = this.getStateMachineLogicalId(stateMachineName, stateMachineObj);
121128
return {
122129
'application/json': this.buildDefaultRequestTemplate(stateMachineLogicalId),
123130
'application/x-www-form-urlencoded': this.buildDefaultRequestTemplate(stateMachineLogicalId),

lib/deploy/events/apiGateway/methods.test.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,19 @@ describe('#methods()', () => {
8282
.to.have.property('Integration');
8383
});
8484

85+
it('should set stateMachinelogical ID to RequestTemplates when customName is not set', () => {
86+
expect(serverlessStepFunctions.getMethodIntegration('stateMachine').Properties
87+
.Integration.RequestTemplates['application/json']['Fn::Join'][1][2].Ref)
88+
.to.be.equal('StateMachineStepFunctionsStateMachine');
89+
});
90+
91+
it('should set custom stateMachinelogical ID to RequestTemplates when customName is set',
92+
() => {
93+
expect(serverlessStepFunctions.getMethodIntegration('stateMachine', { name: 'custom' })
94+
.Properties.Integration.RequestTemplates['application/json']['Fn::Join'][1][2].Ref)
95+
.to.be.equal('Custom');
96+
});
97+
8598
it('should set Access-Control-Allow-Origin header when cors is true',
8699
() => {
87100
expect(serverlessStepFunctions.getMethodIntegration('stateMachine', 'custom', {
@@ -113,7 +126,7 @@ describe('#methods()', () => {
113126
it('should set custom stateMachinelogical ID in default templates when customName is set',
114127
() => {
115128
const requestTemplates = serverlessStepFunctions
116-
.getIntegrationRequestTemplates('stateMachine', 'custom');
129+
.getIntegrationRequestTemplates('stateMachine', { name: 'custom' });
117130
expect(requestTemplates['application/json']['Fn::Join'][1][2].Ref)
118131
.to.be.equal('Custom');
119132
});

lib/deploy/events/schedule/compileScheduledEvents.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ module.exports = {
7474
}
7575

7676
const stateMachineLogicalId = this
77-
.getStateMachineLogicalId(stateMachineName, stateMachineObj.name);
77+
.getStateMachineLogicalId(stateMachineName, stateMachineObj);
7878
const scheduleLogicalId = this
7979
.getScheduleLogicalId(stateMachineName, scheduleNumberInFunction);
8080
const scheduleIamRoleLogicalId = this

lib/deploy/stepFunctions/compileStateMachines.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,6 @@ module.exports = {
1010
let DefinitionString;
1111
let RoleArn;
1212
let DependsOn;
13-
let Name;
14-
15-
if (stateMachineObj.name) {
16-
Name = stateMachineObj.name;
17-
}
1813

1914
if (stateMachineObj.definition) {
2015
DefinitionString = JSON.stringify(stateMachineObj.definition);
@@ -52,9 +47,10 @@ module.exports = {
5247
DependsOn = 'IamRoleStateMachineExecution';
5348
}
5449

55-
const stateMachineLogicalId = this.getStateMachineLogicalId(stateMachineName, Name);
50+
const stateMachineLogicalId = this.getStateMachineLogicalId(stateMachineName,
51+
stateMachineObj);
5652
const stateMachineOutputLogicalId = this
57-
.getStateMachineOutputLogicalId(stateMachineName, Name);
53+
.getStateMachineOutputLogicalId(stateMachineName, stateMachineObj);
5854

5955
const stateMachineTemplate = `
6056
{
@@ -72,8 +68,9 @@ module.exports = {
7268
[stateMachineLogicalId]: JSON.parse(stateMachineTemplate),
7369
};
7470

75-
if (Name) {
76-
newStateMachineObject[stateMachineLogicalId].Properties.StateMachineName = Name;
71+
if (stateMachineObj.name) {
72+
newStateMachineObject[stateMachineLogicalId].Properties.StateMachineName
73+
= stateMachineObj.name;
7774
}
7875

7976
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources,

lib/invoke/invoke.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,9 @@ const path = require('path');
55

66
module.exports = {
77
getStateMachineArn() {
8-
let stateMachineOutputKey;
9-
if (this.serverless.service.stepFunctions.stateMachines[this.options.name].name) {
10-
stateMachineOutputKey =
11-
this.getStateMachineOutputLogicalId(this.options.name
12-
, this.serverless.service.stepFunctions.stateMachines[this.options.name].name);
13-
} else {
14-
stateMachineOutputKey =
15-
this.getStateMachineOutputLogicalId(this.options.name);
16-
}
8+
const stateMachineOutputKey =
9+
this.getStateMachineOutputLogicalId(this.options.name,
10+
this.serverless.service.stepFunctions.stateMachines[this.options.name]);
1711

1812
const stackName = this.provider.naming.getStackName(this.options.stage);
1913

lib/naming.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
'use strict';
22

33
module.exports = {
4-
getStateMachineLogicalId(stateMachineName, customName) {
5-
if (customName) {
6-
return `${this.provider.naming.getNormalizedFunctionName(customName)}`;
4+
getStateMachineLogicalId(stateMachineName, stateMachine) {
5+
const custom = stateMachine ? stateMachine.id || stateMachine.name : null;
6+
7+
if (custom) {
8+
return `${this.provider.naming.getNormalizedFunctionName(custom)}`;
79
}
10+
811
return `${this.provider.naming
912
.getNormalizedFunctionName(stateMachineName)}StepFunctionsStateMachine`;
1013
},
1114

12-
getStateMachineOutputLogicalId(stateMachineName, customName) {
13-
if (customName) {
14-
return `${this.provider.naming.getNormalizedFunctionName(customName)}Arn`;
15+
getStateMachineOutputLogicalId(stateMachineName, stateMachine) {
16+
const custom = stateMachine ? stateMachine.id || stateMachine.name : null;
17+
18+
if (custom) {
19+
return `${this.provider.naming.getNormalizedFunctionName(custom)}Arn`;
1520
}
21+
1622
return `${this.provider.naming
1723
.getNormalizedFunctionName(stateMachineName)}StepFunctionsStateMachineArn`;
1824
},

lib/naming.test.js

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,50 @@ describe('#naming', () => {
3434

3535
describe('#getStateMachineLogicalId() -- Named', () => {
3636
it('should normalize the stateMachine name and add the standard suffix', () => {
37-
expect(serverlessStepFunctions.getStateMachineLogicalId('stateMachine', 'alphaNumeric')).to
38-
.equal('AlphaNumeric');
37+
expect(serverlessStepFunctions.getStateMachineLogicalId('stateMachine',
38+
{ name: 'alphaNumeric' }))
39+
.to.equal('AlphaNumeric');
3940
});
4041
});
4142

4243
describe('#getStateMachineOutputLogicalId() -- Named', () => {
4344
it('should normalize the stateMachine output name and add the standard suffix', () => {
44-
expect(serverlessStepFunctions.getStateMachineOutputLogicalId('stateMachine', 'alphaNumeric'))
45+
expect(serverlessStepFunctions.getStateMachineOutputLogicalId('stateMachine',
46+
{ name: 'alphaNumeric' }))
4547
.to.equal('AlphaNumericArn');
4648
});
4749
});
4850

51+
describe('#getStateMachineLogicalId() -- With Id', () => {
52+
it('should normalize the stateMachine name and add the standard suffix', () => {
53+
expect(serverlessStepFunctions.getStateMachineLogicalId('stateMachine',
54+
{ id: 'foo', name: 'alphaNumeric' }))
55+
.to.equal('Foo');
56+
});
57+
});
58+
59+
describe('#getStateMachineOutputLogicalId() -- With Id', () => {
60+
it('should normalize the stateMachine output name and add the standard suffix', () => {
61+
expect(serverlessStepFunctions.getStateMachineOutputLogicalId('stateMachine',
62+
{ id: 'foo', name: 'alphaNumeric' }))
63+
.to.equal('FooArn');
64+
});
65+
});
66+
67+
describe('#getStateMachineLogicalId() -- With Only Id', () => {
68+
it('should normalize the stateMachine name and add the standard suffix', () => {
69+
expect(serverlessStepFunctions.getStateMachineLogicalId('stateMachine', { id: 'foo' })).to
70+
.equal('Foo');
71+
});
72+
});
73+
74+
describe('#getStateMachineOutputLogicalId() -- With Only Id', () => {
75+
it('should normalize the stateMachine output name and add the standard suffix', () => {
76+
expect(serverlessStepFunctions.getStateMachineOutputLogicalId('stateMachine', { id: 'foo' }))
77+
.to.equal('FooArn');
78+
});
79+
});
80+
4981
describe('#getActivityLogicalId()', () => {
5082
it('should normalize the activity name and add the standard suffix', () => {
5183
expect(serverlessStepFunctions.getActivityLogicalId('activity')).to

0 commit comments

Comments
 (0)