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 CHANGED
@@ -1 +1,2 @@
1
- coverage
1
+ coverage
2
+ test_integration
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 Juanjo Diaz
3
+ Copyright (c) 2021 Juanjo Diaz
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  Keep your lambdas warm during winter.
10
10
 
11
11
  **Requirements:**
12
- * Serverless *v1.12.x* or higher (Recommended *v1.33.x* or higher because of [this](https://github.com/juanjoDiaz/serverless-plugin-warmup/pull/69)).
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, exclude: ['**'], include: ['.warmup/${warmerName}/**'] }`)
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
- exclude: # exclude additional binaries that are included at the serverless package level
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/${self:service}-${opt:stage, self:provider.stage}/*:*
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/${self:service}-${opt:stage, self:provider.stage}/*:*:*
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:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${self:service}-${opt:stage, self:provider.stage}-*
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": "5.2.3",
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": "^7.24.0",
35
- "eslint-config-airbnb-base": "^14.2.1",
36
- "eslint-plugin-import": "^2.22.1",
37
- "husky": "^6.0.0",
38
- "jest": "^26.6.3"
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
- exclude: Array.isArray(config.package.exclude)
29
- ? config.package.exclude
30
- : defaultOpts.package.exclude,
31
- include: Array.isArray(config.package.include)
32
- ? (config.package.include.includes(path.join(folderName, '**'))
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
- include: [...defaultOpts.package.include, path.join(folderName, '**')],
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
- // Negating the includes to work around https://github.com/serverless/serverless/issues/8093
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.rmdir(
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.rmdir(defaultDir, { recursive: true });
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 you functions using warmer "${warmerName}".`);
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/index.js
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
- anyOf: [
31
- { type: 'string', pattern: scheduleSyntax },
32
- {
33
- type: 'object',
34
- properties: {
35
- rate: { type: 'string', pattern: scheduleSyntax },
36
- enabled: { type: 'boolean' },
37
- alias: { type: 'string' },
38
- name: {
39
- type: 'string', minLength: 1, maxLength: 64, pattern: '[\\.\\-_A-Za-z0-9]+',
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
- description: { type: 'string', maxLength: 512 },
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
- exclude: { type: 'array', items: { type: 'string' } },
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
- type: 'object',
129
- properties: { ...globalConfigSchemaProperties, ...functionConfigSchemaProperties },
130
- additionalProperties: false,
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
- type: 'object',
144
- properties: { functionConfigSchemaProperties },
145
- additionalProperties: false,
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 at ${new Date().toISOString()} */
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