/
stage.js
98 lines (84 loc) · 3.33 KB
/
stage.js
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
'use strict';
const BbPromise = require('bluebird');
const ensureApiGatewayCloudWatchRole = require('../../lib/ensure-api-gateway-cloud-watch-role');
const ServerlessError = require('../../../../../../../serverless-error');
const defaultLogLevel = 'INFO';
const validLogLevels = new Set(['INFO', 'ERROR']);
module.exports = {
async compileStage() {
return BbPromise.try(() => {
const { service, provider } = this.serverless.service;
const stage = this.options.stage;
const cfTemplate = provider.compiledCloudFormationTemplate;
// immediately return if we're using an external websocket API id
// stage will be updated as part of the AWS::ApiGatewayV2::Deployment for the websocket
if (provider.apiGateway && provider.apiGateway.websocketApiId) return null;
// logs
const logs = provider.logs && provider.logs.websocket;
const stageLogicalId = this.provider.naming.getWebsocketsStageLogicalId();
const logGroupLogicalId = this.provider.naming.getWebsocketsLogGroupLogicalId();
const stageResource = {
Type: 'AWS::ApiGatewayV2::Stage',
Properties: {
ApiId: this.provider.getApiGatewayWebsocketApiId(),
// DeploymentId is generated at deployment.js file
StageName: this.provider.getStage(),
Description: this.serverless.service.provider.websockets
? this.serverless.service.provider.websockets.description
: this.serverless.service.provider.websocketsDescription || 'Serverless Websockets',
},
};
Object.assign(cfTemplate.Resources, { [stageLogicalId]: stageResource });
if (!logs) return null;
let level = defaultLogLevel;
if (logs.level) {
level = logs.level;
if (!validLogLevels.has(level)) {
throw new ServerlessError(
`provider.logs.websocket.level is set to an invalid value. Support values are ${Array.from(
validLogLevels
).join(', ')}, got ${level}.`,
'WEBSOCKETS_INVALID_LOGS_LEVEL'
);
}
}
// create log-specific resources
Object.assign(stageResource.Properties, {
AccessLogSettings: {
DestinationArn: {
'Fn::Sub': `arn:\${AWS::Partition}:logs:\${AWS::Region}:\${AWS::AccountId}:log-group:\${${logGroupLogicalId}}`,
},
Format: [
'$context.identity.sourceIp',
'$context.identity.caller',
'$context.identity.user',
'[$context.requestTime]',
'"$context.eventType $context.routeKey $context.connectionId"',
'$context.requestId',
].join(' '),
},
DefaultRouteSettings: {
DataTraceEnabled: true,
LoggingLevel: level,
},
});
Object.assign(cfTemplate.Resources, {
[logGroupLogicalId]: getLogGroupResource(service, stage, this.provider),
});
return ensureApiGatewayCloudWatchRole(this.provider);
});
},
};
function getLogGroupResource(service, stage, provider) {
const resource = {
Type: 'AWS::Logs::LogGroup',
Properties: {
LogGroupName: `/aws/websocket/${service}-${stage}`,
},
};
const logRetentionInDays = provider.getLogRetentionInDays();
if (logRetentionInDays) {
resource.Properties.RetentionInDays = logRetentionInDays;
}
return resource;
}