@cloudsnorkel/cdk-github-runners 0.14.0 → 0.14.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.
Files changed (51) hide show
  1. package/.jsii +70 -70
  2. package/API.md +3 -3
  3. package/README.md +52 -7
  4. package/assets/delete-failed-runner.lambda/index.js +44 -20
  5. package/assets/idle-runner-repear.lambda/index.js +44 -20
  6. package/assets/image-builders/aws-image-builder/delete-resources.lambda/index.js +209 -0
  7. package/assets/image-builders/aws-image-builder/versioner.lambda/index.js +28 -4
  8. package/assets/image-builders/build-image.lambda/index.js +0 -24
  9. package/assets/setup.lambda/index.js +16 -16
  10. package/assets/status.lambda/index.js +44 -20
  11. package/assets/token-retriever.lambda/index.js +44 -20
  12. package/assets/webhook-handler.lambda/index.js +44 -20
  13. package/lib/access.js +1 -1
  14. package/lib/image-builders/api.js +1 -1
  15. package/lib/image-builders/aws-image-builder/ami.d.ts +8 -0
  16. package/lib/image-builders/aws-image-builder/ami.js +3 -1
  17. package/lib/image-builders/aws-image-builder/builder.d.ts +2 -0
  18. package/lib/image-builders/aws-image-builder/builder.js +108 -68
  19. package/lib/image-builders/aws-image-builder/common.js +1 -1
  20. package/lib/image-builders/aws-image-builder/container.d.ts +6 -0
  21. package/lib/image-builders/aws-image-builder/container.js +3 -1
  22. package/lib/image-builders/aws-image-builder/delete-resources-function.d.ts +13 -0
  23. package/lib/image-builders/aws-image-builder/delete-resources-function.js +23 -0
  24. package/lib/image-builders/aws-image-builder/delete-resources.lambda.d.ts +9 -0
  25. package/lib/image-builders/aws-image-builder/delete-resources.lambda.js +159 -0
  26. package/lib/image-builders/aws-image-builder/deprecated/ami.d.ts +2 -2
  27. package/lib/image-builders/aws-image-builder/deprecated/ami.js +18 -37
  28. package/lib/image-builders/aws-image-builder/deprecated/container.js +13 -35
  29. package/lib/image-builders/aws-image-builder/deprecated/linux-components.js +1 -1
  30. package/lib/image-builders/aws-image-builder/deprecated/windows-components.js +1 -1
  31. package/lib/image-builders/aws-image-builder/workflow.js +2 -1
  32. package/lib/image-builders/build-image.lambda.d.ts +1 -3
  33. package/lib/image-builders/build-image.lambda.js +1 -25
  34. package/lib/image-builders/codebuild-deprecated.js +3 -3
  35. package/lib/image-builders/codebuild.js +2 -2
  36. package/lib/image-builders/components.js +1 -1
  37. package/lib/image-builders/static.js +1 -1
  38. package/lib/providers/codebuild.js +2 -2
  39. package/lib/providers/common.js +3 -3
  40. package/lib/providers/ec2.js +2 -2
  41. package/lib/providers/ecs.js +1 -1
  42. package/lib/providers/fargate.js +2 -2
  43. package/lib/providers/lambda.js +2 -2
  44. package/lib/runner.js +1 -1
  45. package/lib/secrets.js +1 -1
  46. package/package.json +27 -26
  47. package/assets/image-builders/aws-image-builder/delete-ami.lambda/index.js +0 -129
  48. package/lib/image-builders/aws-image-builder/delete-ami-function.d.ts +0 -13
  49. package/lib/image-builders/aws-image-builder/delete-ami-function.js +0 -23
  50. package/lib/image-builders/aws-image-builder/delete-ami.lambda.d.ts +0 -2
  51. package/lib/image-builders/aws-image-builder/delete-ami.lambda.js +0 -70
@@ -1,129 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/image-builders/aws-image-builder/delete-ami.lambda.ts
21
- var delete_ami_lambda_exports = {};
22
- __export(delete_ami_lambda_exports, {
23
- handler: () => handler
24
- });
25
- module.exports = __toCommonJS(delete_ami_lambda_exports);
26
- var import_client_ec2 = require("@aws-sdk/client-ec2");
27
-
28
- // src/lambda-helpers.ts
29
- var import_client_secrets_manager = require("@aws-sdk/client-secrets-manager");
30
- var sm = new import_client_secrets_manager.SecretsManagerClient();
31
- async function customResourceRespond(event, responseStatus, reason, physicalResourceId, data) {
32
- const responseBody = JSON.stringify({
33
- Status: responseStatus,
34
- Reason: reason,
35
- PhysicalResourceId: physicalResourceId,
36
- StackId: event.StackId,
37
- RequestId: event.RequestId,
38
- LogicalResourceId: event.LogicalResourceId,
39
- NoEcho: false,
40
- Data: data
41
- });
42
- console.log("Responding", responseBody);
43
- const parsedUrl = require("url").parse(event.ResponseURL);
44
- const requestOptions = {
45
- hostname: parsedUrl.hostname,
46
- path: parsedUrl.path,
47
- method: "PUT",
48
- headers: {
49
- "content-type": "",
50
- "content-length": responseBody.length
51
- }
52
- };
53
- return new Promise((resolve, reject) => {
54
- try {
55
- const request = require("https").request(requestOptions, resolve);
56
- request.on("error", reject);
57
- request.write(responseBody);
58
- request.end();
59
- } catch (e) {
60
- reject(e);
61
- }
62
- });
63
- }
64
-
65
- // src/image-builders/aws-image-builder/delete-ami.lambda.ts
66
- var ec2 = new import_client_ec2.EC2Client();
67
- async function deleteAmis(stackName, builderName) {
68
- const images = await ec2.send(new import_client_ec2.DescribeImagesCommand({
69
- Owners: ["self"],
70
- Filters: [
71
- {
72
- Name: "tag:GitHubRunners:Stack",
73
- Values: [stackName]
74
- },
75
- {
76
- Name: "tag:GitHubRunners:Builder",
77
- Values: [builderName]
78
- }
79
- ]
80
- }));
81
- let imagesToDelete = images.Images ?? [];
82
- console.log({
83
- notice: `Found ${imagesToDelete.length} AMIs`,
84
- images: imagesToDelete.map((i) => i.ImageId)
85
- });
86
- for (const image of imagesToDelete) {
87
- if (!image.ImageId) {
88
- console.warn({
89
- notice: "No image id?",
90
- image
91
- });
92
- continue;
93
- }
94
- console.log(`Deregistering ${image.ImageId}`);
95
- await ec2.send(new import_client_ec2.DeregisterImageCommand({
96
- ImageId: image.ImageId
97
- }));
98
- for (const blockMapping of image.BlockDeviceMappings ?? []) {
99
- if (blockMapping.Ebs?.SnapshotId) {
100
- console.log(`Deleting ${blockMapping.Ebs.SnapshotId}`);
101
- await ec2.send(new import_client_ec2.DeleteSnapshotCommand({
102
- SnapshotId: blockMapping.Ebs.SnapshotId
103
- }));
104
- }
105
- }
106
- }
107
- }
108
- async function handler(event, context) {
109
- try {
110
- console.log({ ...event, ResponseURL: "..." });
111
- switch (event.RequestType) {
112
- case "Create":
113
- case "Update":
114
- await customResourceRespond(event, "SUCCESS", "OK", "DeleteAmis", {});
115
- break;
116
- case "Delete":
117
- await deleteAmis(event.ResourceProperties.StackName, event.ResourceProperties.BuilderName);
118
- await customResourceRespond(event, "SUCCESS", "OK", event.PhysicalResourceId, {});
119
- break;
120
- }
121
- } catch (e) {
122
- console.error(e);
123
- await customResourceRespond(event, "FAILED", e.message || "Internal Error", context.logStreamName, {});
124
- }
125
- }
126
- // Annotate the CommonJS export names for ESM import in node:
127
- 0 && (module.exports = {
128
- handler
129
- });
@@ -1,13 +0,0 @@
1
- import * as lambda from 'aws-cdk-lib/aws-lambda';
2
- import { Construct } from 'constructs';
3
- /**
4
- * Props for DeleteAmiFunction
5
- */
6
- export interface DeleteAmiFunctionProps extends lambda.FunctionOptions {
7
- }
8
- /**
9
- * An AWS Lambda function which executes src/image-builders/aws-image-builder/delete-ami.
10
- */
11
- export declare class DeleteAmiFunction extends lambda.Function {
12
- constructor(scope: Construct, id: string, props?: DeleteAmiFunctionProps);
13
- }
@@ -1,23 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DeleteAmiFunction = void 0;
4
- // ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".
5
- const path = require("path");
6
- const lambda = require("aws-cdk-lib/aws-lambda");
7
- /**
8
- * An AWS Lambda function which executes src/image-builders/aws-image-builder/delete-ami.
9
- */
10
- class DeleteAmiFunction extends lambda.Function {
11
- constructor(scope, id, props) {
12
- super(scope, id, {
13
- description: 'src/image-builders/aws-image-builder/delete-ami.lambda.ts',
14
- ...props,
15
- runtime: new lambda.Runtime('nodejs18.x', lambda.RuntimeFamily.NODEJS),
16
- handler: 'index.handler',
17
- code: lambda.Code.fromAsset(path.join(__dirname, '../../../assets/image-builders/aws-image-builder/delete-ami.lambda')),
18
- });
19
- this.addEnvironment('AWS_NODEJS_CONNECTION_REUSE_ENABLED', '1', { removeInEdge: true });
20
- }
21
- }
22
- exports.DeleteAmiFunction = DeleteAmiFunction;
23
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVsZXRlLWFtaS1mdW5jdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9pbWFnZS1idWlsZGVycy9hd3MtaW1hZ2UtYnVpbGRlci9kZWxldGUtYW1pLWZ1bmN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZFQUE2RTtBQUM3RSw2QkFBNkI7QUFDN0IsaURBQWlEO0FBU2pEOztHQUVHO0FBQ0gsTUFBYSxpQkFBa0IsU0FBUSxNQUFNLENBQUMsUUFBUTtJQUNwRCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQThCO1FBQ3RFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQ2YsV0FBVyxFQUFFLDJEQUEyRDtZQUN4RSxHQUFHLEtBQUs7WUFDUixPQUFPLEVBQUUsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxNQUFNLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQztZQUN0RSxPQUFPLEVBQUUsZUFBZTtZQUN4QixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsb0VBQW9FLENBQUMsQ0FBQztTQUN4SCxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsY0FBYyxDQUFDLHFDQUFxQyxFQUFFLEdBQUcsRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzFGLENBQUM7Q0FDRjtBQVhELDhDQVdDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gfn4gR2VuZXJhdGVkIGJ5IHByb2plbi4gVG8gbW9kaWZ5LCBlZGl0IC5wcm9qZW5yYy5qcyBhbmQgcnVuIFwibnB4IHByb2plblwiLlxuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuXG4vKipcbiAqIFByb3BzIGZvciBEZWxldGVBbWlGdW5jdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbGV0ZUFtaUZ1bmN0aW9uUHJvcHMgZXh0ZW5kcyBsYW1iZGEuRnVuY3Rpb25PcHRpb25zIHtcbn1cblxuLyoqXG4gKiBBbiBBV1MgTGFtYmRhIGZ1bmN0aW9uIHdoaWNoIGV4ZWN1dGVzIHNyYy9pbWFnZS1idWlsZGVycy9hd3MtaW1hZ2UtYnVpbGRlci9kZWxldGUtYW1pLlxuICovXG5leHBvcnQgY2xhc3MgRGVsZXRlQW1pRnVuY3Rpb24gZXh0ZW5kcyBsYW1iZGEuRnVuY3Rpb24ge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wcz86IERlbGV0ZUFtaUZ1bmN0aW9uUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnc3JjL2ltYWdlLWJ1aWxkZXJzL2F3cy1pbWFnZS1idWlsZGVyL2RlbGV0ZS1hbWkubGFtYmRhLnRzJyxcbiAgICAgIC4uLnByb3BzLFxuICAgICAgcnVudGltZTogbmV3IGxhbWJkYS5SdW50aW1lKCdub2RlanMxOC54JywgbGFtYmRhLlJ1bnRpbWVGYW1pbHkuTk9ERUpTKSxcbiAgICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vLi4vLi4vYXNzZXRzL2ltYWdlLWJ1aWxkZXJzL2F3cy1pbWFnZS1idWlsZGVyL2RlbGV0ZS1hbWkubGFtYmRhJykpLFxuICAgIH0pO1xuICAgIHRoaXMuYWRkRW52aXJvbm1lbnQoJ0FXU19OT0RFSlNfQ09OTkVDVElPTl9SRVVTRV9FTkFCTEVEJywgJzEnLCB7IHJlbW92ZUluRWRnZTogdHJ1ZSB9KTtcbiAgfVxufSJdfQ==
@@ -1,2 +0,0 @@
1
- import * as AWSLambda from 'aws-lambda';
2
- export declare function handler(event: AWSLambda.CloudFormationCustomResourceEvent, context: AWSLambda.Context): Promise<void>;
@@ -1,70 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handler = void 0;
4
- const client_ec2_1 = require("@aws-sdk/client-ec2");
5
- const lambda_helpers_1 = require("../../lambda-helpers");
6
- const ec2 = new client_ec2_1.EC2Client();
7
- async function deleteAmis(stackName, builderName) {
8
- // lifecycle rule runs daily and images are built once a week, so there shouldn't be a need for pagination
9
- const images = await ec2.send(new client_ec2_1.DescribeImagesCommand({
10
- Owners: ['self'],
11
- Filters: [
12
- {
13
- Name: 'tag:GitHubRunners:Stack',
14
- Values: [stackName],
15
- },
16
- {
17
- Name: 'tag:GitHubRunners:Builder',
18
- Values: [builderName],
19
- },
20
- ],
21
- }));
22
- let imagesToDelete = images.Images ?? [];
23
- console.log({
24
- notice: `Found ${imagesToDelete.length} AMIs`,
25
- images: imagesToDelete.map(i => i.ImageId),
26
- });
27
- // delete all that we found
28
- for (const image of imagesToDelete) {
29
- if (!image.ImageId) {
30
- console.warn({
31
- notice: 'No image id?',
32
- image,
33
- });
34
- continue;
35
- }
36
- console.log(`Deregistering ${image.ImageId}`);
37
- await ec2.send(new client_ec2_1.DeregisterImageCommand({
38
- ImageId: image.ImageId,
39
- }));
40
- for (const blockMapping of image.BlockDeviceMappings ?? []) {
41
- if (blockMapping.Ebs?.SnapshotId) {
42
- console.log(`Deleting ${blockMapping.Ebs.SnapshotId}`);
43
- await ec2.send(new client_ec2_1.DeleteSnapshotCommand({
44
- SnapshotId: blockMapping.Ebs.SnapshotId,
45
- }));
46
- }
47
- }
48
- }
49
- }
50
- async function handler(event, context) {
51
- try {
52
- console.log({ ...event, ResponseURL: '...' });
53
- switch (event.RequestType) {
54
- case 'Create':
55
- case 'Update':
56
- await (0, lambda_helpers_1.customResourceRespond)(event, 'SUCCESS', 'OK', 'DeleteAmis', {});
57
- break;
58
- case 'Delete':
59
- await deleteAmis(event.ResourceProperties.StackName, event.ResourceProperties.BuilderName);
60
- await (0, lambda_helpers_1.customResourceRespond)(event, 'SUCCESS', 'OK', event.PhysicalResourceId, {});
61
- break;
62
- }
63
- }
64
- catch (e) {
65
- console.error(e);
66
- await (0, lambda_helpers_1.customResourceRespond)(event, 'FAILED', e.message || 'Internal Error', context.logStreamName, {});
67
- }
68
- }
69
- exports.handler = handler;
70
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVsZXRlLWFtaS5sYW1iZGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaW1hZ2UtYnVpbGRlcnMvYXdzLWltYWdlLWJ1aWxkZXIvZGVsZXRlLWFtaS5sYW1iZGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsb0RBSzZCO0FBRTdCLHlEQUE2RDtBQUU3RCxNQUFNLEdBQUcsR0FBRyxJQUFJLHNCQUFTLEVBQUUsQ0FBQztBQUU1QixLQUFLLFVBQVUsVUFBVSxDQUFDLFNBQWlCLEVBQUUsV0FBbUI7SUFDOUQsMEdBQTBHO0lBQzFHLE1BQU0sTUFBTSxHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLGtDQUFxQixDQUFDO1FBQ3RELE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQztRQUNoQixPQUFPLEVBQUU7WUFDUDtnQkFDRSxJQUFJLEVBQUUseUJBQXlCO2dCQUMvQixNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUM7YUFDcEI7WUFDRDtnQkFDRSxJQUFJLEVBQUUsMkJBQTJCO2dCQUNqQyxNQUFNLEVBQUUsQ0FBQyxXQUFXLENBQUM7YUFDdEI7U0FDRjtLQUNGLENBQUMsQ0FBQyxDQUFDO0lBRUosSUFBSSxjQUFjLEdBQUcsTUFBTSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFFekMsT0FBTyxDQUFDLEdBQUcsQ0FBQztRQUNWLE1BQU0sRUFBRSxTQUFTLGNBQWMsQ0FBQyxNQUFNLE9BQU87UUFDN0MsTUFBTSxFQUFFLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO0tBQzNDLENBQUMsQ0FBQztJQUVILDJCQUEyQjtJQUMzQixLQUFLLE1BQU0sS0FBSyxJQUFJLGNBQWMsRUFBRSxDQUFDO1FBQ25DLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbkIsT0FBTyxDQUFDLElBQUksQ0FBQztnQkFDWCxNQUFNLEVBQUUsY0FBYztnQkFDdEIsS0FBSzthQUNOLENBQUMsQ0FBQztZQUNILFNBQVM7UUFDWCxDQUFDO1FBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFFOUMsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksbUNBQXNCLENBQUM7WUFDeEMsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPO1NBQ3ZCLENBQUMsQ0FBQyxDQUFDO1FBRUosS0FBSyxNQUFNLFlBQVksSUFBSSxLQUFLLENBQUMsbUJBQW1CLElBQUksRUFBRSxFQUFFLENBQUM7WUFDM0QsSUFBSSxZQUFZLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRSxDQUFDO2dCQUNqQyxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksWUFBWSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO2dCQUV2RCxNQUFNLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxrQ0FBcUIsQ0FBQztvQkFDdkMsVUFBVSxFQUFFLFlBQVksQ0FBQyxHQUFHLENBQUMsVUFBVTtpQkFDeEMsQ0FBQyxDQUFDLENBQUM7WUFDTixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDO0FBRU0sS0FBSyxVQUFVLE9BQU8sQ0FBQyxLQUFrRCxFQUFFLE9BQTBCO0lBQzFHLElBQUksQ0FBQztRQUNILE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEtBQUssRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUU5QyxRQUFRLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUMxQixLQUFLLFFBQVEsQ0FBQztZQUNkLEtBQUssUUFBUTtnQkFDWCxNQUFNLElBQUEsc0NBQXFCLEVBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUN0RSxNQUFNO1lBQ1IsS0FBSyxRQUFRO2dCQUNYLE1BQU0sVUFBVSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUMzRixNQUFNLElBQUEsc0NBQXFCLEVBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUNsRixNQUFNO1FBQ1YsQ0FBQztJQUNILENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1gsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqQixNQUFNLElBQUEsc0NBQXFCLEVBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRyxDQUFXLENBQUMsT0FBTyxJQUFJLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDcEgsQ0FBQztBQUNILENBQUM7QUFsQkQsMEJBa0JDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRGVsZXRlU25hcHNob3RDb21tYW5kLFxuICBEZXJlZ2lzdGVySW1hZ2VDb21tYW5kLFxuICBEZXNjcmliZUltYWdlc0NvbW1hbmQsXG4gIEVDMkNsaWVudCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWVjMic7XG5pbXBvcnQgKiBhcyBBV1NMYW1iZGEgZnJvbSAnYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBjdXN0b21SZXNvdXJjZVJlc3BvbmQgfSBmcm9tICcuLi8uLi9sYW1iZGEtaGVscGVycyc7XG5cbmNvbnN0IGVjMiA9IG5ldyBFQzJDbGllbnQoKTtcblxuYXN5bmMgZnVuY3Rpb24gZGVsZXRlQW1pcyhzdGFja05hbWU6IHN0cmluZywgYnVpbGRlck5hbWU6IHN0cmluZykge1xuICAvLyBsaWZlY3ljbGUgcnVsZSBydW5zIGRhaWx5IGFuZCBpbWFnZXMgYXJlIGJ1aWx0IG9uY2UgYSB3ZWVrLCBzbyB0aGVyZSBzaG91bGRuJ3QgYmUgYSBuZWVkIGZvciBwYWdpbmF0aW9uXG4gIGNvbnN0IGltYWdlcyA9IGF3YWl0IGVjMi5zZW5kKG5ldyBEZXNjcmliZUltYWdlc0NvbW1hbmQoe1xuICAgIE93bmVyczogWydzZWxmJ10sXG4gICAgRmlsdGVyczogW1xuICAgICAge1xuICAgICAgICBOYW1lOiAndGFnOkdpdEh1YlJ1bm5lcnM6U3RhY2snLFxuICAgICAgICBWYWx1ZXM6IFtzdGFja05hbWVdLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgTmFtZTogJ3RhZzpHaXRIdWJSdW5uZXJzOkJ1aWxkZXInLFxuICAgICAgICBWYWx1ZXM6IFtidWlsZGVyTmFtZV0sXG4gICAgICB9LFxuICAgIF0sXG4gIH0pKTtcblxuICBsZXQgaW1hZ2VzVG9EZWxldGUgPSBpbWFnZXMuSW1hZ2VzID8/IFtdO1xuXG4gIGNvbnNvbGUubG9nKHtcbiAgICBub3RpY2U6IGBGb3VuZCAke2ltYWdlc1RvRGVsZXRlLmxlbmd0aH0gQU1Jc2AsXG4gICAgaW1hZ2VzOiBpbWFnZXNUb0RlbGV0ZS5tYXAoaSA9PiBpLkltYWdlSWQpLFxuICB9KTtcblxuICAvLyBkZWxldGUgYWxsIHRoYXQgd2UgZm91bmRcbiAgZm9yIChjb25zdCBpbWFnZSBvZiBpbWFnZXNUb0RlbGV0ZSkge1xuICAgIGlmICghaW1hZ2UuSW1hZ2VJZCkge1xuICAgICAgY29uc29sZS53YXJuKHtcbiAgICAgICAgbm90aWNlOiAnTm8gaW1hZ2UgaWQ/JyxcbiAgICAgICAgaW1hZ2UsXG4gICAgICB9KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKGBEZXJlZ2lzdGVyaW5nICR7aW1hZ2UuSW1hZ2VJZH1gKTtcblxuICAgIGF3YWl0IGVjMi5zZW5kKG5ldyBEZXJlZ2lzdGVySW1hZ2VDb21tYW5kKHtcbiAgICAgIEltYWdlSWQ6IGltYWdlLkltYWdlSWQsXG4gICAgfSkpO1xuXG4gICAgZm9yIChjb25zdCBibG9ja01hcHBpbmcgb2YgaW1hZ2UuQmxvY2tEZXZpY2VNYXBwaW5ncyA/PyBbXSkge1xuICAgICAgaWYgKGJsb2NrTWFwcGluZy5FYnM/LlNuYXBzaG90SWQpIHtcbiAgICAgICAgY29uc29sZS5sb2coYERlbGV0aW5nICR7YmxvY2tNYXBwaW5nLkVicy5TbmFwc2hvdElkfWApO1xuXG4gICAgICAgIGF3YWl0IGVjMi5zZW5kKG5ldyBEZWxldGVTbmFwc2hvdENvbW1hbmQoe1xuICAgICAgICAgIFNuYXBzaG90SWQ6IGJsb2NrTWFwcGluZy5FYnMuU25hcHNob3RJZCxcbiAgICAgICAgfSkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlcihldmVudDogQVdTTGFtYmRhLkNsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VFdmVudCwgY29udGV4dDogQVdTTGFtYmRhLkNvbnRleHQpIHtcbiAgdHJ5IHtcbiAgICBjb25zb2xlLmxvZyh7IC4uLmV2ZW50LCBSZXNwb25zZVVSTDogJy4uLicgfSk7XG5cbiAgICBzd2l0Y2ggKGV2ZW50LlJlcXVlc3RUeXBlKSB7XG4gICAgICBjYXNlICdDcmVhdGUnOlxuICAgICAgY2FzZSAnVXBkYXRlJzpcbiAgICAgICAgYXdhaXQgY3VzdG9tUmVzb3VyY2VSZXNwb25kKGV2ZW50LCAnU1VDQ0VTUycsICdPSycsICdEZWxldGVBbWlzJywge30pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ0RlbGV0ZSc6XG4gICAgICAgIGF3YWl0IGRlbGV0ZUFtaXMoZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlN0YWNrTmFtZSwgZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLkJ1aWxkZXJOYW1lKTtcbiAgICAgICAgYXdhaXQgY3VzdG9tUmVzb3VyY2VSZXNwb25kKGV2ZW50LCAnU1VDQ0VTUycsICdPSycsIGV2ZW50LlBoeXNpY2FsUmVzb3VyY2VJZCwge30pO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgIGF3YWl0IGN1c3RvbVJlc291cmNlUmVzcG9uZChldmVudCwgJ0ZBSUxFRCcsIChlIGFzIEVycm9yKS5tZXNzYWdlIHx8ICdJbnRlcm5hbCBFcnJvcicsIGNvbnRleHQubG9nU3RyZWFtTmFtZSwge30pO1xuICB9XG59XG4iXX0=