aws-cdk 2.1006.0 → 3.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.
- package/README.md +1 -1
- package/THIRD_PARTY_LICENSES +104 -86
- package/build-info.json +2 -2
- package/db.json.gz +0 -0
- package/lib/api/aws-auth.d.ts +1 -0
- package/lib/api/{logs/index.js → aws-auth.js} +2 -3
- package/lib/api/bootstrap.d.ts +1 -0
- package/lib/api/bootstrap.js +18 -0
- package/lib/api/cloud-assembly.d.ts +1 -0
- package/lib/api/cloud-assembly.js +18 -0
- package/lib/api/cloudformation.d.ts +1 -0
- package/lib/api/cloudformation.js +18 -0
- package/lib/api/context.d.ts +1 -40
- package/lib/api/context.js +16 -80
- package/lib/api/deployments.d.ts +1 -0
- package/lib/api/deployments.js +18 -0
- package/lib/api/environment.d.ts +1 -0
- package/lib/api/environment.js +18 -0
- package/lib/api/garbage-collection.d.ts +1 -0
- package/lib/api/garbage-collection.js +18 -0
- package/lib/api/hotswap.d.ts +1 -0
- package/lib/api/hotswap.js +18 -0
- package/lib/api/index.d.ts +5 -1
- package/lib/api/index.js +6 -2
- package/lib/api/logs-monitor.d.ts +1 -0
- package/lib/api/logs-monitor.js +18 -0
- package/lib/api/notices.d.ts +1 -0
- package/lib/api/notices.js +18 -0
- package/lib/api/plugin.d.ts +1 -0
- package/lib/api/{resource-import/index.js → plugin.js} +2 -3
- package/lib/api/resource-import.d.ts +1 -0
- package/lib/api/resource-import.js +18 -0
- package/lib/api/rwlock.d.ts +1 -0
- package/lib/api/{garbage-collection/index.js → rwlock.js} +2 -2
- package/lib/api/settings.d.ts +1 -26
- package/lib/api/settings.js +16 -103
- package/lib/api/stack-events.d.ts +1 -0
- package/lib/api/stack-events.js +18 -0
- package/lib/api/tags.d.ts +1 -9
- package/lib/api/tags.js +16 -8
- package/lib/api/toolkit-info.d.ts +1 -52
- package/lib/api/toolkit-info.js +16 -152
- package/lib/api/tree.d.ts +1 -31
- package/lib/api/tree.js +16 -35
- package/lib/api/work-graph.d.ts +1 -0
- package/lib/api/work-graph.js +18 -0
- package/lib/api-private.d.ts +3 -0
- package/lib/api-private.js +22 -0
- package/lib/cli/cdk-toolkit.d.ts +20 -16
- package/lib/cli/cdk-toolkit.js +102 -37
- package/lib/cli/cli-config.js +2 -2
- package/lib/cli/cli.d.ts +1 -1
- package/lib/cli/cli.js +22 -19
- package/lib/cli/io-host/cli-io-host.js +2 -2
- package/lib/cli/pretty-print-error.js +3 -1
- package/lib/cli/util/npm.d.ts +4 -1
- package/lib/cli/util/npm.js +25 -13
- package/lib/cli/version.d.ts +1 -1
- package/lib/cli/version.js +21 -25
- package/lib/commands/context.js +3 -2
- package/lib/commands/diff.d.ts +1 -50
- package/lib/commands/diff.js +5 -213
- package/lib/commands/init/init.js +3 -2
- package/lib/commands/list-stacks.js +4 -4
- package/lib/context-providers/ami.d.ts +1 -13
- package/lib/context-providers/ami.js +16 -48
- package/lib/context-providers/availability-zones.d.ts +1 -13
- package/lib/context-providers/availability-zones.js +16 -25
- package/lib/context-providers/cc-api-provider.d.ts +1 -30
- package/lib/context-providers/cc-api-provider.js +16 -136
- package/lib/context-providers/endpoint-service-availability-zones.d.ts +1 -13
- package/lib/context-providers/endpoint-service-availability-zones.js +16 -31
- package/lib/context-providers/hosted-zones.d.ts +1 -12
- package/lib/context-providers/hosted-zones.js +16 -65
- package/lib/context-providers/index.d.ts +1 -44
- package/lib/context-providers/index.js +15 -126
- package/lib/context-providers/keys.d.ts +1 -13
- package/lib/context-providers/keys.js +16 -50
- package/lib/context-providers/load-balancers.d.ts +1 -20
- package/lib/context-providers/load-balancers.js +16 -154
- package/lib/context-providers/security-groups.d.ts +1 -9
- package/lib/context-providers/security-groups.js +16 -66
- package/lib/context-providers/ssm-parameters.d.ts +1 -25
- package/lib/context-providers/ssm-parameters.js +16 -57
- package/lib/context-providers/vpcs.d.ts +1 -13
- package/lib/context-providers/vpcs.js +16 -285
- package/lib/{api/cxapp → cxapp}/cloud-assembly.d.ts +3 -59
- package/lib/cxapp/cloud-assembly.js +108 -0
- package/lib/{api/cxapp → cxapp}/cloud-executable.d.ts +10 -3
- package/lib/cxapp/cloud-executable.js +92 -0
- package/lib/{api/cxapp → cxapp}/environments.d.ts +1 -2
- package/lib/{api/cxapp → cxapp}/environments.js +2 -2
- package/lib/cxapp/exec.d.ts +14 -0
- package/lib/cxapp/exec.js +157 -0
- package/lib/cxapp/index.d.ts +4 -0
- package/lib/{api/bootstrap → cxapp}/index.js +5 -3
- package/lib/index.js +134493 -125222
- package/lib/init-templates/.init-version.json +1 -1
- package/lib/init-templates/.recommended-feature-flags.json +3 -1
- package/lib/legacy-aws-auth.d.ts +74 -0
- package/lib/legacy-aws-auth.js +40 -0
- package/lib/legacy-exports-source.d.ts +13 -18
- package/lib/legacy-exports-source.js +42 -49
- package/lib/legacy-exports.d.ts +3 -6
- package/lib/legacy-exports.js +5 -5
- package/lib/legacy-types.d.ts +31 -0
- package/lib/legacy-types.js +3 -0
- package/package.json +19 -18
- package/lib/api/aws-auth/account-cache.d.ts +0 -36
- package/lib/api/aws-auth/account-cache.js +0 -99
- package/lib/api/aws-auth/awscli-compatible.d.ts +0 -42
- package/lib/api/aws-auth/awscli-compatible.js +0 -263
- package/lib/api/aws-auth/cached.d.ts +0 -11
- package/lib/api/aws-auth/cached.js +0 -26
- package/lib/api/aws-auth/credential-plugins.d.ts +0 -36
- package/lib/api/aws-auth/credential-plugins.js +0 -152
- package/lib/api/aws-auth/index.d.ts +0 -3
- package/lib/api/aws-auth/index.js +0 -20
- package/lib/api/aws-auth/provider-caching.d.ts +0 -13
- package/lib/api/aws-auth/provider-caching.js +0 -24
- package/lib/api/aws-auth/sdk-logger.d.ts +0 -69
- package/lib/api/aws-auth/sdk-logger.js +0 -124
- package/lib/api/aws-auth/sdk-provider.d.ts +0 -207
- package/lib/api/aws-auth/sdk-provider.js +0 -357
- package/lib/api/aws-auth/sdk.d.ts +0 -229
- package/lib/api/aws-auth/sdk.js +0 -373
- package/lib/api/aws-auth/tracing.d.ts +0 -11
- package/lib/api/aws-auth/tracing.js +0 -60
- package/lib/api/aws-auth/user-agent.d.ts +0 -7
- package/lib/api/aws-auth/user-agent.js +0 -20
- package/lib/api/aws-auth/util.d.ts +0 -6
- package/lib/api/aws-auth/util.js +0 -23
- package/lib/api/bootstrap/bootstrap-environment.d.ts +0 -35
- package/lib/api/bootstrap/bootstrap-environment.js +0 -321
- package/lib/api/bootstrap/bootstrap-props.d.ts +0 -130
- package/lib/api/bootstrap/bootstrap-props.js +0 -14
- package/lib/api/bootstrap/deploy-bootstrap.d.ts +0 -39
- package/lib/api/bootstrap/deploy-bootstrap.js +0 -141
- package/lib/api/bootstrap/index.d.ts +0 -2
- package/lib/api/bootstrap/legacy-template.d.ts +0 -2
- package/lib/api/bootstrap/legacy-template.js +0 -82
- package/lib/api/cloudformation/evaluate-cloudformation-template.d.ts +0 -85
- package/lib/api/cloudformation/evaluate-cloudformation-template.js +0 -440
- package/lib/api/cloudformation/index.d.ts +0 -4
- package/lib/api/cloudformation/index.js +0 -21
- package/lib/api/cloudformation/nested-stack-helpers.d.ts +0 -25
- package/lib/api/cloudformation/nested-stack-helpers.js +0 -86
- package/lib/api/cloudformation/stack-helpers.d.ts +0 -96
- package/lib/api/cloudformation/stack-helpers.js +0 -158
- package/lib/api/cloudformation/template-body-parameter.d.ts +0 -22
- package/lib/api/cloudformation/template-body-parameter.js +0 -104
- package/lib/api/cxapp/cloud-assembly.js +0 -304
- package/lib/api/cxapp/cloud-executable.js +0 -89
- package/lib/api/cxapp/exec.d.ts +0 -56
- package/lib/api/cxapp/exec.js +0 -272
- package/lib/api/deployments/asset-manifest-builder.d.ts +0 -8
- package/lib/api/deployments/asset-manifest-builder.js +0 -35
- package/lib/api/deployments/asset-publishing.d.ts +0 -60
- package/lib/api/deployments/asset-publishing.js +0 -141
- package/lib/api/deployments/assets.d.ts +0 -11
- package/lib/api/deployments/assets.js +0 -109
- package/lib/api/deployments/cfn-api.d.ts +0 -138
- package/lib/api/deployments/cfn-api.js +0 -438
- package/lib/api/deployments/checks.d.ts +0 -9
- package/lib/api/deployments/checks.js +0 -72
- package/lib/api/deployments/deploy-stack.d.ts +0 -155
- package/lib/api/deployments/deploy-stack.js +0 -478
- package/lib/api/deployments/deployment-method.d.ts +0 -24
- package/lib/api/deployments/deployment-method.js +0 -3
- package/lib/api/deployments/deployment-result.d.ts +0 -21
- package/lib/api/deployments/deployment-result.js +0 -10
- package/lib/api/deployments/deployments.d.ts +0 -296
- package/lib/api/deployments/deployments.js +0 -331
- package/lib/api/deployments/hotswap-deployments.d.ts +0 -17
- package/lib/api/deployments/hotswap-deployments.js +0 -441
- package/lib/api/deployments/index.d.ts +0 -4
- package/lib/api/deployments/index.js +0 -21
- package/lib/api/environment/environment-access.d.ts +0 -140
- package/lib/api/environment/environment-access.js +0 -202
- package/lib/api/environment/environment-resources.d.ts +0 -75
- package/lib/api/environment/environment-resources.js +0 -207
- package/lib/api/environment/index.d.ts +0 -3
- package/lib/api/environment/index.js +0 -20
- package/lib/api/environment/placeholders.d.ts +0 -10
- package/lib/api/environment/placeholders.js +0 -23
- package/lib/api/garbage-collection/garbage-collector.d.ts +0 -158
- package/lib/api/garbage-collection/garbage-collector.js +0 -599
- package/lib/api/garbage-collection/index.d.ts +0 -1
- package/lib/api/garbage-collection/progress-printer.d.ts +0 -23
- package/lib/api/garbage-collection/progress-printer.js +0 -70
- package/lib/api/garbage-collection/stack-refresh.d.ts +0 -49
- package/lib/api/garbage-collection/stack-refresh.js +0 -151
- package/lib/api/hotswap/appsync-mapping-templates.d.ts +0 -4
- package/lib/api/hotswap/appsync-mapping-templates.js +0 -162
- package/lib/api/hotswap/code-build-projects.d.ts +0 -4
- package/lib/api/hotswap/code-build-projects.js +0 -62
- package/lib/api/hotswap/common.d.ts +0 -89
- package/lib/api/hotswap/common.js +0 -128
- package/lib/api/hotswap/ecs-services.d.ts +0 -4
- package/lib/api/hotswap/ecs-services.js +0 -159
- package/lib/api/hotswap/lambda-functions.d.ts +0 -4
- package/lib/api/hotswap/lambda-functions.js +0 -297
- package/lib/api/hotswap/s3-bucket-deployments.d.ts +0 -5
- package/lib/api/hotswap/s3-bucket-deployments.js +0 -117
- package/lib/api/hotswap/stepfunctions-state-machines.d.ts +0 -4
- package/lib/api/hotswap/stepfunctions-state-machines.js +0 -48
- package/lib/api/logs/find-cloudwatch-logs.d.ts +0 -25
- package/lib/api/logs/find-cloudwatch-logs.js +0 -95
- package/lib/api/logs/index.d.ts +0 -2
- package/lib/api/logs/logs-monitor.d.ts +0 -76
- package/lib/api/logs/logs-monitor.js +0 -187
- package/lib/api/plugin/context-provider-plugin.d.ts +0 -6
- package/lib/api/plugin/context-provider-plugin.js +0 -7
- package/lib/api/plugin/index.d.ts +0 -3
- package/lib/api/plugin/index.js +0 -20
- package/lib/api/plugin/mode.d.ts +0 -4
- package/lib/api/plugin/mode.js +0 -9
- package/lib/api/plugin/plugin.d.ts +0 -63
- package/lib/api/plugin/plugin.js +0 -102
- package/lib/api/resource-import/importer.d.ts +0 -220
- package/lib/api/resource-import/importer.js +0 -331
- package/lib/api/resource-import/index.d.ts +0 -2
- package/lib/api/resource-import/migrator.d.ts +0 -26
- package/lib/api/resource-import/migrator.js +0 -71
- package/lib/api/stack-events/index.d.ts +0 -3
- package/lib/api/stack-events/index.js +0 -20
- package/lib/api/stack-events/stack-activity-monitor.d.ts +0 -100
- package/lib/api/stack-events/stack-activity-monitor.js +0 -142
- package/lib/api/stack-events/stack-event-poller.d.ts +0 -69
- package/lib/api/stack-events/stack-event-poller.js +0 -128
- package/lib/api/stack-events/stack-progress-monitor.d.ts +0 -48
- package/lib/api/stack-events/stack-progress-monitor.js +0 -94
- package/lib/api/stack-events/stack-status.d.ts +0 -42
- package/lib/api/stack-events/stack-status.js +0 -88
- package/lib/api/util/rwlock.d.ts +0 -65
- package/lib/api/util/rwlock.js +0 -179
- package/lib/api/work-graph/index.d.ts +0 -3
- package/lib/api/work-graph/index.js +0 -20
- package/lib/api/work-graph/work-graph-builder.d.ts +0 -34
- package/lib/api/work-graph/work-graph-builder.js +0 -168
- package/lib/api/work-graph/work-graph-types.d.ts +0 -50
- package/lib/api/work-graph/work-graph-types.js +0 -13
- package/lib/api/work-graph/work-graph.d.ts +0 -72
- package/lib/api/work-graph/work-graph.js +0 -346
- package/lib/cli/activity-printer/base.d.ts +0 -50
- package/lib/cli/activity-printer/base.js +0 -114
- package/lib/cli/activity-printer/current.d.ts +0 -26
- package/lib/cli/activity-printer/current.js +0 -118
- package/lib/cli/activity-printer/display.d.ts +0 -13
- package/lib/cli/activity-printer/display.js +0 -80
- package/lib/cli/activity-printer/history.d.ts +0 -32
- package/lib/cli/activity-printer/history.js +0 -108
- package/lib/cli/activity-printer/index.d.ts +0 -3
- package/lib/cli/activity-printer/index.js +0 -20
- package/lib/notices.d.ts +0 -203
- package/lib/notices.js +0 -411
|
@@ -1,599 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GarbageCollector = exports.ObjectAsset = exports.ImageAsset = exports.ECR_ISOLATED_TAG = exports.S3_ISOLATED_TAG = void 0;
|
|
4
|
-
const chalk = require("chalk");
|
|
5
|
-
const promptly = require("promptly");
|
|
6
|
-
const toolkit_info_1 = require("../toolkit-info");
|
|
7
|
-
const progress_printer_1 = require("./progress-printer");
|
|
8
|
-
const stack_refresh_1 = require("./stack-refresh");
|
|
9
|
-
const api_1 = require("../../../../@aws-cdk/tmp-toolkit-helpers/src/api");
|
|
10
|
-
const private_1 = require("../../../../@aws-cdk/tmp-toolkit-helpers/src/api/io/private");
|
|
11
|
-
const mode_1 = require("../plugin/mode");
|
|
12
|
-
// Must use a require() otherwise esbuild complains
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports,@typescript-eslint/consistent-type-imports
|
|
14
|
-
const pLimit = require('p-limit');
|
|
15
|
-
exports.S3_ISOLATED_TAG = 'aws-cdk:isolated';
|
|
16
|
-
exports.ECR_ISOLATED_TAG = 'aws-cdk.isolated'; // ':' is not valid in ECR tags
|
|
17
|
-
const P_LIMIT = 50;
|
|
18
|
-
const DAY = 24 * 60 * 60 * 1000; // Number of milliseconds in a day
|
|
19
|
-
/**
|
|
20
|
-
* An image asset that lives in the bootstrapped ECR Repository
|
|
21
|
-
*/
|
|
22
|
-
class ImageAsset {
|
|
23
|
-
constructor(digest, size, tags, manifest) {
|
|
24
|
-
this.digest = digest;
|
|
25
|
-
this.size = size;
|
|
26
|
-
this.tags = tags;
|
|
27
|
-
this.manifest = manifest;
|
|
28
|
-
}
|
|
29
|
-
getTag(tag) {
|
|
30
|
-
return this.tags.find(t => t.includes(tag));
|
|
31
|
-
}
|
|
32
|
-
hasTag(tag) {
|
|
33
|
-
return this.tags.some(t => t.includes(tag));
|
|
34
|
-
}
|
|
35
|
-
hasIsolatedTag() {
|
|
36
|
-
return this.hasTag(exports.ECR_ISOLATED_TAG);
|
|
37
|
-
}
|
|
38
|
-
getIsolatedTag() {
|
|
39
|
-
return this.getTag(exports.ECR_ISOLATED_TAG);
|
|
40
|
-
}
|
|
41
|
-
isolatedTagBefore(date) {
|
|
42
|
-
const dateIsolated = this.dateIsolated();
|
|
43
|
-
if (!dateIsolated || dateIsolated == '') {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
return new Date(dateIsolated) < date;
|
|
47
|
-
}
|
|
48
|
-
buildImageTag(inc) {
|
|
49
|
-
// isolatedTag will look like "X-aws-cdk.isolated-YYYYY"
|
|
50
|
-
return `${inc}-${exports.ECR_ISOLATED_TAG}-${String(Date.now())}`;
|
|
51
|
-
}
|
|
52
|
-
dateIsolated() {
|
|
53
|
-
// isolatedTag will look like "X-aws-cdk.isolated-YYYYY"
|
|
54
|
-
return this.getIsolatedTag()?.split('-')[3];
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
exports.ImageAsset = ImageAsset;
|
|
58
|
-
/**
|
|
59
|
-
* An object asset that lives in the bootstrapped S3 Bucket
|
|
60
|
-
*/
|
|
61
|
-
class ObjectAsset {
|
|
62
|
-
constructor(bucket, key, size) {
|
|
63
|
-
this.bucket = bucket;
|
|
64
|
-
this.key = key;
|
|
65
|
-
this.size = size;
|
|
66
|
-
this.cached_tags = undefined;
|
|
67
|
-
}
|
|
68
|
-
fileName() {
|
|
69
|
-
return this.key.split('.')[0];
|
|
70
|
-
}
|
|
71
|
-
async allTags(s3) {
|
|
72
|
-
if (this.cached_tags) {
|
|
73
|
-
return this.cached_tags;
|
|
74
|
-
}
|
|
75
|
-
const response = await s3.getObjectTagging({ Bucket: this.bucket, Key: this.key });
|
|
76
|
-
this.cached_tags = response.TagSet;
|
|
77
|
-
return this.cached_tags;
|
|
78
|
-
}
|
|
79
|
-
getTag(tag) {
|
|
80
|
-
if (!this.cached_tags) {
|
|
81
|
-
throw new api_1.ToolkitError('Cannot call getTag before allTags');
|
|
82
|
-
}
|
|
83
|
-
return this.cached_tags.find((t) => t.Key === tag)?.Value;
|
|
84
|
-
}
|
|
85
|
-
hasTag(tag) {
|
|
86
|
-
if (!this.cached_tags) {
|
|
87
|
-
throw new api_1.ToolkitError('Cannot call hasTag before allTags');
|
|
88
|
-
}
|
|
89
|
-
return this.cached_tags.some((t) => t.Key === tag);
|
|
90
|
-
}
|
|
91
|
-
hasIsolatedTag() {
|
|
92
|
-
return this.hasTag(exports.S3_ISOLATED_TAG);
|
|
93
|
-
}
|
|
94
|
-
isolatedTagBefore(date) {
|
|
95
|
-
const tagValue = this.getTag(exports.S3_ISOLATED_TAG);
|
|
96
|
-
if (!tagValue || tagValue == '') {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
return new Date(tagValue) < date;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
exports.ObjectAsset = ObjectAsset;
|
|
103
|
-
/**
|
|
104
|
-
* A class to facilitate Garbage Collection of S3 and ECR assets
|
|
105
|
-
*/
|
|
106
|
-
class GarbageCollector {
|
|
107
|
-
constructor(props) {
|
|
108
|
-
this.props = props;
|
|
109
|
-
this.ioHelper = props.ioHelper;
|
|
110
|
-
this.garbageCollectS3Assets = ['s3', 'all'].includes(props.type);
|
|
111
|
-
this.garbageCollectEcrAssets = ['ecr', 'all'].includes(props.type);
|
|
112
|
-
this.permissionToDelete = ['delete-tagged', 'full'].includes(props.action);
|
|
113
|
-
this.permissionToTag = ['tag', 'full'].includes(props.action);
|
|
114
|
-
this.confirm = props.confirm ?? true;
|
|
115
|
-
this.bootstrapStackName = props.bootstrapStackName ?? toolkit_info_1.DEFAULT_TOOLKIT_STACK_NAME;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Perform garbage collection on the resolved environment.
|
|
119
|
-
*/
|
|
120
|
-
async garbageCollect() {
|
|
121
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${this.garbageCollectS3Assets} ${this.garbageCollectEcrAssets}`));
|
|
122
|
-
// SDKs
|
|
123
|
-
const sdk = (await this.props.sdkProvider.forEnvironment(this.props.resolvedEnvironment, mode_1.Mode.ForWriting)).sdk;
|
|
124
|
-
const cfn = sdk.cloudFormation();
|
|
125
|
-
const qualifier = await this.bootstrapQualifier(sdk, this.bootstrapStackName);
|
|
126
|
-
const activeAssets = new stack_refresh_1.ActiveAssetCache();
|
|
127
|
-
// Grab stack templates first
|
|
128
|
-
await (0, stack_refresh_1.refreshStacks)(cfn, this.ioHelper, activeAssets, qualifier);
|
|
129
|
-
// Start the background refresh
|
|
130
|
-
const backgroundStackRefresh = new stack_refresh_1.BackgroundStackRefresh({
|
|
131
|
-
cfn,
|
|
132
|
-
ioHelper: this.ioHelper,
|
|
133
|
-
activeAssets,
|
|
134
|
-
qualifier,
|
|
135
|
-
});
|
|
136
|
-
backgroundStackRefresh.start();
|
|
137
|
-
try {
|
|
138
|
-
if (this.garbageCollectS3Assets) {
|
|
139
|
-
await this.garbageCollectS3(sdk, activeAssets, backgroundStackRefresh);
|
|
140
|
-
}
|
|
141
|
-
if (this.garbageCollectEcrAssets) {
|
|
142
|
-
await this.garbageCollectEcr(sdk, activeAssets, backgroundStackRefresh);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
catch (err) {
|
|
146
|
-
throw new api_1.ToolkitError(err);
|
|
147
|
-
}
|
|
148
|
-
finally {
|
|
149
|
-
backgroundStackRefresh.stop();
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Perform garbage collection on ECR assets
|
|
154
|
-
*/
|
|
155
|
-
async garbageCollectEcr(sdk, activeAssets, backgroundStackRefresh) {
|
|
156
|
-
const ecr = sdk.ecr();
|
|
157
|
-
const repo = await this.bootstrapRepositoryName(sdk, this.bootstrapStackName);
|
|
158
|
-
const numImages = await this.numImagesInRepo(ecr, repo);
|
|
159
|
-
const printer = new progress_printer_1.ProgressPrinter(this.ioHelper, numImages, 1000);
|
|
160
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Found bootstrap repo ${repo} with ${numImages} images`));
|
|
161
|
-
try {
|
|
162
|
-
// const batches = 1;
|
|
163
|
-
const batchSize = 1000;
|
|
164
|
-
const currentTime = Date.now();
|
|
165
|
-
const graceDays = this.props.rollbackBufferDays;
|
|
166
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Parsing through ${numImages} images in batches`));
|
|
167
|
-
printer.start();
|
|
168
|
-
for await (const batch of this.readRepoInBatches(ecr, repo, batchSize, currentTime)) {
|
|
169
|
-
await backgroundStackRefresh.noOlderThan(600000); // 10 mins
|
|
170
|
-
const { included: isolated, excluded: notIsolated } = partition(batch, asset => !asset.tags.some(t => activeAssets.contains(t)));
|
|
171
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${isolated.length} isolated images`));
|
|
172
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${notIsolated.length} not isolated images`));
|
|
173
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${batch.length} images total`));
|
|
174
|
-
let deletables = isolated;
|
|
175
|
-
let taggables = [];
|
|
176
|
-
let untaggables = [];
|
|
177
|
-
if (graceDays > 0) {
|
|
178
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg('Filtering out images that are not old enough to delete'));
|
|
179
|
-
// We delete images that are not referenced in ActiveAssets and have the Isolated Tag with a date
|
|
180
|
-
// earlier than the current time - grace period.
|
|
181
|
-
deletables = isolated.filter(img => img.isolatedTagBefore(new Date(currentTime - (graceDays * DAY))));
|
|
182
|
-
// We tag images that are not referenced in ActiveAssets and do not have the Isolated Tag.
|
|
183
|
-
taggables = isolated.filter(img => !img.hasIsolatedTag());
|
|
184
|
-
// We untag images that are referenced in ActiveAssets and currently have the Isolated Tag.
|
|
185
|
-
untaggables = notIsolated.filter(img => img.hasIsolatedTag());
|
|
186
|
-
}
|
|
187
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${deletables.length} deletable assets`));
|
|
188
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${taggables.length} taggable assets`));
|
|
189
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${untaggables.length} assets to untag`));
|
|
190
|
-
if (this.permissionToDelete && deletables.length > 0) {
|
|
191
|
-
await this.confirmationPrompt(printer, deletables, 'image');
|
|
192
|
-
await this.parallelDeleteEcr(ecr, repo, deletables, printer);
|
|
193
|
-
}
|
|
194
|
-
if (this.permissionToTag && taggables.length > 0) {
|
|
195
|
-
await this.parallelTagEcr(ecr, repo, taggables, printer);
|
|
196
|
-
}
|
|
197
|
-
if (this.permissionToTag && untaggables.length > 0) {
|
|
198
|
-
await this.parallelUntagEcr(ecr, repo, untaggables);
|
|
199
|
-
}
|
|
200
|
-
printer.reportScannedAsset(batch.length);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
catch (err) {
|
|
204
|
-
throw new api_1.ToolkitError(err);
|
|
205
|
-
}
|
|
206
|
-
finally {
|
|
207
|
-
printer.stop();
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Perform garbage collection on S3 assets
|
|
212
|
-
*/
|
|
213
|
-
async garbageCollectS3(sdk, activeAssets, backgroundStackRefresh) {
|
|
214
|
-
const s3 = sdk.s3();
|
|
215
|
-
const bucket = await this.bootstrapBucketName(sdk, this.bootstrapStackName);
|
|
216
|
-
const numObjects = await this.numObjectsInBucket(s3, bucket);
|
|
217
|
-
const printer = new progress_printer_1.ProgressPrinter(this.ioHelper, numObjects, 1000);
|
|
218
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Found bootstrap bucket ${bucket} with ${numObjects} objects`));
|
|
219
|
-
try {
|
|
220
|
-
const batchSize = 1000;
|
|
221
|
-
const currentTime = Date.now();
|
|
222
|
-
const graceDays = this.props.rollbackBufferDays;
|
|
223
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Parsing through ${numObjects} objects in batches`));
|
|
224
|
-
printer.start();
|
|
225
|
-
// Process objects in batches of 1000
|
|
226
|
-
// This is the batch limit of s3.DeleteObject and we intend to optimize for the "worst case" scenario
|
|
227
|
-
// where gc is run for the first time on a long-standing bucket where ~100% of objects are isolated.
|
|
228
|
-
for await (const batch of this.readBucketInBatches(s3, bucket, batchSize, currentTime)) {
|
|
229
|
-
await backgroundStackRefresh.noOlderThan(600000); // 10 mins
|
|
230
|
-
const { included: isolated, excluded: notIsolated } = partition(batch, asset => !activeAssets.contains(asset.fileName()));
|
|
231
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${isolated.length} isolated assets`));
|
|
232
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${notIsolated.length} not isolated assets`));
|
|
233
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${batch.length} objects total`));
|
|
234
|
-
let deletables = isolated;
|
|
235
|
-
let taggables = [];
|
|
236
|
-
let untaggables = [];
|
|
237
|
-
if (graceDays > 0) {
|
|
238
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg('Filtering out assets that are not old enough to delete'));
|
|
239
|
-
await this.parallelReadAllTags(s3, batch);
|
|
240
|
-
// We delete objects that are not referenced in ActiveAssets and have the Isolated Tag with a date
|
|
241
|
-
// earlier than the current time - grace period.
|
|
242
|
-
deletables = isolated.filter(obj => obj.isolatedTagBefore(new Date(currentTime - (graceDays * DAY))));
|
|
243
|
-
// We tag objects that are not referenced in ActiveAssets and do not have the Isolated Tag.
|
|
244
|
-
taggables = isolated.filter(obj => !obj.hasIsolatedTag());
|
|
245
|
-
// We untag objects that are referenced in ActiveAssets and currently have the Isolated Tag.
|
|
246
|
-
untaggables = notIsolated.filter(obj => obj.hasIsolatedTag());
|
|
247
|
-
}
|
|
248
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${deletables.length} deletable assets`));
|
|
249
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${taggables.length} taggable assets`));
|
|
250
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`${untaggables.length} assets to untag`));
|
|
251
|
-
if (this.permissionToDelete && deletables.length > 0) {
|
|
252
|
-
await this.confirmationPrompt(printer, deletables, 'object');
|
|
253
|
-
await this.parallelDeleteS3(s3, bucket, deletables, printer);
|
|
254
|
-
}
|
|
255
|
-
if (this.permissionToTag && taggables.length > 0) {
|
|
256
|
-
await this.parallelTagS3(s3, bucket, taggables, currentTime, printer);
|
|
257
|
-
}
|
|
258
|
-
if (this.permissionToTag && untaggables.length > 0) {
|
|
259
|
-
await this.parallelUntagS3(s3, bucket, untaggables);
|
|
260
|
-
}
|
|
261
|
-
printer.reportScannedAsset(batch.length);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
catch (err) {
|
|
265
|
-
throw new api_1.ToolkitError(err);
|
|
266
|
-
}
|
|
267
|
-
finally {
|
|
268
|
-
printer.stop();
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
async parallelReadAllTags(s3, objects) {
|
|
272
|
-
const limit = pLimit(P_LIMIT);
|
|
273
|
-
for (const obj of objects) {
|
|
274
|
-
await limit(() => obj.allTags(s3));
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
/**
|
|
278
|
-
* Untag assets that were previously tagged, but now currently referenced.
|
|
279
|
-
* Since this is treated as an implementation detail, we do not print the results in the printer.
|
|
280
|
-
*/
|
|
281
|
-
async parallelUntagEcr(ecr, repo, untaggables) {
|
|
282
|
-
const limit = pLimit(P_LIMIT);
|
|
283
|
-
for (const img of untaggables) {
|
|
284
|
-
const tag = img.getIsolatedTag();
|
|
285
|
-
await limit(() => ecr.batchDeleteImage({
|
|
286
|
-
repositoryName: repo,
|
|
287
|
-
imageIds: [{
|
|
288
|
-
imageTag: tag,
|
|
289
|
-
}],
|
|
290
|
-
}));
|
|
291
|
-
}
|
|
292
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Untagged ${untaggables.length} assets`));
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Untag assets that were previously tagged, but now currently referenced.
|
|
296
|
-
* Since this is treated as an implementation detail, we do not print the results in the printer.
|
|
297
|
-
*/
|
|
298
|
-
async parallelUntagS3(s3, bucket, untaggables) {
|
|
299
|
-
const limit = pLimit(P_LIMIT);
|
|
300
|
-
for (const obj of untaggables) {
|
|
301
|
-
const tags = await obj.allTags(s3) ?? [];
|
|
302
|
-
const updatedTags = tags.filter((tag) => tag.Key !== exports.S3_ISOLATED_TAG);
|
|
303
|
-
await limit(() => s3.deleteObjectTagging({
|
|
304
|
-
Bucket: bucket,
|
|
305
|
-
Key: obj.key,
|
|
306
|
-
}));
|
|
307
|
-
await limit(() => s3.putObjectTagging({
|
|
308
|
-
Bucket: bucket,
|
|
309
|
-
Key: obj.key,
|
|
310
|
-
Tagging: {
|
|
311
|
-
TagSet: updatedTags,
|
|
312
|
-
},
|
|
313
|
-
}));
|
|
314
|
-
}
|
|
315
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Untagged ${untaggables.length} assets`));
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Tag images in parallel using p-limit
|
|
319
|
-
*/
|
|
320
|
-
async parallelTagEcr(ecr, repo, taggables, printer) {
|
|
321
|
-
const limit = pLimit(P_LIMIT);
|
|
322
|
-
for (let i = 0; i < taggables.length; i++) {
|
|
323
|
-
const img = taggables[i];
|
|
324
|
-
const tagEcr = async () => {
|
|
325
|
-
try {
|
|
326
|
-
await ecr.putImage({
|
|
327
|
-
repositoryName: repo,
|
|
328
|
-
imageDigest: img.digest,
|
|
329
|
-
imageManifest: img.manifest,
|
|
330
|
-
imageTag: img.buildImageTag(i),
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
catch (error) {
|
|
334
|
-
// This is a false negative -- an isolated asset is untagged
|
|
335
|
-
// likely due to an imageTag collision. We can safely ignore,
|
|
336
|
-
// and the isolated asset will be tagged next time.
|
|
337
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Warning: unable to tag image ${JSON.stringify(img.tags)} with ${img.buildImageTag(i)} due to the following error: ${error}`));
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
await limit(() => tagEcr());
|
|
341
|
-
}
|
|
342
|
-
printer.reportTaggedAsset(taggables);
|
|
343
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Tagged ${taggables.length} assets`));
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* Tag objects in parallel using p-limit. The putObjectTagging API does not
|
|
347
|
-
* support batch tagging so we must handle the parallelism client-side.
|
|
348
|
-
*/
|
|
349
|
-
async parallelTagS3(s3, bucket, taggables, date, printer) {
|
|
350
|
-
const limit = pLimit(P_LIMIT);
|
|
351
|
-
for (const obj of taggables) {
|
|
352
|
-
await limit(() => s3.putObjectTagging({
|
|
353
|
-
Bucket: bucket,
|
|
354
|
-
Key: obj.key,
|
|
355
|
-
Tagging: {
|
|
356
|
-
TagSet: [
|
|
357
|
-
{
|
|
358
|
-
Key: exports.S3_ISOLATED_TAG,
|
|
359
|
-
Value: String(date),
|
|
360
|
-
},
|
|
361
|
-
],
|
|
362
|
-
},
|
|
363
|
-
}));
|
|
364
|
-
}
|
|
365
|
-
printer.reportTaggedAsset(taggables);
|
|
366
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Tagged ${taggables.length} assets`));
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Delete images in parallel. The deleteImage API supports batches of 100.
|
|
370
|
-
*/
|
|
371
|
-
async parallelDeleteEcr(ecr, repo, deletables, printer) {
|
|
372
|
-
const batchSize = 100;
|
|
373
|
-
const imagesToDelete = deletables.map(img => ({
|
|
374
|
-
imageDigest: img.digest,
|
|
375
|
-
}));
|
|
376
|
-
try {
|
|
377
|
-
const batches = [];
|
|
378
|
-
for (let i = 0; i < imagesToDelete.length; i += batchSize) {
|
|
379
|
-
batches.push(imagesToDelete.slice(i, i + batchSize));
|
|
380
|
-
}
|
|
381
|
-
// Delete images in batches
|
|
382
|
-
for (const batch of batches) {
|
|
383
|
-
await ecr.batchDeleteImage({
|
|
384
|
-
imageIds: batch,
|
|
385
|
-
repositoryName: repo,
|
|
386
|
-
});
|
|
387
|
-
const deletedCount = batch.length;
|
|
388
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Deleted ${deletedCount} assets`));
|
|
389
|
-
printer.reportDeletedAsset(deletables.slice(0, deletedCount));
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
catch (err) {
|
|
393
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_ERROR.msg(`Error deleting images: ${err}`));
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* Delete objects in parallel. The deleteObjects API supports batches of 1000.
|
|
398
|
-
*/
|
|
399
|
-
async parallelDeleteS3(s3, bucket, deletables, printer) {
|
|
400
|
-
const batchSize = 1000;
|
|
401
|
-
const objectsToDelete = deletables.map(asset => ({
|
|
402
|
-
Key: asset.key,
|
|
403
|
-
}));
|
|
404
|
-
try {
|
|
405
|
-
const batches = [];
|
|
406
|
-
for (let i = 0; i < objectsToDelete.length; i += batchSize) {
|
|
407
|
-
batches.push(objectsToDelete.slice(i, i + batchSize));
|
|
408
|
-
}
|
|
409
|
-
// Delete objects in batches
|
|
410
|
-
for (const batch of batches) {
|
|
411
|
-
await s3.deleteObjects({
|
|
412
|
-
Bucket: bucket,
|
|
413
|
-
Delete: {
|
|
414
|
-
Objects: batch,
|
|
415
|
-
Quiet: true,
|
|
416
|
-
},
|
|
417
|
-
});
|
|
418
|
-
const deletedCount = batch.length;
|
|
419
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(`Deleted ${deletedCount} assets`));
|
|
420
|
-
printer.reportDeletedAsset(deletables.slice(0, deletedCount));
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
catch (err) {
|
|
424
|
-
await this.ioHelper.notify(private_1.IO.DEFAULT_TOOLKIT_DEBUG.msg(chalk.red(`Error deleting objects: ${err}`)));
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
async bootstrapBucketName(sdk, bootstrapStackName) {
|
|
428
|
-
const toolkitInfo = await toolkit_info_1.ToolkitInfo.lookup(this.props.resolvedEnvironment, sdk, this.ioHelper, bootstrapStackName);
|
|
429
|
-
return toolkitInfo.bucketName;
|
|
430
|
-
}
|
|
431
|
-
async bootstrapRepositoryName(sdk, bootstrapStackName) {
|
|
432
|
-
const toolkitInfo = await toolkit_info_1.ToolkitInfo.lookup(this.props.resolvedEnvironment, sdk, this.ioHelper, bootstrapStackName);
|
|
433
|
-
return toolkitInfo.repositoryName;
|
|
434
|
-
}
|
|
435
|
-
async bootstrapQualifier(sdk, bootstrapStackName) {
|
|
436
|
-
const toolkitInfo = await toolkit_info_1.ToolkitInfo.lookup(this.props.resolvedEnvironment, sdk, this.ioHelper, bootstrapStackName);
|
|
437
|
-
return toolkitInfo.bootstrapStack.parameters.Qualifier;
|
|
438
|
-
}
|
|
439
|
-
async numObjectsInBucket(s3, bucket) {
|
|
440
|
-
let totalCount = 0;
|
|
441
|
-
let continuationToken;
|
|
442
|
-
do {
|
|
443
|
-
const response = await s3.listObjectsV2({
|
|
444
|
-
Bucket: bucket,
|
|
445
|
-
ContinuationToken: continuationToken,
|
|
446
|
-
});
|
|
447
|
-
totalCount += response.KeyCount ?? 0;
|
|
448
|
-
continuationToken = response.NextContinuationToken;
|
|
449
|
-
} while (continuationToken);
|
|
450
|
-
return totalCount;
|
|
451
|
-
}
|
|
452
|
-
async numImagesInRepo(ecr, repo) {
|
|
453
|
-
let totalCount = 0;
|
|
454
|
-
let nextToken;
|
|
455
|
-
do {
|
|
456
|
-
const response = await ecr.listImages({
|
|
457
|
-
repositoryName: repo,
|
|
458
|
-
nextToken: nextToken,
|
|
459
|
-
});
|
|
460
|
-
totalCount += response.imageIds?.length ?? 0;
|
|
461
|
-
nextToken = response.nextToken;
|
|
462
|
-
} while (nextToken);
|
|
463
|
-
return totalCount;
|
|
464
|
-
}
|
|
465
|
-
async *readRepoInBatches(ecr, repo, batchSize = 1000, currentTime) {
|
|
466
|
-
let continuationToken;
|
|
467
|
-
do {
|
|
468
|
-
const batch = [];
|
|
469
|
-
while (batch.length < batchSize) {
|
|
470
|
-
const response = await ecr.listImages({
|
|
471
|
-
repositoryName: repo,
|
|
472
|
-
nextToken: continuationToken,
|
|
473
|
-
});
|
|
474
|
-
// No images in the repository
|
|
475
|
-
if (!response.imageIds || response.imageIds.length === 0) {
|
|
476
|
-
break;
|
|
477
|
-
}
|
|
478
|
-
// map unique image digest to (possibly multiple) tags
|
|
479
|
-
const images = imageMap(response.imageIds ?? []);
|
|
480
|
-
const imageIds = Object.keys(images).map(key => ({
|
|
481
|
-
imageDigest: key,
|
|
482
|
-
}));
|
|
483
|
-
const describeImageInfo = await ecr.describeImages({
|
|
484
|
-
repositoryName: repo,
|
|
485
|
-
imageIds: imageIds,
|
|
486
|
-
});
|
|
487
|
-
const getImageInfo = await ecr.batchGetImage({
|
|
488
|
-
repositoryName: repo,
|
|
489
|
-
imageIds: imageIds,
|
|
490
|
-
});
|
|
491
|
-
const combinedImageInfo = describeImageInfo.imageDetails?.map(imageDetail => {
|
|
492
|
-
const matchingImage = getImageInfo.images?.find(img => img.imageId?.imageDigest === imageDetail.imageDigest);
|
|
493
|
-
return {
|
|
494
|
-
...imageDetail,
|
|
495
|
-
manifest: matchingImage?.imageManifest,
|
|
496
|
-
};
|
|
497
|
-
});
|
|
498
|
-
for (const image of combinedImageInfo ?? []) {
|
|
499
|
-
const lastModified = image.imagePushedAt ?? new Date(currentTime);
|
|
500
|
-
// Store the image if it was pushed earlier than today - createdBufferDays
|
|
501
|
-
if (image.imageDigest && lastModified < new Date(currentTime - (this.props.createdBufferDays * DAY))) {
|
|
502
|
-
batch.push(new ImageAsset(image.imageDigest, image.imageSizeInBytes ?? 0, image.imageTags ?? [], image.manifest ?? ''));
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
continuationToken = response.nextToken;
|
|
506
|
-
if (!continuationToken)
|
|
507
|
-
break; // No more images to fetch
|
|
508
|
-
}
|
|
509
|
-
if (batch.length > 0) {
|
|
510
|
-
yield batch;
|
|
511
|
-
}
|
|
512
|
-
} while (continuationToken);
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* Generator function that reads objects from the S3 Bucket in batches.
|
|
516
|
-
*/
|
|
517
|
-
async *readBucketInBatches(s3, bucket, batchSize = 1000, currentTime) {
|
|
518
|
-
let continuationToken;
|
|
519
|
-
do {
|
|
520
|
-
const batch = [];
|
|
521
|
-
while (batch.length < batchSize) {
|
|
522
|
-
const response = await s3.listObjectsV2({
|
|
523
|
-
Bucket: bucket,
|
|
524
|
-
ContinuationToken: continuationToken,
|
|
525
|
-
});
|
|
526
|
-
response.Contents?.forEach((obj) => {
|
|
527
|
-
const key = obj.Key ?? '';
|
|
528
|
-
const size = obj.Size ?? 0;
|
|
529
|
-
const lastModified = obj.LastModified ?? new Date(currentTime);
|
|
530
|
-
// Store the object if it has a Key and
|
|
531
|
-
// if it has not been modified since today - createdBufferDays
|
|
532
|
-
if (key && lastModified < new Date(currentTime - (this.props.createdBufferDays * DAY))) {
|
|
533
|
-
batch.push(new ObjectAsset(bucket, key, size));
|
|
534
|
-
}
|
|
535
|
-
});
|
|
536
|
-
continuationToken = response.NextContinuationToken;
|
|
537
|
-
if (!continuationToken)
|
|
538
|
-
break; // No more objects to fetch
|
|
539
|
-
}
|
|
540
|
-
if (batch.length > 0) {
|
|
541
|
-
yield batch;
|
|
542
|
-
}
|
|
543
|
-
} while (continuationToken);
|
|
544
|
-
}
|
|
545
|
-
async confirmationPrompt(printer, deletables, type) {
|
|
546
|
-
const pluralize = (name, count) => {
|
|
547
|
-
return count === 1 ? name : `${name}s`;
|
|
548
|
-
};
|
|
549
|
-
if (this.confirm) {
|
|
550
|
-
const message = [
|
|
551
|
-
`Found ${deletables.length} ${pluralize(type, deletables.length)} to delete based off of the following criteria:`,
|
|
552
|
-
`- ${type}s have been isolated for > ${this.props.rollbackBufferDays} days`,
|
|
553
|
-
`- ${type}s were created > ${this.props.createdBufferDays} days ago`,
|
|
554
|
-
'',
|
|
555
|
-
'Delete this batch (yes/no/delete-all)?',
|
|
556
|
-
].join('\n');
|
|
557
|
-
printer.pause();
|
|
558
|
-
const response = await promptly.prompt(message, { trim: true });
|
|
559
|
-
// Anything other than yes/y/delete-all is treated as no
|
|
560
|
-
if (!response || !['yes', 'y', 'delete-all'].includes(response.toLowerCase())) {
|
|
561
|
-
throw new api_1.ToolkitError('Deletion aborted by user');
|
|
562
|
-
}
|
|
563
|
-
else if (response.toLowerCase() == 'delete-all') {
|
|
564
|
-
this.confirm = false;
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
printer.resume();
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
exports.GarbageCollector = GarbageCollector;
|
|
571
|
-
function partition(xs, pred) {
|
|
572
|
-
const result = {
|
|
573
|
-
included: [],
|
|
574
|
-
excluded: [],
|
|
575
|
-
};
|
|
576
|
-
for (const x of xs) {
|
|
577
|
-
if (pred(x)) {
|
|
578
|
-
result.included.push(x);
|
|
579
|
-
}
|
|
580
|
-
else {
|
|
581
|
-
result.excluded.push(x);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
return result;
|
|
585
|
-
}
|
|
586
|
-
function imageMap(imageIds) {
|
|
587
|
-
const images = {};
|
|
588
|
-
for (const image of imageIds ?? []) {
|
|
589
|
-
if (!image.imageDigest || !image.imageTag) {
|
|
590
|
-
continue;
|
|
591
|
-
}
|
|
592
|
-
if (!images[image.imageDigest]) {
|
|
593
|
-
images[image.imageDigest] = [];
|
|
594
|
-
}
|
|
595
|
-
images[image.imageDigest].push(image.imageTag);
|
|
596
|
-
}
|
|
597
|
-
return images;
|
|
598
|
-
}
|
|
599
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FyYmFnZS1jb2xsZWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJnYXJiYWdlLWNvbGxlY3Rvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFHQSwrQkFBK0I7QUFDL0IscUNBQXFDO0FBRXJDLGtEQUEwRTtBQUMxRSx5REFBcUQ7QUFDckQsbURBQTBGO0FBQzFGLDBFQUFnRjtBQUNoRix5RkFBZ0c7QUFDaEcseUNBQXNDO0FBRXRDLG1EQUFtRDtBQUNuRCw0R0FBNEc7QUFDNUcsTUFBTSxNQUFNLEdBQTZCLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUUvQyxRQUFBLGVBQWUsR0FBRyxrQkFBa0IsQ0FBQztBQUNyQyxRQUFBLGdCQUFnQixHQUFHLGtCQUFrQixDQUFDLENBQUMsK0JBQStCO0FBQ25GLE1BQU0sT0FBTyxHQUFHLEVBQUUsQ0FBQztBQUNuQixNQUFNLEdBQUcsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxrQ0FBa0M7QUFJbkU7O0dBRUc7QUFDSCxNQUFhLFVBQVU7SUFDckIsWUFDa0IsTUFBYyxFQUNkLElBQVksRUFDWixJQUFjLEVBQ2QsUUFBZ0I7UUFIaEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFNBQUksR0FBSixJQUFJLENBQVE7UUFDWixTQUFJLEdBQUosSUFBSSxDQUFVO1FBQ2QsYUFBUSxHQUFSLFFBQVEsQ0FBUTtJQUVsQyxDQUFDO0lBRU8sTUFBTSxDQUFDLEdBQVc7UUFDeEIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRU8sTUFBTSxDQUFDLEdBQVc7UUFDeEIsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMs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QUUsQ0FBQztRQUNuQixJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ1osTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUIsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxQixDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCxTQUFTLFFBQVEsQ0FBQyxRQUEyQjtJQUMzQyxNQUFNLE1BQU0sR0FBNkIsRUFBRSxDQUFDO0lBQzVDLEtBQUssTUFBTSxLQUFLLElBQUksUUFBUSxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQ25DLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzFDLFNBQVM7UUFDWCxDQUFDO1FBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztZQUMvQixNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNqQyxDQUFDO1FBQ0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHR5cGUgeyBJbWFnZUlkZW50aWZpZXIgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtZWNyJztcbmltcG9ydCB0eXBlIHsgVGFnIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXMzJztcbmltcG9ydCAqIGFzIGNoYWxrIGZyb20gJ2NoYWxrJztcbmltcG9ydCAqIGFzIHByb21wdGx5IGZyb20gJ3Byb21wdGx5JztcbmltcG9ydCB0eXBlIHsgSUVDUkNsaWVudCwgSVMzQ2xpZW50LCBTREssIFNka1Byb3ZpZGVyIH0gZnJvbSAnLi4vYXdzLWF1dGgnO1xuaW1wb3J0IHsgREVGQVVMVF9UT09MS0lUX1NUQUNLX05BTUUsIFRvb2xraXRJbmZvIH0gZnJvbSAnLi4vdG9vbGtpdC1pbmZvJztcbmltcG9ydCB7IFByb2dyZXNzUHJpbnRlciB9IGZyb20gJy4vcHJvZ3Jlc3MtcHJpbnRlcic7XG5pbXBvcnQgeyBBY3RpdmVBc3NldENhY2hlLCBCYWNrZ3JvdW5kU3RhY2tSZWZyZXNoLCByZWZyZXNoU3RhY2tzIH0gZnJvbSAnLi9zdGFjay1yZWZyZXNoJztcbmltcG9ydCB7IFRvb2xraXRFcnJvciB9IGZyb20gJy4uLy4uLy4uLy4uL0Bhd3MtY2RrL3RtcC10b29sa2l0LWhlbHBlcnMvc3JjL2FwaSc7XG5pbXBvcnQgeyBJTywgdHlwZSBJb0hlbHBlciB9IGZyb20gJy4uLy4uLy4uLy4uL0Bhd3MtY2RrL3RtcC10b29sa2l0LWhlbHBlcnMvc3JjL2FwaS9pby9wcml2YXRlJztcbmltcG9ydCB7IE1vZGUgfSBmcm9tICcuLi9wbHVnaW4vbW9kZSc7XG5cbi8vIE11c3QgdXNlIGEgcmVxdWlyZSgpIG90aGVyd2lzZSBlc2J1aWxkIGNvbXBsYWluc1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMsQHR5cGVzY3JpcHQtZXNsaW50L2NvbnNpc3RlbnQtdHlwZS1pbXBvcnRzXG5jb25zdCBwTGltaXQ6IHR5cGVvZiBpbXBvcnQoJ3AtbGltaXQnKSA9IHJlcXVpcmUoJ3AtbGltaXQnKTtcblxuZXhwb3J0IGNvbnN0IFMzX0lTT0xBVEVEX1RBRyA9ICdhd3MtY2RrOmlzb2xhdGVkJztcbmV4cG9ydCBjb25zdCBFQ1JfSVNPTEFURURfVEFHID0gJ2F3cy1jZGsuaXNvbGF0ZWQnOyAvLyAnOicgaXMgbm90IHZhbGlkIGluIEVDUiB0YWdzXG5jb25zdCBQX0xJTUlUID0gNTA7XG5jb25zdCBEQVkgPSAyNCAqIDYwICogNjAgKiAxMDAwOyAvLyBOdW1iZXIgb2YgbWlsbGlzZWNvbmRzIGluIGEgZGF5XG5cbmV4cG9ydCB0eXBlIEdjQXNzZXQgPSBJbWFnZUFzc2V0IHwgT2JqZWN0QXNzZXQ7XG5cbi8qKlxuICogQW4gaW1hZ2UgYXNzZXQgdGhhdCBsaXZlcyBpbiB0aGUgYm9vdHN0cmFwcGVkIEVDUiBSZXBvc2l0b3J5XG4gKi9cbmV4cG9ydCBjbGFzcyBJbWFnZUFzc2V0IHtcbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSBkaWdlc3Q6IHN0cmluZyxcbiAgICBwdWJsaWMgcmVhZG9ubHkgc2l6ZTogbnVtYmVyLFxuICAgIHB1YmxpYyByZWFkb25seSB0YWdzOiBzdHJpbmdbXSxcbiAgICBwdWJsaWMgcmVhZG9ubHkgbWFuaWZlc3Q6IHN0cmluZyxcbiAgKSB7XG4gIH1cblxuICBwcml2YXRlIGdldFRhZyh0YWc6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLnRhZ3MuZmluZCh0ID0+IHQuaW5jbHVkZXModGFnKSk7XG4gIH1cblxuICBwcml2YXRlIGhhc1RhZyh0YWc6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLnRhZ3Muc29tZSh0ID0+IHQuaW5jbHVkZXModGFnKSk7XG4gIH1cblxuICBwdWJsaWMgaGFzSXNvbGF0ZWRUYWcoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzVGFnKEVDUl9JU09MQVRFRF9UQUcpO1xuICB9XG5cbiAgcHVibGljIGdldElzb2xhdGVkVGFnKCkge1xuICAgIHJldHVybiB0aGlzLmdldFRhZyhFQ1JfSVNPTEFURURfVEFHKTtcbiAgfVxuXG4gIHB1YmxpYyBpc29sYXRlZFRhZ0JlZm9yZShkYXRlOiBEYXRlKSB7XG4gICAgY29uc3QgZGF0ZUlzb2xhdGVkID0gdGhpcy5kYXRlSXNvbGF0ZWQoKTtcbiAgICBpZiAoIWRhdGVJc29sYXRlZCB8fCBkYXRlSXNvbGF0ZWQgPT0gJycpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBEYXRlKGRhdGVJc29sYXRlZCkgPCBkYXRlO1xuICB9XG5cbiAgcHVibGljIGJ1aWxkSW1hZ2VUYWcoaW5jOiBudW1iZXIpIHtcbiAgICAvLyBpc29sYXRlZFRhZyB3aWxsIGxvb2sgbGlrZSBcIlgtYXdzLWNkay5pc29sYXRlZC1ZWVlZWVwiXG4gICAgcmV0dXJuIGAke2luY30tJHtFQ1JfSVNPTEFURURfVEFHfS0ke1N0cmluZyhEYXRlLm5vdygpKX1gO1xuICB9XG5cbiAgcHVibGljIGRhdGVJc29sYXRlZCgpIHtcbiAgICAvLyBpc29sYXRlZFRhZyB3aWxsIGxvb2sgbGlrZSBcIlgtYXdzLWNkay5pc29sYXRlZC1ZWVlZWVwiXG4gICAgcmV0dXJuIHRoaXMuZ2V0SXNvbGF0ZWRUYWcoKT8uc3BsaXQoJy0nKVszXTtcbiAgfVxufVxuXG4vKipcbiAqIEFuIG9iamVjdCBhc3NldCB0aGF0IGxpdmVzIGluIHRoZSBib290c3RyYXBwZWQgUzMgQnVja2V0XG4gKi9cbmV4cG9ydCBjbGFzcyBPYmplY3RBc3NldCB7XG4gIHByaXZhdGUgY2FjaGVkX3RhZ3M6IFRhZ1tdIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGJ1Y2tldDogc3RyaW5nLCBwdWJsaWMgcmVhZG9ubHkga2V5OiBzdHJpbmcsIHB1YmxpYyByZWFkb25seSBzaXplOiBudW1iZXIpIHtcbiAgfVxuXG4gIHB1YmxpYyBmaWxlTmFtZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmtleS5zcGxpdCgnLicpWzBdO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGFsbFRhZ3MoczM6IElTM0NsaWVudCkge1xuICAgIGlmICh0aGlzLmNhY2hlZF90YWdzKSB7XG4gICAgICByZXR1cm4gdGhpcy5jYWNoZWRfdGFncztcbiAgICB9XG5cbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHMzLmdldE9iamVjdFRhZ2dpbmcoeyBCdWNrZXQ6IHRoaXMuYnVja2V0LCBLZXk6IHRoaXMua2V5IH0pO1xuICAgIHRoaXMuY2FjaGVkX3RhZ3MgPSByZXNwb25zZS5UYWdTZXQ7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVkX3RhZ3M7XG4gIH1cblxuICBwcml2YXRlIGdldFRhZyh0YWc6IHN0cmluZykge1xuICAgIGlmICghdGhpcy5jYWNoZWRfdGFncykge1xuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignQ2Fubm90IGNhbGwgZ2V0VGFnIGJlZm9yZSBhbGxUYWdzJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmNhY2hlZF90YWdzLmZpbmQoKHQ6IGFueSkgPT4gdC5LZXkgPT09IHRhZyk/LlZhbHVlO1xuICB9XG5cbiAgcHJpdmF0ZSBoYXNUYWcodGFnOiBzdHJpbmcpIHtcbiAgICBpZiAoIXRoaXMuY2FjaGVkX3RhZ3MpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ0Nhbm5vdCBjYWxsIGhhc1RhZyBiZWZvcmUgYWxsVGFncycpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jYWNoZWRfdGFncy5zb21lKCh0OiBhbnkpID0+IHQuS2V5ID09PSB0YWcpO1xuICB9XG5cbiAgcHVibGljIGhhc0lzb2xhdGVkVGFnKCkge1xuICAgIHJldHVybiB0aGlzLmhhc1RhZyhTM19JU09MQVRFRF9UQUcpO1xuICB9XG5cbiAgcHVibGljIGlzb2xhdGVkVGFnQmVmb3JlKGRhdGU6IERhdGUpIHtcbiAgICBjb25zdCB0YWdWYWx1ZSA9IHRoaXMuZ2V0VGFnKFMzX0lTT0xBVEVEX1RBRyk7XG4gICAgaWYgKCF0YWdWYWx1ZSB8fCB0YWdWYWx1ZSA9PSAnJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IERhdGUodGFnVmFsdWUpIDwgZGF0ZTtcbiAgfVxufVxuXG4vKipcbiAqIFByb3BzIGZvciB0aGUgR2FyYmFnZSBDb2xsZWN0b3JcbiAqL1xuaW50ZXJmYWNlIEdhcmJhZ2VDb2xsZWN0b3JQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgYWN0aW9uIHRvIHBlcmZvcm0uIFNwZWNpZnkgdGhpcyBpZiB5b3Ugd2FudCB0byBwZXJmb3JtIGEgdHJ1bmNhdGVkIHNldFxuICAgKiBvZiBhY3Rpb25zIGF2YWlsYWJsZS5cbiAgICovXG4gIHJlYWRvbmx5IGFjdGlvbjogJ3ByaW50JyB8ICd0YWcnIHwgJ2RlbGV0ZS10YWdnZWQnIHwgJ2Z1bGwnO1xuXG4gIC8qKlxuICAgKiBUaGUgdHlwZSBvZiBhc3NldCB0byBnYXJiYWdlIGNvbGxlY3QuXG4gICAqL1xuICByZWFkb25seSB0eXBlOiAnczMnIHwgJ2VjcicgfCAnYWxsJztcblxuICAvKipcbiAgICogVGhlIGRheXMgYW4gYXNzZXQgbXVzdCBiZSBpbiBpc29sYXRpb24gYmVmb3JlIGJlaW5nIGFjdHVhbGx5IGRlbGV0ZWQuXG4gICAqL1xuICByZWFkb25seSByb2xsYmFja0J1ZmZlckRheXM6IG51bWJlcjtcblxuICAvKipcbiAgICogUmVmdXNlIGRlbGV0aW9uIG9mIGFueSBhc3NldHMgeW91bmdlciB0aGFuIHRoaXMgbnVtYmVyIG9mIGRheXMuXG4gICAqL1xuICByZWFkb25seSBjcmVhdGVkQnVmZmVyRGF5czogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgZW52aXJvbm1lbnQgdG8gZGVwbG95IHRoaXMgc3RhY2sgaW5cbiAgICpcbiAgICogVGhlIGVudmlyb25tZW50IG9uIHRoZSBzdGFjayBhcnRpZmFjdCBtYXkgYmUgdW5yZXNvbHZlZCwgdGhpcyBvbmVcbiAgICogbXVzdCBiZSByZXNvbHZlZC5cbiAgICovXG4gIHJlYWRvbmx5IHJlc29sdmVkRW52aXJvbm1lbnQ6IGN4YXBpLkVudmlyb25tZW50O1xuXG4gIC8qKlxuICAgKiBTREsgcHJvdmlkZXIgKHNlZWRlZCB3aXRoIGRlZmF1bHQgY3JlZGVudGlhbHMpXG4gICAqXG4gICAqIFdpbGwgYmUgdXNlZCB0byBtYWtlIFNESyBjYWxscyB0byBDbG91ZEZvcm1hdGlvbiwgUzMsIGFuZCBFQ1IuXG4gICAqL1xuICByZWFkb25seSBzZGtQcm92aWRlcjogU2RrUHJvdmlkZXI7XG5cbiAgLyoqXG4gICAqIFVzZWQgdG8gc2VuZCBtZXNzYWdlcy5cbiAgICovXG4gIHJlYWRvbmx5IGlvSGVscGVyOiBJb0hlbHBlcjtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGJvb3RzdHJhcCBzdGFjayB0byBsb29rIGZvci5cbiAgICpcbiAgICogQGRlZmF1bHQgREVGQVVMVF9UT09MS0lUX1NUQUNLX05BTUVcbiAgICovXG4gIHJlYWRvbmx5IGJvb3RzdHJhcFN0YWNrTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogQ29uZmlybSB3aXRoIHRoZSB1c2VyIGJlZm9yZSBhY3R1YWwgZGVsZXRpb24gaGFwcGVuc1xuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBjb25maXJtPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBIGNsYXNzIHRvIGZhY2lsaXRhdGUgR2FyYmFnZSBDb2xsZWN0aW9uIG9mIFMzIGFuZCBFQ1IgYXNzZXRzXG4gKi9cbmV4cG9ydCBjbGFzcyBHYXJiYWdlQ29sbGVjdG9yIHtcbiAgcHJpdmF0ZSBnYXJiYWdlQ29sbGVjdFMzQXNzZXRzOiBib29sZWFuO1xuICBwcml2YXRlIGdhcmJhZ2VDb2xsZWN0RWNyQXNzZXRzOiBib29sZWFuO1xuICBwcml2YXRlIHBlcm1pc3Npb25Ub0RlbGV0ZTogYm9vbGVhbjtcbiAgcHJpdmF0ZSBwZXJtaXNzaW9uVG9UYWc6IGJvb2xlYW47XG4gIHByaXZhdGUgYm9vdHN0cmFwU3RhY2tOYW1lOiBzdHJpbmc7XG4gIHByaXZhdGUgY29uZmlybTogYm9vbGVhbjtcbiAgcHJpdmF0ZSBpb0hlbHBlcjogSW9IZWxwZXI7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHJlYWRvbmx5IHByb3BzOiBHYXJiYWdlQ29sbGVjdG9yUHJvcHMpIHtcbiAgICB0aGlzLmlvSGVscGVyID0gcHJvcHMuaW9IZWxwZXI7XG5cbiAgICB0aGlzLmdhcmJhZ2VDb2xsZWN0UzNBc3NldHMgPSBbJ3MzJywgJ2FsbCddLmluY2x1ZGVzKHByb3BzLnR5cGUpO1xuICAgIHRoaXMuZ2FyYmFnZUNvbGxlY3RFY3JBc3NldHMgPSBbJ2VjcicsICdhbGwnXS5pbmNsdWRlcyhwcm9wcy50eXBlKTtcblxuICAgIHRoaXMucGVybWlzc2lvblRvRGVsZXRlID0gWydkZWxldGUtdGFnZ2VkJywgJ2Z1bGwnXS5pbmNsdWRlcyhwcm9wcy5hY3Rpb24pO1xuICAgIHRoaXMucGVybWlzc2lvblRvVGFnID0gWyd0YWcnLCAnZnVsbCddLmluY2x1ZGVzKHByb3BzLmFjdGlvbik7XG4gICAgdGhpcy5jb25maXJtID0gcHJvcHMuY29uZmlybSA/PyB0cnVlO1xuXG4gICAgdGhpcy5ib290c3RyYXBTdGFja05hbWUgPSBwcm9wcy5ib290c3RyYXBTdGFja05hbWUgPz8gREVGQVVMVF9UT09MS0lUX1NUQUNLX05BTUU7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSBnYXJiYWdlIGNvbGxlY3Rpb24gb24gdGhlIHJlc29sdmVkIGVudmlyb25tZW50LlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGdhcmJhZ2VDb2xsZWN0KCkge1xuICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coYCR7dGhpcy5nYXJiYWdlQ29sbGVjdFMzQXNzZXRzfSAke3RoaXMuZ2FyYmFnZUNvbGxlY3RFY3JBc3NldHN9YCkpO1xuXG4gICAgLy8gU0RLc1xuICAgIGNvbnN0IHNkayA9IChhd2FpdCB0aGlzLnByb3BzLnNka1Byb3ZpZGVyLmZvckVudmlyb25tZW50KHRoaXMucHJvcHMucmVzb2x2ZWRFbnZpcm9ubWVudCwgTW9kZS5Gb3JXcml0aW5nKSkuc2RrO1xuICAgIGNvbnN0IGNmbiA9IHNkay5jbG91ZEZvcm1hdGlvbigpO1xuXG4gICAgY29uc3QgcXVhbGlmaWVyID0gYXdhaXQgdGhpcy5ib290c3RyYXBRdWFsaWZpZXIoc2RrLCB0aGlzLmJvb3RzdHJhcFN0YWNrTmFtZSk7XG4gICAgY29uc3QgYWN0aXZlQXNzZXRzID0gbmV3IEFjdGl2ZUFzc2V0Q2FjaGUoKTtcblxuICAgIC8vIEdyYWIgc3RhY2sgdGVtcGxhdGVzIGZpcnN0XG4gICAgYXdhaXQgcmVmcmVzaFN0YWNrcyhjZm4sIHRoaXMuaW9IZWxwZXIsIGFjdGl2ZUFzc2V0cywgcXVhbGlmaWVyKTtcbiAgICAvLyBTdGFydCB0aGUgYmFja2dyb3VuZCByZWZyZXNoXG4gICAgY29uc3QgYmFja2dyb3VuZFN0YWNrUmVmcmVzaCA9IG5ldyBCYWNrZ3JvdW5kU3RhY2tSZWZyZXNoKHtcbiAgICAgIGNmbixcbiAgICAgIGlvSGVscGVyOiB0aGlzLmlvSGVscGVyLFxuICAgICAgYWN0aXZlQXNzZXRzLFxuICAgICAgcXVhbGlmaWVyLFxuICAgIH0pO1xuICAgIGJhY2tncm91bmRTdGFja1JlZnJlc2guc3RhcnQoKTtcblxuICAgIHRyeSB7XG4gICAgICBpZiAodGhpcy5nYXJiYWdlQ29sbGVjdFMzQXNzZXRzKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZ2FyYmFnZUNvbGxlY3RTMyhzZGssIGFjdGl2ZUFzc2V0cywgYmFja2dyb3VuZFN0YWNrUmVmcmVzaCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLmdhcmJhZ2VDb2xsZWN0RWNyQXNzZXRzKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZ2FyYmFnZUNvbGxlY3RFY3Ioc2RrLCBhY3RpdmVBc3NldHMsIGJhY2tncm91bmRTdGFja1JlZnJlc2gpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKGVycik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGJhY2tncm91bmRTdGFja1JlZnJlc2guc3RvcCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGdhcmJhZ2UgY29sbGVjdGlvbiBvbiBFQ1IgYXNzZXRzXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2FyYmFnZUNvbGxlY3RFY3Ioc2RrOiBTREssIGFjdGl2ZUFzc2V0czogQWN0aXZlQXNzZXRDYWNoZSwgYmFja2dyb3VuZFN0YWNrUmVmcmVzaDogQmFja2dyb3VuZFN0YWNrUmVmcmVzaCkge1xuICAgIGNvbnN0IGVjciA9IHNkay5lY3IoKTtcbiAgICBjb25zdCByZXBvID0gYXdhaXQgdGhpcy5ib290c3RyYXBSZXBvc2l0b3J5TmFtZShzZGssIHRoaXMuYm9vdHN0cmFwU3RhY2tOYW1lKTtcbiAgICBjb25zdCBudW1JbWFnZXMgPSBhd2FpdCB0aGlzLm51bUltYWdlc0luUmVwbyhlY3IsIHJlcG8pO1xuICAgIGNvbnN0IHByaW50ZXIgPSBuZXcgUHJvZ3Jlc3NQcmludGVyKHRoaXMuaW9IZWxwZXIsIG51bUltYWdlcywgMTAwMCk7XG5cbiAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1RPT0xLSVRfREVCVUcubXNnKGBGb3VuZCBib290c3RyYXAgcmVwbyAke3JlcG99IHdpdGggJHtudW1JbWFnZXN9IGltYWdlc2ApKTtcblxuICAgIHRyeSB7XG4gICAgICAvLyBjb25zdCBiYXRjaGVzID0gMTtcbiAgICAgIGNvbnN0IGJhdGNoU2l6ZSA9IDEwMDA7XG4gICAgICBjb25zdCBjdXJyZW50VGltZSA9IERhdGUubm93KCk7XG4gICAgICBjb25zdCBncmFjZURheXMgPSB0aGlzLnByb3BzLnJvbGxiYWNrQnVmZmVyRGF5cztcblxuICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgUGFyc2luZyB0aHJvdWdoICR7bnVtSW1hZ2VzfSBpbWFnZXMgaW4gYmF0Y2hlc2ApKTtcblxuICAgICAgcHJpbnRlci5zdGFydCgpO1xuXG4gICAgICBmb3IgYXdhaXQgKGNvbnN0IGJhdGNoIG9mIHRoaXMucmVhZFJlcG9JbkJhdGNoZXMoZWNyLCByZXBvLCBiYXRjaFNpemUsIGN1cnJlbnRUaW1lKSkge1xuICAgICAgICBhd2FpdCBiYWNrZ3JvdW5kU3RhY2tSZWZyZXNoLm5vT2xkZXJUaGFuKDYwMF8wMDApOyAvLyAxMCBtaW5zXG5cbiAgICAgICAgY29uc3QgeyBpbmNsdWRlZDogaXNvbGF0ZWQsIGV4Y2x1ZGVkOiBub3RJc29sYXRlZCB9ID0gcGFydGl0aW9uKGJhdGNoLCBhc3NldCA9PiAhYXNzZXQudGFncy5zb21lKHQgPT4gYWN0aXZlQXNzZXRzLmNvbnRhaW5zKHQpKSk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgJHtpc29sYXRlZC5sZW5ndGh9IGlzb2xhdGVkIGltYWdlc2ApKTtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgJHtub3RJc29sYXRlZC5sZW5ndGh9IG5vdCBpc29sYXRlZCBpbWFnZXNgKSk7XG4gICAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coYCR7YmF0Y2gubGVuZ3RofSBpbWFnZXMgdG90YWxgKSk7XG5cbiAgICAgICAgbGV0IGRlbGV0YWJsZXM6IEltYWdlQXNzZXRbXSA9IGlzb2xhdGVkO1xuICAgICAgICBsZXQgdGFnZ2FibGVzOiBJbWFnZUFzc2V0W10gPSBbXTtcbiAgICAgICAgbGV0IHVudGFnZ2FibGVzOiBJbWFnZUFzc2V0W10gPSBbXTtcblxuICAgICAgICBpZiAoZ3JhY2VEYXlzID4gMCkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coJ0ZpbHRlcmluZyBvdXQgaW1hZ2VzIHRoYXQgYXJlIG5vdCBvbGQgZW5vdWdoIHRvIGRlbGV0ZScpKTtcblxuICAgICAgICAgIC8vIFdlIGRlbGV0ZSBpbWFnZXMgdGhhdCBhcmUgbm90IHJlZmVyZW5jZWQgaW4gQWN0aXZlQXNzZXRzIGFuZCBoYXZlIHRoZSBJc29sYXRlZCBUYWcgd2l0aCBhIGRhdGVcbiAgICAgICAgICAvLyBlYXJsaWVyIHRoYW4gdGhlIGN1cnJlbnQgdGltZSAtIGdyYWNlIHBlcmlvZC5cbiAgICAgICAgICBkZWxldGFibGVzID0gaXNvbGF0ZWQuZmlsdGVyKGltZyA9PiBpbWcuaXNvbGF0ZWRUYWdCZWZvcmUobmV3IERhdGUoY3VycmVudFRpbWUgLSAoZ3JhY2VEYXlzICogREFZKSkpKTtcblxuICAgICAgICAgIC8vIFdlIHRhZyBpbWFnZXMgdGhhdCBhcmUgbm90IHJlZmVyZW5jZWQgaW4gQWN0aXZlQXNzZXRzIGFuZCBkbyBub3QgaGF2ZSB0aGUgSXNvbGF0ZWQgVGFnLlxuICAgICAgICAgIHRhZ2dhYmxlcyA9IGlzb2xhdGVkLmZpbHRlcihpbWcgPT4gIWltZy5oYXNJc29sYXRlZFRhZygpKTtcblxuICAgICAgICAgIC8vIFdlIHVudGFnIGltYWdlcyB0aGF0IGFyZSByZWZlcmVuY2VkIGluIEFjdGl2ZUFzc2V0cyBhbmQgY3VycmVudGx5IGhhdmUgdGhlIElzb2xhdGVkIFRhZy5cbiAgICAgICAgICB1bnRhZ2dhYmxlcyA9IG5vdElzb2xhdGVkLmZpbHRlcihpbWcgPT4gaW1nLmhhc0lzb2xhdGVkVGFnKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgJHtkZWxldGFibGVzLmxlbmd0aH0gZGVsZXRhYmxlIGFzc2V0c2ApKTtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgJHt0YWdnYWJsZXMubGVuZ3RofSB0YWdnYWJsZSBhc3NldHNgKSk7XG4gICAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coYCR7dW50YWdnYWJsZXMubGVuZ3RofSBhc3NldHMgdG8gdW50YWdgKSk7XG5cbiAgICAgICAgaWYgKHRoaXMucGVybWlzc2lvblRvRGVsZXRlICYmIGRlbGV0YWJsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuY29uZmlybWF0aW9uUHJvbXB0KHByaW50ZXIsIGRlbGV0YWJsZXMsICdpbWFnZScpO1xuICAgICAgICAgIGF3YWl0IHRoaXMucGFyYWxsZWxEZWxldGVFY3IoZWNyLCByZXBvLCBkZWxldGFibGVzLCBwcmludGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnBlcm1pc3Npb25Ub1RhZyAmJiB0YWdnYWJsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGF3YWl0IHRoaXMucGFyYWxsZWxUYWdFY3IoZWNyLCByZXBvLCB0YWdnYWJsZXMsIHByaW50ZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMucGVybWlzc2lvblRvVGFnICYmIHVudGFnZ2FibGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnBhcmFsbGVsVW50YWdFY3IoZWNyLCByZXBvLCB1bnRhZ2dhYmxlcyk7XG4gICAgICAgIH1cblxuICAgICAgICBwcmludGVyLnJlcG9ydFNjYW5uZWRBc3NldChiYXRjaC5sZW5ndGgpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKGVycik7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHByaW50ZXIuc3RvcCgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGdhcmJhZ2UgY29sbGVjdGlvbiBvbiBTMyBhc3NldHNcbiAgICovXG4gIHB1YmxpYyBhc3luYyBnYXJiYWdlQ29sbGVjdFMzKHNkazogU0RLLCBhY3RpdmVBc3NldHM6IEFjdGl2ZUFzc2V0Q2FjaGUsIGJhY2tncm91bmRTdGFja1JlZnJlc2g6IEJhY2tncm91bmRTdGFja1JlZnJlc2gpIHtcbiAgICBjb25zdCBzMyA9IHNkay5zMygpO1xuICAgIGNvbnN0IGJ1Y2tldCA9IGF3YWl0IHRoaXMuYm9vdHN0cmFwQnVja2V0TmFtZShzZGssIHRoaXMuYm9vdHN0cmFwU3RhY2tOYW1lKTtcbiAgICBjb25zdCBudW1PYmplY3RzID0gYXdhaXQgdGhpcy5udW1PYmplY3RzSW5CdWNrZXQoczMsIGJ1Y2tldCk7XG4gICAgY29uc3QgcHJpbnRlciA9IG5ldyBQcm9ncmVzc1ByaW50ZXIodGhpcy5pb0hlbHBlciwgbnVtT2JqZWN0cywgMTAwMCk7XG5cbiAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1RPT0xLSVRfREVCVUcubXNnKGBGb3VuZCBib290c3RyYXAgYnVja2V0ICR7YnVja2V0fSB3aXRoICR7bnVtT2JqZWN0c30gb2JqZWN0c2ApKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBiYXRjaFNpemUgPSAxMDAwO1xuICAgICAgY29uc3QgY3VycmVudFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgY29uc3QgZ3JhY2VEYXlzID0gdGhpcy5wcm9wcy5yb2xsYmFja0J1ZmZlckRheXM7XG5cbiAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coYFBhcnNpbmcgdGhyb3VnaCAke251bU9iamVjdHN9IG9iamVjdHMgaW4gYmF0Y2hlc2ApKTtcblxuICAgICAgcHJpbnRlci5zdGFydCgpO1xuXG4gICAgICAvLyBQcm9jZXNzIG9iamVjdHMgaW4gYmF0Y2hlcyBvZiAxMDAwXG4gICAgICAvLyBUaGlzIGlzIHRoZSBiYXRjaCBsaW1pdCBvZiBzMy5EZWxldGVPYmplY3QgYW5kIHdlIGludGVuZCB0byBvcHRpbWl6ZSBmb3IgdGhlIFwid29yc3QgY2FzZVwiIHNjZW5hcmlvXG4gICAgICAvLyB3aGVyZSBnYyBpcyBydW4gZm9yIHRoZSBmaXJzdCB0aW1lIG9uIGEgbG9uZy1zdGFuZGluZyBidWNrZXQgd2hlcmUgfjEwMCUgb2Ygb2JqZWN0cyBhcmUgaXNvbGF0ZWQuXG4gICAgICBmb3IgYXdhaXQgKGNvbnN0IGJhdGNoIG9mIHRoaXMucmVhZEJ1Y2tldEluQmF0Y2hlcyhzMywgYnVja2V0LCBiYXRjaFNpemUsIGN1cnJlbnRUaW1lKSkge1xuICAgICAgICBhd2FpdCBiYWNrZ3JvdW5kU3RhY2tSZWZyZXNoLm5vT2xkZXJUaGFuKDYwMF8wMDApOyAvLyAxMCBtaW5zXG5cbiAgICAgICAgY29uc3QgeyBpbmNsdWRlZDogaXNvbGF0ZWQsIGV4Y2x1ZGVkOiBub3RJc29sYXRlZCB9ID0gcGFydGl0aW9uKGJhdGNoLCBhc3NldCA9PiAhYWN0aXZlQXNzZXRzLmNvbnRhaW5zKGFzc2V0LmZpbGVOYW1lKCkpKTtcblxuICAgICAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1RPT0xLSVRfREVCVUcubXNnKGAke2lzb2xhdGVkLmxlbmd0aH0gaXNvbGF0ZWQgYXNzZXRzYCkpO1xuICAgICAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1RPT0xLSVRfREVCVUcubXNnKGAke25vdElzb2xhdGVkLmxlbmd0aH0gbm90IGlzb2xhdGVkIGFzc2V0c2ApKTtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgJHtiYXRjaC5sZW5ndGh9IG9iamVjdHMgdG90YWxgKSk7XG5cbiAgICAgICAgbGV0IGRlbGV0YWJsZXM6IE9iamVjdEFzc2V0W10gPSBpc29sYXRlZDtcbiAgICAgICAgbGV0IHRhZ2dhYmxlczogT2JqZWN0QXNzZXRbXSA9IFtdO1xuICAgICAgICBsZXQgdW50YWdnYWJsZXM6IE9iamVjdEFzc2V0W10gPSBbXTtcblxuICAgICAgICBpZiAoZ3JhY2VEYXlzID4gMCkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coJ0ZpbHRlcmluZyBvdXQgYXNzZXRzIHRoYXQgYXJlIG5vdCBvbGQgZW5vdWdoIHRvIGRlbGV0ZScpKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLnBhcmFsbGVsUmVhZEFsbFRhZ3MoczMsIGJhdGNoKTtcblxuICAgICAgICAgIC8vIFdlIGRlbGV0ZSBvYmplY3RzIHRoYXQgYXJlIG5vdCByZWZlcmVuY2VkIGluIEFjdGl2ZUFzc2V0cyBhbmQgaGF2ZSB0aGUgSXNvbGF0ZWQgVGFnIHdpdGggYSBkYXRlXG4gICAgICAgICAgLy8gZWFybGllciB0aGFuIHRoZSBjdXJyZW50IHRpbWUgLSBncmFjZSBwZXJpb2QuXG4gICAgICAgICAgZGVsZXRhYmxlcyA9IGlzb2xhdGVkLmZpbHRlcihvYmogPT4gb2JqLmlzb2xhdGVkVGFnQmVmb3JlKG5ldyBEYXRlKGN1cnJlbnRUaW1lIC0gKGdyYWNlRGF5cyAqIERBWSkpKSk7XG5cbiAgICAgICAgICAvLyBXZSB0YWcgb2JqZWN0cyB0aGF0IGFyZSBub3QgcmVmZXJlbmNlZCBpbiBBY3RpdmVBc3NldHMgYW5kIGRvIG5vdCBoYXZlIHRoZSBJc29sYXRlZCBUYWcuXG4gICAgICAgICAgdGFnZ2FibGVzID0gaXNvbGF0ZWQuZmlsdGVyKG9iaiA9PiAhb2JqLmhhc0lzb2xhdGVkVGFnKCkpO1xuXG4gICAgICAgICAgLy8gV2UgdW50YWcgb2JqZWN0cyB0aGF0IGFyZSByZWZlcmVuY2VkIGluIEFjdGl2ZUFzc2V0cyBhbmQgY3VycmVudGx5IGhhdmUgdGhlIElzb2xhdGVkIFRhZy5cbiAgICAgICAgICB1bnRhZ2dhYmxlcyA9IG5vdElzb2xhdGVkLmZpbHRlcihvYmogPT4gb2JqLmhhc0lzb2xhdGVkVGFnKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgJHtkZWxldGFibGVzLmxlbmd0aH0gZGVsZXRhYmxlIGFzc2V0c2ApKTtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgJHt0YWdnYWJsZXMubGVuZ3RofSB0YWdnYWJsZSBhc3NldHNgKSk7XG4gICAgICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coYCR7dW50YWdnYWJsZXMubGVuZ3RofSBhc3NldHMgdG8gdW50YWdgKSk7XG5cbiAgICAgICAgaWYgKHRoaXMucGVybWlzc2lvblRvRGVsZXRlICYmIGRlbGV0YWJsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuY29uZmlybWF0aW9uUHJvbXB0KHByaW50ZXIsIGRlbGV0YWJsZXMsICdvYmplY3QnKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLnBhcmFsbGVsRGVsZXRlUzMoczMsIGJ1Y2tldCwgZGVsZXRhYmxlcywgcHJpbnRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5wZXJtaXNzaW9uVG9UYWcgJiYgdGFnZ2FibGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLnBhcmFsbGVsVGFnUzMoczMsIGJ1Y2tldCwgdGFnZ2FibGVzLCBjdXJyZW50VGltZSwgcHJpbnRlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5wZXJtaXNzaW9uVG9UYWcgJiYgdW50YWdnYWJsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGF3YWl0IHRoaXMucGFyYWxsZWxVbnRhZ1MzKHMzLCBidWNrZXQsIHVudGFnZ2FibGVzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHByaW50ZXIucmVwb3J0U2Nhbm5lZEFzc2V0KGJhdGNoLmxlbmd0aCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoZXJyKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgcHJpbnRlci5zdG9wKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwYXJhbGxlbFJlYWRBbGxUYWdzKHMzOiBJUzNDbGllbnQsIG9iamVjdHM6IE9iamVjdEFzc2V0W10pIHtcbiAgICBjb25zdCBsaW1pdCA9IHBMaW1pdChQX0xJTUlUKTtcblxuICAgIGZvciAoY29uc3Qgb2JqIG9mIG9iamVjdHMpIHtcbiAgICAgIGF3YWl0IGxpbWl0KCgpID0+IG9iai5hbGxUYWdzKHMzKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFVudGFnIGFzc2V0cyB0aGF0IHdlcmUgcHJldmlvdXNseSB0YWdnZWQsIGJ1dCBub3cgY3VycmVudGx5IHJlZmVyZW5jZWQuXG4gICAqIFNpbmNlIHRoaXMgaXMgdHJlYXRlZCBhcyBhbiBpbXBsZW1lbnRhdGlvbiBkZXRhaWwsIHdlIGRvIG5vdCBwcmludCB0aGUgcmVzdWx0cyBpbiB0aGUgcHJpbnRlci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcGFyYWxsZWxVbnRhZ0VjcihlY3I6IElFQ1JDbGllbnQsIHJlcG86IHN0cmluZywgdW50YWdnYWJsZXM6IEltYWdlQXNzZXRbXSkge1xuICAgIGNvbnN0IGxpbWl0ID0gcExpbWl0KFBfTElNSVQpO1xuXG4gICAgZm9yIChjb25zdCBpbWcgb2YgdW50YWdnYWJsZXMpIHtcbiAgICAgIGNvbnN0IHRhZyA9IGltZy5nZXRJc29sYXRlZFRhZygpO1xuICAgICAgYXdhaXQgbGltaXQoKCkgPT5cbiAgICAgICAgZWNyLmJhdGNoRGVsZXRlSW1hZ2Uoe1xuICAgICAgICAgIHJlcG9zaXRvcnlOYW1lOiByZXBvLFxuICAgICAgICAgIGltYWdlSWRzOiBbe1xuICAgICAgICAgICAgaW1hZ2VUYWc6IHRhZyxcbiAgICAgICAgICB9XSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coYFVudGFnZ2VkICR7dW50YWdnYWJsZXMubGVuZ3RofSBhc3NldHNgKSk7XG4gIH1cblxuICAvKipcbiAgICogVW50YWcgYXNzZXRzIHRoYXQgd2VyZSBwcmV2aW91c2x5IHRhZ2dlZCwgYnV0IG5vdyBjdXJyZW50bHkgcmVmZXJlbmNlZC5cbiAgICogU2luY2UgdGhpcyBpcyB0cmVhdGVkIGFzIGFuIGltcGxlbWVudGF0aW9uIGRldGFpbCwgd2UgZG8gbm90IHByaW50IHRoZSByZXN1bHRzIGluIHRoZSBwcmludGVyLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwYXJhbGxlbFVudGFnUzMoczM6IElTM0NsaWVudCwgYnVja2V0OiBzdHJpbmcsIHVudGFnZ2FibGVzOiBPYmplY3RBc3NldFtdKSB7XG4gICAgY29uc3QgbGltaXQgPSBwTGltaXQoUF9MSU1JVCk7XG5cbiAgICBmb3IgKGNvbnN0IG9iaiBvZiB1bnRhZ2dhYmxlcykge1xuICAgICAgY29uc3QgdGFncyA9IGF3YWl0IG9iai5hbGxUYWdzKHMzKSA/PyBbXTtcbiAgICAgIGNvbnN0IHVwZGF0ZWRUYWdzID0gdGFncy5maWx0ZXIoKHRhZzogVGFnKSA9PiB0YWcuS2V5ICE9PSBTM19JU09MQVRFRF9UQUcpO1xuICAgICAgYXdhaXQgbGltaXQoKCkgPT5cbiAgICAgICAgczMuZGVsZXRlT2JqZWN0VGFnZ2luZyh7XG4gICAgICAgICAgQnVja2V0OiBidWNrZXQsXG4gICAgICAgICAgS2V5OiBvYmoua2V5LFxuXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICAgIGF3YWl0IGxpbWl0KCgpID0+XG4gICAgICAgIHMzLnB1dE9iamVjdFRhZ2dpbmcoe1xuICAgICAgICAgIEJ1Y2tldDogYnVja2V0LFxuICAgICAgICAgIEtleTogb2JqLmtleSxcbiAgICAgICAgICBUYWdnaW5nOiB7XG4gICAgICAgICAgICBUYWdTZXQ6IHVwZGF0ZWRUYWdzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1RPT0xLSVRfREVCVUcubXNnKGBVbnRhZ2dlZCAke3VudGFnZ2FibGVzLmxlbmd0aH0gYXNzZXRzYCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRhZyBpbWFnZXMgaW4gcGFyYWxsZWwgdXNpbmcgcC1saW1pdFxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwYXJhbGxlbFRhZ0VjcihlY3I6IElFQ1JDbGllbnQsIHJlcG86IHN0cmluZywgdGFnZ2FibGVzOiBJbWFnZUFzc2V0W10sIHByaW50ZXI6IFByb2dyZXNzUHJpbnRlcikge1xuICAgIGNvbnN0IGxpbWl0ID0gcExpbWl0KFBfTElNSVQpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YWdnYWJsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGltZyA9IHRhZ2dhYmxlc1tpXTtcbiAgICAgIGNvbnN0IHRhZ0VjciA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBlY3IucHV0SW1hZ2Uoe1xuICAgICAgICAgICAgcmVwb3NpdG9yeU5hbWU6IHJlcG8sXG4gICAgICAgICAgICBpbWFnZURpZ2VzdDogaW1nLmRpZ2VzdCxcbiAgICAgICAgICAgIGltYWdlTWFuaWZlc3Q6IGltZy5tYW5pZmVzdCxcbiAgICAgICAgICAgIGltYWdlVGFnOiBpbWcuYnVpbGRJbWFnZVRhZyhpKSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAvLyBUaGlzIGlzIGEgZmFsc2UgbmVnYXRpdmUgLS0gYW4gaXNvbGF0ZWQgYXNzZXQgaXMgdW50YWdnZWRcbiAgICAgICAgICAvLyBsaWtlbHkgZHVlIHRvIGFuIGltYWdlVGFnIGNvbGxpc2lvbi4gV2UgY2FuIHNhZmVseSBpZ25vcmUsXG4gICAgICAgICAgLy8gYW5kIHRoZSBpc29sYXRlZCBhc3NldCB3aWxsIGJlIHRhZ2dlZCBuZXh0IHRpbWUuXG4gICAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgV2FybmluZzogdW5hYmxlIHRvIHRhZyBpbWFnZSAke0pTT04uc3RyaW5naWZ5KGltZy50YWdzKX0gd2l0aCAke2ltZy5idWlsZEltYWdlVGFnKGkpfSBkdWUgdG8gdGhlIGZvbGxvd2luZyBlcnJvcjogJHtlcnJvcn1gKSk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBhd2FpdCBsaW1pdCgoKSA9PiB0YWdFY3IoKSk7XG4gICAgfVxuXG4gICAgcHJpbnRlci5yZXBvcnRUYWdnZWRBc3NldCh0YWdnYWJsZXMpO1xuICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coYFRhZ2dlZCAke3RhZ2dhYmxlcy5sZW5ndGh9IGFzc2V0c2ApKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUYWcgb2JqZWN0cyBpbiBwYXJhbGxlbCB1c2luZyBwLWxpbWl0LiBUaGUgcHV0T2JqZWN0VGFnZ2luZyBBUEkgZG9lcyBub3RcbiAgICogc3VwcG9ydCBiYXRjaCB0YWdnaW5nIHNvIHdlIG11c3QgaGFuZGxlIHRoZSBwYXJhbGxlbGlzbSBjbGllbnQtc2lkZS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcGFyYWxsZWxUYWdTMyhzMzogSVMzQ2xpZW50LCBidWNrZXQ6IHN0cmluZywgdGFnZ2FibGVzOiBPYmplY3RBc3NldFtdLCBkYXRlOiBudW1iZXIsIHByaW50ZXI6IFByb2dyZXNzUHJpbnRlcikge1xuICAgIGNvbnN0IGxpbWl0ID0gcExpbWl0KFBfTElNSVQpO1xuXG4gICAgZm9yIChjb25zdCBvYmogb2YgdGFnZ2FibGVzKSB7XG4gICAgICBhd2FpdCBsaW1pdCgoKSA9PlxuICAgICAgICBzMy5wdXRPYmplY3RUYWdnaW5nKHtcbiAgICAgICAgICBCdWNrZXQ6IGJ1Y2tldCxcbiAgICAgICAgICBLZXk6IG9iai5rZXksXG4gICAgICAgICAgVGFnZ2luZzoge1xuICAgICAgICAgICAgVGFnU2V0OiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBLZXk6IFMzX0lTT0xBVEVEX1RBRyxcbiAgICAgICAgICAgICAgICBWYWx1ZTogU3RyaW5nKGRhdGUpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpbnRlci5yZXBvcnRUYWdnZWRBc3NldCh0YWdnYWJsZXMpO1xuICAgIGF3YWl0IHRoaXMuaW9IZWxwZXIubm90aWZ5KElPLkRFRkFVTFRfVE9PTEtJVF9ERUJVRy5tc2coYFRhZ2dlZCAke3RhZ2dhYmxlcy5sZW5ndGh9IGFzc2V0c2ApKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgaW1hZ2VzIGluIHBhcmFsbGVsLiBUaGUgZGVsZXRlSW1hZ2UgQVBJIHN1cHBvcnRzIGJhdGNoZXMgb2YgMTAwLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwYXJhbGxlbERlbGV0ZUVjcihlY3I6IElFQ1JDbGllbnQsIHJlcG86IHN0cmluZywgZGVsZXRhYmxlczogSW1hZ2VBc3NldFtdLCBwcmludGVyOiBQcm9ncmVzc1ByaW50ZXIpIHtcbiAgICBjb25zdCBiYXRjaFNpemUgPSAxMDA7XG4gICAgY29uc3QgaW1hZ2VzVG9EZWxldGUgPSBkZWxldGFibGVzLm1hcChpbWcgPT4gKHtcbiAgICAgIGltYWdlRGlnZXN0OiBpbWcuZGlnZXN0LFxuICAgIH0pKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBiYXRjaGVzID0gW107XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGltYWdlc1RvRGVsZXRlLmxlbmd0aDsgaSArPSBiYXRjaFNpemUpIHtcbiAgICAgICAgYmF0Y2hlcy5wdXNoKGltYWdlc1RvRGVsZXRlLnNsaWNlKGksIGkgKyBiYXRjaFNpemUpKTtcbiAgICAgIH1cbiAgICAgIC8vIERlbGV0ZSBpbWFnZXMgaW4gYmF0Y2hlc1xuICAgICAgZm9yIChjb25zdCBiYXRjaCBvZiBiYXRjaGVzKSB7XG4gICAgICAgIGF3YWl0IGVjci5iYXRjaERlbGV0ZUltYWdlKHtcbiAgICAgICAgICBpbWFnZUlkczogYmF0Y2gsXG4gICAgICAgICAgcmVwb3NpdG9yeU5hbWU6IHJlcG8sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGRlbGV0ZWRDb3VudCA9IGJhdGNoLmxlbmd0aDtcbiAgICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0RFQlVHLm1zZyhgRGVsZXRlZCAke2RlbGV0ZWRDb3VudH0gYXNzZXRzYCkpO1xuICAgICAgICBwcmludGVyLnJlcG9ydERlbGV0ZWRBc3NldChkZWxldGFibGVzLnNsaWNlKDAsIGRlbGV0ZWRDb3VudCkpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgYXdhaXQgdGhpcy5pb0hlbHBlci5ub3RpZnkoSU8uREVGQVVMVF9UT09MS0lUX0VSUk9SLm1zZyhgRXJyb3IgZGVsZXRpbmcgaW1hZ2VzOiAke2Vycn1gKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZSBvYmplY3RzIGluIHBhcmFsbGVsLiBUaGUgZGVsZXRlT2JqZWN0cyBBUEkgc3VwcG9ydHMgYmF0Y2hlcyBvZiAxMDAwLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwYXJhbGxlbERlbGV0ZVMzKHMzOiBJUzNDbGllbnQsIGJ1Y2tldDogc3RyaW5nLCBkZWxldGFibGVzOiBPYmplY3RBc3NldFtdLCBwcmludGVyOiBQcm9ncmVzc1ByaW50ZXIpIHtcbiAgICBjb25zdCBiYXRjaFNpemUgPSAxMDAwO1xuICAgIGNvbnN0IG9iamVjdHNUb0RlbGV0ZSA9IGRlbGV0YWJsZXMubWFwKGFzc2V0ID0+ICh7XG4gICAgICBLZXk6IGFzc2V0LmtleSxcbiAgICB9KSk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgYmF0Y2hlcyA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvYmplY3RzVG9EZWxldGUubGVuZ3RoOyBpICs9IGJhdGNoU2l6ZSkge1xuICAgICAgICBiYXRjaGVzLnB1c2gob2JqZWN0c1RvRGVsZXRlLnNsaWNlKGksIGkgKyBiYXRjaFNpemUpKTtcbiAgICAgIH1cbiAgICAgIC8vIERlbGV0ZSBvYmplY3RzIGluIGJhdGNoZXNcbiAgICAgIGZvciAoY29uc3QgYmF0Y2ggb2YgYmF0Y2hlcykge1xuICAgICAgICBhd2FpdCBzMy5kZWxldGVPYmplY3RzKHtcbiAgICAgICAgICBCdWNrZXQ6IGJ1Y2tldCxcbiAgICAgICAgICBEZWxldGU6IHtcbiAgICAgICAgICAgIE9iamVjdHM6IGJhdGNoLFxuICAgICAgICAgICAgUXVpZXQ6IHRydWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgZGVsZXRlZENvdW50ID0gYmF0Y2gubGVuZ3RoO1xuICAgICAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1RPT0xLSVRfREVCVUcubXNnKGBEZWxldGVkICR7ZGVsZXRlZENvdW50fSBhc3NldHNgKSk7XG4gICAgICAgIHByaW50ZXIucmVwb3J0RGVsZXRlZEFzc2V0KGRlbGV0YWJsZXMuc2xpY2UoMCwgZGVsZXRlZENvdW50KSk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBhd2FpdCB0aGlzLmlvSGVscGVyLm5vdGlmeShJTy5ERUZBVUxUX1RPT0xLSVRfREVCVUcubXNnKGNoYWxrLnJlZChgRXJyb3IgZGVsZXRpbmcgb2JqZWN0czogJHtlcnJ9YCkpKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJvb3RzdHJhcEJ1Y2tldE5hbWUoc2RrOiBTREssIGJvb3RzdHJhcFN0YWNrTmFtZTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB0b29sa2l0SW5mbyA9IGF3YWl0IFRvb2xraXRJbmZvLmxvb2t1cCh0aGlzLnByb3BzLnJlc29sdmVkRW52aXJvbm1lbnQsIHNkaywgdGhpcy5pb0hlbHBlciwgYm9vdHN0cmFwU3RhY2tOYW1lKTtcbiAgICByZXR1cm4gdG9vbGtpdEluZm8uYnVja2V0TmFtZTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYm9vdHN0cmFwUmVwb3NpdG9yeU5hbWUoc2RrOiBTREssIGJvb3RzdHJhcFN0YWNrTmFtZTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCB0b29sa2l0SW5mbyA9IGF3YWl0IFRvb2xraXRJbmZvLmxvb2t1cCh0aGlzLnByb3BzLnJlc29sdmVkRW52aXJvbm1lbnQsIHNkaywgdGhpcy5pb0hlbHBlciwgYm9vdHN0cmFwU3RhY2tOYW1lKTtcbiAgICByZXR1cm4gdG9vbGtpdEluZm8ucmVwb3NpdG9yeU5hbWU7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGJvb3RzdHJhcFF1YWxpZmllcihzZGs6IFNESywgYm9vdHN0cmFwU3RhY2tOYW1lOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICAgIGNvbnN0IHRvb2xraXRJbmZvID0gYXdhaXQgVG9vbGtpdEluZm8ubG9va3VwKHRoaXMucHJvcHMucmVzb2x2ZWRFbnZpcm9ubWVudCwgc2RrLCB0aGlzLmlvSGVscGVyLCBib290c3RyYXBTdGFja05hbWUpO1xuICAgIHJldHVybiB0b29sa2l0SW5mby5ib290c3RyYXBTdGFjay5wYXJhbWV0ZXJzLlF1YWxpZmllcjtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbnVtT2JqZWN0c0luQnVja2V0KHMzOiBJUzNDbGllbnQsIGJ1Y2tldDogc3RyaW5nKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICBsZXQgdG90YWxDb3VudCA9IDA7XG4gICAgbGV0IGNvbnRpbnVhdGlvblRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICBkbyB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHMzLmxpc3RPYmplY3RzVjIoe1xuICAgICAgICBCdWNrZXQ6IGJ1Y2tldCxcbiAgICAgICAgQ29udGludWF0aW9uVG9rZW46IGNvbnRpbnVhdGlvblRva2VuLFxuICAgICAgfSk7XG5cbiAgICAgIHRvdGFsQ291bnQgKz0gcmVzcG9uc2UuS2V5Q291bnQgPz8gMDtcbiAgICAgIGNvbnRpbnVhdGlvblRva2VuID0gcmVzcG9uc2UuTmV4dENvbnRpbnVhdGlvblRva2VuO1xuICAgIH0gd2hpbGUgKGNvbnRpbnVhdGlvblRva2VuKTtcblxuICAgIHJldHVybiB0b3RhbENvdW50O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBudW1JbWFnZXNJblJlcG8oZWNyOiBJRUNSQ2xpZW50LCByZXBvOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGxldCB0b3RhbENvdW50ID0gMDtcbiAgICBsZXQgbmV4dFRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICBkbyB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGVjci5saXN0SW1hZ2VzKHtcbiAgICAgICAgcmVwb3NpdG9yeU5hbWU6IHJlcG8sXG4gICAgICAgIG5leHRUb2tlbjogbmV4dFRva2VuLFxuICAgICAgfSk7XG5cbiAgICAgIHRvdGFsQ291bnQgKz0gcmVzcG9uc2UuaW1hZ2VJZHM/Lmxlbmd0aCA/PyAwO1xuICAgICAgbmV4dFRva2VuID0gcmVzcG9uc2UubmV4dFRva2VuO1xuICAgIH0gd2hpbGUgKG5leHRUb2tlbik7XG5cbiAgICByZXR1cm4gdG90YWxDb3VudDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgKnJlYWRSZXBvSW5CYXRjaGVzKGVjcjogSUVDUkNsaWVudCwgcmVwbzogc3RyaW5nLCBiYXRjaFNpemU6IG51bWJlciA9IDEwMDAsIGN1cnJlbnRUaW1lOiBudW1iZXIpOiBBc3luY0dlbmVyYXRvcjxJbWFnZUFzc2V0W10+IHtcbiAgICBsZXQgY29udGludWF0aW9uVG9rZW46IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgIGRvIHtcbiAgICAgIGNvbnN0IGJhdGNoOiBJbWFnZUFzc2V0W10gPSBbXTtcblxuICAgICAgd2hpbGUgKGJhdGNoLmxlbmd0aCA8IGJhdGNoU2l6ZSkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGVjci5saXN0SW1hZ2VzKHtcbiAgICAgICAgICByZXBvc2l0b3J5TmFtZTogcmVwbyxcbiAgICAgICAgICBuZXh0VG9rZW46IGNvbnRpbnVhdGlvblRva2VuLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBObyBpbWFnZXMgaW4gdGhlIHJlcG9zaXRvcnlcbiAgICAgICAgaWYgKCFyZXNwb25zZS5pbWFnZUlkcyB8fCByZXNwb25zZS5pbWFnZUlkcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG1hcCB1bmlxdWUgaW1hZ2UgZGlnZXN0IHRvIChwb3NzaWJseSBtdWx0aXBsZSkgdGFnc1xuICAgICAgICBjb25zdCBpbWFnZXMgPSBpbWFnZU1hcChyZXNwb25zZS5pbWFnZUlkcyA/PyBbXSk7XG5cbiAgICAgICAgY29uc3QgaW1hZ2VJZHMgPSBPYmplY3Qua2V5cyhpbWFnZXMpLm1hcChrZXkgPT4gKHtcbiAgICAgICAgICBpbWFnZURpZ2VzdDoga2V5LFxuICAgICAgICB9KSk7XG5cbiAgICAgICAgY29uc3QgZGVzY3JpYmVJbWFnZUluZm8gPSBhd2FpdCBlY3IuZGVzY3JpYmVJbWFnZXMoe1xuICAgICAgICAgIHJlcG9zaXRvcnlOYW1lOiByZXBvLFxuICAgICAgICAgIGltYWdlSWRzOiBpbWFnZUlkcyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgZ2V0SW1hZ2VJbmZvID0gYXdhaXQgZWNyLmJhdGNoR2V0SW1hZ2Uoe1xuICAgICAgICAgIHJlcG9zaXRvcnlOYW1lOiByZXBvLFxuICAgICAgICAgIGltYWdlSWRzOiBpbWFnZUlkcyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgY29tYmluZWRJbWFnZUluZm8gPSBkZXNjcmliZUltYWdlSW5mby5pbWFnZURldGFpbHM/Lm1hcChpbWFnZURldGFpbCA9PiB7XG4gICAgICAgICAgY29uc3QgbWF0Y2hpbmdJbWFnZSA9IGdldEltYWdlSW5mby5pbWFnZXM/LmZpbmQoXG4gICAgICAgICAgICBpbWcgPT4gaW1nLmltYWdlSWQ/LmltYWdlRGlnZXN0ID09PSBpbWFnZURldGFpbC5pbWFnZURpZ2VzdCxcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLmltYWdlRGV0YWlsLFxuICAgICAgICAgICAgbWFuaWZlc3Q6IG1hdGNoaW5nSW1hZ2U/LmltYWdlTWFuaWZlc3QsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgZm9yIChjb25zdCBpbWFnZSBvZiBjb21iaW5lZEltYWdlSW5mbyA/PyBbXSkge1xuICAgICAgICAgIGNvbnN0IGxhc3RNb2RpZmllZCA9IGltYWdlLmltYWdlUHVzaGVkQXQgPz8gbmV3IERhdGUoY3VycmVudFRpbWUpO1xuICAgICAgICAgIC8vIFN0b3JlIHRoZSBpbWFnZSBpZiBpdCB3YXMgcHVzaGVkIGVhcmxpZXIgdGhhbiB0b2RheSAtIGNyZWF0ZWRCdWZmZXJEYXlzXG4gICAgICAgICAgaWYgKGltYWdlLmltYWdlRGlnZXN0ICYmIGxhc3RNb2RpZmllZCA8IG5ldyBEYXRlKGN1cnJlbnRUaW1lIC0gKHRoaXMucHJvcHMuY3JlYXRlZEJ1ZmZlckRheXMgKiBEQVkpKSkge1xuICAgICAgICAgICAgYmF0Y2gucHVzaChuZXcgSW1hZ2VBc3NldChpbWFnZS5pbWFnZURpZ2VzdCwgaW1hZ2UuaW1hZ2VTaXplSW5CeXRlcyA/PyAwLCBpbWFnZS5pbWFnZVRhZ3MgPz8gW10sIGltYWdlLm1hbmlmZXN0ID8/ICcnKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29udGludWF0aW9uVG9rZW4gPSByZXNwb25zZS5uZXh0VG9rZW47XG5cbiAgICAgICAgaWYgKCFjb250aW51YXRpb25Ub2tlbikgYnJlYWs7IC8vIE5vIG1vcmUgaW1hZ2VzIHRvIGZldGNoXG4gICAgICB9XG5cbiAgICAgIGlmIChiYXRjaC5sZW5ndGggPiAwKSB7XG4gICAgICAgIHlpZWxkIGJhdGNoO1xuICAgICAgfVxuICAgIH0gd2hpbGUgKGNvbnRpbnVhdGlvblRva2VuKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0b3IgZnVuY3Rpb24gdGhhdCByZWFkcyBvYmplY3RzIGZyb20gdGhlIFMzIEJ1Y2tldCBpbiBiYXRjaGVzLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyAqcmVhZEJ1Y2tldEluQmF0Y2hlcyhzMzogSVMzQ2xpZW50LCBidWNrZXQ6IHN0cmluZywgYmF0Y2hTaXplOiBudW1iZXIgPSAxMDAwLCBjdXJyZW50VGltZTogbnVtYmVyKTogQXN5bmNHZW5lcmF0b3I8T2JqZWN0QXNzZXRbXT4ge1xuICAgIGxldCBjb250aW51YXRpb25Ub2tlbjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gICAgZG8ge1xuICAgICAgY29uc3QgYmF0Y2g6IE9iamVjdEFzc2V0W10gPSBbXTtcblxuICAgICAgd2hpbGUgKGJhdGNoLmxlbmd0aCA8IGJhdGNoU2l6ZSkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHMzLmxpc3RPYmplY3RzVjIoe1xuICAgICAgICAgIEJ1Y2tldDogYnVja2V0LFxuICAgICAgICAgIENvbnRpbnVhdGlvblRva2VuOiBjb250aW51YXRpb25Ub2tlbixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmVzcG9uc2UuQ29udGVudHM/LmZvckVhY2goKG9iajogYW55KSA9PiB7XG4gICAgICAgICAgY29uc3Qga2V5ID0gb2JqLktleSA/PyAnJztcbiAgICAgICAgICBjb25zdCBzaXplID0gb2JqLlNpemUgPz8gMDtcbiAgICAgICAgICBjb25zdCBsYXN0TW9kaWZpZWQgPSBvYmouTGFzdE1vZGlmaWVkID8/IG5ldyBEYXRlKGN1cnJlbnRUaW1lKTtcbiAgICAgICAgICAvLyBTdG9yZSB0aGUgb2JqZWN0IGlmIGl0IGhhcyBhIEtleSBhbmRcbiAgICAgICAgICAvLyBpZiBpdCBoYXMgbm90IGJlZW4gbW9kaWZpZWQgc2luY2UgdG9kYXkgLSBjcmVhdGVkQnVmZmVyRGF5c1xuICAgICAgICAgIGlmIChrZXkgJiYgbGFzdE1vZGlmaWVkIDwgbmV3IERhdGUoY3VycmVudFRpbWUgLSAodGhpcy5wcm9wcy5jcmVhdGVkQnVmZmVyRGF5cyAqIERBWSkpKSB7XG4gICAgICAgICAgICBiYXRjaC5wdXNoKG5ldyBPYmplY3RBc3NldChidWNrZXQsIGtleSwgc2l6ZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29udGludWF0aW9uVG9rZW4gPSByZXNwb25zZS5OZXh0Q29udGludWF0aW9uVG9rZW47XG5cbiAgICAgICAgaWYgKCFjb250aW51YXRpb25Ub2tlbikgYnJlYWs7IC8vIE5vIG1vcmUgb2JqZWN0cyB0byBmZXRjaFxuICAgICAgfVxuXG4gICAgICBpZiAoYmF0Y2gubGVuZ3RoID4gMCkge1xuICAgICAgICB5aWVsZCBiYXRjaDtcbiAgICAgIH1cbiAgICB9IHdoaWxlIChjb250aW51YXRpb25Ub2tlbik7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNvbmZpcm1hdGlvblByb21wdChwcmludGVyOiBQcm9ncmVzc1ByaW50ZXIsIGRlbGV0YWJsZXM6IEdjQXNzZXRbXSwgdHlwZTogc3RyaW5nKSB7XG4gICAgY29uc3QgcGx1cmFsaXplID0gKG5hbWU6IHN0cmluZywgY291bnQ6IG51bWJlcik6IHN0cmluZyA9PiB7XG4gICAgICByZXR1cm4gY291bnQgPT09IDEgPyBuYW1lIDogYCR7bmFtZX1zYDtcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMuY29uZmlybSkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IFtcbiAgICAgICAgYEZvdW5kICR7ZGVsZXRhYmxlcy5sZW5ndGh9ICR7cGx1cmFsaXplKHR5cGUsIGRlbGV0YWJsZXMubGVuZ3RoKX0gdG8gZGVsZXRlIGJhc2VkIG9mZiBvZiB0aGUgZm9sbG93aW5nIGNyaXRlcmlhOmAsXG4gICAgICAgIGAtICR7dHlwZX1zIGhhdmUgYmVlbiBpc29sYXRlZCBmb3IgPiAke3RoaXMucHJvcHMucm9sbGJhY2tCdWZmZXJEYXlzfSBkYXlzYCxcbiAgICAgICAgYC0gJHt0eXBlfXMgd2VyZSBjcmVhdGVkID4gJHt0aGlzLnByb3BzLmNyZWF0ZWRCdWZmZXJEYXlzfSBkYXlzIGFnb2AsXG4gICAgICAgICcnLFxuICAgICAgICAnRGVsZXRlIHRoaXMgYmF0Y2ggKHllcy9uby9kZWxldGUtYWxsKT8nLFxuICAgICAgXS5qb2luKCdcXG4nKTtcbiAgICAgIHByaW50ZXIucGF1c2UoKTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgcHJvbXB0bHkucHJvbXB0KG1lc3NhZ2UsXG4gICAgICAgIHsgdHJpbTogdHJ1ZSB9LFxuICAgICAgKTtcblxuICAgICAgLy8gQW55dGhpbmcgb3RoZXIgdGhhbiB5ZXMveS9kZWxldGUtYWxsIGlzIHRyZWF0ZWQgYXMgbm9cbiAgICAgIGlmICghcmVzcG9uc2UgfHwgIVsneWVzJywgJ3knLCAnZGVsZXRlLWFsbCddLmluY2x1ZGVzKHJlc3BvbnNlLnRvTG93ZXJDYXNlKCkpKSB7XG4gICAgICAgIHRocm93IG5ldyBUb29sa2l0RXJyb3IoJ0RlbGV0aW9uIGFib3J0ZWQgYnkgdXNlcicpO1xuICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS50b0xvd2VyQ2FzZSgpID09ICdkZWxldGUtYWxsJykge1xuICAgICAgICB0aGlzLmNvbmZpcm0gPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcHJpbnRlci5yZXN1bWUoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJ0aXRpb248QT4oeHM6IEl0ZXJhYmxlPEE+LCBwcmVkOiAoeDogQSkgPT4gYm9vbGVhbik6IHsgaW5jbHVkZWQ6IEFbXTsgZXhjbHVkZWQ6IEFbXSB9IHtcbiAgY29uc3QgcmVzdWx0ID0ge1xuICAgIGluY2x1ZGVkOiBbXSBhcyBBW10sXG4gICAgZXhjbHVkZWQ6IFtdIGFzIEFbXSxcbiAgfTtcblxuICBmb3IgKGNvbnN0IHggb2YgeHMpIHtcbiAgICBpZiAocHJlZCh4KSkge1xuICAgICAgcmVzdWx0LmluY2x1ZGVkLnB1c2goeCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdC5leGNsdWRlZC5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIGltYWdlTWFwKGltYWdlSWRzOiBJbWFnZUlkZW50aWZpZXJbXSkge1xuICBjb25zdCBpbWFnZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZ1tdPiA9IHt9O1xuICBmb3IgKGNvbnN0IGltYWdlIG9mIGltYWdlSWRzID8/IFtdKSB7XG4gICAgaWYgKCFpbWFnZS5pbWFnZURpZ2VzdCB8fCAhaW1hZ2UuaW1hZ2VUYWcpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoIWltYWdlc1tpbWFnZS5pbWFnZURpZ2VzdF0pIHtcbiAgICAgIGltYWdlc1tpbWFnZS5pbWFnZURpZ2VzdF0gPSBbXTtcbiAgICB9XG4gICAgaW1hZ2VzW2ltYWdlLmltYWdlRGlnZXN0XS5wdXNoKGltYWdlLmltYWdlVGFnKTtcbiAgfVxuICByZXR1cm4gaW1hZ2VzO1xufVxuIl19
|