Skip to content

Commit 7d531e1

Browse files
fix: "undefined" in API GW deployment's logical id
Closes #294
1 parent 755e334 commit 7d531e1

File tree

2 files changed

+113
-48
lines changed

2 files changed

+113
-48
lines changed

lib/deploy/events/apiGateway/deployment.js

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,31 @@ const BbPromise = require('bluebird');
55

66
module.exports = {
77
compileDeployment() {
8-
this.apiGatewayDeploymentLogicalId = this.provider.naming
9-
.generateApiGatewayDeploymentLogicalId();
8+
const resources = this.serverless.service.provider.compiledCloudFormationTemplate.Resources;
9+
const logicalIds = Object.keys(resources);
10+
const logicalIdFromStack = logicalIds.find(
11+
id => resources[id].Type === 'AWS::ApiGateway::Deployment',
12+
);
13+
const defaultLogicalId = this.provider.naming
14+
.generateApiGatewayDeploymentLogicalId(this.serverless.instanceId);
1015

11-
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Resources, {
12-
[this.apiGatewayDeploymentLogicalId]: {
13-
Type: 'AWS::ApiGateway::Deployment',
14-
Properties: {
15-
RestApiId: this.provider.getApiGatewayRestApiId(),
16-
StageName: this.options.stage,
16+
this.apiGatewayDeploymentLogicalId = logicalIdFromStack || defaultLogicalId;
17+
18+
if (logicalIdFromStack) {
19+
resources[logicalIdFromStack].DependsOn = resources[logicalIdFromStack]
20+
.DependsOn.concat(this.apiGatewayMethodLogicalIds);
21+
} else {
22+
_.merge(resources, {
23+
[this.apiGatewayDeploymentLogicalId]: {
24+
Type: 'AWS::ApiGateway::Deployment',
25+
Properties: {
26+
RestApiId: this.provider.getApiGatewayRestApiId(),
27+
StageName: this.options.stage,
28+
},
29+
DependsOn: this.apiGatewayMethodLogicalIds,
1730
},
18-
DependsOn: this.apiGatewayMethodLogicalIds,
19-
},
20-
});
31+
});
32+
}
2133

2234
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Outputs, {
2335
ServiceEndpoint: {

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

Lines changed: 90 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ describe('#compileDeployment()', () => {
1111

1212
beforeEach(() => {
1313
serverless = new Serverless();
14+
serverless.instanceId = '1234';
1415
serverless.setProvider('aws', new AwsProvider(serverless));
1516
serverless.service.provider.compiledCloudFormationTemplate = {
1617
Resources: {},
@@ -25,45 +26,97 @@ describe('#compileDeployment()', () => {
2526
serverlessStepFunctions.apiGatewayMethodLogicalIds = ['method-dependency1', 'method-dependency2'];
2627
});
2728

28-
it('should create a deployment resource', () => serverlessStepFunctions
29-
.compileDeployment().then(() => {
30-
const apiGatewayDeploymentLogicalId = Object
31-
.keys(serverlessStepFunctions.serverless.service.provider
32-
.compiledCloudFormationTemplate.Resources)[0];
29+
describe('when there are no API Gateway deployment resource', () => {
30+
it('should create a deployment resource', () => serverlessStepFunctions
31+
.compileDeployment().then(() => {
32+
const apiGatewayDeploymentLogicalId = Object
33+
.keys(serverlessStepFunctions.serverless.service.provider
34+
.compiledCloudFormationTemplate.Resources)[0];
3335

34-
expect(
35-
serverlessStepFunctions.serverless.service.provider.compiledCloudFormationTemplate
36-
.Resources[apiGatewayDeploymentLogicalId],
37-
).to.deep.equal({
38-
Type: 'AWS::ApiGateway::Deployment',
39-
DependsOn: ['method-dependency1', 'method-dependency2'],
40-
Properties: {
41-
RestApiId: { Ref: serverlessStepFunctions.apiGatewayRestApiLogicalId },
42-
StageName: 'dev',
43-
},
44-
});
45-
}));
36+
// eslint-disable-next-line no-unused-expressions
37+
expect(apiGatewayDeploymentLogicalId.endsWith('1234')).to.be.true;
38+
expect(
39+
serverlessStepFunctions.serverless.service.provider.compiledCloudFormationTemplate
40+
.Resources[apiGatewayDeploymentLogicalId],
41+
).to.deep.equal({
42+
Type: 'AWS::ApiGateway::Deployment',
43+
DependsOn: ['method-dependency1', 'method-dependency2'],
44+
Properties: {
45+
RestApiId: { Ref: serverlessStepFunctions.apiGatewayRestApiLogicalId },
46+
StageName: 'dev',
47+
},
48+
});
49+
}));
4650

47-
it('should add service endpoint output', () => serverlessStepFunctions.compileDeployment().then(() => {
48-
expect(
49-
serverlessStepFunctions.serverless.service.provider.compiledCloudFormationTemplate
50-
.Outputs.ServiceEndpoint,
51-
).to.deep.equal({
52-
Description: 'URL of the service endpoint',
53-
Value: {
54-
'Fn::Join': [
55-
'',
56-
[
57-
'https://',
58-
{ Ref: serverlessStepFunctions.apiGatewayRestApiLogicalId },
59-
'.execute-api.',
60-
{ Ref: 'AWS::Region' },
61-
'.',
62-
{ Ref: 'AWS::URLSuffix' },
63-
'/dev',
51+
it('should add service endpoint output', () => serverlessStepFunctions
52+
.compileDeployment().then(() => {
53+
expect(
54+
serverlessStepFunctions.serverless.service.provider.compiledCloudFormationTemplate
55+
.Outputs.ServiceEndpoint,
56+
).to.deep.equal({
57+
Description: 'URL of the service endpoint',
58+
Value: {
59+
'Fn::Join': [
60+
'',
61+
[
62+
'https://',
63+
{ Ref: serverlessStepFunctions.apiGatewayRestApiLogicalId },
64+
'.execute-api.',
65+
{ Ref: 'AWS::Region' },
66+
'.',
67+
{ Ref: 'AWS::URLSuffix' },
68+
'/dev',
69+
],
70+
],
71+
},
72+
});
73+
}));
74+
});
75+
76+
describe('when there is an existing API Gateway deployment resource', () => {
77+
beforeEach(() => {
78+
serverlessStepFunctions.serverless.service.provider
79+
.compiledCloudFormationTemplate.Resources.ApiGatewayDeployment1234 = {
80+
Type: 'AWS::ApiGateway::Deployment',
81+
Properties: {
82+
RestApiId: {
83+
Ref: 'ApiGatewayRestApi',
84+
},
85+
StageName: 'dev',
86+
},
87+
DependsOn: [
88+
'ApiGatewayMethodGet',
89+
'ApiGatewayMethodPost',
6490
],
65-
],
66-
},
91+
};
6792
});
68-
}));
93+
94+
it('should append to existing deployment resource', () => serverlessStepFunctions
95+
.compileDeployment().then(() => {
96+
const resourceKeys = Object
97+
.keys(serverlessStepFunctions.serverless.service.provider
98+
.compiledCloudFormationTemplate.Resources);
99+
expect(resourceKeys).to.have.length(1);
100+
101+
const apiGatewayDeploymentLogicalId = resourceKeys[0];
102+
103+
expect(apiGatewayDeploymentLogicalId).to.equal('ApiGatewayDeployment1234');
104+
expect(
105+
serverlessStepFunctions.serverless.service.provider.compiledCloudFormationTemplate
106+
.Resources[apiGatewayDeploymentLogicalId],
107+
).to.deep.equal({
108+
Type: 'AWS::ApiGateway::Deployment',
109+
Properties: {
110+
RestApiId: { Ref: serverlessStepFunctions.apiGatewayRestApiLogicalId },
111+
StageName: 'dev',
112+
},
113+
DependsOn: [
114+
'ApiGatewayMethodGet',
115+
'ApiGatewayMethodPost',
116+
'method-dependency1',
117+
'method-dependency2',
118+
],
119+
});
120+
}));
121+
});
69122
});

0 commit comments

Comments
 (0)