serverless-plugin-warmup 5.2.3 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -1
- package/LICENSE +1 -1
- package/README.md +44 -10
- package/package.json +6 -6
- package/src/config.js +7 -16
- package/src/index.js +10 -3
- package/src/schema.js +77 -62
- package/src/warmer.js +2 -1
package/.eslintignore
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
coverage
|
|
1
|
+
coverage
|
|
2
|
+
test_integration
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
Keep your lambdas warm during winter.
|
|
10
10
|
|
|
11
11
|
**Requirements:**
|
|
12
|
-
* Serverless *
|
|
12
|
+
* Serverless *v2.32.x* or higher
|
|
13
13
|
* AWS provider
|
|
14
14
|
|
|
15
15
|
## How it works
|
|
@@ -64,7 +64,7 @@ The options are the same for all the warmers:
|
|
|
64
64
|
* **vpc** The VPC and subnets in which to deploy. Can be any [Serverless VPC configuration](https://serverless.com/framework/docs/providers/aws/guide/functions#vpc-configuration) or be set to `false` in order to deploy the warmup function outside of a VPC (defaults to the vpc in the provider)
|
|
65
65
|
* **memorySize** The memory to be assigned to the warmer lambda (defaults to `128`)
|
|
66
66
|
* **events** The event that triggers the warmer lambda. Can be any [Serverless event](https://serverless.com/framework/docs/providers/aws/events/) (defaults to `- schedule: rate(5 minutes)`)
|
|
67
|
-
* **package** The package configuration. Can be any [Serverless package configuration](https://serverless.com/framework/docs/providers/aws/guide/packaging#package-configuration) (defaults to `{ individually: true,
|
|
67
|
+
* **package** The package configuration. Can be any [Serverless package configuration](https://serverless.com/framework/docs/providers/aws/guide/packaging#package-configuration) (defaults to `{ individually: true, patterns: ['!**', '.warmup/${warmerName}/**'] }`)
|
|
68
68
|
* **timeout** How many seconds until the warmer lambda times out. (defaults to `10`)
|
|
69
69
|
* **environment** Can be used to set environment variables in the warmer lambda. You can also unset variables configured at the provider by setting them to undefined. However, you should almost never have to change the default. (defaults to unset all package level environment variables. )
|
|
70
70
|
* **tracing** Specify whether to enable/disable tracing at the function level. When tracing is enabled, warmer functions will use NPM to install the X-Ray client and use it to trace requests (It takes any of the values supported by serverless as `boolean`, `Active`or `PassThrough` and defaults to the provider-level setting)
|
|
@@ -97,10 +97,9 @@ custom:
|
|
|
97
97
|
- schedule: 'cron(0/5 8-17 ? * MON-FRI *)' # Run WarmUp every 5 minutes Mon-Fri between 8:00am and 5:55pm (UTC)
|
|
98
98
|
package:
|
|
99
99
|
individually: true
|
|
100
|
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
include:
|
|
100
|
+
patterns:
|
|
101
|
+
- '!../**'
|
|
102
|
+
- '!../../**'
|
|
104
103
|
- ./**
|
|
105
104
|
timeout: 20
|
|
106
105
|
tracing: true
|
|
@@ -191,7 +190,7 @@ If no role is provided at the `custom.warmup` level, each warmer function gets a
|
|
|
191
190
|
* Invoke the functions that it should warm (and only those)
|
|
192
191
|
* Create and attach elastic network interfaces (ENIs) which is necessary if deploying to a VPC
|
|
193
192
|
|
|
194
|
-
The default role looks like:
|
|
193
|
+
The default role for each warmer looks like:
|
|
195
194
|
|
|
196
195
|
```yaml
|
|
197
196
|
resources:
|
|
@@ -219,18 +218,20 @@ resources:
|
|
|
219
218
|
- logs:CreateLogGroup
|
|
220
219
|
- logs:CreateLogStream
|
|
221
220
|
Resource:
|
|
222
|
-
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/${
|
|
221
|
+
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${warmer.name}:*
|
|
223
222
|
- Effect: Allow
|
|
224
223
|
Action:
|
|
225
224
|
- logs:PutLogEvents
|
|
226
225
|
Resource:
|
|
227
|
-
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/${
|
|
226
|
+
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${warmer.name}:*:*
|
|
228
227
|
# Warmer lambda to invoke the functions to be warmed
|
|
229
228
|
- Effect: 'Allow'
|
|
230
229
|
Action:
|
|
231
230
|
- lambda:InvokeFunction
|
|
232
231
|
Resource:
|
|
233
|
-
- !Sub arn:
|
|
232
|
+
- !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${fn1.name}
|
|
233
|
+
- !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${fn2.name}
|
|
234
|
+
# and one more row for each function that must be warmed up by the warmer
|
|
234
235
|
# Warmer lambda to manage ENIS (only needed if deploying to VPC, https://docs.aws.amazon.com/lambda/latest/dg/vpc.html)
|
|
235
236
|
- Effect: Allow
|
|
236
237
|
Action:
|
|
@@ -448,6 +449,39 @@ The `warmers` flag takes a comma-separated list of warmer names. If it's nor pro
|
|
|
448
449
|
|
|
449
450
|
## Migrations
|
|
450
451
|
|
|
452
|
+
### v5.X to v6.X
|
|
453
|
+
|
|
454
|
+
#### Removed include/exclude in favour of patterns
|
|
455
|
+
|
|
456
|
+
From Serverless 2.32.0 the `patterns` option is the recommended approach to include/exclude files from packaging. In version 3.X, the `include` and `exclude` are removed.
|
|
457
|
+
|
|
458
|
+
This plugin applies the same philosophy.
|
|
459
|
+
|
|
460
|
+
What used to be:
|
|
461
|
+
```yaml
|
|
462
|
+
custom:
|
|
463
|
+
warmup:
|
|
464
|
+
default:
|
|
465
|
+
enabled: 'prod'
|
|
466
|
+
package:
|
|
467
|
+
individually: true
|
|
468
|
+
exclude: '../**',
|
|
469
|
+
include: 'myFolder'
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
is the same as
|
|
473
|
+
```yaml
|
|
474
|
+
custom:
|
|
475
|
+
warmup:
|
|
476
|
+
default:
|
|
477
|
+
enabled: 'prod'
|
|
478
|
+
package:
|
|
479
|
+
individually: true
|
|
480
|
+
patterns:
|
|
481
|
+
- '!../**',
|
|
482
|
+
- 'myFolder'
|
|
483
|
+
```
|
|
484
|
+
|
|
451
485
|
### v4.X to v5.X
|
|
452
486
|
|
|
453
487
|
#### Support multiple warmer
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "serverless-plugin-warmup",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "Keep your lambdas warm during winter.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"homepage": "https://github.com/juanjoDiaz/serverless-plugin-warmup",
|
|
32
32
|
"dependencies": {},
|
|
33
33
|
"devDependencies": {
|
|
34
|
-
"eslint": "^
|
|
35
|
-
"eslint-config-airbnb-base": "^
|
|
36
|
-
"eslint-plugin-import": "^2.
|
|
37
|
-
"husky": "^
|
|
38
|
-
"jest": "^
|
|
34
|
+
"eslint": "^8.5.0",
|
|
35
|
+
"eslint-config-airbnb-base": "^15.0.0",
|
|
36
|
+
"eslint-plugin-import": "^2.24.2",
|
|
37
|
+
"husky": "^7.0.2",
|
|
38
|
+
"jest": "^27.2.0"
|
|
39
39
|
}
|
|
40
40
|
}
|
package/src/config.js
CHANGED
|
@@ -25,18 +25,15 @@ function getWarmerConfig(config, defaultOpts) {
|
|
|
25
25
|
individually: (config.package.individually !== undefined)
|
|
26
26
|
? config.package.individually
|
|
27
27
|
: defaultOpts.package.individually,
|
|
28
|
-
|
|
29
|
-
? config.package.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
? config.package.include
|
|
34
|
-
: [...config.package.include, path.join(folderName, '**')])
|
|
35
|
-
: [...defaultOpts.package.include, path.join(folderName, '**')],
|
|
28
|
+
patterns: ['!**', ...Array.isArray(config.package.patterns)
|
|
29
|
+
? (config.package.patterns.includes(path.join(folderName, '**'))
|
|
30
|
+
? config.package.patterns
|
|
31
|
+
: [...config.package.patterns, path.join(folderName, '**')])
|
|
32
|
+
: [...defaultOpts.package.patterns, path.join(folderName, '**')]],
|
|
36
33
|
}
|
|
37
34
|
: {
|
|
38
35
|
...defaultOpts.package,
|
|
39
|
-
|
|
36
|
+
patterns: ['!**', ...defaultOpts.package.patterns, path.join(folderName, '**')],
|
|
40
37
|
},
|
|
41
38
|
memorySize: (config.memorySize !== undefined) ? config.memorySize : defaultOpts.memorySize,
|
|
42
39
|
timeout: (config.timeout !== undefined) ? config.timeout : defaultOpts.timeout,
|
|
@@ -146,13 +143,7 @@ function getConfigsByWarmer(service, stage) {
|
|
|
146
143
|
events: [{ schedule: 'rate(5 minutes)' }],
|
|
147
144
|
package: {
|
|
148
145
|
individually: true,
|
|
149
|
-
|
|
150
|
-
include: service.package && service.package.include
|
|
151
|
-
? service.package.include
|
|
152
|
-
.filter((pattern) => !pattern.startsWith('!'))
|
|
153
|
-
.map((pattern) => `!${pattern}`)
|
|
154
|
-
: [],
|
|
155
|
-
exclude: ['**'],
|
|
146
|
+
patterns: [],
|
|
156
147
|
},
|
|
157
148
|
timeout: 10,
|
|
158
149
|
environment: Object.keys(service.provider.environment || [])
|
package/src/index.js
CHANGED
|
@@ -63,6 +63,7 @@ class WarmUp {
|
|
|
63
63
|
'after:package:initialize': () => this.serverless.pluginManager.spawn('warmup:addWarmers'),
|
|
64
64
|
'after:package:createDeploymentArtifacts': () => this.serverless.pluginManager.spawn('warmup:cleanupTempDir'),
|
|
65
65
|
'after:deploy:deploy': () => this.serverless.pluginManager.spawn('warmup:prewarm'),
|
|
66
|
+
'after:deploy:function:deploy': () => this.serverless.pluginManager.spawn('warmup:prewarm'),
|
|
66
67
|
'before:warmup:addWarmers:addWarmers': this.configPlugin.bind(this),
|
|
67
68
|
'warmup:addWarmers:addWarmers': this.initializeWarmers.bind(this),
|
|
68
69
|
'before:warmup:cleanupTempDir:cleanup': this.configPlugin.bind(this),
|
|
@@ -115,7 +116,7 @@ class WarmUp {
|
|
|
115
116
|
|
|
116
117
|
await Promise.all(foldersToClean.map(async (folderToClean) => {
|
|
117
118
|
try {
|
|
118
|
-
await fs.
|
|
119
|
+
await fs.rm(
|
|
119
120
|
path.join(this.serviceDir, folderToClean),
|
|
120
121
|
{ recursive: true },
|
|
121
122
|
);
|
|
@@ -132,7 +133,7 @@ class WarmUp {
|
|
|
132
133
|
foldersToClean.some((folder) => folder.startsWith('.warmup'))
|
|
133
134
|
&& (await fs.readdir(defaultDir)).length === 0
|
|
134
135
|
) {
|
|
135
|
-
await fs.
|
|
136
|
+
await fs.rm(defaultDir, { recursive: true });
|
|
136
137
|
}
|
|
137
138
|
} catch (err) {
|
|
138
139
|
if (err.code !== 'ENOENT') {
|
|
@@ -176,6 +177,12 @@ class WarmUp {
|
|
|
176
177
|
return;
|
|
177
178
|
}
|
|
178
179
|
|
|
180
|
+
// Avoid double processing due to the workaround for webpack/bundle plugins
|
|
181
|
+
// resetting the plugin and ignoring changes
|
|
182
|
+
if (this.serverless.service.functions[`warmUpPlugin${capitalize(warmerName)}`]) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
179
186
|
this.serverless.cli.log(`WarmUp: Creating warmer "${warmerName}" to warm up ${warmerConfig.functions.length} function${warmerConfig.functions.length === 1 ? '' : 's'}:`);
|
|
180
187
|
warmerConfig.functions.forEach((func) => this.serverless.cli.log(` * ${func.name}`));
|
|
181
188
|
|
|
@@ -206,7 +213,7 @@ class WarmUp {
|
|
|
206
213
|
return;
|
|
207
214
|
}
|
|
208
215
|
|
|
209
|
-
this.serverless.cli.log(`WarmUp: Prewarming up
|
|
216
|
+
this.serverless.cli.log(`WarmUp: Prewarming up your functions using warmer "${warmerName}".`);
|
|
210
217
|
|
|
211
218
|
try {
|
|
212
219
|
const { SERVERLESS_ALIAS } = this.serverless.service.getFunction(`warmUpPlugin${capitalize(warmerName)}`).environment || {};
|
package/src/schema.js
CHANGED
|
@@ -5,7 +5,7 @@ function extendServerlessSchema(serverless) {
|
|
|
5
5
|
// Most of these are taken from
|
|
6
6
|
// https://github.com/serverless/serverless/blob/master/lib/configSchema.js
|
|
7
7
|
// https://github.com/serverless/serverless/blob/master/lib/plugins/aws/provider.js
|
|
8
|
-
// https://github.com/serverless/serverless/blob/master/lib/plugins/aws/package/compile/events/schedule
|
|
8
|
+
// https://github.com/serverless/serverless/blob/master/lib/plugins/aws/package/compile/events/schedule.js
|
|
9
9
|
|
|
10
10
|
const rateSyntax = '^rate\\((?:1 (?:minute|hour|day)|(?:1\\d+|[2-9]\\d*) (?:minute|hour|day)s)\\)$';
|
|
11
11
|
const cronSyntax = '^cron\\(\\S+ \\S+ \\S+ \\S+ \\S+ \\S+\\)$';
|
|
@@ -27,67 +27,78 @@ function extendServerlessSchema(serverless) {
|
|
|
27
27
|
type: 'array',
|
|
28
28
|
items: {
|
|
29
29
|
type: 'object',
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
properties: {
|
|
31
|
+
schedule: {
|
|
32
|
+
anyOf: [
|
|
33
|
+
{ type: 'string', pattern: scheduleSyntax },
|
|
34
|
+
{
|
|
35
|
+
type: 'object',
|
|
36
|
+
properties: {
|
|
37
|
+
rate: {
|
|
38
|
+
type: 'array',
|
|
39
|
+
minItems: 1,
|
|
40
|
+
items: {
|
|
41
|
+
type: 'string',
|
|
42
|
+
pattern: scheduleSyntax,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
enabled: { type: 'boolean' },
|
|
46
|
+
name: {
|
|
47
|
+
type: 'string', minLength: 1, maxLength: 64, pattern: '[\\.\\-_A-Za-z0-9]+',
|
|
48
|
+
},
|
|
49
|
+
description: { type: 'string', maxLength: 512 },
|
|
50
|
+
input: {
|
|
51
|
+
anyOf: [
|
|
52
|
+
{ type: 'string', maxLength: 8192 },
|
|
53
|
+
{
|
|
54
|
+
type: 'object',
|
|
55
|
+
oneOf: [
|
|
56
|
+
{
|
|
57
|
+
properties: {
|
|
58
|
+
body: { type: 'string', maxLength: 8192 },
|
|
59
|
+
},
|
|
60
|
+
required: ['body'],
|
|
61
|
+
additionalProperties: false,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
not: {
|
|
65
|
+
required: ['body'],
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
inputPath: { type: 'string', maxLength: 256 },
|
|
73
|
+
inputTransformer: {
|
|
74
|
+
type: 'object',
|
|
75
|
+
properties: {
|
|
76
|
+
inputTemplate: {
|
|
77
|
+
type: 'string',
|
|
78
|
+
minLength: 1,
|
|
79
|
+
maxLength: 8192,
|
|
80
|
+
},
|
|
81
|
+
inputPathsMap: { type: 'object' },
|
|
82
|
+
},
|
|
83
|
+
required: ['inputTemplate'],
|
|
84
|
+
additionalProperties: false,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
required: ['rate'],
|
|
88
|
+
additionalProperties: false,
|
|
40
89
|
},
|
|
41
|
-
|
|
42
|
-
// input: {
|
|
43
|
-
// anyOf: [
|
|
44
|
-
// { type: 'string', maxLength: 8192 },
|
|
45
|
-
// {
|
|
46
|
-
// type: 'object',
|
|
47
|
-
// oneOf: [
|
|
48
|
-
// {
|
|
49
|
-
// properties: {
|
|
50
|
-
// body: { type: 'string', maxLength: 8192 },
|
|
51
|
-
// },
|
|
52
|
-
// required: ['body'],
|
|
53
|
-
// additionalProperties: false,
|
|
54
|
-
// },
|
|
55
|
-
// {
|
|
56
|
-
// not: {
|
|
57
|
-
// required: ['body'],
|
|
58
|
-
// },
|
|
59
|
-
// },
|
|
60
|
-
// ],
|
|
61
|
-
// },
|
|
62
|
-
// ],
|
|
63
|
-
// },
|
|
64
|
-
// inputPath: { type: 'string', maxLength: 256 },
|
|
65
|
-
// inputTransformer: {
|
|
66
|
-
// type: 'object',
|
|
67
|
-
// properties: {
|
|
68
|
-
// inputTemplate: {
|
|
69
|
-
// type: 'string',
|
|
70
|
-
// minLength: 1,
|
|
71
|
-
// maxLength: 8192,
|
|
72
|
-
// },
|
|
73
|
-
// inputPathsMap: { type: 'object' },
|
|
74
|
-
// },
|
|
75
|
-
// required: ['inputTemplate'],
|
|
76
|
-
// additionalProperties: false,
|
|
77
|
-
// },
|
|
78
|
-
},
|
|
79
|
-
required: ['rate'],
|
|
80
|
-
additionalProperties: false,
|
|
90
|
+
],
|
|
81
91
|
},
|
|
82
|
-
|
|
92
|
+
},
|
|
93
|
+
required: ['schedule'],
|
|
94
|
+
additionalProperties: false,
|
|
83
95
|
},
|
|
84
96
|
},
|
|
85
97
|
package: {
|
|
86
98
|
type: 'object',
|
|
87
99
|
properties: {
|
|
88
100
|
artifact: { type: 'string' },
|
|
89
|
-
|
|
90
|
-
include: { type: 'array', items: { type: 'string' } },
|
|
101
|
+
patterns: { type: 'array', items: { type: 'string' } },
|
|
91
102
|
individually: { type: 'boolean' },
|
|
92
103
|
},
|
|
93
104
|
additionalProperties: false,
|
|
@@ -124,10 +135,12 @@ function extendServerlessSchema(serverless) {
|
|
|
124
135
|
serverless.configSchemaHandler.defineCustomProperties({
|
|
125
136
|
properties: {
|
|
126
137
|
warmup: {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
138
|
+
patternProperties: {
|
|
139
|
+
'.*': {
|
|
140
|
+
type: 'object',
|
|
141
|
+
properties: { ...globalConfigSchemaProperties, ...functionConfigSchemaProperties },
|
|
142
|
+
additionalProperties: false,
|
|
143
|
+
},
|
|
131
144
|
},
|
|
132
145
|
},
|
|
133
146
|
},
|
|
@@ -139,10 +152,12 @@ function extendServerlessSchema(serverless) {
|
|
|
139
152
|
type: 'object',
|
|
140
153
|
properties: {
|
|
141
154
|
warmup: {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
155
|
+
patternProperties: {
|
|
156
|
+
'.*': {
|
|
157
|
+
type: 'object',
|
|
158
|
+
properties: { functionConfigSchemaProperties },
|
|
159
|
+
additionalProperties: false,
|
|
160
|
+
},
|
|
146
161
|
},
|
|
147
162
|
},
|
|
148
163
|
},
|
package/src/warmer.js
CHANGED
|
@@ -128,7 +128,7 @@ function addWarmUpFunctionRoleToResources(service, stage, warmerName, warmerConf
|
|
|
128
128
|
async function createWarmUpFunctionArtifact(functions, tracing, region, handlerFolder) {
|
|
129
129
|
const warmUpFunction = `'use strict';
|
|
130
130
|
|
|
131
|
-
/** Generated by Serverless WarmUp Plugin
|
|
131
|
+
/** Generated by Serverless WarmUp Plugin **/
|
|
132
132
|
|
|
133
133
|
${tracing
|
|
134
134
|
? `const AWSXRay = require('aws-xray-sdk-core');
|
|
@@ -228,6 +228,7 @@ function addWarmUpFunctionToService(service, warmerName, warmerConfig) {
|
|
|
228
228
|
...(warmerConfig.role ? { role: warmerConfig.role } : {}),
|
|
229
229
|
...(warmerConfig.tags ? { tags: warmerConfig.tags } : {}),
|
|
230
230
|
...(warmerConfig.vpc ? { vpc: warmerConfig.vpc } : {}),
|
|
231
|
+
layers: [],
|
|
231
232
|
};
|
|
232
233
|
}
|
|
233
234
|
|