@ashishpandeyone/cdk-lambda-web-function 0.1.0 → 0.1.2
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/.jsii +1457 -135
- package/.jsii.tabl.json +1 -1
- package/API.md +2349 -238
- package/README.md +133 -7
- package/assets/web-function-deployment/index.js +58 -0
- package/assets/web-function-provider/index.js +23 -23
- package/lib/index.d.ts +3 -0
- package/lib/index.js +4 -1
- package/lib/nodejs-web-function.d.ts +153 -0
- package/lib/nodejs-web-function.js +113 -0
- package/lib/private/bundling.d.ts +68 -0
- package/lib/private/bundling.js +192 -0
- package/lib/private/provider-protocol.d.ts +40 -0
- package/lib/private/provider-protocol.js +9 -2
- package/lib/private/provider.js +2 -2
- package/lib/private/revision-cleanup.d.ts +19 -0
- package/lib/private/revision-cleanup.js +38 -0
- package/lib/private/traffic-shift.d.ts +20 -0
- package/lib/private/traffic-shift.js +143 -0
- package/lib/web-function-deployment.d.ts +89 -0
- package/lib/web-function-deployment.js +90 -0
- package/lib/web-function-endpoint.d.ts +122 -19
- package/lib/web-function-endpoint.js +139 -18
- package/lib/web-function-grants.d.ts +2 -2
- package/lib/web-function-grants.js +4 -4
- package/lib/web-function-revision.d.ts +45 -0
- package/lib/web-function-revision.js +40 -0
- package/lib/web-function.d.ts +60 -25
- package/lib/web-function.js +80 -26
- package/package.json +7 -2
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* CloudFormation passes every scalar property to the handler as a string.
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.ENDPOINT_LOOKUP_RESOURCE_TYPE = exports.LOG_GROUP_RESOURCE_TYPE = exports.CODE_RESOURCE_TYPE = void 0;
|
|
10
|
+
exports.TRAFFIC_SHIFT_RESOURCE_TYPE = exports.REVISION_CLEANUP_RESOURCE_TYPE = exports.ENDPOINT_LOOKUP_RESOURCE_TYPE = exports.LOG_GROUP_RESOURCE_TYPE = exports.CODE_RESOURCE_TYPE = void 0;
|
|
11
11
|
exports.regionalDomainAttribute = regionalDomainAttribute;
|
|
12
12
|
/** Copies a code zip into the stack's code bucket and returns the object's version. */
|
|
13
13
|
exports.CODE_RESOURCE_TYPE = 'Custom::LambdaWebCode';
|
|
@@ -19,4 +19,11 @@ exports.ENDPOINT_LOOKUP_RESOURCE_TYPE = 'Custom::LambdaWebEndpointLookup';
|
|
|
19
19
|
function regionalDomainAttribute(region) {
|
|
20
20
|
return `Domain.${region}`;
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
/** Deletes a function's oldest revisions beyond a count, except those that are in use or may be rolled back to. */
|
|
23
|
+
exports.REVISION_CLEANUP_RESOURCE_TYPE = 'Custom::LambdaWebRevisionCleanup';
|
|
24
|
+
/**
|
|
25
|
+
* Moves an endpoint's traffic to a revision in steps, watching alarms (canary and linear deployments).
|
|
26
|
+
* Served by the deployment provider (`handlers/web-function-deployment`), not the shared provider: it can run for up to an hour.
|
|
27
|
+
*/
|
|
28
|
+
exports.TRAFFIC_SHIFT_RESOURCE_TYPE = 'Custom::LambdaWebTrafficShift';
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXItcHJvdG9jb2wuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJpdmF0ZS9wcm92aWRlci1wcm90b2NvbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7QUEyQ0gsMERBRUM7QUEzQ0QsdUZBQXVGO0FBQzFFLFFBQUEsa0JBQWtCLEdBQUcsdUJBQXVCLENBQUM7QUFjMUQsdUdBQXVHO0FBQzFGLFFBQUEsdUJBQXVCLEdBQUcsMkJBQTJCLENBQUM7QUFjbkUsZ0hBQWdIO0FBQ25HLFFBQUEsNkJBQTZCLEdBQUcsaUNBQWlDLENBQUM7QUFTL0UsZ0ZBQWdGO0FBQ2hGLFNBQWdCLHVCQUF1QixDQUFDLE1BQWM7SUFDcEQsT0FBTyxVQUFVLE1BQU0sRUFBRSxDQUFDO0FBQzVCLENBQUM7QUFFRCxtSEFBbUg7QUFDdEcsUUFBQSw4QkFBOEIsR0FBRyxrQ0FBa0MsQ0FBQztBQWFqRjs7O0dBR0c7QUFDVSxRQUFBLDJCQUEyQixHQUFHLCtCQUErQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb250cmFjdCBiZXR3ZWVuIHRoZSBjb25zdHJ1Y3RzIGFuZCB0aGUgY3VzdG9tIHJlc291cmNlIGhhbmRsZXIgaW5cbiAqIGBoYW5kbGVycy93ZWItZnVuY3Rpb24tcHJvdmlkZXJgLiBCb3RoIHNpZGVzIGltcG9ydCB0aGlzIGZpbGUsIHNvIHJlc291cmNlXG4gKiB0eXBlcyBhbmQgcHJvcGVydHkgbmFtZXMgY2FuJ3QgZHJpZnQgYXBhcnQuXG4gKlxuICogQ2xvdWRGb3JtYXRpb24gcGFzc2VzIGV2ZXJ5IHNjYWxhciBwcm9wZXJ0eSB0byB0aGUgaGFuZGxlciBhcyBhIHN0cmluZy5cbiAqL1xuXG4vKiogQ29waWVzIGEgY29kZSB6aXAgaW50byB0aGUgc3RhY2sncyBjb2RlIGJ1Y2tldCBhbmQgcmV0dXJucyB0aGUgb2JqZWN0J3MgdmVyc2lvbi4gKi9cbmV4cG9ydCBjb25zdCBDT0RFX1JFU09VUkNFX1RZUEUgPSAnQ3VzdG9tOjpMYW1iZGFXZWJDb2RlJztcblxuZXhwb3J0IGludGVyZmFjZSBDb2RlUHJvcGVydGllcyB7XG4gIHJlYWRvbmx5IFNvdXJjZUJ1Y2tldDogc3RyaW5nO1xuICByZWFkb25seSBTb3VyY2VLZXk6IHN0cmluZztcbiAgcmVhZG9ubHkgU291cmNlVmVyc2lvbj86IHN0cmluZztcbiAgcmVhZG9ubHkgRGVzdGluYXRpb25CdWNrZXQ6IHN0cmluZztcbiAgcmVhZG9ubHkgRGVzdGluYXRpb25LZXk6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb2RlQXR0cmlidXRlcyB7XG4gIHJlYWRvbmx5IFZlcnNpb25JZDogc3RyaW5nO1xufVxuXG4vKiogRW5zdXJlcyBvbmUgbG9nIGdyb3VwIChpbiBhbnkgcmVnaW9uKSBleGlzdHMgd2l0aCB0aGUgZ2l2ZW4gcmV0ZW50aW9uLCBhbmQgcmVtb3ZlcyBpdCBvbiBkZWxldGUuICovXG5leHBvcnQgY29uc3QgTE9HX0dST1VQX1JFU09VUkNFX1RZUEUgPSAnQ3VzdG9tOjpMYW1iZGFXZWJMb2dHcm91cCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9nR3JvdXBQcm9wZXJ0aWVzIHtcbiAgcmVhZG9ubHkgUmVnaW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IExvZ0dyb3VwTmFtZTogc3RyaW5nO1xuICAvKiogRGF5cywgb3IgJ0luZmluaXRlJyBmb3Igbm8gcmV0ZW50aW9uLiAqL1xuICByZWFkb25seSBSZXRlbnRpb25JbkRheXM6IHN0cmluZztcbiAgcmVhZG9ubHkgUmVtb3ZhbFBvbGljeTogJ3JldGFpbicgfCAnZGVzdHJveSc7XG4gIC8qKiBTZWNvbmRzIHRvIHdhaXQgYmVmb3JlIGRlbGV0aW5nLCBzbyBlbnZpcm9ubWVudHMgc3RpbGwgc2h1dHRpbmcgZG93biBjYW4gZmx1c2ggdGhlaXIgbGFzdCBsaW5lcy4gKi9cbiAgcmVhZG9ubHkgRmx1c2hXYWl0U2Vjb25kczogc3RyaW5nO1xuICAvKiogU2Vjb25kcyB0byB3YWl0IGJlZm9yZSBjaGVja2luZyBvbmNlIG1vcmUgdGhhdCB0aGUgc2VydmljZSBoYXNuJ3QgcmUtY3JlYXRlZCB0aGUgZ3JvdXAuICovXG4gIHJlYWRvbmx5IFJlY2hlY2tXYWl0U2Vjb25kczogc3RyaW5nO1xufVxuXG4vKiogUmVhZHMgYW4gZW5kcG9pbnQncyBwZXItcmVnaW9uIGRvbWFpbiBuYW1lcywgd2hpY2ggQ2xvdWRGb3JtYXRpb24gY2FuJ3QgaW5kZXggb3V0IG9mIGBSZWdpb25hbEVuZHBvaW50c2AuICovXG5leHBvcnQgY29uc3QgRU5EUE9JTlRfTE9PS1VQX1JFU09VUkNFX1RZUEUgPSAnQ3VzdG9tOjpMYW1iZGFXZWJFbmRwb2ludExvb2t1cCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRW5kcG9pbnRMb29rdXBQcm9wZXJ0aWVzIHtcbiAgcmVhZG9ubHkgRnVuY3Rpb25Bcm46IHN0cmluZztcbiAgcmVhZG9ubHkgRW5kcG9pbnROYW1lOiBzdHJpbmc7XG4gIC8qKiBDaGFuZ2VzIHdoZW5ldmVyIHRoZSBlbmRwb2ludCBpcyByZXBsYWNlZCwgc28gdGhlIGxvb2t1cCBydW5zIGFnYWluLiAqL1xuICByZWFkb25seSBFbmRwb2ludEFybjogc3RyaW5nO1xufVxuXG4vKiogQXR0cmlidXRlIG5hbWUgaG9sZGluZyB0aGUgZG9tYWluIG9mIG9uZSByZWdpb24sIGUuZy4gYERvbWFpbi51cy1lYXN0LTFgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lvbmFsRG9tYWluQXR0cmlidXRlKHJlZ2lvbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBEb21haW4uJHtyZWdpb259YDtcbn1cblxuLyoqIERlbGV0ZXMgYSBmdW5jdGlvbidzIG9sZGVzdCByZXZpc2lvbnMgYmV5b25kIGEgY291bnQsIGV4Y2VwdCB0aG9zZSB0aGF0IGFyZSBpbiB1c2Ugb3IgbWF5IGJlIHJvbGxlZCBiYWNrIHRvLiAqL1xuZXhwb3J0IGNvbnN0IFJFVklTSU9OX0NMRUFOVVBfUkVTT1VSQ0VfVFlQRSA9ICdDdXN0b206OkxhbWJkYVdlYlJldmlzaW9uQ2xlYW51cCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmV2aXNpb25DbGVhbnVwUHJvcGVydGllcyB7XG4gIHJlYWRvbmx5IEZ1bmN0aW9uQXJuOiBzdHJpbmc7XG4gIC8qKiBIb3cgbWFueSBvZiB0aGUgbmV3ZXN0IHJldmlzaW9ucyB0byBrZWVwLiAqL1xuICByZWFkb25seSBLZWVwOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBSZXZpc2lvbnMgdGhlIHRlbXBsYXRlIHVzZXMgKHRoZSBjdXJyZW50IG9uZSBhbmQgYW55IGFuIGVuZHBvaW50IHJvdXRlcyB0bykuIEFsd2F5cyBrZXB0LCBhbmQgb24gYW4gdXBkYXRlXG4gICAqIHRoZSBwcmV2aW91cyB0ZW1wbGF0ZSdzIGFyZSBrZXB0IHRvbzogdGhleSdyZSB3aGF0IGEgcm9sbGJhY2sgcm91dGVzIGJhY2sgdG8uXG4gICAqL1xuICByZWFkb25seSBSZXZpc2lvbklkczogc3RyaW5nW107XG59XG5cbi8qKlxuICogTW92ZXMgYW4gZW5kcG9pbnQncyB0cmFmZmljIHRvIGEgcmV2aXNpb24gaW4gc3RlcHMsIHdhdGNoaW5nIGFsYXJtcyAoY2FuYXJ5IGFuZCBsaW5lYXIgZGVwbG95bWVudHMpLlxuICogU2VydmVkIGJ5IHRoZSBkZXBsb3ltZW50IHByb3ZpZGVyIChgaGFuZGxlcnMvd2ViLWZ1bmN0aW9uLWRlcGxveW1lbnRgKSwgbm90IHRoZSBzaGFyZWQgcHJvdmlkZXI6IGl0IGNhbiBydW4gZm9yIHVwIHRvIGFuIGhvdXIuXG4gKi9cbmV4cG9ydCBjb25zdCBUUkFGRklDX1NISUZUX1JFU09VUkNFX1RZUEUgPSAnQ3VzdG9tOjpMYW1iZGFXZWJUcmFmZmljU2hpZnQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFRyYWZmaWNTaGlmdFByb3BlcnRpZXMge1xuICByZWFkb25seSBGdW5jdGlvbkFybjogc3RyaW5nO1xuICByZWFkb25seSBFbmRwb2ludE5hbWU6IHN0cmluZztcbiAgLyoqIFRoZSByZXZpc2lvbiB0aGF0IGVuZHMgdXAgd2l0aCBhbGwgb2YgdGhlIGVuZHBvaW50J3MgdHJhZmZpYy4gKi9cbiAgcmVhZG9ubHkgUmV2aXNpb25JZDogc3RyaW5nO1xuICAvKiogVGhlIHJldmlzaW9uJ3Mgc2hhcmUgb2YgdHJhZmZpYyBhdCBlYWNoIHN0ZXAsIGluIHBlcmNlbnQsIGNvbW1hLXNlcGFyYXRlZDsgdGhlIGxhc3QgaXMgMTAwLiAqL1xuICByZWFkb25seSBTdGVwczogc3RyaW5nO1xuICAvKiogU2Vjb25kcyBlYWNoIHN0ZXAgc2VydmVzIChjb3VudGVkIGZyb20gd2hlbiBpdHMgdXBkYXRlIHN0YXJ0ZWQpIGJlZm9yZSB0aGUgbmV4dC4gKi9cbiAgcmVhZG9ubHkgV2FpdFNlY29uZHM6IHN0cmluZztcbiAgLyoqIEFsYXJtcyAoaW4gYW55IHJlZ2lvbikgdGhhdCBzdG9wIHRoZSBkZXBsb3ltZW50IGFuZCByZXN0b3JlIHRoZSBwcmV2aW91cyB3ZWlnaHRzLiAqL1xuICByZWFkb25seSBBbGFybUFybnM/OiBzdHJpbmdbXTtcbiAgLyoqIEhhc2ggb2YgdGhlIGVuZHBvaW50J3Mgb3RoZXIgc2V0dGluZ3M6IGFueSBlbmRwb2ludCBjaGFuZ2UgcmUtY2hlY2tzIGl0cyB0cmFmZmljIGJlZm9yZSBDbG91ZEZvcm1hdGlvbiB3cml0ZXMgaXQuICovXG4gIHJlYWRvbmx5IEVuZHBvaW50Q29uZmlnOiBzdHJpbmc7XG59XG5cbi8qKiBXaGF0IGBvbkV2ZW50YCBoYW5kcyB0byBgaXNDb21wbGV0ZWAgKHRoZSBQcm92aWRlciBmcmFtZXdvcmsgcGFzc2VzIGl0IGFzIGBEYXRhYCkuICovXG5leHBvcnQgaW50ZXJmYWNlIFRyYWZmaWNTaGlmdFN0YXRlIHtcbiAgLyoqIGBub25lYDogbm90aGluZyB0byBkbzsgYHNoaWZ0YDogbW92aW5nIGluIHN0ZXBzOyBgc3dpdGNoYDogYWxsIGF0IG9uY2UsIHdpdGhvdXQgYWxhcm1zIChzdGFjayByb2xsYmFjaykuICovXG4gIHJlYWRvbmx5IEFjdGlvbjogJ25vbmUnIHwgJ3NoaWZ0JyB8ICdzd2l0Y2gnO1xuICAvKiogYHNoaWZ0YDogdGhlIGVuZHBvaW50J3Mgd2VpZ2h0cyBiZWZvcmUgdGhlIGRlcGxveW1lbnQgKEpTT04gYFt7cmV2aXNpb25JZCwgd2VpZ2h0fV1gKSwgcmVzdG9yZWQgd2hlbiBhbiBhbGFybSBmaXJlcy4gKi9cbiAgcmVhZG9ubHkgUHJldmlvdXNXZWlnaHRzPzogc3RyaW5nO1xuICAvKiogYHN3aXRjaGA6IHRoZSB3ZWlnaHRzIGJlaW5nIHdyaXR0ZW4gKEpTT04gYFt7cmV2aXNpb25JZCwgd2VpZ2h0fV1gKS4gKi9cbiAgcmVhZG9ubHkgVGFyZ2V0V2VpZ2h0cz86IHN0cmluZztcbn1cbiJdfQ==
|
package/lib/private/provider.js
CHANGED
|
@@ -49,7 +49,7 @@ function webFunctionProvider(scope) {
|
|
|
49
49
|
// Log group deletion waits for late flushes (75s + a re-check) on top of the API calls.
|
|
50
50
|
timeout: aws_cdk_lib_1.Duration.minutes(5),
|
|
51
51
|
memorySize: aws_cdk_lib_1.Size.mebibytes(256),
|
|
52
|
-
description: 'Copies code, manages log groups
|
|
52
|
+
description: 'Copies code, manages log groups, looks up endpoints and cleans up revisions for Lambda Web Functions',
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
const granted = new WeakMap();
|
|
@@ -74,4 +74,4 @@ function grantToProvider(provider, statement) {
|
|
|
74
74
|
seen.add(key);
|
|
75
75
|
provider.addToRolePolicy({ Effect: 'Allow', ...statement });
|
|
76
76
|
}
|
|
77
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
77
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJpdmF0ZS9wcm92aWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQVNBLGtEQVNDO0FBYUQsMENBVUM7QUF6Q0QsZ0RBQWtDO0FBQ2xDLDZDQUEyRztBQUczRzs7OztHQUlHO0FBQ0gsU0FBZ0IsbUJBQW1CLENBQUMsS0FBZ0I7SUFDbEQsT0FBTyxvQ0FBc0IsQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsbUNBQW1DLEVBQUU7UUFDNUYsYUFBYSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLHVCQUF1QixDQUFDO1FBQ2xGLE9BQU8sRUFBRSwyQ0FBNkIsQ0FBQyxXQUFXO1FBQ2xELHdGQUF3RjtRQUN4RixPQUFPLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQzVCLFVBQVUsRUFBRSxrQkFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUM7UUFDL0IsV0FBVyxFQUFFLHNHQUFzRztLQUNwSCxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLEVBQXVDLENBQUM7QUFFbkU7Ozs7Ozs7O0dBUUc7QUFDSCxTQUFnQixlQUFlLENBQUMsUUFBZ0MsRUFBRSxTQUFxRTtJQUNySSxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLG1CQUFLLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDakMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ1YsSUFBSSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUM7UUFDakIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDOUIsQ0FBQztJQUNELElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUM7UUFBRSxPQUFPO0lBQzFCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDZCxRQUFRLENBQUMsZUFBZSxDQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLFNBQVMsRUFBRSxDQUFDLENBQUM7QUFDOUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7IEN1c3RvbVJlc291cmNlUHJvdmlkZXIsIEN1c3RvbVJlc291cmNlUHJvdmlkZXJSdW50aW1lLCBEdXJhdGlvbiwgU2l6ZSwgU3RhY2sgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgdHlwZSB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuXG4vKipcbiAqIFRoZSBzaW5nbGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIChvbmUgTGFtYmRhIHBlciBzdGFjaykgYmVoaW5kIGNvZGUgY29waWVzLCBsb2cgZ3JvdXBzXG4gKiBhbmQgZW5kcG9pbnQgbG9va3Vwcy4gSXQncyBhIGNvcmUgYEN1c3RvbVJlc291cmNlUHJvdmlkZXJgLCBub3QgYSBgbGFtYmRhLkZ1bmN0aW9uYCwgc29cbiAqIHRvb2xzIHRoYXQgZGlzY292ZXIgZnVuY3Rpb25zIGJ5IGNsYXNzIChlLmcuIGNkay13YXRjaGZ1bCkgZG9uJ3QgcGljayBpdCB1cC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdlYkZ1bmN0aW9uUHJvdmlkZXIoc2NvcGU6IENvbnN0cnVjdCk6IEN1c3RvbVJlc291cmNlUHJvdmlkZXIge1xuICByZXR1cm4gQ3VzdG9tUmVzb3VyY2VQcm92aWRlci5nZXRPckNyZWF0ZVByb3ZpZGVyKHNjb3BlLCAnQ3VzdG9tOjpMYW1iZGFXZWJGdW5jdGlvblByb3ZpZGVyJywge1xuICAgIGNvZGVEaXJlY3Rvcnk6IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicsICcuLicsICdhc3NldHMnLCAnd2ViLWZ1bmN0aW9uLXByb3ZpZGVyJyksXG4gICAgcnVudGltZTogQ3VzdG9tUmVzb3VyY2VQcm92aWRlclJ1bnRpbWUuTk9ERUpTXzI0X1gsXG4gICAgLy8gTG9nIGdyb3VwIGRlbGV0aW9uIHdhaXRzIGZvciBsYXRlIGZsdXNoZXMgKDc1cyArIGEgcmUtY2hlY2spIG9uIHRvcCBvZiB0aGUgQVBJIGNhbGxzLlxuICAgIHRpbWVvdXQ6IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgbWVtb3J5U2l6ZTogU2l6ZS5tZWJpYnl0ZXMoMjU2KSxcbiAgICBkZXNjcmlwdGlvbjogJ0NvcGllcyBjb2RlLCBtYW5hZ2VzIGxvZyBncm91cHMsIGxvb2tzIHVwIGVuZHBvaW50cyBhbmQgY2xlYW5zIHVwIHJldmlzaW9ucyBmb3IgTGFtYmRhIFdlYiBGdW5jdGlvbnMnLFxuICB9KTtcbn1cblxuY29uc3QgZ3JhbnRlZCA9IG5ldyBXZWFrTWFwPEN1c3RvbVJlc291cmNlUHJvdmlkZXIsIFNldDxzdHJpbmc+PigpO1xuXG4vKipcbiAqIEFkZHMgYSBzdGF0ZW1lbnQgdG8gdGhlIHNoYXJlZCBwcm92aWRlcidzIHJvbGUsIG9uY2UuXG4gKlxuICogR3JhbnRzIG11c3QgYmUgKipzdGFibGUgYWNyb3NzIHVwZGF0ZXMqKjogc2NvcGVkIGJ5IHByZWZpeGVzIHRoYXQgZG9uJ3QgY2hhbmdlIHdoZW4gYVxuICogcmVzb3VyY2UgaXMgcmVuYW1lZCBvciByZXBsYWNlZC4gQ2xvdWRGb3JtYXRpb24gdXBkYXRlcyB0aGUgcm9sZSBqdXN0IGJlZm9yZSAoYW5kIG9uIHJvbGxiYWNrLFxuICogcmV2ZXJ0cyBpdCBqdXN0IGJlZm9yZSkgdGhlIGN1c3RvbSByZXNvdXJjZXMgcnVuLCBhbmQgSUFNIHRha2VzIHNlY29uZHMgdG8gbWludXRlcyB0b1xuICogcHJvcGFnYXRlLCBzbyBwZXItbmFtZSBncmFudHMgZmFpbCB3aXRoIEFjY2Vzc0RlbmllZCBvbiByZW5hbWVzIGFuZCBvbiByb2xsYmFjayBjbGVhbnVwLlxuICogVGhleSBtdXN0IGFsc28gbmV2ZXIgcmVmZXJlbmNlIGF0dHJpYnV0ZXMgb2YgcmVzb3VyY2VzIHRoYXQgdXNlIHRoZSBwcm92aWRlciAoY3ljbGUpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ3JhbnRUb1Byb3ZpZGVyKHByb3ZpZGVyOiBDdXN0b21SZXNvdXJjZVByb3ZpZGVyLCBzdGF0ZW1lbnQ6IHsgQWN0aW9uOiBzdHJpbmcgfCBzdHJpbmdbXTsgUmVzb3VyY2U6IHN0cmluZyB8IHN0cmluZ1tdIH0pOiB2b2lkIHtcbiAgY29uc3Qga2V5ID0gSlNPTi5zdHJpbmdpZnkoU3RhY2sub2YocHJvdmlkZXIpLnJlc29sdmUoc3RhdGVtZW50KSk7XG4gIGxldCBzZWVuID0gZ3JhbnRlZC5nZXQocHJvdmlkZXIpO1xuICBpZiAoIXNlZW4pIHtcbiAgICBzZWVuID0gbmV3IFNldCgpO1xuICAgIGdyYW50ZWQuc2V0KHByb3ZpZGVyLCBzZWVuKTtcbiAgfVxuICBpZiAoc2Vlbi5oYXMoa2V5KSkgcmV0dXJuO1xuICBzZWVuLmFkZChrZXkpO1xuICBwcm92aWRlci5hZGRUb1JvbGVQb2xpY3koeyBFZmZlY3Q6ICdBbGxvdycsIC4uLnN0YXRlbWVudCB9KTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CustomResource } from 'aws-cdk-lib';
|
|
2
|
+
import { Construct } from 'constructs';
|
|
3
|
+
export interface RevisionCleanupProps {
|
|
4
|
+
/** Literal function name: the provider's IAM must not reference attributes of resources that use the provider (dependency cycle). */
|
|
5
|
+
readonly functionName: string;
|
|
6
|
+
readonly functionArn: string;
|
|
7
|
+
/** How many of the newest revisions to keep. */
|
|
8
|
+
readonly keep: number;
|
|
9
|
+
/** Revisions the template uses, read when the template is synthesized (endpoints can be added later). */
|
|
10
|
+
readonly revisionIds: () => string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Deletes a function's oldest revisions beyond `keep` on every deployment. Runs after the endpoints
|
|
14
|
+
* (add them as dependencies), so the revisions they just stopped routing to are eligible.
|
|
15
|
+
*/
|
|
16
|
+
export declare class RevisionCleanup extends Construct {
|
|
17
|
+
readonly resource: CustomResource;
|
|
18
|
+
constructor(scope: Construct, id: string, props: RevisionCleanupProps);
|
|
19
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RevisionCleanup = void 0;
|
|
4
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
5
|
+
const constructs_1 = require("constructs");
|
|
6
|
+
const provider_1 = require("./provider");
|
|
7
|
+
const provider_protocol_1 = require("./provider-protocol");
|
|
8
|
+
/**
|
|
9
|
+
* Deletes a function's oldest revisions beyond `keep` on every deployment. Runs after the endpoints
|
|
10
|
+
* (add them as dependencies), so the revisions they just stopped routing to are eligible.
|
|
11
|
+
*/
|
|
12
|
+
class RevisionCleanup extends constructs_1.Construct {
|
|
13
|
+
resource;
|
|
14
|
+
constructor(scope, id, props) {
|
|
15
|
+
super(scope, id);
|
|
16
|
+
const provider = (0, provider_1.webFunctionProvider)(this);
|
|
17
|
+
// Stable grant (see grantToProvider): the function and its revisions, by name.
|
|
18
|
+
const functionArn = aws_cdk_lib_1.Stack.of(this).formatArn({
|
|
19
|
+
service: 'lambda', resource: 'web-function', resourceName: props.functionName, arnFormat: aws_cdk_lib_1.ArnFormat.SLASH_RESOURCE_NAME,
|
|
20
|
+
});
|
|
21
|
+
(0, provider_1.grantToProvider)(provider, {
|
|
22
|
+
Action: ['lambda:ListWebFunctionRevisions', 'lambda:DeleteWebFunctionRevision'],
|
|
23
|
+
Resource: [functionArn, `${functionArn}/revision/*`],
|
|
24
|
+
});
|
|
25
|
+
const properties = {
|
|
26
|
+
FunctionArn: props.functionArn,
|
|
27
|
+
Keep: String(props.keep),
|
|
28
|
+
RevisionIds: aws_cdk_lib_1.Lazy.list({ produce: () => [...new Set(props.revisionIds())] }),
|
|
29
|
+
};
|
|
30
|
+
this.resource = new aws_cdk_lib_1.CustomResource(this, 'Resource', {
|
|
31
|
+
serviceToken: provider.serviceToken,
|
|
32
|
+
resourceType: provider_protocol_1.REVISION_CLEANUP_RESOURCE_TYPE,
|
|
33
|
+
properties: { ...properties },
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.RevisionCleanup = RevisionCleanup;
|
|
38
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV2aXNpb24tY2xlYW51cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcml2YXRlL3JldmlzaW9uLWNsZWFudXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkNBQXFFO0FBQ3JFLDJDQUF1QztBQUN2Qyx5Q0FBa0U7QUFDbEUsMkRBQXFHO0FBWXJHOzs7R0FHRztBQUNILE1BQWEsZUFBZ0IsU0FBUSxzQkFBUztJQUM1QixRQUFRLENBQWlCO0lBRXpDLFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBMkI7UUFDbkUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNqQixNQUFNLFFBQVEsR0FBRyxJQUFBLDhCQUFtQixFQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNDLCtFQUErRTtRQUMvRSxNQUFNLFdBQVcsR0FBRyxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUM7WUFDM0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsY0FBYyxFQUFFLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWSxFQUFFLFNBQVMsRUFBRSx1QkFBUyxDQUFDLG1CQUFtQjtTQUN4SCxDQUFDLENBQUM7UUFDSCxJQUFBLDBCQUFlLEVBQUMsUUFBUSxFQUFFO1lBQ3hCLE1BQU0sRUFBRSxDQUFDLGlDQUFpQyxFQUFFLGtDQUFrQyxDQUFDO1lBQy9FLFFBQVEsRUFBRSxDQUFDLFdBQVcsRUFBRSxHQUFHLFdBQVcsYUFBYSxDQUFDO1NBQ3JELENBQUMsQ0FBQztRQUVILE1BQU0sVUFBVSxHQUE4QjtZQUM1QyxXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVc7WUFDOUIsSUFBSSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO1lBQ3hCLFdBQVcsRUFBRSxrQkFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQzdFLENBQUM7UUFDRixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksNEJBQWMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBQ25ELFlBQVksRUFBRSxRQUFRLENBQUMsWUFBWTtZQUNuQyxZQUFZLEVBQUUsa0RBQThCO1lBQzVDLFVBQVUsRUFBRSxFQUFFLEdBQUcsVUFBVSxFQUFFO1NBQzlCLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQTFCRCwwQ0EwQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBcm5Gb3JtYXQsIEN1c3RvbVJlc291cmNlLCBMYXp5LCBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgZ3JhbnRUb1Byb3ZpZGVyLCB3ZWJGdW5jdGlvblByb3ZpZGVyIH0gZnJvbSAnLi9wcm92aWRlcic7XG5pbXBvcnQgeyBSRVZJU0lPTl9DTEVBTlVQX1JFU09VUkNFX1RZUEUsIHR5cGUgUmV2aXNpb25DbGVhbnVwUHJvcGVydGllcyB9IGZyb20gJy4vcHJvdmlkZXItcHJvdG9jb2wnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJldmlzaW9uQ2xlYW51cFByb3BzIHtcbiAgLyoqIExpdGVyYWwgZnVuY3Rpb24gbmFtZTogdGhlIHByb3ZpZGVyJ3MgSUFNIG11c3Qgbm90IHJlZmVyZW5jZSBhdHRyaWJ1dGVzIG9mIHJlc291cmNlcyB0aGF0IHVzZSB0aGUgcHJvdmlkZXIgKGRlcGVuZGVuY3kgY3ljbGUpLiAqL1xuICByZWFkb25seSBmdW5jdGlvbk5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgZnVuY3Rpb25Bcm46IHN0cmluZztcbiAgLyoqIEhvdyBtYW55IG9mIHRoZSBuZXdlc3QgcmV2aXNpb25zIHRvIGtlZXAuICovXG4gIHJlYWRvbmx5IGtlZXA6IG51bWJlcjtcbiAgLyoqIFJldmlzaW9ucyB0aGUgdGVtcGxhdGUgdXNlcywgcmVhZCB3aGVuIHRoZSB0ZW1wbGF0ZSBpcyBzeW50aGVzaXplZCAoZW5kcG9pbnRzIGNhbiBiZSBhZGRlZCBsYXRlcikuICovXG4gIHJlYWRvbmx5IHJldmlzaW9uSWRzOiAoKSA9PiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBEZWxldGVzIGEgZnVuY3Rpb24ncyBvbGRlc3QgcmV2aXNpb25zIGJleW9uZCBga2VlcGAgb24gZXZlcnkgZGVwbG95bWVudC4gUnVucyBhZnRlciB0aGUgZW5kcG9pbnRzXG4gKiAoYWRkIHRoZW0gYXMgZGVwZW5kZW5jaWVzKSwgc28gdGhlIHJldmlzaW9ucyB0aGV5IGp1c3Qgc3RvcHBlZCByb3V0aW5nIHRvIGFyZSBlbGlnaWJsZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFJldmlzaW9uQ2xlYW51cCBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSByZXNvdXJjZTogQ3VzdG9tUmVzb3VyY2U7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFJldmlzaW9uQ2xlYW51cFByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICBjb25zdCBwcm92aWRlciA9IHdlYkZ1bmN0aW9uUHJvdmlkZXIodGhpcyk7XG4gICAgLy8gU3RhYmxlIGdyYW50IChzZWUgZ3JhbnRUb1Byb3ZpZGVyKTogdGhlIGZ1bmN0aW9uIGFuZCBpdHMgcmV2aXNpb25zLCBieSBuYW1lLlxuICAgIGNvbnN0IGZ1bmN0aW9uQXJuID0gU3RhY2sub2YodGhpcykuZm9ybWF0QXJuKHtcbiAgICAgIHNlcnZpY2U6ICdsYW1iZGEnLCByZXNvdXJjZTogJ3dlYi1mdW5jdGlvbicsIHJlc291cmNlTmFtZTogcHJvcHMuZnVuY3Rpb25OYW1lLCBhcm5Gb3JtYXQ6IEFybkZvcm1hdC5TTEFTSF9SRVNPVVJDRV9OQU1FLFxuICAgIH0pO1xuICAgIGdyYW50VG9Qcm92aWRlcihwcm92aWRlciwge1xuICAgICAgQWN0aW9uOiBbJ2xhbWJkYTpMaXN0V2ViRnVuY3Rpb25SZXZpc2lvbnMnLCAnbGFtYmRhOkRlbGV0ZVdlYkZ1bmN0aW9uUmV2aXNpb24nXSxcbiAgICAgIFJlc291cmNlOiBbZnVuY3Rpb25Bcm4sIGAke2Z1bmN0aW9uQXJufS9yZXZpc2lvbi8qYF0sXG4gICAgfSk7XG5cbiAgICBjb25zdCBwcm9wZXJ0aWVzOiBSZXZpc2lvbkNsZWFudXBQcm9wZXJ0aWVzID0ge1xuICAgICAgRnVuY3Rpb25Bcm46IHByb3BzLmZ1bmN0aW9uQXJuLFxuICAgICAgS2VlcDogU3RyaW5nKHByb3BzLmtlZXApLFxuICAgICAgUmV2aXNpb25JZHM6IExhenkubGlzdCh7IHByb2R1Y2U6ICgpID0+IFsuLi5uZXcgU2V0KHByb3BzLnJldmlzaW9uSWRzKCkpXSB9KSxcbiAgICB9O1xuICAgIHRoaXMucmVzb3VyY2UgPSBuZXcgQ3VzdG9tUmVzb3VyY2UodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgc2VydmljZVRva2VuOiBwcm92aWRlci5zZXJ2aWNlVG9rZW4sXG4gICAgICByZXNvdXJjZVR5cGU6IFJFVklTSU9OX0NMRUFOVVBfUkVTT1VSQ0VfVFlQRSxcbiAgICAgIHByb3BlcnRpZXM6IHsgLi4ucHJvcGVydGllcyB9LFxuICAgIH0pO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CustomResource } from 'aws-cdk-lib';
|
|
2
|
+
import { Construct } from 'constructs';
|
|
3
|
+
import type { WebFunctionDeployment } from '../web-function-deployment';
|
|
4
|
+
export interface TrafficShiftProps {
|
|
5
|
+
/** Literal function name, for stable IAM grants. */
|
|
6
|
+
readonly functionName: string;
|
|
7
|
+
readonly functionArn: string;
|
|
8
|
+
readonly endpointName: string;
|
|
9
|
+
readonly revisionId: string;
|
|
10
|
+
readonly deployment: WebFunctionDeployment;
|
|
11
|
+
/** The endpoint's other settings: any change makes the shift run, so it can re-check the traffic before CloudFormation writes it. */
|
|
12
|
+
readonly endpointConfig: unknown;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Moves an endpoint's traffic to `revisionId` in steps before CloudFormation updates the endpoint (which must depend on it).
|
|
16
|
+
*/
|
|
17
|
+
export declare class TrafficShift extends Construct {
|
|
18
|
+
readonly resource: CustomResource;
|
|
19
|
+
constructor(scope: Construct, id: string, props: TrafficShiftProps);
|
|
20
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.TrafficShift = void 0;
|
|
37
|
+
const node_crypto_1 = require("node:crypto");
|
|
38
|
+
const path = __importStar(require("node:path"));
|
|
39
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
40
|
+
const iam = __importStar(require("aws-cdk-lib/aws-iam"));
|
|
41
|
+
const lambda = __importStar(require("aws-cdk-lib/aws-lambda"));
|
|
42
|
+
const logs = __importStar(require("aws-cdk-lib/aws-logs"));
|
|
43
|
+
const cr = __importStar(require("aws-cdk-lib/custom-resources"));
|
|
44
|
+
const constructs_1 = require("constructs");
|
|
45
|
+
const provider_protocol_1 = require("./provider-protocol");
|
|
46
|
+
/** The Provider framework gives up after this long and fails the deployment (with a message), before CloudFormation's own 1-hour limit. */
|
|
47
|
+
const TOTAL_TIMEOUT = aws_cdk_lib_1.Duration.minutes(55);
|
|
48
|
+
const PROVIDER_ID = 'LambdaWebDeploymentProvider';
|
|
49
|
+
/**
|
|
50
|
+
* The stack's deployment provider: a CDK Provider framework (a Step Functions waiter) around `onEvent` and `isComplete`
|
|
51
|
+
* from `handlers/web-function-deployment`, because a canary or linear deployment can run for up to an hour.
|
|
52
|
+
* One per stack, shared by every endpoint that deploys in steps.
|
|
53
|
+
*/
|
|
54
|
+
class DeploymentProvider extends constructs_1.Construct {
|
|
55
|
+
static of(scope) {
|
|
56
|
+
const stack = aws_cdk_lib_1.Stack.of(scope);
|
|
57
|
+
return stack.node.tryFindChild(PROVIDER_ID) ?? new DeploymentProvider(stack, PROVIDER_ID);
|
|
58
|
+
}
|
|
59
|
+
serviceToken;
|
|
60
|
+
role;
|
|
61
|
+
granted = new Set();
|
|
62
|
+
constructor(scope, id) {
|
|
63
|
+
super(scope, id);
|
|
64
|
+
this.role = new iam.Role(this, 'Role', {
|
|
65
|
+
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
|
|
66
|
+
managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')],
|
|
67
|
+
});
|
|
68
|
+
// Rollback detection: is the stack rolling back? (the provider's own stack only).
|
|
69
|
+
this.grant({ actions: ['cloudformation:DescribeStacks'], resources: [aws_cdk_lib_1.Stack.of(this).stackId] });
|
|
70
|
+
// Composite alarms are only returned with DescribeAlarms on '*'.
|
|
71
|
+
this.grant({ actions: ['cloudwatch:DescribeAlarms'], resources: ['*'] });
|
|
72
|
+
const logGroup = new logs.LogGroup(this, 'Logs', { retention: logs.RetentionDays.ONE_MONTH, removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY });
|
|
73
|
+
const handler = (name, handlerName, description) => new lambda.Function(this, name, {
|
|
74
|
+
runtime: lambda.Runtime.NODEJS_24_X,
|
|
75
|
+
architecture: lambda.Architecture.ARM_64,
|
|
76
|
+
code: lambda.Code.fromAsset(path.join(__dirname, '..', '..', 'assets', 'web-function-deployment')),
|
|
77
|
+
handler: `index.${handlerName}`,
|
|
78
|
+
role: this.role,
|
|
79
|
+
// isComplete waits up to 5 minutes for a restore to reach every region before failing the deployment.
|
|
80
|
+
timeout: aws_cdk_lib_1.Duration.minutes(7),
|
|
81
|
+
memorySize: 256,
|
|
82
|
+
logGroup,
|
|
83
|
+
description,
|
|
84
|
+
});
|
|
85
|
+
const provider = new cr.Provider(this, 'Provider', {
|
|
86
|
+
onEventHandler: handler('OnEvent', 'onEvent', 'Starts canary and linear deployments of Lambda Web Function endpoints'),
|
|
87
|
+
isCompleteHandler: handler('IsComplete', 'isComplete', 'Moves Lambda Web Function endpoint traffic step by step and watches alarms'),
|
|
88
|
+
queryInterval: aws_cdk_lib_1.Duration.seconds(15),
|
|
89
|
+
totalTimeout: TOTAL_TIMEOUT,
|
|
90
|
+
logGroup,
|
|
91
|
+
});
|
|
92
|
+
this.serviceToken = provider.serviceToken;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Adds a statement to the handlers' role, once. Like the shared provider's grants, they must be stable across
|
|
96
|
+
* updates (prefixes, not names that change) and never reference attributes of resources that use the provider.
|
|
97
|
+
*/
|
|
98
|
+
grant(statement) {
|
|
99
|
+
const key = JSON.stringify(aws_cdk_lib_1.Stack.of(this).resolve(statement));
|
|
100
|
+
if (this.granted.has(key))
|
|
101
|
+
return;
|
|
102
|
+
this.granted.add(key);
|
|
103
|
+
this.role.addToPrincipalPolicy(new iam.PolicyStatement(statement));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Moves an endpoint's traffic to `revisionId` in steps before CloudFormation updates the endpoint (which must depend on it).
|
|
108
|
+
*/
|
|
109
|
+
class TrafficShift extends constructs_1.Construct {
|
|
110
|
+
resource;
|
|
111
|
+
constructor(scope, id, props) {
|
|
112
|
+
super(scope, id);
|
|
113
|
+
const stack = aws_cdk_lib_1.Stack.of(this);
|
|
114
|
+
const provider = DeploymentProvider.of(this);
|
|
115
|
+
const functionArn = stack.formatArn({
|
|
116
|
+
service: 'lambda', resource: 'web-function', resourceName: props.functionName, arnFormat: aws_cdk_lib_1.ArnFormat.SLASH_RESOURCE_NAME,
|
|
117
|
+
});
|
|
118
|
+
// Stable grant (see grantToProvider): every endpoint and revision of the function.
|
|
119
|
+
provider.grant({
|
|
120
|
+
actions: ['lambda:GetWebFunctionEndpoint', 'lambda:UpdateWebFunctionEndpoint'],
|
|
121
|
+
resources: [functionArn, `${functionArn}/endpoint/*`, `${functionArn}/revision/*`],
|
|
122
|
+
});
|
|
123
|
+
const deployment = props.deployment;
|
|
124
|
+
const properties = {
|
|
125
|
+
FunctionArn: props.functionArn,
|
|
126
|
+
EndpointName: props.endpointName,
|
|
127
|
+
RevisionId: props.revisionId,
|
|
128
|
+
Steps: deployment._steps.join(','),
|
|
129
|
+
WaitSeconds: String(deployment._waitSeconds),
|
|
130
|
+
AlarmArns: deployment._alarms.length > 0 ? deployment._alarms.map((a) => a.alarmArn) : undefined,
|
|
131
|
+
EndpointConfig: (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(stack.resolve(props.endpointConfig))).digest('hex').slice(0, 16),
|
|
132
|
+
};
|
|
133
|
+
this.resource = new aws_cdk_lib_1.CustomResource(this, 'Resource', {
|
|
134
|
+
serviceToken: provider.serviceToken,
|
|
135
|
+
resourceType: provider_protocol_1.TRAFFIC_SHIFT_RESOURCE_TYPE,
|
|
136
|
+
properties: { ...properties },
|
|
137
|
+
// CloudFormation's maximum; the provider fails the deployment itself after 55 minutes.
|
|
138
|
+
serviceTimeout: aws_cdk_lib_1.Duration.hours(1),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.TrafficShift = TrafficShift;
|
|
143
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhZmZpYy1zaGlmdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcml2YXRlL3RyYWZmaWMtc2hpZnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsNkNBQXlDO0FBQ3pDLGdEQUFrQztBQUNsQyw2Q0FBd0Y7QUFDeEYseURBQTJDO0FBQzNDLCtEQUFpRDtBQUNqRCwyREFBNkM7QUFDN0MsaUVBQW1EO0FBQ25ELDJDQUF1QztBQUN2QywyREFBK0Y7QUFHL0YsMklBQTJJO0FBQzNJLE1BQU0sYUFBYSxHQUFHLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQzNDLE1BQU0sV0FBVyxHQUFHLDZCQUE2QixDQUFDO0FBRWxEOzs7O0dBSUc7QUFDSCxNQUFNLGtCQUFtQixTQUFRLHNCQUFTO0lBQ2pDLE1BQU0sQ0FBQyxFQUFFLENBQUMsS0FBZ0I7UUFDL0IsTUFBTSxLQUFLLEdBQUcsbUJBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDOUIsT0FBUSxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQW9DLElBQUksSUFBSSxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDaEksQ0FBQztJQUVlLFlBQVksQ0FBUztJQUNwQixJQUFJLENBQVc7SUFDZixPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUU3QyxZQUFvQixLQUFnQixFQUFFLEVBQVU7UUFDOUMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUNqQixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFO1lBQ3JDLFNBQVMsRUFBRSxJQUFJLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxzQkFBc0IsQ0FBQztZQUMzRCxlQUFlLEVBQUUsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLHdCQUF3QixDQUFDLDBDQUEwQyxDQUFDLENBQUM7U0FDMUcsQ0FBQyxDQUFDO1FBQ0gsa0ZBQWtGO1FBQ2xGLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQywrQkFBK0IsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNoRyxpRUFBaUU7UUFDakUsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLDJCQUEyQixDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRXpFLE1BQU0sUUFBUSxHQUFHLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsU0FBUyxFQUFFLGFBQWEsRUFBRSwyQkFBYSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDcEksTUFBTSxPQUFPLEdBQUcsQ0FBQyxJQUFZLEVBQUUsV0FBbUIsRUFBRSxXQUFtQixFQUFFLEVBQUUsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRTtZQUMxRyxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXO1lBQ25DLFlBQVksRUFBRSxNQUFNLENBQUMsWUFBWSxDQUFDLE1BQU07WUFDeEMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLHlCQUF5QixDQUFDLENBQUM7WUFDbEcsT0FBTyxFQUFFLFNBQVMsV0FBVyxFQUFFO1lBQy9CLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtZQUNmLHNHQUFzRztZQUN0RyxPQUFPLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQzVCLFVBQVUsRUFBRSxHQUFHO1lBQ2YsUUFBUTtZQUNSLFdBQVc7U0FDWixDQUFDLENBQUM7UUFDSCxNQUFNLFFBQVEsR0FBRyxJQUFJLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRTtZQUNqRCxjQUFjLEVBQUUsT0FBTyxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsdUVBQXVFLENBQUM7WUFDdEgsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLFlBQVksRUFBRSxZQUFZLEVBQUUsNEVBQTRFLENBQUM7WUFDcEksYUFBYSxFQUFFLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNuQyxZQUFZLEVBQUUsYUFBYTtZQUMzQixRQUFRO1NBQ1QsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFlBQVksR0FBRyxRQUFRLENBQUMsWUFBWSxDQUFDO0lBQzVDLENBQUM7SUFFRDs7O09BR0c7SUFDSSxLQUFLLENBQUMsU0FBcUQ7UUFDaEUsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxtQkFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUM5RCxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQztZQUFFLE9BQU87UUFDbEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdEIsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztJQUNyRSxDQUFDO0NBQ0Y7QUFhRDs7R0FFRztBQUNILE1BQWEsWUFBYSxTQUFRLHNCQUFTO0lBQ3pCLFFBQVEsQ0FBaUI7SUFFekMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUF3QjtRQUNoRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2pCLE1BQU0sS0FBSyxHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdCLE1BQU0sUUFBUSxHQUFHLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QyxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDO1lBQ2xDLE9BQU8sRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVksRUFBRSxTQUFTLEVBQUUsdUJBQVMsQ0FBQyxtQkFBbUI7U0FDeEgsQ0FBQyxDQUFDO1FBQ0gsbUZBQW1GO1FBQ25GLFFBQVEsQ0FBQyxLQUFLLENBQUM7WUFDYixPQUFPLEVBQUUsQ0FBQywrQkFBK0IsRUFBRSxrQ0FBa0MsQ0FBQztZQUM5RSxTQUFTLEVBQUUsQ0FBQyxXQUFXLEVBQUUsR0FBRyxXQUFXLGFBQWEsRUFBRSxHQUFHLFdBQVcsYUFBYSxDQUFDO1NBQ25GLENBQUMsQ0FBQztRQUVILE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUM7UUFDcEMsTUFBTSxVQUFVLEdBQTJCO1lBQ3pDLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVztZQUM5QixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVk7WUFDaEMsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVO1lBQzVCLEtBQUssRUFBRSxVQUFVLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7WUFDbEMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDO1lBQzVDLFNBQVMsRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVM7WUFDaEcsY0FBYyxFQUFFLElBQUEsd0JBQVUsRUFBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDO1NBQzVILENBQUM7UUFDRixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksNEJBQWMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBQ25ELFlBQVksRUFBRSxRQUFRLENBQUMsWUFBWTtZQUNuQyxZQUFZLEVBQUUsK0NBQTJCO1lBQ3pDLFVBQVUsRUFBRSxFQUFFLEdBQUcsVUFBVSxFQUFFO1lBQzdCLHVGQUF1RjtZQUN2RixjQUFjLEVBQUUsc0JBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1NBQ2xDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQWxDRCxvQ0FrQ0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgQXJuRm9ybWF0LCBDdXN0b21SZXNvdXJjZSwgRHVyYXRpb24sIFJlbW92YWxQb2xpY3ksIFN0YWNrIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0ICogYXMgbG9ncyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG5pbXBvcnQgKiBhcyBjciBmcm9tICdhd3MtY2RrLWxpYi9jdXN0b20tcmVzb3VyY2VzJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgVFJBRkZJQ19TSElGVF9SRVNPVVJDRV9UWVBFLCB0eXBlIFRyYWZmaWNTaGlmdFByb3BlcnRpZXMgfSBmcm9tICcuL3Byb3ZpZGVyLXByb3RvY29sJztcbmltcG9ydCB0eXBlIHsgV2ViRnVuY3Rpb25EZXBsb3ltZW50IH0gZnJvbSAnLi4vd2ViLWZ1bmN0aW9uLWRlcGxveW1lbnQnO1xuXG4vKiogVGhlIFByb3ZpZGVyIGZyYW1ld29yayBnaXZlcyB1cCBhZnRlciB0aGlzIGxvbmcgYW5kIGZhaWxzIHRoZSBkZXBsb3ltZW50ICh3aXRoIGEgbWVzc2FnZSksIGJlZm9yZSBDbG91ZEZvcm1hdGlvbidzIG93biAxLWhvdXIgbGltaXQuICovXG5jb25zdCBUT1RBTF9USU1FT1VUID0gRHVyYXRpb24ubWludXRlcyg1NSk7XG5jb25zdCBQUk9WSURFUl9JRCA9ICdMYW1iZGFXZWJEZXBsb3ltZW50UHJvdmlkZXInO1xuXG4vKipcbiAqIFRoZSBzdGFjaydzIGRlcGxveW1lbnQgcHJvdmlkZXI6IGEgQ0RLIFByb3ZpZGVyIGZyYW1ld29yayAoYSBTdGVwIEZ1bmN0aW9ucyB3YWl0ZXIpIGFyb3VuZCBgb25FdmVudGAgYW5kIGBpc0NvbXBsZXRlYFxuICogZnJvbSBgaGFuZGxlcnMvd2ViLWZ1bmN0aW9uLWRlcGxveW1lbnRgLCBiZWNhdXNlIGEgY2FuYXJ5IG9yIGxpbmVhciBkZXBsb3ltZW50IGNhbiBydW4gZm9yIHVwIHRvIGFuIGhvdXIuXG4gKiBPbmUgcGVyIHN0YWNrLCBzaGFyZWQgYnkgZXZlcnkgZW5kcG9pbnQgdGhhdCBkZXBsb3lzIGluIHN0ZXBzLlxuICovXG5jbGFzcyBEZXBsb3ltZW50UHJvdmlkZXIgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwdWJsaWMgc3RhdGljIG9mKHNjb3BlOiBDb25zdHJ1Y3QpOiBEZXBsb3ltZW50UHJvdmlkZXIge1xuICAgIGNvbnN0IHN0YWNrID0gU3RhY2sub2Yoc2NvcGUpO1xuICAgIHJldHVybiAoc3RhY2subm9kZS50cnlGaW5kQ2hpbGQoUFJPVklERVJfSUQpIGFzIERlcGxveW1lbnRQcm92aWRlciB8IHVuZGVmaW5lZCkgPz8gbmV3IERlcGxveW1lbnRQcm92aWRlcihzdGFjaywgUFJPVklERVJfSUQpO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IHNlcnZpY2VUb2tlbjogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IHJvbGU6IGlhbS5Sb2xlO1xuICBwcml2YXRlIHJlYWRvbmx5IGdyYW50ZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuICAgIHRoaXMucm9sZSA9IG5ldyBpYW0uUm9sZSh0aGlzLCAnUm9sZScsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdsYW1iZGEuYW1hem9uYXdzLmNvbScpLFxuICAgICAgbWFuYWdlZFBvbGljaWVzOiBbaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdzZXJ2aWNlLXJvbGUvQVdTTGFtYmRhQmFzaWNFeGVjdXRpb25Sb2xlJyldLFxuICAgIH0pO1xuICAgIC8vIFJvbGxiYWNrIGRldGVjdGlvbjogaXMgdGhlIHN0YWNrIHJvbGxpbmcgYmFjaz8gKHRoZSBwcm92aWRlcidzIG93biBzdGFjayBvbmx5KS5cbiAgICB0aGlzLmdyYW50KHsgYWN0aW9uczogWydjbG91ZGZvcm1hdGlvbjpEZXNjcmliZVN0YWNrcyddLCByZXNvdXJjZXM6IFtTdGFjay5vZih0aGlzKS5zdGFja0lkXSB9KTtcbiAgICAvLyBDb21wb3NpdGUgYWxhcm1zIGFyZSBvbmx5IHJldHVybmVkIHdpdGggRGVzY3JpYmVBbGFybXMgb24gJyonLlxuICAgIHRoaXMuZ3JhbnQoeyBhY3Rpb25zOiBbJ2Nsb3Vkd2F0Y2g6RGVzY3JpYmVBbGFybXMnXSwgcmVzb3VyY2VzOiBbJyonXSB9KTtcblxuICAgIGNvbnN0IGxvZ0dyb3VwID0gbmV3IGxvZ3MuTG9nR3JvdXAodGhpcywgJ0xvZ3MnLCB7IHJldGVudGlvbjogbG9ncy5SZXRlbnRpb25EYXlzLk9ORV9NT05USCwgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZIH0pO1xuICAgIGNvbnN0IGhhbmRsZXIgPSAobmFtZTogc3RyaW5nLCBoYW5kbGVyTmFtZTogc3RyaW5nLCBkZXNjcmlwdGlvbjogc3RyaW5nKSA9PiBuZXcgbGFtYmRhLkZ1bmN0aW9uKHRoaXMsIG5hbWUsIHtcbiAgICAgIHJ1bnRpbWU6IGxhbWJkYS5SdW50aW1lLk5PREVKU18yNF9YLFxuICAgICAgYXJjaGl0ZWN0dXJlOiBsYW1iZGEuQXJjaGl0ZWN0dXJlLkFSTV82NCxcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4nLCAnLi4nLCAnYXNzZXRzJywgJ3dlYi1mdW5jdGlvbi1kZXBsb3ltZW50JykpLFxuICAgICAgaGFuZGxlcjogYGluZGV4LiR7aGFuZGxlck5hbWV9YCxcbiAgICAgIHJvbGU6IHRoaXMucm9sZSxcbiAgICAgIC8vIGlzQ29tcGxldGUgd2FpdHMgdXAgdG8gNSBtaW51dGVzIGZvciBhIHJlc3RvcmUgdG8gcmVhY2ggZXZlcnkgcmVnaW9uIGJlZm9yZSBmYWlsaW5nIHRoZSBkZXBsb3ltZW50LlxuICAgICAgdGltZW91dDogRHVyYXRpb24ubWludXRlcyg3KSxcbiAgICAgIG1lbW9yeVNpemU6IDI1NixcbiAgICAgIGxvZ0dyb3VwLFxuICAgICAgZGVzY3JpcHRpb24sXG4gICAgfSk7XG4gICAgY29uc3QgcHJvdmlkZXIgPSBuZXcgY3IuUHJvdmlkZXIodGhpcywgJ1Byb3ZpZGVyJywge1xuICAgICAgb25FdmVudEhhbmRsZXI6IGhhbmRsZXIoJ09uRXZlbnQnLCAnb25FdmVudCcsICdTdGFydHMgY2FuYXJ5IGFuZCBsaW5lYXIgZGVwbG95bWVudHMgb2YgTGFtYmRhIFdlYiBGdW5jdGlvbiBlbmRwb2ludHMnKSxcbiAgICAgIGlzQ29tcGxldGVIYW5kbGVyOiBoYW5kbGVyKCdJc0NvbXBsZXRlJywgJ2lzQ29tcGxldGUnLCAnTW92ZXMgTGFtYmRhIFdlYiBGdW5jdGlvbiBlbmRwb2ludCB0cmFmZmljIHN0ZXAgYnkgc3RlcCBhbmQgd2F0Y2hlcyBhbGFybXMnKSxcbiAgICAgIHF1ZXJ5SW50ZXJ2YWw6IER1cmF0aW9uLnNlY29uZHMoMTUpLFxuICAgICAgdG90YWxUaW1lb3V0OiBUT1RBTF9USU1FT1VULFxuICAgICAgbG9nR3JvdXAsXG4gICAgfSk7XG4gICAgdGhpcy5zZXJ2aWNlVG9rZW4gPSBwcm92aWRlci5zZXJ2aWNlVG9rZW47XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHN0YXRlbWVudCB0byB0aGUgaGFuZGxlcnMnIHJvbGUsIG9uY2UuIExpa2UgdGhlIHNoYXJlZCBwcm92aWRlcidzIGdyYW50cywgdGhleSBtdXN0IGJlIHN0YWJsZSBhY3Jvc3NcbiAgICogdXBkYXRlcyAocHJlZml4ZXMsIG5vdCBuYW1lcyB0aGF0IGNoYW5nZSkgYW5kIG5ldmVyIHJlZmVyZW5jZSBhdHRyaWJ1dGVzIG9mIHJlc291cmNlcyB0aGF0IHVzZSB0aGUgcHJvdmlkZXIuXG4gICAqL1xuICBwdWJsaWMgZ3JhbnQoc3RhdGVtZW50OiB7IGFjdGlvbnM6IHN0cmluZ1tdOyByZXNvdXJjZXM6IHN0cmluZ1tdIH0pOiB2b2lkIHtcbiAgICBjb25zdCBrZXkgPSBKU09OLnN0cmluZ2lmeShTdGFjay5vZih0aGlzKS5yZXNvbHZlKHN0YXRlbWVudCkpO1xuICAgIGlmICh0aGlzLmdyYW50ZWQuaGFzKGtleSkpIHJldHVybjtcbiAgICB0aGlzLmdyYW50ZWQuYWRkKGtleSk7XG4gICAgdGhpcy5yb2xlLmFkZFRvUHJpbmNpcGFsUG9saWN5KG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHN0YXRlbWVudCkpO1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJhZmZpY1NoaWZ0UHJvcHMge1xuICAvKiogTGl0ZXJhbCBmdW5jdGlvbiBuYW1lLCBmb3Igc3RhYmxlIElBTSBncmFudHMuICovXG4gIHJlYWRvbmx5IGZ1bmN0aW9uTmFtZTogc3RyaW5nO1xuICByZWFkb25seSBmdW5jdGlvbkFybjogc3RyaW5nO1xuICByZWFkb25seSBlbmRwb2ludE5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgcmV2aXNpb25JZDogc3RyaW5nO1xuICByZWFkb25seSBkZXBsb3ltZW50OiBXZWJGdW5jdGlvbkRlcGxveW1lbnQ7XG4gIC8qKiBUaGUgZW5kcG9pbnQncyBvdGhlciBzZXR0aW5nczogYW55IGNoYW5nZSBtYWtlcyB0aGUgc2hpZnQgcnVuLCBzbyBpdCBjYW4gcmUtY2hlY2sgdGhlIHRyYWZmaWMgYmVmb3JlIENsb3VkRm9ybWF0aW9uIHdyaXRlcyBpdC4gKi9cbiAgcmVhZG9ubHkgZW5kcG9pbnRDb25maWc6IHVua25vd247XG59XG5cbi8qKlxuICogTW92ZXMgYW4gZW5kcG9pbnQncyB0cmFmZmljIHRvIGByZXZpc2lvbklkYCBpbiBzdGVwcyBiZWZvcmUgQ2xvdWRGb3JtYXRpb24gdXBkYXRlcyB0aGUgZW5kcG9pbnQgKHdoaWNoIG11c3QgZGVwZW5kIG9uIGl0KS5cbiAqL1xuZXhwb3J0IGNsYXNzIFRyYWZmaWNTaGlmdCBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSByZXNvdXJjZTogQ3VzdG9tUmVzb3VyY2U7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFRyYWZmaWNTaGlmdFByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIGNvbnN0IHByb3ZpZGVyID0gRGVwbG95bWVudFByb3ZpZGVyLm9mKHRoaXMpO1xuICAgIGNvbnN0IGZ1bmN0aW9uQXJuID0gc3RhY2suZm9ybWF0QXJuKHtcbiAgICAgIHNlcnZpY2U6ICdsYW1iZGEnLCByZXNvdXJjZTogJ3dlYi1mdW5jdGlvbicsIHJlc291cmNlTmFtZTogcHJvcHMuZnVuY3Rpb25OYW1lLCBhcm5Gb3JtYXQ6IEFybkZvcm1hdC5TTEFTSF9SRVNPVVJDRV9OQU1FLFxuICAgIH0pO1xuICAgIC8vIFN0YWJsZSBncmFudCAoc2VlIGdyYW50VG9Qcm92aWRlcik6IGV2ZXJ5IGVuZHBvaW50IGFuZCByZXZpc2lvbiBvZiB0aGUgZnVuY3Rpb24uXG4gICAgcHJvdmlkZXIuZ3JhbnQoe1xuICAgICAgYWN0aW9uczogWydsYW1iZGE6R2V0V2ViRnVuY3Rpb25FbmRwb2ludCcsICdsYW1iZGE6VXBkYXRlV2ViRnVuY3Rpb25FbmRwb2ludCddLFxuICAgICAgcmVzb3VyY2VzOiBbZnVuY3Rpb25Bcm4sIGAke2Z1bmN0aW9uQXJufS9lbmRwb2ludC8qYCwgYCR7ZnVuY3Rpb25Bcm59L3JldmlzaW9uLypgXSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGRlcGxveW1lbnQgPSBwcm9wcy5kZXBsb3ltZW50O1xuICAgIGNvbnN0IHByb3BlcnRpZXM6IFRyYWZmaWNTaGlmdFByb3BlcnRpZXMgPSB7XG4gICAgICBGdW5jdGlvbkFybjogcHJvcHMuZnVuY3Rpb25Bcm4sXG4gICAgICBFbmRwb2ludE5hbWU6IHByb3BzLmVuZHBvaW50TmFtZSxcbiAgICAgIFJldmlzaW9uSWQ6IHByb3BzLnJldmlzaW9uSWQsXG4gICAgICBTdGVwczogZGVwbG95bWVudC5fc3RlcHMuam9pbignLCcpLFxuICAgICAgV2FpdFNlY29uZHM6IFN0cmluZyhkZXBsb3ltZW50Ll93YWl0U2Vjb25kcyksXG4gICAgICBBbGFybUFybnM6IGRlcGxveW1lbnQuX2FsYXJtcy5sZW5ndGggPiAwID8gZGVwbG95bWVudC5fYWxhcm1zLm1hcCgoYSkgPT4gYS5hbGFybUFybikgOiB1bmRlZmluZWQsXG4gICAgICBFbmRwb2ludENvbmZpZzogY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKEpTT04uc3RyaW5naWZ5KHN0YWNrLnJlc29sdmUocHJvcHMuZW5kcG9pbnRDb25maWcpKSkuZGlnZXN0KCdoZXgnKS5zbGljZSgwLCAxNiksXG4gICAgfTtcbiAgICB0aGlzLnJlc291cmNlID0gbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIHNlcnZpY2VUb2tlbjogcHJvdmlkZXIuc2VydmljZVRva2VuLFxuICAgICAgcmVzb3VyY2VUeXBlOiBUUkFGRklDX1NISUZUX1JFU09VUkNFX1RZUEUsXG4gICAgICBwcm9wZXJ0aWVzOiB7IC4uLnByb3BlcnRpZXMgfSxcbiAgICAgIC8vIENsb3VkRm9ybWF0aW9uJ3MgbWF4aW11bTsgdGhlIHByb3ZpZGVyIGZhaWxzIHRoZSBkZXBsb3ltZW50IGl0c2VsZiBhZnRlciA1NSBtaW51dGVzLlxuICAgICAgc2VydmljZVRpbWVvdXQ6IER1cmF0aW9uLmhvdXJzKDEpLFxuICAgIH0pO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Duration } from 'aws-cdk-lib';
|
|
2
|
+
import type * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
|
|
3
|
+
/**
|
|
4
|
+
* Options for a canary deployment.
|
|
5
|
+
*/
|
|
6
|
+
export interface WebFunctionCanaryDeploymentOptions {
|
|
7
|
+
/**
|
|
8
|
+
* The share of traffic, in whole percent (1-99), that the new revision gets first.
|
|
9
|
+
*/
|
|
10
|
+
readonly percent: number;
|
|
11
|
+
/**
|
|
12
|
+
* How long the new revision serves `percent` before it gets all traffic (1-45 minutes).
|
|
13
|
+
* Make it longer than the time your alarms need to fire (period × evaluation periods).
|
|
14
|
+
*/
|
|
15
|
+
readonly bake: Duration;
|
|
16
|
+
/**
|
|
17
|
+
* Alarms that stop the deployment: if one is in ALARM, the endpoint goes back to the previous
|
|
18
|
+
* revision and the deployment fails, so CloudFormation rolls the stack back.
|
|
19
|
+
*
|
|
20
|
+
* They're checked before traffic moves, during the bake, and once the new revision has all traffic.
|
|
21
|
+
* Use alarms in any region (by ARN), including composite alarms.
|
|
22
|
+
*
|
|
23
|
+
* @default - no alarms: traffic moves on a timer
|
|
24
|
+
*/
|
|
25
|
+
readonly alarms?: cloudwatch.IAlarm[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Options for a linear deployment.
|
|
29
|
+
*/
|
|
30
|
+
export interface WebFunctionLinearDeploymentOptions {
|
|
31
|
+
/**
|
|
32
|
+
* The share of traffic, in whole percent (5-50), that moves to the new revision at each step.
|
|
33
|
+
*/
|
|
34
|
+
readonly percent: number;
|
|
35
|
+
/**
|
|
36
|
+
* How long each step serves before the next one (at least 1 minute, and at most 45 minutes in total).
|
|
37
|
+
*/
|
|
38
|
+
readonly interval: Duration;
|
|
39
|
+
/**
|
|
40
|
+
* Alarms that stop the deployment: if one is in ALARM, the endpoint goes back to the previous
|
|
41
|
+
* revision and the deployment fails, so CloudFormation rolls the stack back.
|
|
42
|
+
*
|
|
43
|
+
* They're checked before traffic moves, during every step, and once the new revision has all traffic.
|
|
44
|
+
* Use alarms in any region (by ARN), including composite alarms.
|
|
45
|
+
*
|
|
46
|
+
* @default - no alarms: traffic moves on a timer
|
|
47
|
+
*/
|
|
48
|
+
readonly alarms?: cloudwatch.IAlarm[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* How an endpoint moves its traffic to a new revision.
|
|
52
|
+
*/
|
|
53
|
+
export declare class WebFunctionDeployment {
|
|
54
|
+
/**
|
|
55
|
+
* All traffic moves to the new revision at once, as soon as it's ready (the default).
|
|
56
|
+
*/
|
|
57
|
+
static allAtOnce(): WebFunctionDeployment;
|
|
58
|
+
/**
|
|
59
|
+
* The new revision first gets `percent` of the traffic for `bake`, then all of it.
|
|
60
|
+
*/
|
|
61
|
+
static canary(options: WebFunctionCanaryDeploymentOptions): WebFunctionDeployment;
|
|
62
|
+
/**
|
|
63
|
+
* The new revision gets `percent` more of the traffic every `interval` until it has all of it.
|
|
64
|
+
*/
|
|
65
|
+
static linear(options: WebFunctionLinearDeploymentOptions): WebFunctionDeployment;
|
|
66
|
+
/**
|
|
67
|
+
* The new revision's share of traffic at each step, in percent; the last is 100.
|
|
68
|
+
*
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
readonly _steps: number[];
|
|
72
|
+
/**
|
|
73
|
+
* Seconds each step serves before the next.
|
|
74
|
+
*
|
|
75
|
+
* @internal
|
|
76
|
+
*/
|
|
77
|
+
readonly _waitSeconds: number;
|
|
78
|
+
/** @internal */
|
|
79
|
+
readonly _alarms: cloudwatch.IAlarm[];
|
|
80
|
+
/** @internal */
|
|
81
|
+
readonly _kind: string;
|
|
82
|
+
private constructor();
|
|
83
|
+
/**
|
|
84
|
+
* Whether traffic moves in steps (canary or linear) rather than all at once.
|
|
85
|
+
*
|
|
86
|
+
* @internal
|
|
87
|
+
*/
|
|
88
|
+
get _gradual(): boolean;
|
|
89
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebFunctionDeployment = void 0;
|
|
4
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
5
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
6
|
+
/** Longest total wait of a deployment: the deployment step must finish within CloudFormation's 1-hour custom resource limit. */
|
|
7
|
+
const MAX_TOTAL_WAIT_MINUTES = 45;
|
|
8
|
+
/** Most traffic steps: each one also waits for the endpoint to update in every region. */
|
|
9
|
+
const MAX_STEPS = 20;
|
|
10
|
+
/**
|
|
11
|
+
* How an endpoint moves its traffic to a new revision.
|
|
12
|
+
*/
|
|
13
|
+
class WebFunctionDeployment {
|
|
14
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@ashishpandeyone/cdk-lambda-web-function.WebFunctionDeployment", version: "0.1.2" };
|
|
15
|
+
/**
|
|
16
|
+
* All traffic moves to the new revision at once, as soon as it's ready (the default).
|
|
17
|
+
*/
|
|
18
|
+
static allAtOnce() {
|
|
19
|
+
return new WebFunctionDeployment('allAtOnce', [100], 0, []);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The new revision first gets `percent` of the traffic for `bake`, then all of it.
|
|
23
|
+
*/
|
|
24
|
+
static canary(options) {
|
|
25
|
+
const percent = wholePercent('canary', 'percent', options.percent, 1, 99);
|
|
26
|
+
const bake = minutes('canary', 'bake', options.bake, MAX_TOTAL_WAIT_MINUTES);
|
|
27
|
+
return new WebFunctionDeployment('canary', [percent, 100], bake.toSeconds(), options.alarms ?? []);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The new revision gets `percent` more of the traffic every `interval` until it has all of it.
|
|
31
|
+
*/
|
|
32
|
+
static linear(options) {
|
|
33
|
+
const percent = wholePercent('linear', 'percent', options.percent, 100 / MAX_STEPS, 50);
|
|
34
|
+
const interval = minutes('linear', 'interval', options.interval, MAX_TOTAL_WAIT_MINUTES);
|
|
35
|
+
const steps = [];
|
|
36
|
+
for (let p = percent; p < 100; p += percent)
|
|
37
|
+
steps.push(p);
|
|
38
|
+
steps.push(100);
|
|
39
|
+
const total = interval.toSeconds() * (steps.length - 1);
|
|
40
|
+
if (total > MAX_TOTAL_WAIT_MINUTES * 60) {
|
|
41
|
+
throw new Error(`WebFunctionDeployment.linear: ${steps.length - 1} intervals of ${interval.toHumanString()} take ${total / 60} minutes; at most ${MAX_TOTAL_WAIT_MINUTES} are allowed`);
|
|
42
|
+
}
|
|
43
|
+
return new WebFunctionDeployment('linear', steps, interval.toSeconds(), options.alarms ?? []);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The new revision's share of traffic at each step, in percent; the last is 100.
|
|
47
|
+
*
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
_steps;
|
|
51
|
+
/**
|
|
52
|
+
* Seconds each step serves before the next.
|
|
53
|
+
*
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
_waitSeconds;
|
|
57
|
+
/** @internal */
|
|
58
|
+
_alarms;
|
|
59
|
+
/** @internal */
|
|
60
|
+
_kind;
|
|
61
|
+
constructor(kind, steps, waitSeconds, alarms) {
|
|
62
|
+
this._kind = kind;
|
|
63
|
+
this._steps = steps;
|
|
64
|
+
this._waitSeconds = waitSeconds;
|
|
65
|
+
this._alarms = alarms;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Whether traffic moves in steps (canary or linear) rather than all at once.
|
|
69
|
+
*
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
get _gradual() {
|
|
73
|
+
return this._steps.length > 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.WebFunctionDeployment = WebFunctionDeployment;
|
|
77
|
+
function wholePercent(kind, name, value, min, max) {
|
|
78
|
+
if (aws_cdk_lib_1.Token.isUnresolved(value) || !Number.isInteger(value) || value < min || value > max) {
|
|
79
|
+
throw new Error(`WebFunctionDeployment.${kind}: ${name} must be a whole number from ${Math.ceil(min)} to ${max}, got ${value}`);
|
|
80
|
+
}
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
function minutes(kind, name, value, maxMinutes) {
|
|
84
|
+
const seconds = value.toSeconds();
|
|
85
|
+
if (aws_cdk_lib_1.Token.isUnresolved(seconds) || seconds < 60 || seconds > maxMinutes * 60) {
|
|
86
|
+
throw new Error(`WebFunctionDeployment.${kind}: ${name} must be from 1 to ${maxMinutes} minutes, got ${aws_cdk_lib_1.Token.isUnresolved(seconds) ? 'a token' : value.toHumanString()}`);
|
|
87
|
+
}
|
|
88
|
+
return aws_cdk_lib_1.Duration.seconds(seconds);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViLWZ1bmN0aW9uLWRlcGxveW1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd2ViLWZ1bmN0aW9uLWRlcGxveW1lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLDZDQUE4QztBQUc5QyxnSUFBZ0k7QUFDaEksTUFBTSxzQkFBc0IsR0FBRyxFQUFFLENBQUM7QUFDbEMsMEZBQTBGO0FBQzFGLE1BQU0sU0FBUyxHQUFHLEVBQUUsQ0FBQztBQXVEckI7O0dBRUc7QUFDSCxNQUFhLHFCQUFxQjs7SUFDaEM7O09BRUc7SUFDSSxNQUFNLENBQUMsU0FBUztRQUNyQixPQUFPLElBQUkscUJBQXFCLENBQUMsV0FBVyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBMkM7UUFDOUQsTUFBTSxPQUFPLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDMUUsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO1FBQzdFLE9BQU8sSUFBSSxxQkFBcUIsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLE9BQU8sQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDLENBQUM7SUFDckcsQ0FBQztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUEyQztRQUM5RCxNQUFNLE9BQU8sR0FBRyxZQUFZLENBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLEdBQUcsR0FBRyxTQUFTLEVBQUUsRUFB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SyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUM1SyxDQUFDO0lBQ0QsT0FBTyxzQkFBUSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUNuQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRHVyYXRpb24sIFRva2VuIH0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHR5cGUgKiBhcyBjbG91ZHdhdGNoIGZyb20gJ2F3cy1jZGstbGliL2F3cy1jbG91ZHdhdGNoJztcblxuLyoqIExvbmdlc3QgdG90YWwgd2FpdCBvZiBhIGRlcGxveW1lbnQ6IHRoZSBkZXBsb3ltZW50IHN0ZXAgbXVzdCBmaW5pc2ggd2l0aGluIENsb3VkRm9ybWF0aW9uJ3MgMS1ob3VyIGN1c3RvbSByZXNvdXJjZSBsaW1pdC4gKi9cbmNvbnN0IE1BWF9UT1RBTF9XQUlUX01JTlVURVMgPSA0NTtcbi8qKiBNb3N0IHRyYWZmaWMgc3RlcHM6IGVhY2ggb25lIGFsc28gd2FpdHMgZm9yIHRoZSBlbmRwb2ludCB0byB1cGRhdGUgaW4gZXZlcnkgcmVnaW9uLiAqL1xuY29uc3QgTUFYX1NURVBTID0gMjA7XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgYSBjYW5hcnkgZGVwbG95bWVudC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBXZWJGdW5jdGlvbkNhbmFyeURlcGxveW1lbnRPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBzaGFyZSBvZiB0cmFmZmljLCBpbiB3aG9sZSBwZXJjZW50ICgxLTk5KSwgdGhhdCB0aGUgbmV3IHJldmlzaW9uIGdldHMgZmlyc3QuXG4gICAqL1xuICByZWFkb25seSBwZXJjZW50OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEhvdyBsb25nIHRoZSBuZXcgcmV2aXNpb24gc2VydmVzIGBwZXJjZW50YCBiZWZvcmUgaXQgZ2V0cyBhbGwgdHJhZmZpYyAoMS00NSBtaW51dGVzKS5cbiAgICogTWFrZSBpdCBsb25nZXIgdGhhbiB0aGUgdGltZSB5b3VyIGFsYXJtcyBuZWVkIHRvIGZpcmUgKHBlcmlvZCDDlyBldmFsdWF0aW9uIHBlcmlvZHMpLlxuICAgKi9cbiAgcmVhZG9ubHkgYmFrZTogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIEFsYXJtcyB0aGF0IHN0b3AgdGhlIGRlcGxveW1lbnQ6IGlmIG9uZSBpcyBpbiBBTEFSTSwgdGhlIGVuZHBvaW50IGdvZXMgYmFjayB0byB0aGUgcHJldmlvdXNcbiAgICogcmV2aXNpb24gYW5kIHRoZSBkZXBsb3ltZW50IGZhaWxzLCBzbyBDbG91ZEZvcm1hdGlvbiByb2xscyB0aGUgc3RhY2sgYmFjay5cbiAgICpcbiAgICogVGhleSdyZSBjaGVja2VkIGJlZm9yZSB0cmFmZmljIG1vdmVzLCBkdXJpbmcgdGhlIGJha2UsIGFuZCBvbmNlIHRoZSBuZXcgcmV2aXNpb24gaGFzIGFsbCB0cmFmZmljLlxuICAgKiBVc2UgYWxhcm1zIGluIGFueSByZWdpb24gKGJ5IEFSTiksIGluY2x1ZGluZyBjb21wb3NpdGUgYWxhcm1zLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGFsYXJtczogdHJhZmZpYyBtb3ZlcyBvbiBhIHRpbWVyXG4gICAqL1xuICByZWFkb25seSBhbGFybXM/OiBjbG91ZHdhdGNoLklBbGFybVtdO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGEgbGluZWFyIGRlcGxveW1lbnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgV2ViRnVuY3Rpb25MaW5lYXJEZXBsb3ltZW50T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgc2hhcmUgb2YgdHJhZmZpYywgaW4gd2hvbGUgcGVyY2VudCAoNS01MCksIHRoYXQgbW92ZXMgdG8gdGhlIG5ldyByZXZpc2lvbiBhdCBlYWNoIHN0ZXAuXG4gICAqL1xuICByZWFkb25seSBwZXJjZW50OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEhvdyBsb25nIGVhY2ggc3RlcCBzZXJ2ZXMgYmVmb3JlIHRoZSBuZXh0IG9uZSAoYXQgbGVhc3QgMSBtaW51dGUsIGFuZCBhdCBtb3N0IDQ1IG1pbnV0ZXMgaW4gdG90YWwpLlxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZXJ2YWw6IER1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBBbGFybXMgdGhhdCBzdG9wIHRoZSBkZXBsb3ltZW50OiBpZiBvbmUgaXMgaW4gQUxBUk0sIHRoZSBlbmRwb2ludCBnb2VzIGJhY2sgdG8gdGhlIHByZXZpb3VzXG4gICAqIHJldmlzaW9uIGFuZCB0aGUgZGVwbG95bWVudCBmYWlscywgc28gQ2xvdWRGb3JtYXRpb24gcm9sbHMgdGhlIHN0YWNrIGJhY2suXG4gICAqXG4gICAqIFRoZXkncmUgY2hlY2tlZCBiZWZvcmUgdHJhZmZpYyBtb3ZlcywgZHVyaW5nIGV2ZXJ5IHN0ZXAsIGFuZCBvbmNlIHRoZSBuZXcgcmV2aXNpb24gaGFzIGFsbCB0cmFmZmljLlxuICAgKiBVc2UgYWxhcm1zIGluIGFueSByZWdpb24gKGJ5IEFSTiksIGluY2x1ZGluZyBjb21wb3NpdGUgYWxhcm1zLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGFsYXJtczogdHJhZmZpYyBtb3ZlcyBvbiBhIHRpbWVyXG4gICAqL1xuICByZWFkb25seSBhbGFybXM/OiBjbG91ZHdhdGNoLklBbGFybVtdO1xufVxuXG4vKipcbiAqIEhvdyBhbiBlbmRwb2ludCBtb3ZlcyBpdHMgdHJhZmZpYyB0byBhIG5ldyByZXZpc2lvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIFdlYkZ1bmN0aW9uRGVwbG95bWVudCB7XG4gIC8qKlxuICAgKiBBbGwgdHJhZmZpYyBtb3ZlcyB0byB0aGUgbmV3IHJldmlzaW9uIGF0IG9uY2UsIGFzIHNvb24gYXMgaXQncyByZWFkeSAodGhlIGRlZmF1bHQpLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBhbGxBdE9uY2UoKTogV2ViRnVuY3Rpb25EZXBsb3ltZW50IHtcbiAgICByZXR1cm4gbmV3IFdlYkZ1bmN0aW9uRGVwbG95bWVudCgnYWxsQXRPbmNlJywgWzEwMF0sIDAsIFtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgbmV3IHJldmlzaW9uIGZpcnN0IGdldHMgYHBlcmNlbnRgIG9mIHRoZSB0cmFmZmljIGZvciBgYmFrZWAsIHRoZW4gYWxsIG9mIGl0LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjYW5hcnkob3B0aW9uczogV2ViRnVuY3Rpb25DYW5hcnlEZXBsb3ltZW50T3B0aW9ucyk6IFdlYkZ1bmN0aW9uRGVwbG95bWVudCB7XG4gICAgY29uc3QgcGVyY2VudCA9IHdob2xlUGVyY2VudCgnY2FuYXJ5JywgJ3BlcmNlbnQnLCBvcHRpb25zLnBlcmNlbnQsIDEsIDk5KTtcbiAgICBjb25zdCBiYWtlID0gbWludXRlcygnY2FuYXJ5JywgJ2Jha2UnLCBvcHRpb25zLmJha2UsIE1BWF9UT1RBTF9XQUlUX01JTlVURVMpO1xuICAgIHJldHVybiBuZXcgV2ViRnVuY3Rpb25EZXBsb3ltZW50KCdjYW5hcnknLCBbcGVyY2VudCwgMTAwXSwgYmFrZS50b1NlY29uZHMoKSwgb3B0aW9ucy5hbGFybXMgPz8gW10pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBuZXcgcmV2aXNpb24gZ2V0cyBgcGVyY2VudGAgbW9yZSBvZiB0aGUgdHJhZmZpYyBldmVyeSBgaW50ZXJ2YWxgIHVudGlsIGl0IGhhcyBhbGwgb2YgaXQuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGxpbmVhcihvcHRpb25zOiBXZWJGdW5jdGlvbkxpbmVhckRlcGxveW1lbnRPcHRpb25zKTogV2ViRnVuY3Rpb25EZXBsb3ltZW50IHtcbiAgICBjb25zdCBwZXJjZW50ID0gd2hvbGVQZXJjZW50KCdsaW5lYXInLCAncGVyY2VudCcsIG9wdGlvbnMucGVyY2VudCwgMTAwIC8gTUFYX1NURVBTLCA1MCk7XG4gICAgY29uc3QgaW50ZXJ2YWwgPSBtaW51dGVzKCdsaW5lYXInLCAnaW50ZXJ2YWwnLCBvcHRpb25zLmludGVydmFsLCBNQVhfVE9UQUxfV0FJVF9NSU5VVEVTKTtcbiAgICBjb25zdCBzdGVwczogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBwID0gcGVyY2VudDsgcCA8IDEwMDsgcCArPSBwZXJjZW50KSBzdGVwcy5wdXNoKHApO1xuICAgIHN0ZXBzLnB1c2goMTAwKTtcbiAgICBjb25zdCB0b3RhbCA9IGludGVydmFsLnRvU2Vjb25kcygpICogKHN0ZXBzLmxlbmd0aCAtIDEpO1xuICAgIGlmICh0b3RhbCA+IE1BWF9UT1RBTF9XQUlUX01JTlVURVMgKiA2MCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBXZWJGdW5jdGlvbkRlcGxveW1lbnQubGluZWFyOiAke3N0ZXBzLmxlbmd0aCAtIDF9IGludGVydmFscyBvZiAke2ludGVydmFsLnRvSHVtYW5TdHJpbmcoKX0gdGFrZSAke3RvdGFsIC8gNjB9IG1pbnV0ZXM7IGF0IG1vc3QgJHtNQVhfVE9UQUxfV0FJVF9NSU5VVEVTfSBhcmUgYWxsb3dlZGApO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IFdlYkZ1bmN0aW9uRGVwbG95bWVudCgnbGluZWFyJywgc3RlcHMsIGludGVydmFsLnRvU2Vjb25kcygpLCBvcHRpb25zLmFsYXJtcyA/PyBbXSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIG5ldyByZXZpc2lvbidzIHNoYXJlIG9mIHRyYWZmaWMgYXQgZWFjaCBzdGVwLCBpbiBwZXJjZW50OyB0aGUgbGFzdCBpcyAxMDAuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IF9zdGVwczogbnVtYmVyW107XG5cbiAgLyoqXG4gICAqIFNlY29uZHMgZWFjaCBzdGVwIHNlcnZlcyBiZWZvcmUgdGhlIG5leHQuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IF93YWl0U2Vjb25kczogbnVtYmVyO1xuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHVibGljIHJlYWRvbmx5IF9hbGFybXM6IGNsb3Vkd2F0Y2guSUFsYXJtW107XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBwdWJsaWMgcmVhZG9ubHkgX2tpbmQ6IHN0cmluZztcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKGtpbmQ6IHN0cmluZywgc3RlcHM6IG51bWJlcltdLCB3YWl0U2Vjb25kczogbnVtYmVyLCBhbGFybXM6IGNsb3Vkd2F0Y2guSUFsYXJtW10pIHtcbiAgICB0aGlzLl9raW5kID0ga2luZDtcbiAgICB0aGlzLl9zdGVwcyA9IHN0ZXBzO1xuICAgIHRoaXMuX3dhaXRTZWNvbmRzID0gd2FpdFNlY29uZHM7XG4gICAgdGhpcy5fYWxhcm1zID0gYWxhcm1zO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdHJhZmZpYyBtb3ZlcyBpbiBzdGVwcyAoY2FuYXJ5IG9yIGxpbmVhcikgcmF0aGVyIHRoYW4gYWxsIGF0IG9uY2UuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIGdldCBfZ3JhZHVhbCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fc3RlcHMubGVuZ3RoID4gMTtcbiAgfVxufVxuXG5mdW5jdGlvbiB3aG9sZVBlcmNlbnQoa2luZDogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIHZhbHVlOiBudW1iZXIsIG1pbjogbnVtYmVyLCBtYXg6IG51bWJlcik6IG51bWJlciB7XG4gIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQodmFsdWUpIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSB8fCB2YWx1ZSA8IG1pbiB8fCB2YWx1ZSA+IG1heCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgV2ViRnVuY3Rpb25EZXBsb3ltZW50LiR7a2luZH06ICR7bmFtZX0gbXVzdCBiZSBhIHdob2xlIG51bWJlciBmcm9tICR7TWF0aC5jZWlsKG1pbil9IHRvICR7bWF4fSwgZ290ICR7dmFsdWV9YCk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuXG5mdW5jdGlvbiBtaW51dGVzKGtpbmQ6IHN0cmluZywgbmFtZTogc3RyaW5nLCB2YWx1ZTogRHVyYXRpb24sIG1heE1pbnV0ZXM6IG51bWJlcik6IER1cmF0aW9uIHtcbiAgY29uc3Qgc2Vjb25kcyA9IHZhbHVlLnRvU2Vjb25kcygpO1xuICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKHNlY29uZHMpIHx8IHNlY29uZHMgPCA2MCB8fCBzZWNvbmRzID4gbWF4TWludXRlcyAqIDYwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBXZWJGdW5jdGlvbkRlcGxveW1lbnQuJHtraW5kfTogJHtuYW1lfSBtdXN0IGJlIGZyb20gMSB0byAke21heE1pbnV0ZXN9IG1pbnV0ZXMsIGdvdCAke1Rva2VuLmlzVW5yZXNvbHZlZChzZWNvbmRzKSA/ICdhIHRva2VuJyA6IHZhbHVlLnRvSHVtYW5TdHJpbmcoKX1gKTtcbiAgfVxuICByZXR1cm4gRHVyYXRpb24uc2Vjb25kcyhzZWNvbmRzKTtcbn1cbiJdfQ==
|