@adobe/helix-deploy 4.14.0 → 5.0.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.
@@ -9,14 +9,16 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
- const Fastly = require('@adobe/fastly-native-promises');
12
+ import Fastly from '@adobe/fastly-native-promises';
13
+ import chalk from 'chalk';
14
+ import FastlyConfig from './FastlyConfig.js';
15
+ import BaseDeployer from '../deploy/BaseDeployer.js';
16
+
13
17
  const {
14
18
  toString, vcl, time, req, res, str, concat,
15
- } = require('@adobe/fastly-native-promises').loghelpers;
16
- const FastlyConfig = require('./FastlyConfig.js');
17
- const BaseDeployer = require('../deploy/BaseDeployer.js');
19
+ } = Fastly.loghelpers;
18
20
 
19
- class FastlyGateway {
21
+ export default class FastlyGateway {
20
22
  constructor(baseConfig, config) {
21
23
  Object.assign(this, {
22
24
  cfg: baseConfig,
@@ -29,20 +31,15 @@ class FastlyGateway {
29
31
  }
30
32
 
31
33
  ready() {
32
- return !!this._cfg.service && !!this._cfg.auth && !!this._cfg.checkpath;
34
+ return !!this._cfg.service && !!this._cfg.auth;
33
35
  }
34
36
 
35
- /**
36
- * A weaker version of `ready` that works without a check path
37
- * and checks whether links can be updated.
38
- * @returns boolean true if links can be updated
39
- */
40
- updateable() {
41
- return !!this._cfg.service && !!this._cfg.auth;
37
+ canDeploy() {
38
+ return this.ready() && this._deployers.length > 0;
42
39
  }
43
40
 
44
41
  async updateLinks(links, version) {
45
- this.log.info(`Updating links on the Gateway for version ${version}`);
42
+ this.log.info(`--: updating links on the Gateway for version ${version}...`);
46
43
  const fakeDeployer = new BaseDeployer({
47
44
  links, version, log: this.log,
48
45
  });
@@ -58,6 +55,7 @@ class FastlyGateway {
58
55
 
59
56
  await this._fastly.bulkUpdateDictItems(undefined, 'aliases', ...versionstrings);
60
57
  this._fastly.discard();
58
+ this.log.info(chalk`{green ok:} updated links on the Gateway for version ${version}.`);
61
59
  }
62
60
 
63
61
  init() {
@@ -91,6 +89,7 @@ class FastlyGateway {
91
89
  }
92
90
  await this._fastly.updateDictItem(undefined, 'tokens', this.cfg.packageToken, `${Math.floor(Date.now() / 1000) + (365 * 24 * 3600)}`);
93
91
  this._fastly.discard();
92
+ this.log.info(chalk`{green ok:} updating app (package) parameters on Fastly gateway.`);
94
93
  }
95
94
 
96
95
  selectBackendVCL() {
@@ -190,7 +189,7 @@ if (req.url ~ "^/([^/]+)/([^/@_]+)([@_]([^/@_?]+)+)?(.*$)") {
190
189
 
191
190
  async enableLogging(version) {
192
191
  if (this._cfg.coralogixToken) {
193
- this.log.info('Set up Gateway logging to Coralogix');
192
+ this.log.info(chalk`--: Set up Gateway logging to {yellow Coralogix}`);
194
193
  await this._fastly.writeHttps(version, 'helix-coralogix', {
195
194
  name: 'helix-coralogix',
196
195
  format: toString({
@@ -303,198 +302,207 @@ if (req.url ~ "^/([^/]+)/([^/@_]+)([@_]([^/@_?]+)+)?(.*$)") {
303
302
  }
304
303
 
305
304
  async deploy() {
306
- this.log.info('Set up Fastly Gateway');
307
-
308
- await this._fastly.transact(async (newversion) => {
309
- await this.enableLogging(newversion);
310
-
311
- this.log.info('create condition');
312
- await this._fastly.writeCondition(newversion, 'false', {
313
- name: 'false',
314
- statement: 'false',
315
- type: 'request',
316
- });
317
-
318
- await this._fastly.writeDictionary(newversion, 'priorities', {
319
- name: 'priorities',
320
- write_only: 'false',
321
- });
322
-
323
- await this._fastly.writeDictionary(newversion, 'aliases', {
324
- name: 'aliases',
325
- write_only: 'false',
326
- });
327
-
328
- await this._fastly.writeDictionary(newversion, 'tokens', {
329
- name: 'tokens',
330
- write_only: 'false',
331
- });
332
-
333
- await this._fastly.writeDictionary(newversion, 'packageparams', {
334
- name: 'packageparams',
335
- write_only: 'true',
336
- });
337
-
338
- if (this._cfg.checkinterval > 0) {
339
- // set up health checks
305
+ this.log.info(chalk`--: Set up {yellow Fastly} Gateway`);
306
+ try {
307
+ await this._fastly.transact(async (newversion) => {
308
+ await this.enableLogging(newversion);
309
+
310
+ this.log.info('--: create condition');
311
+ await this._fastly.writeCondition(newversion, 'false', {
312
+ name: 'false',
313
+ statement: 'false',
314
+ type: 'request',
315
+ });
316
+
317
+ this.log.info('--: create dictionaries');
318
+ await this._fastly.writeDictionary(newversion, 'priorities', {
319
+ name: 'priorities',
320
+ write_only: 'false',
321
+ });
322
+
323
+ await this._fastly.writeDictionary(newversion, 'aliases', {
324
+ name: 'aliases',
325
+ write_only: 'false',
326
+ });
327
+
328
+ await this._fastly.writeDictionary(newversion, 'tokens', {
329
+ name: 'tokens',
330
+ write_only: 'false',
331
+ });
332
+
333
+ await this._fastly.writeDictionary(newversion, 'packageparams', {
334
+ name: 'packageparams',
335
+ write_only: 'true',
336
+ });
337
+
338
+ if (this._cfg.checkinterval > 0 && this._cfg.checkpath) {
339
+ this.log.info('--: setup health-check');
340
+ // set up health checks
341
+ await Promise.all(this._deployers
342
+ .map((deployer) => ({
343
+ check_interval: this._cfg.checkinterval,
344
+ expected_response: 200,
345
+ host: deployer.host,
346
+ http_version: '1.1',
347
+ method: 'GET',
348
+ initial: 1,
349
+ name: `${deployer.name}Check`,
350
+ path: `${deployer.basePath}${this._cfg.checkpath}`,
351
+ threshold: 2,
352
+ timeout: 5000,
353
+ window: 3,
354
+ }))
355
+ .map((healthcheck) => this._fastly
356
+ .writeHealthcheck(newversion, healthcheck.name, healthcheck)));
357
+ }
358
+
359
+ // set up backends
340
360
  await Promise.all(this._deployers
341
361
  .map((deployer) => ({
342
- check_interval: this._cfg.checkinterval,
343
- expected_response: 200,
344
- host: deployer.host,
345
- http_version: '1.1',
346
- method: 'GET',
347
- initial: 1,
348
- name: `${deployer.name}Check`,
349
- path: deployer.basePath + this._cfg.checkpath,
350
- threshold: 2,
351
- timeout: 5000,
352
- window: 3,
362
+ hostname: deployer.host,
363
+ ssl_cert_hostname: deployer.host,
364
+ ssl_sni_hostname: deployer.host,
365
+ address: deployer.host,
366
+ override_host: deployer.host,
367
+ name: deployer.name,
368
+ error_threshold: 0,
369
+ first_byte_timeout: 60000,
370
+ weight: 100,
371
+ connect_timeout: 5000,
372
+ port: 443,
373
+ between_bytes_timeout: 10000,
374
+ shield: '', // 'bwi-va-us',
375
+ max_conn: 200,
376
+ use_ssl: true,
377
+ request_condition: 'false',
353
378
  }))
354
- .map((healthcheck) => this._fastly
355
- .writeHealthcheck(newversion, healthcheck.name, healthcheck)));
356
- }
357
-
358
- // set up backends
359
- await Promise.all(this._deployers
360
- .map((deployer) => ({
361
- hostname: deployer.host,
362
- ssl_cert_hostname: deployer.host,
363
- ssl_sni_hostname: deployer.host,
364
- address: deployer.host,
365
- override_host: deployer.host,
366
- name: deployer.name,
367
- error_threshold: 0,
368
- first_byte_timeout: 60000,
369
- weight: 100,
370
- connect_timeout: 5000,
371
- port: 443,
372
- between_bytes_timeout: 10000,
373
- shield: '', // 'bwi-va-us',
374
- max_conn: 200,
375
- use_ssl: true,
376
- request_condition: 'false',
377
- }))
378
- .map((backend) => {
379
- const retval = backend;
380
- if (this._cfg.checkinterval > 0) {
381
- retval.healthcheck = `${backend.name}Check`;
382
- }
383
- return retval;
384
- })
385
- .map(async (backend) => {
386
- try {
387
- return await this._fastly.createBackend(newversion, backend);
388
- } catch (e) {
389
- return this._fastly.updateBackend(newversion, backend.name, backend);
390
- }
391
- }));
392
-
393
- await this._fastly.writeSnippet(newversion, 'packageparams.auth', {
394
- name: 'packageparams.auth',
395
- priority: 9,
396
- dynamic: 0,
397
- type: 'recv',
398
- content: `
399
- if (req.http.Authorization) {
400
- if(time.is_after(std.time(table.lookup(tokens, regsub(req.http.Authorization, "^Bearer ", ""), "expired"), std.integer2time(0)), time.start)) {
401
- error 600 "Get Package Params";
379
+ .map((backend) => {
380
+ const retval = backend;
381
+ if (this._cfg.checkinterval > 0 && this._cfg.checkpath) {
382
+ retval.healthcheck = `${backend.name}Check`;
383
+ }
384
+ return retval;
385
+ })
386
+ .map(async (backend) => {
387
+ this.log.info(`--: create backend ${backend.name} -> ${backend.hostname}`);
388
+ try {
389
+ return await this._fastly.createBackend(newversion, backend);
390
+ } catch (e) {
391
+ return this._fastly.updateBackend(newversion, backend.name, backend);
392
+ }
393
+ }));
394
+
395
+ this.log.info('--: write VLC snippets');
396
+ await this._fastly.writeSnippet(newversion, 'packageparams.auth', {
397
+ name: 'packageparams.auth',
398
+ priority: 9,
399
+ dynamic: 0,
400
+ type: 'recv',
401
+ content: `
402
+ if (req.http.Authorization) {
403
+ if(time.is_after(std.time(table.lookup(tokens, regsub(req.http.Authorization, "^Bearer ", ""), "expired"), std.integer2time(0)), time.start)) {
404
+ error 600 "Get Package Params";
405
+ }
406
+ }`,
407
+ });
408
+
409
+ await this._fastly.writeSnippet(newversion, `${this.cfg.packageName}.params`, {
410
+ name: `${this.cfg.packageName}.params`,
411
+ priority: 10,
412
+ dynamic: 0,
413
+ type: 'error',
414
+ content: this.listPackageParamsVCL(),
415
+ });
416
+
417
+ await this._fastly.writeSnippet(newversion, 'backend', {
418
+ name: 'backend',
419
+ priority: 10,
420
+ dynamic: 0,
421
+ type: 'recv',
422
+ content: this.selectBackendVCL(),
423
+ });
424
+
425
+ await this._fastly.writeSnippet(newversion, 'missurl', {
426
+ name: 'missurl',
427
+ priority: 10,
428
+ dynamic: 0,
429
+ type: 'miss',
430
+ content: this.setURLVCL(),
431
+ });
432
+
433
+ await this._fastly.writeSnippet(newversion, 'passurl', {
434
+ name: 'passurl',
435
+ priority: 10,
436
+ dynamic: 0,
437
+ type: 'pass',
438
+ content: this.setURLVCL(),
439
+ });
440
+
441
+ await this._fastly.writeSnippet(newversion, 'logurl', {
442
+ name: 'logurl',
443
+ priority: 10,
444
+ dynamic: 0,
445
+ type: 'fetch',
446
+ content: `set beresp.http.X-Backend-URL = bereq.url;
447
+ set beresp.http.X-Backend-Name = req.backend;
448
+ set beresp.http.X-Backend-Health = req.http.X-Backend-Health;
449
+ set beresp.cacheable = false;`,
450
+ });
451
+
452
+ await this._fastly.writeSnippet(newversion, 'stashsurrogates', {
453
+ name: 'stashsurrogates',
454
+ priority: 10,
455
+ dynamic: 0,
456
+ type: 'fetch',
457
+ content: `
458
+ set beresp.http.X-Surrogate-Key = beresp.http.Surrogate-Key;
459
+ set beresp.http.X-Surrogate-Control = beresp.http.Surrogate-Control;`,
460
+ });
461
+
462
+ let restartcontent = `
463
+ # restart the request in case of flakiness
464
+ if (req.restarts < 2 && (resp.status == 503 || resp.status == 504) && (req.request == "GET" || req.request == "HEAD" || req.request == "PUT" || req.request == "DELETE")) {
465
+ restart;
402
466
  }
403
- }`,
404
- });
405
-
406
- await this._fastly.writeSnippet(newversion, `${this.cfg.packageName}.params`, {
407
- name: `${this.cfg.packageName}.params`,
408
- priority: 10,
409
- dynamic: 0,
410
- type: 'error',
411
- content: this.listPackageParamsVCL(),
412
- });
413
-
414
- await this._fastly.writeSnippet(newversion, 'backend', {
415
- name: 'backend',
416
- priority: 10,
417
- dynamic: 0,
418
- type: 'recv',
419
- content: this.selectBackendVCL(),
420
- });
421
-
422
- await this._fastly.writeSnippet(newversion, 'missurl', {
423
- name: 'missurl',
424
- priority: 10,
425
- dynamic: 0,
426
- type: 'miss',
427
- content: this.setURLVCL(),
428
- });
429
-
430
- await this._fastly.writeSnippet(newversion, 'passurl', {
431
- name: 'passurl',
432
- priority: 10,
433
- dynamic: 0,
434
- type: 'pass',
435
- content: this.setURLVCL(),
436
- });
437
-
438
- await this._fastly.writeSnippet(newversion, 'logurl', {
439
- name: 'logurl',
440
- priority: 10,
441
- dynamic: 0,
442
- type: 'fetch',
443
- content: `set beresp.http.X-Backend-URL = bereq.url;
444
- set beresp.http.X-Backend-Name = req.backend;
445
- set beresp.http.X-Backend-Health = req.http.X-Backend-Health;
446
- set beresp.cacheable = false;`,
447
- });
448
-
449
- await this._fastly.writeSnippet(newversion, 'stashsurrogates', {
450
- name: 'stashsurrogates',
451
- priority: 10,
452
- dynamic: 0,
453
- type: 'fetch',
454
- content: `
455
- set beresp.http.X-Surrogate-Key = beresp.http.Surrogate-Key;
456
- set beresp.http.X-Surrogate-Control = beresp.http.Surrogate-Control;`,
457
- });
458
-
459
- let restartcontent = `
460
- # restart the request in case of flakiness
461
- if (req.restarts < 2 && (resp.status == 503 || resp.status == 504) && (req.request == "GET" || req.request == "HEAD" || req.request == "PUT" || req.request == "DELETE")) {
462
- restart;
463
- }
464
- set resp.http.x-gateway-restarts = req.restarts;
465
- unset resp.http.Fastly-Restarts;`;
466
-
467
- if (this._deployers.find((deployer) => deployer.name === 'Google')) {
468
- restartcontent += `
469
- # If Google can't find a function, it sends a redirect to the login page instead
470
- # of a 404. This fixes it.
471
- if (resp.status == 302 && req.backend == F_Google && resp.http.Location ~ "^https://accounts.google.com/ServiceLogin") {
472
- set resp.status = 404;
473
- }
474
- `;
475
- }
476
- await this._fastly.writeSnippet(newversion, 'restart', {
477
- name: 'restart',
478
- priority: 10,
479
- dynamic: 0,
480
- type: 'deliver',
481
- content: restartcontent,
482
- });
483
-
484
- await this._fastly.writeSnippet(newversion, 'restoresurrogates', {
485
- name: 'restoresurrogates',
486
- priority: 10,
487
- dynamic: 0,
488
- type: 'deliver',
489
- content: `
490
- set resp.http.Surrogate-Key = resp.http.X-Surrogate-Key;
491
- set resp.http.Surrogate-Control = resp.http.X-Surrogate-Control;`,
492
- });
493
- }, true);
494
-
495
- this._fastly.discard();
467
+ set resp.http.x-gateway-restarts = req.restarts;
468
+ unset resp.http.Fastly-Restarts;`;
469
+
470
+ if (this._deployers.find((deployer) => deployer.name === 'Google')) {
471
+ restartcontent += `
472
+ # If Google can't find a function, it sends a redirect to the login page instead
473
+ # of a 404. This fixes it.
474
+ if (resp.status == 302 && req.backend == F_Google && resp.http.Location ~ "^https://accounts.google.com/ServiceLogin") {
475
+ set resp.status = 404;
476
+ }
477
+ `;
478
+ }
479
+ await this._fastly.writeSnippet(newversion, 'restart', {
480
+ name: 'restart',
481
+ priority: 10,
482
+ dynamic: 0,
483
+ type: 'deliver',
484
+ content: restartcontent,
485
+ });
486
+
487
+ await this._fastly.writeSnippet(newversion, 'restoresurrogates', {
488
+ name: 'restoresurrogates',
489
+ priority: 10,
490
+ dynamic: 0,
491
+ type: 'deliver',
492
+ content: `
493
+ set resp.http.Surrogate-Key = resp.http.X-Surrogate-Key;
494
+ set resp.http.Surrogate-Control = resp.http.X-Surrogate-Control;`,
495
+ });
496
+ }, true);
497
+
498
+ this.log.info(chalk`{green ok}: Set up {yellow Fastly} Gateway done.`);
499
+ } catch (e) {
500
+ this.log.error(chalk`{red error}: failed to setup gateway: ${e.message}`);
501
+ throw e;
502
+ } finally {
503
+ this._fastly.discard();
504
+ }
496
505
  }
497
506
  }
498
507
 
499
508
  FastlyGateway.Config = FastlyConfig;
500
- module.exports = FastlyGateway;
package/src/index.js CHANGED
@@ -12,6 +12,6 @@
12
12
  * governing permissions and limitations under the License.
13
13
  */
14
14
 
15
- const CLI = require('./cli.js');
15
+ import CLI from './cli.js';
16
16
 
17
17
  new CLI().run(process.argv.slice(2));
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2019 Adobe. All rights reserved.
2
+ * Copyright 2021 Adobe. All rights reserved.
3
3
  * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
4
  * you may not use this file except in compliance with the License. You may obtain a copy
5
5
  * of the License at http://www.apache.org/licenses/LICENSE-2.0
@@ -9,15 +9,4 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
-
13
- module.exports = {
14
- // modules that are provided by the runtime container
15
- externals: [
16
- // 'express',
17
- // 'body-parser',
18
- // 'cls-hooked',
19
- // 'request',
20
- // 'request-promise',
21
- /^openwhisk(\/.*)?$/,
22
- ],
23
- };
12
+ module.exports = require('../package.json');
@@ -9,9 +9,7 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
- // eslint-disable-next-line no-underscore-dangle
13
- global.__rootdir = __dirname;
14
-
12
+ const { dirname } = require('path');
15
13
  const {
16
14
  openwhisk,
17
15
  aws,
@@ -19,6 +17,9 @@ const {
19
17
  azure,
20
18
  } = require('@adobe/helix-universal').adapter;
21
19
 
20
+ // eslint-disable-next-line no-underscore-dangle
21
+ global.__rootdir = dirname(__filename); // __dirname is transformed by webpack, __filename isn't
22
+
22
23
  module.exports = Object.assign(azure, {
23
24
  main: openwhisk,
24
25
  lambda: aws,
@@ -10,8 +10,8 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
  /* eslint-env serviceworker */
13
- const fastly = require('./fastly-adapter');
14
- const cloudflare = require('./cloudflare-adapter');
13
+ const fastly = require('./fastly-adapter.js');
14
+ const cloudflare = require('./cloudflare-adapter.js');
15
15
 
16
16
  /* eslint-disable no-restricted-globals */
17
17
  if (typeof addEventListener === 'function') {
package/src/utils.js CHANGED
@@ -9,8 +9,12 @@
9
9
  * OF ANY KIND, either express or implied. See the License for the specific language
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
- const { fork } = require('child_process');
13
- const path = require('path');
12
+ import { fileURLToPath } from 'url';
13
+ import { fork } from 'child_process';
14
+ import path from 'path';
15
+
16
+ // eslint-disable-next-line no-underscore-dangle
17
+ const __dirname = path.resolve(fileURLToPath(import.meta.url), '..');
14
18
 
15
19
  /**
16
20
  * @typedef {object} VersionCoordinates
@@ -54,7 +58,7 @@ const path = require('path');
54
58
  * @param {VersionSpec} versionspec - which version is current
55
59
  * @returns {NamedAction[]} - a list of actions that can safely be deleted
56
60
  */
57
- function filterActions(fns, now, {
61
+ export function filterActions(fns, now, {
58
62
  ciAge, patchAge, minorAge, majorAge, ciNum, patchNum, minorNum, majorNum,
59
63
  } = {}, { patchVersion, minorVersion, majorVersion } = {}) {
60
64
  // sort by updated date
@@ -151,7 +155,7 @@ function filterActions(fns, now, {
151
155
  ...cleanmajorbyage, ...cleanmajorbycount];
152
156
  }
153
157
 
154
- async function validateBundle(bundlePath, invoke = false) {
158
+ export async function validateBundle(bundlePath, invoke = false) {
155
159
  try {
156
160
  const opts = {
157
161
  invoke,
@@ -175,8 +179,3 @@ async function validateBundle(bundlePath, invoke = false) {
175
179
  };
176
180
  }
177
181
  }
178
-
179
- module.exports = {
180
- filterActions,
181
- validateBundle,
182
- };