serverless-plugin-warmup 5.3.0 → 6.2.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
@@ -43,6 +43,7 @@ custom:
43
43
  events:
44
44
  - schedule: cron(0/5 8-17 ? * MON-FRI *)
45
45
  concurrency: 10
46
+ logRetentionInDays: 10
46
47
  outOfOfficeHoursWarmer:
47
48
  enabled: true
48
49
  events:
@@ -64,10 +65,11 @@ The options are the same for all the warmers:
64
65
  * **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
66
  * **memorySize** The memory to be assigned to the warmer lambda (defaults to `128`)
66
67
  * **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}/**'] }`)
68
+ * **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
69
  * **timeout** How many seconds until the warmer lambda times out. (defaults to `10`)
69
70
  * **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
71
  * **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)
72
+ * **logRetentionInDays** Set the retention time in days for the log group associated to this warmer lamba
71
73
  * **prewarm** If set to true, it warms up your lambdas right after deploying (defaults to `false`)
72
74
 
73
75
  There are also some options which can be set under `custom.warmup.<yourWarmer>` to be applied to all your lambdas or under `yourLambda.warmup.<yourWarmer>` to overridde the global configuration for that particular lambda. Keep in mind that in order to configure a warmer at the function level, it needed to be previously configured at the `custom` section or the pluging will error.
@@ -97,13 +99,13 @@ custom:
97
99
  - schedule: 'cron(0/5 8-17 ? * MON-FRI *)' # Run WarmUp every 5 minutes Mon-Fri between 8:00am and 5:55pm (UTC)
98
100
  package:
99
101
  individually: true
100
- exclude: # exclude additional binaries that are included at the serverless package level
101
- - ../**
102
- - ../../**
103
- include:
102
+ patterns:
103
+ - '!../**'
104
+ - '!../../**'
104
105
  - ./**
105
106
  timeout: 20
106
107
  tracing: true
108
+ logRetentionInDays: 10
107
109
  prewarm: true # Run WarmUp immediately after a deploymentlambda
108
110
  clientContext:
109
111
  source: my-custom-source
@@ -191,7 +193,7 @@ If no role is provided at the `custom.warmup` level, each warmer function gets a
191
193
  * Invoke the functions that it should warm (and only those)
192
194
  * Create and attach elastic network interfaces (ENIs) which is necessary if deploying to a VPC
193
195
 
194
- The default role looks like:
196
+ The default role for each warmer looks like:
195
197
 
196
198
  ```yaml
197
199
  resources:
@@ -219,18 +221,20 @@ resources:
219
221
  - logs:CreateLogGroup
220
222
  - logs:CreateLogStream
221
223
  Resource:
222
- - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/${self:service}-${opt:stage, self:provider.stage}/*:*
224
+ - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${warmer.name}:*
223
225
  - Effect: Allow
224
226
  Action:
225
227
  - logs:PutLogEvents
226
228
  Resource:
227
- - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/${self:service}-${opt:stage, self:provider.stage}/*:*:*
229
+ - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${warmer.name}:*:*
228
230
  # Warmer lambda to invoke the functions to be warmed
229
231
  - Effect: 'Allow'
230
232
  Action:
231
233
  - lambda:InvokeFunction
232
234
  Resource:
233
- - !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${self:service}-${opt:stage, self:provider.stage}-*
235
+ - !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${fn1.name}
236
+ - !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${fn2.name}
237
+ # and one more row for each function that must be warmed up by the warmer
234
238
  # Warmer lambda to manage ENIS (only needed if deploying to VPC, https://docs.aws.amazon.com/lambda/latest/dg/vpc.html)
235
239
  - Effect: Allow
236
240
  Action:
@@ -448,6 +452,39 @@ The `warmers` flag takes a comma-separated list of warmer names. If it's nor pro
448
452
 
449
453
  ## Migrations
450
454
 
455
+ ### v5.X to v6.X
456
+
457
+ #### Removed include/exclude in favour of patterns
458
+
459
+ 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.
460
+
461
+ This plugin applies the same philosophy.
462
+
463
+ What used to be:
464
+ ```yaml
465
+ custom:
466
+ warmup:
467
+ default:
468
+ enabled: 'prod'
469
+ package:
470
+ individually: true
471
+ exclude: '../**',
472
+ include: 'myFolder'
473
+ ```
474
+
475
+ is the same as
476
+ ```yaml
477
+ custom:
478
+ warmup:
479
+ default:
480
+ enabled: 'prod'
481
+ package:
482
+ individually: true
483
+ patterns:
484
+ - '!../**',
485
+ - 'myFolder'
486
+ ```
487
+
451
488
  ### v4.X to v5.X
452
489
 
453
490
  #### Support multiple warmer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serverless-plugin-warmup",
3
- "version": "5.3.0",
3
+ "version": "6.2.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.26.0",
35
- "eslint-config-airbnb-base": "^14.2.1",
36
- "eslint-plugin-import": "^2.23.2",
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,
@@ -44,6 +41,9 @@ function getWarmerConfig(config, defaultOpts) {
44
41
  ? config.environment
45
42
  : defaultOpts.environment,
46
43
  tracing: (config.tracing !== undefined) ? config.tracing : defaultOpts.tracing,
44
+ logRetentionInDays: (config.logRetentionInDays !== undefined)
45
+ ? config.logRetentionInDays
46
+ : defaultOpts.logRetentionInDays,
47
47
  prewarm: (config.prewarm !== undefined) ? config.prewarm : defaultOpts.prewarm,
48
48
  };
49
49
  /* eslint-enable no-nested-ternary */
@@ -146,13 +146,7 @@ function getConfigsByWarmer(service, stage) {
146
146
  events: [{ schedule: 'rate(5 minutes)' }],
147
147
  package: {
148
148
  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: ['**'],
149
+ patterns: [],
156
150
  },
157
151
  timeout: 10,
158
152
  environment: Object.keys(service.provider.environment || [])
package/src/index.js CHANGED
@@ -116,7 +116,7 @@ class WarmUp {
116
116
 
117
117
  await Promise.all(foldersToClean.map(async (folderToClean) => {
118
118
  try {
119
- await fs.rmdir(
119
+ await fs.rm(
120
120
  path.join(this.serviceDir, folderToClean),
121
121
  { recursive: true },
122
122
  );
@@ -133,7 +133,7 @@ class WarmUp {
133
133
  foldersToClean.some((folder) => folder.startsWith('.warmup'))
134
134
  && (await fs.readdir(defaultDir)).length === 0
135
135
  ) {
136
- await fs.rmdir(defaultDir, { recursive: true });
136
+ await fs.rm(defaultDir, { recursive: true });
137
137
  }
138
138
  } catch (err) {
139
139
  if (err.code !== 'ENOENT') {
@@ -177,6 +177,12 @@ class WarmUp {
177
177
  return;
178
178
  }
179
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
+
180
186
  this.serverless.cli.log(`WarmUp: Creating warmer "${warmerName}" to warm up ${warmerConfig.functions.length} function${warmerConfig.functions.length === 1 ? '' : 's'}:`);
181
187
  warmerConfig.functions.forEach((func) => this.serverless.cli.log(` * ${func.name}`));
182
188
 
@@ -207,7 +213,7 @@ class WarmUp {
207
213
  return;
208
214
  }
209
215
 
210
- 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}".`);
211
217
 
212
218
  try {
213
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,
@@ -96,6 +107,10 @@ function extendServerlessSchema(serverless) {
96
107
  timeout: { $ref: '#/definitions/awsLambdaTimeout' },
97
108
  environment: { $ref: '#/definitions/awsLambdaEnvironment' },
98
109
  tracing: { $ref: '#/definitions/awsLambdaTracing' },
110
+ logRetentionInDays: {
111
+ type: 'number',
112
+ enum: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653],
113
+ },
99
114
  prewarm: { type: 'boolean' },
100
115
  };
101
116
 
@@ -124,10 +139,12 @@ function extendServerlessSchema(serverless) {
124
139
  serverless.configSchemaHandler.defineCustomProperties({
125
140
  properties: {
126
141
  warmup: {
127
- '.*': {
128
- type: 'object',
129
- properties: { ...globalConfigSchemaProperties, ...functionConfigSchemaProperties },
130
- additionalProperties: false,
142
+ patternProperties: {
143
+ '.*': {
144
+ type: 'object',
145
+ properties: { ...globalConfigSchemaProperties, ...functionConfigSchemaProperties },
146
+ additionalProperties: false,
147
+ },
131
148
  },
132
149
  },
133
150
  },
@@ -139,10 +156,12 @@ function extendServerlessSchema(serverless) {
139
156
  type: 'object',
140
157
  properties: {
141
158
  warmup: {
142
- '.*': {
143
- type: 'object',
144
- properties: { functionConfigSchemaProperties },
145
- additionalProperties: false,
159
+ patternProperties: {
160
+ '.*': {
161
+ type: 'object',
162
+ properties: functionConfigSchemaProperties,
163
+ additionalProperties: false,
164
+ },
146
165
  },
147
166
  },
148
167
  },
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');
@@ -225,9 +225,13 @@ function addWarmUpFunctionToService(service, warmerName, warmerConfig) {
225
225
  ? { environment: warmerConfig.environment }
226
226
  : {}),
227
227
  ...(warmerConfig.tracing !== undefined ? { tracing: warmerConfig.tracing } : {}),
228
+ ...(warmerConfig.logRetentionInDays !== undefined
229
+ ? { logRetentionInDays: warmerConfig.logRetentionInDays }
230
+ : {}),
228
231
  ...(warmerConfig.role ? { role: warmerConfig.role } : {}),
229
232
  ...(warmerConfig.tags ? { tags: warmerConfig.tags } : {}),
230
233
  ...(warmerConfig.vpc ? { vpc: warmerConfig.vpc } : {}),
234
+ layers: [],
231
235
  };
232
236
  }
233
237