@aws-cdk/aws-glue-alpha 2.176.0-alpha.0 → 2.178.0-alpha.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/.jsii +6187 -3907
- package/.jsii.tabl.json.gz +0 -0
- package/.warnings.jsii.js +525 -235
- package/README.md +422 -159
- package/awslint.json +5 -5
- package/lib/code.js +4 -5
- package/lib/connection.js +15 -3
- package/lib/constants.d.ts +261 -0
- package/lib/constants.js +281 -0
- package/lib/data-format.js +5 -5
- package/lib/data-quality-ruleset.js +6 -3
- package/lib/database.js +5 -2
- package/lib/external-table.js +20 -2
- package/lib/index.d.ts +13 -2
- package/lib/index.js +14 -3
- package/lib/jobs/job.d.ts +393 -0
- package/lib/jobs/job.js +298 -0
- package/lib/jobs/pyspark-etl-job.d.ts +81 -0
- package/lib/jobs/pyspark-etl-job.js +130 -0
- package/lib/jobs/pyspark-flex-etl-job.d.ts +83 -0
- package/lib/jobs/pyspark-flex-etl-job.js +137 -0
- package/lib/jobs/pyspark-streaming-job.d.ts +81 -0
- package/lib/jobs/pyspark-streaming-job.js +130 -0
- package/lib/jobs/python-shell-job.d.ts +55 -0
- package/lib/jobs/python-shell-job.js +99 -0
- package/lib/jobs/ray-job.d.ts +44 -0
- package/lib/jobs/ray-job.js +89 -0
- package/lib/jobs/scala-spark-etl-job.d.ts +78 -0
- package/lib/jobs/scala-spark-etl-job.js +134 -0
- package/lib/jobs/scala-spark-flex-etl-job.d.ts +109 -0
- package/lib/jobs/scala-spark-flex-etl-job.js +143 -0
- package/lib/jobs/scala-spark-streaming-job.d.ts +77 -0
- package/lib/jobs/scala-spark-streaming-job.js +131 -0
- package/lib/jobs/spark-ui-utils.d.ts +53 -0
- package/lib/jobs/spark-ui-utils.js +26 -0
- package/lib/s3-table.d.ts +4 -4
- package/lib/s3-table.js +20 -2
- package/lib/schema.d.ts +1 -1
- package/lib/schema.js +2 -2
- package/lib/security-configuration.js +5 -2
- package/lib/storage-parameter.js +1 -1
- package/lib/table-base.d.ts +1 -1
- package/lib/table-base.js +2 -2
- package/lib/table-deprecated.js +1 -1
- package/lib/triggers/trigger-options.d.ts +205 -0
- package/lib/triggers/trigger-options.js +39 -0
- package/lib/triggers/workflow.d.ts +203 -0
- package/lib/triggers/workflow.js +371 -0
- package/package.json +8 -8
- package/rosetta/default.ts-fixture +1 -1
- package/lib/job-executable.d.ts +0 -384
- package/lib/job-executable.js +0 -348
- package/lib/job.d.ts +0 -574
- package/lib/job.js +0 -531
package/lib/job.js
DELETED
|
@@ -1,531 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var _a, _b;
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.Job = exports.ExecutionClass = exports.MetricType = exports.JobState = exports.WorkerType = void 0;
|
|
5
|
-
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
|
6
|
-
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
7
|
-
const os_1 = require("os");
|
|
8
|
-
const cloudwatch = require("aws-cdk-lib/aws-cloudwatch");
|
|
9
|
-
const events = require("aws-cdk-lib/aws-events");
|
|
10
|
-
const iam = require("aws-cdk-lib/aws-iam");
|
|
11
|
-
const s3 = require("aws-cdk-lib/aws-s3");
|
|
12
|
-
const cdk = require("aws-cdk-lib/core");
|
|
13
|
-
const _1 = require(".");
|
|
14
|
-
const aws_glue_1 = require("aws-cdk-lib/aws-glue");
|
|
15
|
-
/**
|
|
16
|
-
* The type of predefined worker that is allocated when a job runs.
|
|
17
|
-
*
|
|
18
|
-
* If you need to use a WorkerType that doesn't exist as a static member, you
|
|
19
|
-
* can instantiate a `WorkerType` object, e.g: `WorkerType.of('other type')`.
|
|
20
|
-
*/
|
|
21
|
-
class WorkerType {
|
|
22
|
-
/**
|
|
23
|
-
* Custom worker type
|
|
24
|
-
* @param workerType custom worker type
|
|
25
|
-
*/
|
|
26
|
-
static of(workerType) {
|
|
27
|
-
return new WorkerType(workerType);
|
|
28
|
-
}
|
|
29
|
-
constructor(name) {
|
|
30
|
-
this.name = name;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
exports.WorkerType = WorkerType;
|
|
34
|
-
_a = JSII_RTTI_SYMBOL_1;
|
|
35
|
-
WorkerType[_a] = { fqn: "@aws-cdk/aws-glue-alpha.WorkerType", version: "2.176.0-alpha.0" };
|
|
36
|
-
/**
|
|
37
|
-
* Each worker provides 4 vCPU, 16 GB of memory and a 50GB disk, and 2 executors per worker.
|
|
38
|
-
*/
|
|
39
|
-
WorkerType.STANDARD = new WorkerType('Standard');
|
|
40
|
-
/**
|
|
41
|
-
* Each worker maps to 1 DPU (4 vCPU, 16 GB of memory, 64 GB disk), and provides 1 executor per worker. Suitable for memory-intensive jobs.
|
|
42
|
-
*/
|
|
43
|
-
WorkerType.G_1X = new WorkerType('G.1X');
|
|
44
|
-
/**
|
|
45
|
-
* Each worker maps to 2 DPU (8 vCPU, 32 GB of memory, 128 GB disk), and provides 1 executor per worker. Suitable for memory-intensive jobs.
|
|
46
|
-
*/
|
|
47
|
-
WorkerType.G_2X = new WorkerType('G.2X');
|
|
48
|
-
/**
|
|
49
|
-
* Each worker maps to 4 DPU (16 vCPU, 64 GB of memory, 256 GB disk), and provides 1 executor per worker. We recommend this worker type for jobs whose workloads contain your most demanding transforms, aggregations, joins, and queries. This worker type is available only for AWS Glue version 3.0 or later jobs.
|
|
50
|
-
*/
|
|
51
|
-
WorkerType.G_4X = new WorkerType('G.4X');
|
|
52
|
-
/**
|
|
53
|
-
* Each worker maps to 8 DPU (32 vCPU, 128 GB of memory, 512 GB disk), and provides 1 executor per worker. We recommend this worker type for jobs whose workloads contain your most demanding transforms, aggregations, joins, and queries. This worker type is available only for AWS Glue version 3.0 or later jobs.
|
|
54
|
-
*/
|
|
55
|
-
WorkerType.G_8X = new WorkerType('G.8X');
|
|
56
|
-
/**
|
|
57
|
-
* Each worker maps to 0.25 DPU (2 vCPU, 4 GB of memory, 64 GB disk), and provides 1 executor per worker. Suitable for low volume streaming jobs.
|
|
58
|
-
*/
|
|
59
|
-
WorkerType.G_025X = new WorkerType('G.025X');
|
|
60
|
-
/**
|
|
61
|
-
* Each worker maps to 2 high-memory DPU [M-DPU] (8 vCPU, 64 GB of memory, 128 GB disk). Supported in Ray jobs.
|
|
62
|
-
*/
|
|
63
|
-
WorkerType.Z_2X = new WorkerType('Z.2X');
|
|
64
|
-
/**
|
|
65
|
-
* Job states emitted by Glue to CloudWatch Events.
|
|
66
|
-
*
|
|
67
|
-
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html#glue-event-types
|
|
68
|
-
*/
|
|
69
|
-
var JobState;
|
|
70
|
-
(function (JobState) {
|
|
71
|
-
/**
|
|
72
|
-
* State indicating job run succeeded
|
|
73
|
-
*/
|
|
74
|
-
JobState["SUCCEEDED"] = "SUCCEEDED";
|
|
75
|
-
/**
|
|
76
|
-
* State indicating job run failed
|
|
77
|
-
*/
|
|
78
|
-
JobState["FAILED"] = "FAILED";
|
|
79
|
-
/**
|
|
80
|
-
* State indicating job run timed out
|
|
81
|
-
*/
|
|
82
|
-
JobState["TIMEOUT"] = "TIMEOUT";
|
|
83
|
-
/**
|
|
84
|
-
* State indicating job is starting
|
|
85
|
-
*/
|
|
86
|
-
JobState["STARTING"] = "STARTING";
|
|
87
|
-
/**
|
|
88
|
-
* State indicating job is running
|
|
89
|
-
*/
|
|
90
|
-
JobState["RUNNING"] = "RUNNING";
|
|
91
|
-
/**
|
|
92
|
-
* State indicating job is stopping
|
|
93
|
-
*/
|
|
94
|
-
JobState["STOPPING"] = "STOPPING";
|
|
95
|
-
/**
|
|
96
|
-
* State indicating job stopped
|
|
97
|
-
*/
|
|
98
|
-
JobState["STOPPED"] = "STOPPED";
|
|
99
|
-
})(JobState || (exports.JobState = JobState = {}));
|
|
100
|
-
/**
|
|
101
|
-
* The Glue CloudWatch metric type.
|
|
102
|
-
*
|
|
103
|
-
* @see https://docs.aws.amazon.com/glue/latest/dg/monitoring-awsglue-with-cloudwatch-metrics.html
|
|
104
|
-
*/
|
|
105
|
-
var MetricType;
|
|
106
|
-
(function (MetricType) {
|
|
107
|
-
/**
|
|
108
|
-
* A value at a point in time.
|
|
109
|
-
*/
|
|
110
|
-
MetricType["GAUGE"] = "gauge";
|
|
111
|
-
/**
|
|
112
|
-
* An aggregate number.
|
|
113
|
-
*/
|
|
114
|
-
MetricType["COUNT"] = "count";
|
|
115
|
-
})(MetricType || (exports.MetricType = MetricType = {}));
|
|
116
|
-
/**
|
|
117
|
-
* The ExecutionClass whether the job is run with a standard or flexible execution class.
|
|
118
|
-
*
|
|
119
|
-
* @see https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html#aws-glue-api-jobs-job-Job
|
|
120
|
-
* @see https://docs.aws.amazon.com/glue/latest/dg/add-job.html
|
|
121
|
-
*/
|
|
122
|
-
var ExecutionClass;
|
|
123
|
-
(function (ExecutionClass) {
|
|
124
|
-
/**
|
|
125
|
-
* The flexible execution class is appropriate for time-insensitive jobs whose start
|
|
126
|
-
* and completion times may vary.
|
|
127
|
-
*/
|
|
128
|
-
ExecutionClass["FLEX"] = "FLEX";
|
|
129
|
-
/**
|
|
130
|
-
* The standard execution class is ideal for time-sensitive workloads that require fast job
|
|
131
|
-
* startup and dedicated resources.
|
|
132
|
-
*/
|
|
133
|
-
ExecutionClass["STANDARD"] = "STANDARD";
|
|
134
|
-
})(ExecutionClass || (exports.ExecutionClass = ExecutionClass = {}));
|
|
135
|
-
class JobBase extends cdk.Resource {
|
|
136
|
-
/**
|
|
137
|
-
* Create a CloudWatch Event Rule for this Glue Job when it's in a given state
|
|
138
|
-
*
|
|
139
|
-
* @param id construct id
|
|
140
|
-
* @param options event options. Note that some values are overridden if provided, these are
|
|
141
|
-
* - eventPattern.source = ['aws.glue']
|
|
142
|
-
* - eventPattern.detailType = ['Glue Job State Change', 'Glue Job Run Status']
|
|
143
|
-
* - eventPattern.detail.jobName = [this.jobName]
|
|
144
|
-
*
|
|
145
|
-
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html#glue-event-types
|
|
146
|
-
*/
|
|
147
|
-
onEvent(id, options = {}) {
|
|
148
|
-
const rule = new events.Rule(this, id, options);
|
|
149
|
-
rule.addTarget(options.target);
|
|
150
|
-
rule.addEventPattern({
|
|
151
|
-
source: ['aws.glue'],
|
|
152
|
-
detailType: ['Glue Job State Change', 'Glue Job Run Status'],
|
|
153
|
-
detail: {
|
|
154
|
-
jobName: [this.jobName],
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
return rule;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Create a CloudWatch Event Rule for the transition into the input jobState.
|
|
161
|
-
*
|
|
162
|
-
* @param id construct id.
|
|
163
|
-
* @param jobState the job state.
|
|
164
|
-
* @param options optional event options.
|
|
165
|
-
*/
|
|
166
|
-
onStateChange(id, jobState, options = {}) {
|
|
167
|
-
const rule = this.onEvent(id, {
|
|
168
|
-
description: `Rule triggered when Glue job ${this.jobName} is in ${jobState} state`,
|
|
169
|
-
...options,
|
|
170
|
-
});
|
|
171
|
-
rule.addEventPattern({
|
|
172
|
-
detail: {
|
|
173
|
-
state: [jobState],
|
|
174
|
-
},
|
|
175
|
-
});
|
|
176
|
-
return rule;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Create a CloudWatch Event Rule matching JobState.SUCCEEDED.
|
|
180
|
-
*
|
|
181
|
-
* @param id construct id.
|
|
182
|
-
* @param options optional event options. default is {}.
|
|
183
|
-
*/
|
|
184
|
-
onSuccess(id, options = {}) {
|
|
185
|
-
return this.onStateChange(id, JobState.SUCCEEDED, options);
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Return a CloudWatch Event Rule matching FAILED state.
|
|
189
|
-
*
|
|
190
|
-
* @param id construct id.
|
|
191
|
-
* @param options optional event options. default is {}.
|
|
192
|
-
*/
|
|
193
|
-
onFailure(id, options = {}) {
|
|
194
|
-
return this.onStateChange(id, JobState.FAILED, options);
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Return a CloudWatch Event Rule matching TIMEOUT state.
|
|
198
|
-
*
|
|
199
|
-
* @param id construct id.
|
|
200
|
-
* @param options optional event options. default is {}.
|
|
201
|
-
*/
|
|
202
|
-
onTimeout(id, options = {}) {
|
|
203
|
-
return this.onStateChange(id, JobState.TIMEOUT, options);
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Create a CloudWatch metric.
|
|
207
|
-
*
|
|
208
|
-
* @param metricName name of the metric typically prefixed with `glue.driver.`, `glue.<executorId>.` or `glue.ALL.`.
|
|
209
|
-
* @param type the metric type.
|
|
210
|
-
* @param props metric options.
|
|
211
|
-
*
|
|
212
|
-
* @see https://docs.aws.amazon.com/glue/latest/dg/monitoring-awsglue-with-cloudwatch-metrics.html
|
|
213
|
-
*/
|
|
214
|
-
metric(metricName, type, props) {
|
|
215
|
-
return new cloudwatch.Metric({
|
|
216
|
-
metricName,
|
|
217
|
-
namespace: 'Glue',
|
|
218
|
-
dimensionsMap: {
|
|
219
|
-
JobName: this.jobName,
|
|
220
|
-
JobRunId: 'ALL',
|
|
221
|
-
Type: type,
|
|
222
|
-
},
|
|
223
|
-
...props,
|
|
224
|
-
}).attachTo(this);
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Return a CloudWatch Metric indicating job success.
|
|
228
|
-
*
|
|
229
|
-
* This metric is based on the Rule returned by no-args onSuccess() call.
|
|
230
|
-
*/
|
|
231
|
-
metricSuccess(props) {
|
|
232
|
-
return metricRule(this.metricJobStateRule('SuccessMetricRule', JobState.SUCCEEDED), props);
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Return a CloudWatch Metric indicating job failure.
|
|
236
|
-
*
|
|
237
|
-
* This metric is based on the Rule returned by no-args onFailure() call.
|
|
238
|
-
*/
|
|
239
|
-
metricFailure(props) {
|
|
240
|
-
return metricRule(this.metricJobStateRule('FailureMetricRule', JobState.FAILED), props);
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Return a CloudWatch Metric indicating job timeout.
|
|
244
|
-
*
|
|
245
|
-
* This metric is based on the Rule returned by no-args onTimeout() call.
|
|
246
|
-
*/
|
|
247
|
-
metricTimeout(props) {
|
|
248
|
-
return metricRule(this.metricJobStateRule('TimeoutMetricRule', JobState.TIMEOUT), props);
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Creates or retrieves a singleton event rule for the input job state for use with the metric JobState methods.
|
|
252
|
-
*
|
|
253
|
-
* @param id construct id.
|
|
254
|
-
* @param jobState the job state.
|
|
255
|
-
* @private
|
|
256
|
-
*/
|
|
257
|
-
metricJobStateRule(id, jobState) {
|
|
258
|
-
return this.node.tryFindChild(id) ?? this.onStateChange(id, jobState);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* A Glue Job.
|
|
263
|
-
*/
|
|
264
|
-
class Job extends JobBase {
|
|
265
|
-
/**
|
|
266
|
-
* Creates a Glue Job
|
|
267
|
-
*
|
|
268
|
-
* @param scope The scope creating construct (usually `this`).
|
|
269
|
-
* @param id The construct's id.
|
|
270
|
-
* @param attrs Import attributes
|
|
271
|
-
*/
|
|
272
|
-
static fromJobAttributes(scope, id, attrs) {
|
|
273
|
-
try {
|
|
274
|
-
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_JobAttributes(attrs);
|
|
275
|
-
}
|
|
276
|
-
catch (error) {
|
|
277
|
-
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
278
|
-
Error.captureStackTrace(error, this.fromJobAttributes);
|
|
279
|
-
}
|
|
280
|
-
throw error;
|
|
281
|
-
}
|
|
282
|
-
class Import extends JobBase {
|
|
283
|
-
constructor() {
|
|
284
|
-
super(...arguments);
|
|
285
|
-
this.jobName = attrs.jobName;
|
|
286
|
-
this.jobArn = jobArn(scope, attrs.jobName);
|
|
287
|
-
this.grantPrincipal = attrs.role ?? new iam.UnknownPrincipal({ resource: this });
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
return new Import(scope, id);
|
|
291
|
-
}
|
|
292
|
-
constructor(scope, id, props) {
|
|
293
|
-
super(scope, id, {
|
|
294
|
-
physicalName: props.jobName,
|
|
295
|
-
});
|
|
296
|
-
try {
|
|
297
|
-
jsiiDeprecationWarnings._aws_cdk_aws_glue_alpha_JobProps(props);
|
|
298
|
-
}
|
|
299
|
-
catch (error) {
|
|
300
|
-
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
301
|
-
Error.captureStackTrace(error, Job);
|
|
302
|
-
}
|
|
303
|
-
throw error;
|
|
304
|
-
}
|
|
305
|
-
const executable = props.executable.bind();
|
|
306
|
-
this.role = props.role ?? new iam.Role(this, 'ServiceRole', {
|
|
307
|
-
assumedBy: new iam.ServicePrincipal('glue.amazonaws.com'),
|
|
308
|
-
managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSGlueServiceRole')],
|
|
309
|
-
});
|
|
310
|
-
this.grantPrincipal = this.role;
|
|
311
|
-
const sparkUI = props.sparkUI?.enabled ? this.setupSparkUI(executable, this.role, props.sparkUI) : undefined;
|
|
312
|
-
this.sparkUILoggingLocation = sparkUI?.location;
|
|
313
|
-
const continuousLoggingArgs = props.continuousLogging?.enabled ? this.setupContinuousLogging(this.role, props.continuousLogging) : {};
|
|
314
|
-
const profilingMetricsArgs = props.enableProfilingMetrics ? { '--enable-metrics': '' } : {};
|
|
315
|
-
const defaultArguments = {
|
|
316
|
-
...this.executableArguments(executable),
|
|
317
|
-
...continuousLoggingArgs,
|
|
318
|
-
...profilingMetricsArgs,
|
|
319
|
-
...sparkUI?.args,
|
|
320
|
-
...this.checkNoReservedArgs(props.defaultArguments),
|
|
321
|
-
};
|
|
322
|
-
if (props.executionClass === ExecutionClass.FLEX) {
|
|
323
|
-
if (executable.type !== _1.JobType.ETL) {
|
|
324
|
-
throw new Error('FLEX ExecutionClass is only available for JobType.ETL jobs');
|
|
325
|
-
}
|
|
326
|
-
if ([_1.GlueVersion.V0_9, _1.GlueVersion.V1_0, _1.GlueVersion.V2_0].includes(executable.glueVersion)) {
|
|
327
|
-
throw new Error('FLEX ExecutionClass is only available for GlueVersion 3.0 or later');
|
|
328
|
-
}
|
|
329
|
-
if (props.workerType && (props.workerType !== WorkerType.G_1X && props.workerType !== WorkerType.G_2X)) {
|
|
330
|
-
throw new Error('FLEX ExecutionClass is only available for WorkerType G_1X or G_2X');
|
|
331
|
-
}
|
|
332
|
-
if (props.jobRunQueuingEnabled === true) {
|
|
333
|
-
throw new Error('FLEX ExecutionClass is only available if job run queuing is disabled');
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
// Validate Ray job properties
|
|
337
|
-
// See https://github.com/aws/aws-cdk/issues/29612
|
|
338
|
-
if (executable.type.name === _1.JobType.RAY.name) {
|
|
339
|
-
if (props.workerType !== WorkerType.Z_2X) {
|
|
340
|
-
throw new Error(`WorkerType must be Z_2X for Ray jobs, got: ${props.workerType}`);
|
|
341
|
-
}
|
|
342
|
-
if (props.timeout !== undefined) {
|
|
343
|
-
throw new Error('Timeout cannot be set for Ray jobs');
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
let maxCapacity = props.maxCapacity;
|
|
347
|
-
if (maxCapacity !== undefined && (props.workerType && props.workerCount !== undefined)) {
|
|
348
|
-
throw new Error('maxCapacity cannot be used when setting workerType and workerCount');
|
|
349
|
-
}
|
|
350
|
-
if (executable.type !== _1.JobType.PYTHON_SHELL) {
|
|
351
|
-
if (maxCapacity !== undefined && ![_1.GlueVersion.V0_9, _1.GlueVersion.V1_0].includes(executable.glueVersion)) {
|
|
352
|
-
throw new Error('maxCapacity cannot be used when GlueVersion 2.0 or later');
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
else {
|
|
356
|
-
// max capacity validation for python shell jobs (defaults to 0.0625)
|
|
357
|
-
maxCapacity = maxCapacity ?? 0.0625;
|
|
358
|
-
if (maxCapacity !== 0.0625 && maxCapacity !== 1) {
|
|
359
|
-
throw new Error(`maxCapacity value must be either 0.0625 or 1 for JobType.PYTHON_SHELL jobs, received ${maxCapacity}`);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
if ((!props.workerType && props.workerCount !== undefined) || (props.workerType && props.workerCount === undefined)) {
|
|
363
|
-
throw new Error('Both workerType and workerCount must be set');
|
|
364
|
-
}
|
|
365
|
-
if (props.jobRunQueuingEnabled === true && props.maxRetries !== undefined && !cdk.Token.isUnresolved(props.maxRetries) && props.maxRetries > 0) {
|
|
366
|
-
throw new Error(`Maximum retries was set to ${props.maxRetries}, must be set to 0 with job run queuing enabled`);
|
|
367
|
-
}
|
|
368
|
-
const jobResource = new aws_glue_1.CfnJob(this, 'Resource', {
|
|
369
|
-
name: props.jobName,
|
|
370
|
-
description: props.description,
|
|
371
|
-
role: this.role.roleArn,
|
|
372
|
-
command: {
|
|
373
|
-
name: executable.type.name,
|
|
374
|
-
scriptLocation: this.codeS3ObjectUrl(executable.script),
|
|
375
|
-
pythonVersion: executable.pythonVersion,
|
|
376
|
-
runtime: executable.runtime ? executable.runtime.name : undefined,
|
|
377
|
-
},
|
|
378
|
-
glueVersion: executable.glueVersion.name,
|
|
379
|
-
workerType: props.workerType?.name,
|
|
380
|
-
numberOfWorkers: props.workerCount,
|
|
381
|
-
jobRunQueuingEnabled: props.jobRunQueuingEnabled,
|
|
382
|
-
maxCapacity: props.maxCapacity,
|
|
383
|
-
maxRetries: props.maxRetries,
|
|
384
|
-
executionClass: props.executionClass,
|
|
385
|
-
executionProperty: props.maxConcurrentRuns ? { maxConcurrentRuns: props.maxConcurrentRuns } : undefined,
|
|
386
|
-
notificationProperty: props.notifyDelayAfter ? { notifyDelayAfter: props.notifyDelayAfter.toMinutes() } : undefined,
|
|
387
|
-
timeout: props.timeout?.toMinutes(),
|
|
388
|
-
connections: props.connections ? { connections: props.connections.map((connection) => connection.connectionName) } : undefined,
|
|
389
|
-
securityConfiguration: props.securityConfiguration?.securityConfigurationName,
|
|
390
|
-
tags: props.tags,
|
|
391
|
-
defaultArguments,
|
|
392
|
-
});
|
|
393
|
-
const resourceName = this.getResourceNameAttribute(jobResource.ref);
|
|
394
|
-
this.jobArn = jobArn(this, resourceName);
|
|
395
|
-
this.jobName = resourceName;
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Check no usage of reserved arguments.
|
|
399
|
-
*
|
|
400
|
-
* @see https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-glue-arguments.html
|
|
401
|
-
*/
|
|
402
|
-
checkNoReservedArgs(defaultArguments) {
|
|
403
|
-
if (defaultArguments) {
|
|
404
|
-
const reservedArgs = new Set(['--debug', '--mode', '--JOB_NAME']);
|
|
405
|
-
Object.keys(defaultArguments).forEach((arg) => {
|
|
406
|
-
if (reservedArgs.has(arg)) {
|
|
407
|
-
throw new Error(`The ${arg} argument is reserved by Glue. Don't set it`);
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
return defaultArguments;
|
|
412
|
-
}
|
|
413
|
-
executableArguments(config) {
|
|
414
|
-
const args = {};
|
|
415
|
-
args['--job-language'] = config.language;
|
|
416
|
-
if (config.className) {
|
|
417
|
-
args['--class'] = config.className;
|
|
418
|
-
}
|
|
419
|
-
if (config.extraJars && config.extraJars?.length > 0) {
|
|
420
|
-
args['--extra-jars'] = config.extraJars.map(code => this.codeS3ObjectUrl(code)).join(',');
|
|
421
|
-
}
|
|
422
|
-
if (config.extraPythonFiles && config.extraPythonFiles.length > 0) {
|
|
423
|
-
args['--extra-py-files'] = config.extraPythonFiles.map(code => this.codeS3ObjectUrl(code)).join(',');
|
|
424
|
-
}
|
|
425
|
-
if (config.s3PythonModules && config.s3PythonModules.length > 0) {
|
|
426
|
-
args['--s3-py-modules'] = config.s3PythonModules.map(code => this.codeS3ObjectUrl(code)).join(',');
|
|
427
|
-
}
|
|
428
|
-
if (config.extraFiles && config.extraFiles.length > 0) {
|
|
429
|
-
args['--extra-files'] = config.extraFiles.map(code => this.codeS3ObjectUrl(code)).join(',');
|
|
430
|
-
}
|
|
431
|
-
if (config.extraJarsFirst) {
|
|
432
|
-
args['--user-jars-first'] = 'true';
|
|
433
|
-
}
|
|
434
|
-
return args;
|
|
435
|
-
}
|
|
436
|
-
setupSparkUI(executable, role, props) {
|
|
437
|
-
if (_1.JobType.PYTHON_SHELL === executable.type) {
|
|
438
|
-
throw new Error('Spark UI is not available for JobType.PYTHON_SHELL jobs');
|
|
439
|
-
}
|
|
440
|
-
else if (_1.JobType.RAY === executable.type) {
|
|
441
|
-
throw new Error('Spark UI is not available for JobType.RAY jobs');
|
|
442
|
-
}
|
|
443
|
-
this.validatePrefix(props.prefix);
|
|
444
|
-
const bucket = props.bucket ?? new s3.Bucket(this, 'SparkUIBucket');
|
|
445
|
-
bucket.grantReadWrite(role, this.cleanPrefixForGrant(props.prefix));
|
|
446
|
-
const args = {
|
|
447
|
-
'--enable-spark-ui': 'true',
|
|
448
|
-
'--spark-event-logs-path': bucket.s3UrlForObject(props.prefix).replace(/\/?$/, '/'), // path will always end with a slash
|
|
449
|
-
};
|
|
450
|
-
return {
|
|
451
|
-
location: {
|
|
452
|
-
prefix: props.prefix,
|
|
453
|
-
bucket,
|
|
454
|
-
},
|
|
455
|
-
args,
|
|
456
|
-
};
|
|
457
|
-
}
|
|
458
|
-
validatePrefix(prefix) {
|
|
459
|
-
if (!prefix || cdk.Token.isUnresolved(prefix)) {
|
|
460
|
-
// skip validation if prefix is not specified or is a token
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
const errors = [];
|
|
464
|
-
if (prefix.startsWith('/')) {
|
|
465
|
-
errors.push('Prefix must not begin with \'/\'');
|
|
466
|
-
}
|
|
467
|
-
if (!prefix.endsWith('/')) {
|
|
468
|
-
errors.push('Prefix must end with \'/\'');
|
|
469
|
-
}
|
|
470
|
-
if (errors.length > 0) {
|
|
471
|
-
throw new Error(`Invalid prefix format (value: ${prefix})${os_1.EOL}${errors.join(os_1.EOL)}`);
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
cleanPrefixForGrant(prefix) {
|
|
475
|
-
return prefix !== undefined ? `${prefix}*` : undefined;
|
|
476
|
-
}
|
|
477
|
-
setupContinuousLogging(role, props) {
|
|
478
|
-
const args = {
|
|
479
|
-
'--enable-continuous-cloudwatch-log': 'true',
|
|
480
|
-
'--enable-continuous-log-filter': (props.quiet ?? true).toString(),
|
|
481
|
-
};
|
|
482
|
-
if (props.logGroup) {
|
|
483
|
-
args['--continuous-log-logGroup'] = props.logGroup.logGroupName;
|
|
484
|
-
props.logGroup.grantWrite(role);
|
|
485
|
-
}
|
|
486
|
-
if (props.logStreamPrefix) {
|
|
487
|
-
args['--continuous-log-logStreamPrefix'] = props.logStreamPrefix;
|
|
488
|
-
}
|
|
489
|
-
if (props.conversionPattern) {
|
|
490
|
-
args['--continuous-log-conversionPattern'] = props.conversionPattern;
|
|
491
|
-
}
|
|
492
|
-
return args;
|
|
493
|
-
}
|
|
494
|
-
codeS3ObjectUrl(code) {
|
|
495
|
-
const s3Location = code.bind(this, this.role).s3Location;
|
|
496
|
-
return `s3://${s3Location.bucketName}/${s3Location.objectKey}`;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
exports.Job = Job;
|
|
500
|
-
_b = JSII_RTTI_SYMBOL_1;
|
|
501
|
-
Job[_b] = { fqn: "@aws-cdk/aws-glue-alpha.Job", version: "2.176.0-alpha.0" };
|
|
502
|
-
/**
|
|
503
|
-
* Create a CloudWatch Metric that's based on Glue Job events.
|
|
504
|
-
* @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html#glue-event-types
|
|
505
|
-
* The metric has namespace = 'AWS/Events', metricName = 'TriggeredRules' and RuleName = rule.ruleName dimension.
|
|
506
|
-
*
|
|
507
|
-
* @param rule for use in setting RuleName dimension value
|
|
508
|
-
* @param props metric properties
|
|
509
|
-
*/
|
|
510
|
-
function metricRule(rule, props) {
|
|
511
|
-
return new cloudwatch.Metric({
|
|
512
|
-
namespace: 'AWS/Events',
|
|
513
|
-
metricName: 'TriggeredRules',
|
|
514
|
-
dimensionsMap: { RuleName: rule.ruleName },
|
|
515
|
-
statistic: cloudwatch.Statistic.SUM,
|
|
516
|
-
...props,
|
|
517
|
-
}).attachTo(rule);
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* Returns the job arn
|
|
521
|
-
* @param scope
|
|
522
|
-
* @param jobName
|
|
523
|
-
*/
|
|
524
|
-
function jobArn(scope, jobName) {
|
|
525
|
-
return cdk.Stack.of(scope).formatArn({
|
|
526
|
-
service: 'glue',
|
|
527
|
-
resource: 'job',
|
|
528
|
-
resourceName: jobName,
|
|
529
|
-
});
|
|
530
|
-
}
|
|
531
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiam9iLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiam9iLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDJCQUF5QjtBQUN6Qix5REFBeUQ7QUFDekQsaURBQWlEO0FBQ2pELDJDQUEyQztBQUUzQyx5Q0FBeUM7QUFDekMsd0NBQXdDO0FBRXhDLHdCQUFtRjtBQUVuRixtREFBOEM7QUFHOUM7Ozs7O0dBS0c7QUFDSCxNQUFhLFVBQVU7SUFvQ3JCOzs7T0FHRztJQUNJLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBa0I7UUFDakMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQztLQUNuQztJQU9ELFlBQW9CLElBQVk7UUFDOUIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7S0FDbEI7O0FBbkRILGdDQW9EQzs7O0FBbkRDOztHQUVHO0FBQ29CLG1CQUFRLEdBQUcsSUFBSSxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUM7QUFFN0Q7O0dBRUc7QUFDb0IsZUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBRXJEOztHQUVHO0FBQ29CLGVBQUksR0FBRyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUVyRDs7R0FFRztBQUNvQixlQUFJLEdBQUcsSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7QUFFckQ7O0dBRUc7QUFDb0IsZUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBRXJEOztHQUVHO0FBQ29CLGlCQUFNLEdBQUcsSUFBSSxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7QUFFekQ7O0dBRUc7QUFDb0IsZUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBb0J2RDs7OztHQUlHO0FBQ0gsSUFBWSxRQW1DWDtBQW5DRCxXQUFZLFFBQVE7SUFDbEI7O09BRUc7SUFDSCxtQ0FBdUIsQ0FBQTtJQUV2Qjs7T0FFRztJQUNILDZCQUFp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IHsgRU9MIH0gZnJvbSAnb3MnO1xuaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQgKiBhcyBldmVudHMgZnJvbSAnYXdzLWNkay1saWIvYXdzLWV2ZW50cyc7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBsb2dzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sb2dzJztcbmltcG9ydCAqIGFzIHMzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWIvY29yZSc7XG5pbXBvcnQgKiBhcyBjb25zdHJ1Y3RzIGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgQ29kZSwgR2x1ZVZlcnNpb24sIEpvYkV4ZWN1dGFibGUsIEpvYkV4ZWN1dGFibGVDb25maWcsIEpvYlR5cGUgfSBmcm9tICcuJztcbmltcG9ydCB7IElDb25uZWN0aW9uIH0gZnJvbSAnLi9jb25uZWN0aW9uJztcbmltcG9ydCB7IENmbkpvYiB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1nbHVlJztcbmltcG9ydCB7IElTZWN1cml0eUNvbmZpZ3VyYXRpb24gfSBmcm9tICcuL3NlY3VyaXR5LWNvbmZpZ3VyYXRpb24nO1xuXG4vKipcbiAqIFRoZSB0eXBlIG9mIHByZWRlZmluZWQgd29ya2VyIHRoYXQgaXMgYWxsb2NhdGVkIHdoZW4gYSBqb2IgcnVucy5cbiAqXG4gKiBJZiB5b3UgbmVlZCB0byB1c2UgYSBXb3JrZXJUeXBlIHRoYXQgZG9lc24ndCBleGlzdCBhcyBhIHN0YXRpYyBtZW1iZXIsIHlvdVxuICogY2FuIGluc3RhbnRpYXRlIGEgYFdvcmtlclR5cGVgIG9iamVjdCwgZS5nOiBgV29ya2VyVHlwZS5vZignb3RoZXIgdHlwZScpYC5cbiAqL1xuZXhwb3J0IGNsYXNzIFdvcmtlclR5cGUge1xuICAvKipcbiAgICogRWFjaCB3b3JrZXIgcHJvdmlkZXMgNCB2Q1BVLCAxNiBHQiBvZiBtZW1vcnkgYW5kIGEgNTBHQiBkaXNrLCBhbmQgMiBleGVjdXRvcnMgcGVyIHdvcmtlci5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgU1RBTkRBUkQgPSBuZXcgV29ya2VyVHlwZSgnU3RhbmRhcmQnKTtcblxuICAvKipcbiAgICogRWFjaCB3b3JrZXIgbWFwcyB0byAxIERQVSAoNCB2Q1BVLCAxNiBHQiBvZiBtZW1vcnksIDY0IEdCIGRpc2spLCBhbmQgcHJvdmlkZXMgMSBleGVjdXRvciBwZXIgd29ya2VyLiBTdWl0YWJsZSBmb3IgbWVtb3J5LWludGVuc2l2ZSBqb2JzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBHXzFYID0gbmV3IFdvcmtlclR5cGUoJ0cuMVgnKTtcblxuICAvKipcbiAgICogRWFjaCB3b3JrZXIgbWFwcyB0byAyIERQVSAoOCB2Q1BVLCAzMiBHQiBvZiBtZW1vcnksIDEyOCBHQiBkaXNrKSwgYW5kIHByb3ZpZGVzIDEgZXhlY3V0b3IgcGVyIHdvcmtlci4gU3VpdGFibGUgZm9yIG1lbW9yeS1pbnRlbnNpdmUgam9icy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgR18yWCA9IG5ldyBXb3JrZXJUeXBlKCdHLjJYJyk7XG5cbiAgLyoqXG4gICAqIEVhY2ggd29ya2VyIG1hcHMgdG8gNCBEUFUgKDE2IHZDUFUsIDY0IEdCIG9mIG1lbW9yeSwgMjU2IEdCIGRpc2spLCBhbmQgcHJvdmlkZXMgMSBleGVjdXRvciBwZXIgd29ya2VyLiBXZSByZWNvbW1lbmQgdGhpcyB3b3JrZXIgdHlwZSBmb3Igam9icyB3aG9zZSB3b3JrbG9hZHMgY29udGFpbiB5b3VyIG1vc3QgZGVtYW5kaW5nIHRyYW5zZm9ybXMsIGFnZ3JlZ2F0aW9ucywgam9pbnMsIGFuZCBxdWVyaWVzLiBUaGlzIHdvcmtlciB0eXBlIGlzIGF2YWlsYWJsZSBvbmx5IGZvciBBV1MgR2x1ZSB2ZXJzaW9uIDMuMCBvciBsYXRlciBqb2JzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBHXzRYID0gbmV3IFdvcmtlclR5cGUoJ0cuNFgnKTtcblxuICAvKipcbiAgICogRWFjaCB3b3JrZXIgbWFwcyB0byA4IERQVSAoMzIgdkNQVSwgMTI4IEdCIG9mIG1lbW9yeSwgNTEyIEdCIGRpc2spLCBhbmQgcHJvdmlkZXMgMSBleGVjdXRvciBwZXIgd29ya2VyLiBXZSByZWNvbW1lbmQgdGhpcyB3b3JrZXIgdHlwZSBmb3Igam9icyB3aG9zZSB3b3JrbG9hZHMgY29udGFpbiB5b3VyIG1vc3QgZGVtYW5kaW5nIHRyYW5zZm9ybXMsIGFnZ3JlZ2F0aW9ucywgam9pbnMsIGFuZCBxdWVyaWVzLiBUaGlzIHdvcmtlciB0eXBlIGlzIGF2YWlsYWJsZSBvbmx5IGZvciBBV1MgR2x1ZSB2ZXJzaW9uIDMuMCBvciBsYXRlciBqb2JzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBHXzhYID0gbmV3IFdvcmtlclR5cGUoJ0cuOFgnKTtcblxuICAvKipcbiAgICogRWFjaCB3b3JrZXIgbWFwcyB0byAwLjI1IERQVSAoMiB2Q1BVLCA0IEdCIG9mIG1lbW9yeSwgNjQgR0IgZGlzayksIGFuZCBwcm92aWRlcyAxIGV4ZWN1dG9yIHBlciB3b3JrZXIuIFN1aXRhYmxlIGZvciBsb3cgdm9sdW1lIHN0cmVhbWluZyBqb2JzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBHXzAyNVggPSBuZXcgV29ya2VyVHlwZSgnRy4wMjVYJyk7XG5cbiAgLyoqXG4gICAqIEVhY2ggd29ya2VyIG1hcHMgdG8gMiBoaWdoLW1lbW9yeSBEUFUgW00tRFBVXSAoOCB2Q1BVLCA2NCBHQiBvZiBtZW1vcnksIDEyOCBHQiBkaXNrKS4gU3VwcG9ydGVkIGluIFJheSBqb2JzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBaXzJYID0gbmV3IFdvcmtlclR5cGUoJ1ouMlgnKTtcblxuICAvKipcbiAgICogQ3VzdG9tIHdvcmtlciB0eXBlXG4gICAqIEBwYXJhbSB3b3JrZXJUeXBlIGN1c3RvbSB3b3JrZXIgdHlwZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBvZih3b3JrZXJUeXBlOiBzdHJpbmcpOiBXb3JrZXJUeXBlIHtcbiAgICByZXR1cm4gbmV3IFdvcmtlclR5cGUod29ya2VyVHlwZSk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhpcyBXb3JrZXJUeXBlLCBhcyBleHBlY3RlZCBieSBKb2IgcmVzb3VyY2UuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IobmFtZTogc3RyaW5nKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG4vKipcbiAqIEpvYiBzdGF0ZXMgZW1pdHRlZCBieSBHbHVlIHRvIENsb3VkV2F0Y2ggRXZlbnRzLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkV2F0Y2gvbGF0ZXN0L2V2ZW50cy9FdmVudFR5cGVzLmh0bWwjZ2x1ZS1ldmVudC10eXBlc1xuICovXG5leHBvcnQgZW51bSBKb2JTdGF0ZSB7XG4gIC8qKlxuICAgKiBTdGF0ZSBpbmRpY2F0aW5nIGpvYiBydW4gc3VjY2VlZGVkXG4gICAqL1xuICBTVUNDRUVERUQgPSAnU1VDQ0VFREVEJyxcblxuICAvKipcbiAgICogU3RhdGUgaW5kaWNhdGluZyBqb2IgcnVuIGZhaWxlZFxuICAgKi9cbiAgRkFJTEVEID0gJ0ZBSUxFRCcsXG5cbiAgLyoqXG4gICAqIFN0YXRlIGluZGljYXRpbmcgam9iIHJ1biB0aW1lZCBvdXRcbiAgICovXG4gIFRJTUVPVVQgPSAnVElNRU9VVCcsXG5cbiAgLyoqXG4gICAqIFN0YXRlIGluZGljYXRpbmcgam9iIGlzIHN0YXJ0aW5nXG4gICAqL1xuICBTVEFSVElORyA9ICdTVEFSVElORycsXG5cbiAgLyoqXG4gICAqIFN0YXRlIGluZGljYXRpbmcgam9iIGlzIHJ1bm5pbmdcbiAgICovXG4gIFJVTk5JTkcgPSAnUlVOTklORycsXG5cbiAgLyoqXG4gICAqIFN0YXRlIGluZGljYXRpbmcgam9iIGlzIHN0b3BwaW5nXG4gICAqL1xuICBTVE9QUElORyA9ICdTVE9QUElORycsXG5cbiAgLyoqXG4gICAqIFN0YXRlIGluZGljYXRpbmcgam9iIHN0b3BwZWRcbiAgICovXG4gIFNUT1BQRUQgPSAnU1RPUFBFRCcsXG59XG5cbi8qKlxuICogVGhlIEdsdWUgQ2xvdWRXYXRjaCBtZXRyaWMgdHlwZS5cbiAqXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy9tb25pdG9yaW5nLWF3c2dsdWUtd2l0aC1jbG91ZHdhdGNoLW1ldHJpY3MuaHRtbFxuICovXG5leHBvcnQgZW51bSBNZXRyaWNUeXBlIHtcbiAgLyoqXG4gICAqIEEgdmFsdWUgYXQgYSBwb2ludCBpbiB0aW1lLlxuICAgKi9cbiAgR0FVR0UgPSAnZ2F1Z2UnLFxuXG4gIC8qKlxuICAgKiBBbiBhZ2dyZWdhdGUgbnVtYmVyLlxuICAgKi9cbiAgQ09VTlQgPSAnY291bnQnLFxufVxuXG4vKipcbiAqIFRoZSBFeGVjdXRpb25DbGFzcyB3aGV0aGVyIHRoZSBqb2IgaXMgcnVuIHdpdGggYSBzdGFuZGFyZCBvciBmbGV4aWJsZSBleGVjdXRpb24gY2xhc3MuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZ2x1ZS9sYXRlc3QvZGcvYXdzLWdsdWUtYXBpLWpvYnMtam9iLmh0bWwjYXdzLWdsdWUtYXBpLWpvYnMtam9iLUpvYlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZ2x1ZS9sYXRlc3QvZGcvYWRkLWpvYi5odG1sXG4gKi9cbmV4cG9ydCBlbnVtIEV4ZWN1dGlvbkNsYXNzIHtcbiAgLyoqXG4gICAqIFRoZSBmbGV4aWJsZSBleGVjdXRpb24gY2xhc3MgaXMgYXBwcm9wcmlhdGUgZm9yIHRpbWUtaW5zZW5zaXRpdmUgam9icyB3aG9zZSBzdGFydFxuICAgKiBhbmQgY29tcGxldGlvbiB0aW1lcyBtYXkgdmFyeS5cbiAgICovXG4gIEZMRVggPSAnRkxFWCcsXG5cbiAgLyoqXG4gICAqIFRoZSBzdGFuZGFyZCBleGVjdXRpb24gY2xhc3MgaXMgaWRlYWwgZm9yIHRpbWUtc2Vuc2l0aXZlIHdvcmtsb2FkcyB0aGF0IHJlcXVpcmUgZmFzdCBqb2JcbiAgICogc3RhcnR1cCBhbmQgZGVkaWNhdGVkIHJlc291cmNlcy5cbiAgICovXG4gIFNUQU5EQVJEID0gJ1NUQU5EQVJEJyxcbn1cblxuLyoqXG4gKiBJbnRlcmZhY2UgcmVwcmVzZW50aW5nIGEgY3JlYXRlZCBvciBhbiBpbXBvcnRlZCBgSm9iYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJSm9iIGV4dGVuZHMgY2RrLklSZXNvdXJjZSwgaWFtLklHcmFudGFibGUge1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGpvYi5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgam9iTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgQVJOIG9mIHRoZSBqb2IuXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IGpvYkFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGEgQ2xvdWRXYXRjaCBldmVudCBydWxlIHRyaWdnZXJlZCB3aGVuIHNvbWV0aGluZyBoYXBwZW5zIHdpdGggdGhpcyBqb2IuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkV2F0Y2gvbGF0ZXN0L2V2ZW50cy9FdmVudFR5cGVzLmh0bWwjZ2x1ZS1ldmVudC10eXBlc1xuICAgKi9cbiAgb25FdmVudChpZDogc3RyaW5nLCBvcHRpb25zPzogZXZlbnRzLk9uRXZlbnRPcHRpb25zKTogZXZlbnRzLlJ1bGU7XG5cbiAgLyoqXG4gICAqIERlZmluZXMgYSBDbG91ZFdhdGNoIGV2ZW50IHJ1bGUgdHJpZ2dlcmVkIHdoZW4gdGhpcyBqb2IgbW92ZXMgdG8gdGhlIGlucHV0IGpvYlN0YXRlLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZFdhdGNoL2xhdGVzdC9ldmVudHMvRXZlbnRUeXBlcy5odG1sI2dsdWUtZXZlbnQtdHlwZXNcbiAgICovXG4gIG9uU3RhdGVDaGFuZ2UoaWQ6IHN0cmluZywgam9iU3RhdGU6IEpvYlN0YXRlLCBvcHRpb25zPzogZXZlbnRzLk9uRXZlbnRPcHRpb25zKTogZXZlbnRzLlJ1bGU7XG5cbiAgLyoqXG4gICAqIERlZmluZXMgYSBDbG91ZFdhdGNoIGV2ZW50IHJ1bGUgdHJpZ2dlcmVkIHdoZW4gdGhpcyBqb2IgbW92ZXMgdG8gdGhlIFNVQ0NFRURFRCBzdGF0ZS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRXYXRjaC9sYXRlc3QvZXZlbnRzL0V2ZW50VHlwZXMuaHRtbCNnbHVlLWV2ZW50LXR5cGVzXG4gICAqL1xuICBvblN1Y2Nlc3MoaWQ6IHN0cmluZywgb3B0aW9ucz86IGV2ZW50cy5PbkV2ZW50T3B0aW9ucyk6IGV2ZW50cy5SdWxlO1xuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGEgQ2xvdWRXYXRjaCBldmVudCBydWxlIHRyaWdnZXJlZCB3aGVuIHRoaXMgam9iIG1vdmVzIHRvIHRoZSBGQUlMRUQgc3RhdGUuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkV2F0Y2gvbGF0ZXN0L2V2ZW50cy9FdmVudFR5cGVzLmh0bWwjZ2x1ZS1ldmVudC10eXBlc1xuICAgKi9cbiAgb25GYWlsdXJlKGlkOiBzdHJpbmcsIG9wdGlvbnM/OiBldmVudHMuT25FdmVudE9wdGlvbnMpOiBldmVudHMuUnVsZTtcblxuICAvKipcbiAgICogRGVmaW5lcyBhIENsb3VkV2F0Y2ggZXZlbnQgcnVsZSB0cmlnZ2VyZWQgd2hlbiB0aGlzIGpvYiBtb3ZlcyB0byB0aGUgVElNRU9VVCBzdGF0ZS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRXYXRjaC9sYXRlc3QvZXZlbnRzL0V2ZW50VHlwZXMuaHRtbCNnbHVlLWV2ZW50LXR5cGVzXG4gICAqL1xuICBvblRpbWVvdXQoaWQ6IHN0cmluZywgb3B0aW9ucz86IGV2ZW50cy5PbkV2ZW50T3B0aW9ucyk6IGV2ZW50cy5SdWxlO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBDbG91ZFdhdGNoIG1ldHJpYy5cbiAgICpcbiAgICogQHBhcmFtIG1ldHJpY05hbWUgbmFtZSBvZiB0aGUgbWV0cmljIHR5cGljYWxseSBwcmVmaXhlZCB3aXRoIGBnbHVlLmRyaXZlci5gLCBgZ2x1ZS48ZXhlY3V0b3JJZD4uYCBvciBgZ2x1ZS5BTEwuYC5cbiAgICogQHBhcmFtIHR5cGUgdGhlIG1ldHJpYyB0eXBlLlxuICAgKiBAcGFyYW0gcHJvcHMgbWV0cmljIG9wdGlvbnMuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL21vbml0b3JpbmctYXdzZ2x1ZS13aXRoLWNsb3Vkd2F0Y2gtbWV0cmljcy5odG1sXG4gICAqL1xuICBtZXRyaWMobWV0cmljTmFtZTogc3RyaW5nLCB0eXBlOiBNZXRyaWNUeXBlLCBwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBDbG91ZFdhdGNoIE1ldHJpYyBpbmRpY2F0aW5nIGpvYiBzdWNjZXNzLlxuICAgKi9cbiAgbWV0cmljU3VjY2Vzcyhwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBDbG91ZFdhdGNoIE1ldHJpYyBpbmRpY2F0aW5nIGpvYiBmYWlsdXJlLlxuICAgKi9cbiAgbWV0cmljRmFpbHVyZShwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBDbG91ZFdhdGNoIE1ldHJpYyBpbmRpY2F0aW5nIGpvYiB0aW1lb3V0LlxuICAgKi9cbiAgbWV0cmljVGltZW91dChwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xufVxuXG5hYnN0cmFjdCBjbGFzcyBKb2JCYXNlIGV4dGVuZHMgY2RrLlJlc291cmNlIGltcGxlbWVudHMgSUpvYiB7XG5cbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IGpvYkFybjogc3RyaW5nO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgam9iTmFtZTogc3RyaW5nO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgZ3JhbnRQcmluY2lwYWw6IGlhbS5JUHJpbmNpcGFsO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBDbG91ZFdhdGNoIEV2ZW50IFJ1bGUgZm9yIHRoaXMgR2x1ZSBKb2Igd2hlbiBpdCdzIGluIGEgZ2l2ZW4gc3RhdGVcbiAgICpcbiAgICogQHBhcmFtIGlkIGNvbnN0cnVjdCBpZFxuICAgKiBAcGFyYW0gb3B0aW9ucyBldmVudCBvcHRpb25zLiBOb3RlIHRoYXQgc29tZSB2YWx1ZXMgYXJlIG92ZXJyaWRkZW4gaWYgcHJvdmlkZWQsIHRoZXNlIGFyZVxuICAgKiAgLSBldmVudFBhdHRlcm4uc291cmNlID0gWydhd3MuZ2x1ZSddXG4gICAqICAtIGV2ZW50UGF0dGVybi5kZXRhaWxUeXBlID0gWydHbHVlIEpvYiBTdGF0ZSBDaGFuZ2UnLCAnR2x1ZSBKb2IgUnVuIFN0YXR1cyddXG4gICAqICAtIGV2ZW50UGF0dGVybi5kZXRhaWwuam9iTmFtZSA9IFt0aGlzLmpvYk5hbWVdXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkV2F0Y2gvbGF0ZXN0L2V2ZW50cy9FdmVudFR5cGVzLmh0bWwjZ2x1ZS1ldmVudC10eXBlc1xuICAgKi9cbiAgcHVibGljIG9uRXZlbnQoaWQ6IHN0cmluZywgb3B0aW9uczogZXZlbnRzLk9uRXZlbnRPcHRpb25zID0ge30pOiBldmVudHMuUnVsZSB7XG4gICAgY29uc3QgcnVsZSA9IG5ldyBldmVudHMuUnVsZSh0aGlzLCBpZCwgb3B0aW9ucyk7XG4gICAgcnVsZS5hZGRUYXJnZXQob3B0aW9ucy50YXJnZXQpO1xuICAgIHJ1bGUuYWRkRXZlbnRQYXR0ZXJuKHtcbiAgICAgIHNvdXJjZTogWydhd3MuZ2x1ZSddLFxuICAgICAgZGV0YWlsVHlwZTogWydHbHVlIEpvYiBTdGF0ZSBDaGFuZ2UnLCAnR2x1ZSBKb2IgUnVuIFN0YXR1cyddLFxuICAgICAgZGV0YWlsOiB7XG4gICAgICAgIGpvYk5hbWU6IFt0aGlzLmpvYk5hbWVdLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICByZXR1cm4gcnVsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBDbG91ZFdhdGNoIEV2ZW50IFJ1bGUgZm9yIHRoZSB0cmFuc2l0aW9uIGludG8gdGhlIGlucHV0IGpvYlN0YXRlLlxuICAgKlxuICAgKiBAcGFyYW0gaWQgY29uc3RydWN0IGlkLlxuICAgKiBAcGFyYW0gam9iU3RhdGUgdGhlIGpvYiBzdGF0ZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgb3B0aW9uYWwgZXZlbnQgb3B0aW9ucy5cbiAgICovXG4gIHB1YmxpYyBvblN0YXRlQ2hhbmdlKGlkOiBzdHJpbmcsIGpvYlN0YXRlOiBKb2JTdGF0ZSwgb3B0aW9uczogZXZlbnRzLk9uRXZlbnRPcHRpb25zID0ge30pOiBldmVudHMuUnVsZSB7XG4gICAgY29uc3QgcnVsZSA9IHRoaXMub25FdmVudChpZCwge1xuICAgICAgZGVzY3JpcHRpb246IGBSdWxlIHRyaWdnZXJlZCB3aGVuIEdsdWUgam9iICR7dGhpcy5qb2JOYW1lfSBpcyBpbiAke2pvYlN0YXRlfSBzdGF0ZWAsXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH0pO1xuICAgIHJ1bGUuYWRkRXZlbnRQYXR0ZXJuKHtcbiAgICAgIGRldGFpbDoge1xuICAgICAgICBzdGF0ZTogW2pvYlN0YXRlXSxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgcmV0dXJuIHJ1bGU7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgQ2xvdWRXYXRjaCBFdmVudCBSdWxlIG1hdGNoaW5nIEpvYlN0YXRlLlNVQ0NFRURFRC5cbiAgICpcbiAgICogQHBhcmFtIGlkIGNvbnN0cnVjdCBpZC5cbiAgICogQHBhcmFtIG9wdGlvbnMgb3B0aW9uYWwgZXZlbnQgb3B0aW9ucy4gZGVmYXVsdCBpcyB7fS5cbiAgICovXG4gIHB1YmxpYyBvblN1Y2Nlc3MoaWQ6IHN0cmluZywgb3B0aW9uczogZXZlbnRzLk9uRXZlbnRPcHRpb25zID0ge30pOiBldmVudHMuUnVsZSB7XG4gICAgcmV0dXJuIHRoaXMub25TdGF0ZUNoYW5nZShpZCwgSm9iU3RhdGUuU1VDQ0VFREVELCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBDbG91ZFdhdGNoIEV2ZW50IFJ1bGUgbWF0Y2hpbmcgRkFJTEVEIHN0YXRlLlxuICAgKlxuICAgKiBAcGFyYW0gaWQgY29uc3RydWN0IGlkLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBvcHRpb25hbCBldmVudCBvcHRpb25zLiBkZWZhdWx0IGlzIHt9LlxuICAgKi9cbiAgcHVibGljIG9uRmFpbHVyZShpZDogc3RyaW5nLCBvcHRpb25zOiBldmVudHMuT25FdmVudE9wdGlvbnMgPSB7fSk6IGV2ZW50cy5SdWxlIHtcbiAgICByZXR1cm4gdGhpcy5vblN0YXRlQ2hhbmdlKGlkLCBKb2JTdGF0ZS5GQUlMRUQsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIENsb3VkV2F0Y2ggRXZlbnQgUnVsZSBtYXRjaGluZyBUSU1FT1VUIHN0YXRlLlxuICAgKlxuICAgKiBAcGFyYW0gaWQgY29uc3RydWN0IGlkLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBvcHRpb25hbCBldmVudCBvcHRpb25zLiBkZWZhdWx0IGlzIHt9LlxuICAgKi9cbiAgcHVibGljIG9uVGltZW91dChpZDogc3RyaW5nLCBvcHRpb25zOiBldmVudHMuT25FdmVudE9wdGlvbnMgPSB7fSk6IGV2ZW50cy5SdWxlIHtcbiAgICByZXR1cm4gdGhpcy5vblN0YXRlQ2hhbmdlKGlkLCBKb2JTdGF0ZS5USU1FT1VULCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBDbG91ZFdhdGNoIG1ldHJpYy5cbiAgICpcbiAgICogQHBhcmFtIG1ldHJpY05hbWUgbmFtZSBvZiB0aGUgbWV0cmljIHR5cGljYWxseSBwcmVmaXhlZCB3aXRoIGBnbHVlLmRyaXZlci5gLCBgZ2x1ZS48ZXhlY3V0b3JJZD4uYCBvciBgZ2x1ZS5BTEwuYC5cbiAgICogQHBhcmFtIHR5cGUgdGhlIG1ldHJpYyB0eXBlLlxuICAgKiBAcGFyYW0gcHJvcHMgbWV0cmljIG9wdGlvbnMuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL21vbml0b3JpbmctYXdzZ2x1ZS13aXRoLWNsb3Vkd2F0Y2gtbWV0cmljcy5odG1sXG4gICAqL1xuICBwdWJsaWMgbWV0cmljKG1ldHJpY05hbWU6IHN0cmluZywgdHlwZTogTWV0cmljVHlwZSwgcHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICBtZXRyaWNOYW1lLFxuICAgICAgbmFtZXNwYWNlOiAnR2x1ZScsXG4gICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgIEpvYk5hbWU6IHRoaXMuam9iTmFtZSxcbiAgICAgICAgSm9iUnVuSWQ6ICdBTEwnLFxuICAgICAgICBUeXBlOiB0eXBlLFxuICAgICAgfSxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pLmF0dGFjaFRvKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIENsb3VkV2F0Y2ggTWV0cmljIGluZGljYXRpbmcgam9iIHN1Y2Nlc3MuXG4gICAqXG4gICAqIFRoaXMgbWV0cmljIGlzIGJhc2VkIG9uIHRoZSBSdWxlIHJldHVybmVkIGJ5IG5vLWFyZ3Mgb25TdWNjZXNzKCkgY2FsbC5cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNTdWNjZXNzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiBtZXRyaWNSdWxlKHRoaXMubWV0cmljSm9iU3RhdGVSdWxlKCdTdWNjZXNzTWV0cmljUnVsZScsIEpvYlN0YXRlLlNVQ0NFRURFRCksIHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBDbG91ZFdhdGNoIE1ldHJpYyBpbmRpY2F0aW5nIGpvYiBmYWlsdXJlLlxuICAgKlxuICAgKiBUaGlzIG1ldHJpYyBpcyBiYXNlZCBvbiB0aGUgUnVsZSByZXR1cm5lZCBieSBuby1hcmdzIG9uRmFpbHVyZSgpIGNhbGwuXG4gICAqL1xuICBwdWJsaWMgbWV0cmljRmFpbHVyZShwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gbWV0cmljUnVsZSh0aGlzLm1ldHJpY0pvYlN0YXRlUnVsZSgnRmFpbHVyZU1ldHJpY1J1bGUnLCBKb2JTdGF0ZS5GQUlMRUQpLCBwcm9wcyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGEgQ2xvdWRXYXRjaCBNZXRyaWMgaW5kaWNhdGluZyBqb2IgdGltZW91dC5cbiAgICpcbiAgICogVGhpcyBtZXRyaWMgaXMgYmFzZWQgb24gdGhlIFJ1bGUgcmV0dXJuZWQgYnkgbm8tYXJncyBvblRpbWVvdXQoKSBjYWxsLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY1RpbWVvdXQocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIG1ldHJpY1J1bGUodGhpcy5tZXRyaWNKb2JTdGF0ZVJ1bGUoJ1RpbWVvdXRNZXRyaWNSdWxlJywgSm9iU3RhdGUuVElNRU9VVCksIHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIG9yIHJldHJpZXZlcyBhIHNpbmdsZXRvbiBldmVudCBydWxlIGZvciB0aGUgaW5wdXQgam9iIHN0YXRlIGZvciB1c2Ugd2l0aCB0aGUgbWV0cmljIEpvYlN0YXRlIG1ldGhvZHMuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBjb25zdHJ1Y3QgaWQuXG4gICAqIEBwYXJhbSBqb2JTdGF0ZSB0aGUgam9iIHN0YXRlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBtZXRyaWNKb2JTdGF0ZVJ1bGUoaWQ6IHN0cmluZywgam9iU3RhdGU6IEpvYlN0YXRlKTogZXZlbnRzLlJ1bGUge1xuICAgIHJldHVybiB0aGlzLm5vZGUudHJ5RmluZENoaWxkKGlkKSBhcyBldmVudHMuUnVsZSA/PyB0aGlzLm9uU3RhdGVDaGFuZ2UoaWQsIGpvYlN0YXRlKTtcbiAgfVxufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGVuYWJsaW5nIFNwYXJrIFVJIG1vbml0b3JpbmcgZmVhdHVyZSBmb3IgU3BhcmstYmFzZWQgR2x1ZSBqb2JzLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL21vbml0b3Itc3BhcmstdWktam9icy5odG1sXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy9hd3MtZ2x1ZS1wcm9ncmFtbWluZy1ldGwtZ2x1ZS1hcmd1bWVudHMuaHRtbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNwYXJrVUlQcm9wcyB7XG4gIC8qKlxuICAgKiBFbmFibGUgU3BhcmsgVUkuXG4gICAqL1xuICByZWFkb25seSBlbmFibGVkOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgYnVja2V0IHdoZXJlIHRoZSBHbHVlIGpvYiBzdG9yZXMgdGhlIGxvZ3MuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYSBuZXcgYnVja2V0IHdpbGwgYmUgY3JlYXRlZC5cbiAgICovXG4gIHJlYWRvbmx5IGJ1Y2tldD86IHMzLklCdWNrZXQ7XG5cbiAgLyoqXG4gICAqIFRoZSBwYXRoIGluc2lkZSB0aGUgYnVja2V0IChvYmplY3RzIHByZWZpeCkgd2hlcmUgdGhlIEdsdWUgam9iIHN0b3JlcyB0aGUgbG9ncy5cbiAgICogVXNlIGZvcm1hdCBgJ2Zvby9iYXIvJ2BcbiAgICpcbiAgICogQGRlZmF1bHQgLSB0aGUgbG9ncyB3aWxsIGJlIHdyaXR0ZW4gYXQgdGhlIHJvb3Qgb2YgdGhlIGJ1Y2tldFxuICAgKi9cbiAgcmVhZG9ubHkgcHJlZml4Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBTcGFyayBVSSBsb2dnaW5nIGxvY2F0aW9uLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL21vbml0b3Itc3BhcmstdWktam9icy5odG1sXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy9hd3MtZ2x1ZS1wcm9ncmFtbWluZy1ldGwtZ2x1ZS1hcmd1bWVudHMuaHRtbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNwYXJrVUlMb2dnaW5nTG9jYXRpb24ge1xuICAvKipcbiAgICogVGhlIGJ1Y2tldCB3aGVyZSB0aGUgR2x1ZSBqb2Igc3RvcmVzIHRoZSBsb2dzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGEgbmV3IGJ1Y2tldCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAqL1xuICByZWFkb25seSBidWNrZXQ6IHMzLklCdWNrZXQ7XG5cbiAgLyoqXG4gICAqIFRoZSBwYXRoIGluc2lkZSB0aGUgYnVja2V0IChvYmplY3RzIHByZWZpeCkgd2hlcmUgdGhlIEdsdWUgam9iIHN0b3JlcyB0aGUgbG9ncy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0aGUgbG9ncyB3aWxsIGJlIHdyaXR0ZW4gYXQgdGhlIHJvb3Qgb2YgdGhlIGJ1Y2tldFxuICAgKi9cbiAgcmVhZG9ubHkgcHJlZml4Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGVuYWJsaW5nIENvbnRpbnVvdXMgTG9nZ2luZyBmb3IgR2x1ZSBKb2JzLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL21vbml0b3ItY29udGludW91cy1sb2dnaW5nLWVuYWJsZS5odG1sXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy9hd3MtZ2x1ZS1wcm9ncmFtbWluZy1ldGwtZ2x1ZS1hcmd1bWVudHMuaHRtbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbnRpbnVvdXNMb2dnaW5nUHJvcHMge1xuICAvKipcbiAgICogRW5hYmxlIGNvbnRpbnVvdXMgbG9nZ2luZy5cbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZWQ6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgYSBjdXN0b20gQ2xvdWRXYXRjaCBsb2cgZ3JvdXAgbmFtZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBhIGxvZyBncm91cCBpcyBjcmVhdGVkIHdpdGggbmFtZSBgL2F3cy1nbHVlL2pvYnMvbG9ncy12Mi9gLlxuICAgKi9cbiAgcmVhZG9ubHkgbG9nR3JvdXA/OiBsb2dzLklMb2dHcm91cDtcblxuICAvKipcbiAgICogU3BlY2lmeSBhIGN1c3RvbSBDbG91ZFdhdGNoIGxvZyBzdHJlYW0gcHJlZml4LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHRoZSBqb2IgcnVuIElELlxuICAgKi9cbiAgcmVhZG9ubHkgbG9nU3RyZWFtUHJlZml4Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBGaWx0ZXIgb3V0IG5vbi11c2VmdWwgQXBhY2hlIFNwYXJrIGRyaXZlci9leGVjdXRvciBhbmQgQXBhY2hlIEhhZG9vcCBZQVJOIGhlYXJ0YmVhdCBsb2cgbWVzc2FnZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHF1aWV0PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQXBwbHkgdGhlIHByb3ZpZGVkIGNvbnZlcnNpb24gcGF0dGVybi5cbiAgICpcbiAgICogVGhpcyBpcyBhIExvZzRqIENvbnZlcnNpb24gUGF0dGVybiB0byBjdXN0b21pemUgZHJpdmVyIGFuZCBleGVjdXRvciBsb2dzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBgJWR7eXkvTU0vZGQgSEg6bW06c3N9ICVwICVjezF9OiAlbSVuYFxuICAgKi9cbiAgcmVhZG9ubHkgY29udmVyc2lvblBhdHRlcm4/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQXR0cmlidXRlcyBmb3IgaW1wb3J0aW5nIGBKb2JgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEpvYkF0dHJpYnV0ZXMge1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGpvYi5cbiAgICovXG4gIHJlYWRvbmx5IGpvYk5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIElBTSByb2xlIGFzc3VtZWQgYnkgR2x1ZSB0byBydW4gdGhpcyBqb2IuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdW5kZWZpbmVkXG4gICAqL1xuICByZWFkb25seSByb2xlPzogaWFtLklSb2xlO1xufVxuXG4vKipcbiAqIENvbnN0cnVjdGlvbiBwcm9wZXJ0aWVzIGZvciBgSm9iYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBKb2JQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgam9iJ3MgZXhlY3V0YWJsZSBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhlY3V0YWJsZTogSm9iRXhlY3V0YWJsZTtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGpvYi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBhIG5hbWUgaXMgYXV0b21hdGljYWxseSBnZW5lcmF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IGpvYk5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBkZXNjcmlwdGlvbiBvZiB0aGUgam9iLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHZhbHVlXG4gICAqL1xuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcblxuICAvKipcbiAgICogU3BlY2lmaWVzIHdoZXRoZXIgam9iIHJ1biBxdWV1aW5nIGlzIGVuYWJsZWQgZm9yIHRoZSBqb2IgcnVucyBmb3IgdGhpcyBqb2IuXG4gICAqIEEgdmFsdWUgb2YgdHJ1ZSBtZWFucyBqb2IgcnVuIHF1ZXVpbmcgaXMgZW5hYmxlZCBmb3IgdGhlIGpvYiBydW5zLlxuICAgKiBJZiBmYWxzZSBvciBub3QgcG9wdWxhdGVkLCB0aGUgam9iIHJ1bnMgd2lsbCBub3QgYmUgY29uc2lkZXJlZCBmb3IgcXVldWVpbmcuXG4gICAqIElmIHRoaXMgZmllbGQgZG9lcyBub3QgbWF0Y2ggdGhlIHZhbHVlIHNldCBpbiB0aGUgam9iIHJ1biwgdGhlbiB0aGUgdmFsdWUgZnJvbSB0aGUgam9iIHJ1biBmaWVsZCB3aWxsIGJlIHVzZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gam9iIHJ1biBxdWV1aW5nXG4gICAqL1xuICByZWFkb25seSBqb2JSdW5RdWV1aW5nRW5hYmxlZD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgQVdTIEdsdWUgZGF0YSBwcm9jZXNzaW5nIHVuaXRzIChEUFVzKSB0aGF0IGNhbiBiZSBhbGxvY2F0ZWQgd2hlbiB0aGlzIGpvYiBydW5zLlxuICAgKiBDYW5ub3QgYmUgdXNlZCBmb3IgR2x1ZSB2ZXJzaW9uIDIuMCBhbmQgbGF0ZXIgLSB3b3JrZXJUeXBlIGFuZCB3b3JrZXJDb3VudCBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIDEwIHdoZW4gam9iIHR5cGUgaXMgQXBhY2hlIFNwYXJrIEVUTCBvciBzdHJlYW1pbmcsIDAuMDYyNSB3aGVuIGpvYiB0eXBlIGlzIFB5dGhvbiBzaGVsbFxuICAgKi9cbiAgcmVhZG9ubHkgbWF4Q2FwYWNpdHk/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcyB0byByZXRyeSB0aGlzIGpvYiBhZnRlciBhIGpvYiBydW4gZmFpbHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IDBcbiAgICovXG4gIHJlYWRvbmx5IG1heFJldHJpZXM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIG51bWJlciBvZiBjb25jdXJyZW50IHJ1bnMgYWxsb3dlZCBmb3IgdGhlIGpvYi5cbiAgICpcbiAgICogQW4gZXJyb3IgaXMgcmV0dXJuZWQgd2hlbiB0aGlzIHRocmVzaG9sZCBpcyByZWFjaGVkLiBUaGUgbWF4aW11bSB2YWx1ZSB5b3UgY2FuIHNwZWNpZnkgaXMgY29udHJvbGxlZCBieSBhIHNlcnZpY2UgbGltaXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDFcbiAgICovXG4gIHJlYWRvbmx5IG1heENvbmN1cnJlbnRSdW5zPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIG1pbnV0ZXMgdG8gd2FpdCBhZnRlciBhIGpvYiBydW4gc3RhcnRzLCBiZWZvcmUgc2VuZGluZyBhIGpvYiBydW4gZGVsYXkgbm90aWZpY2F0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGRlbGF5IG5vdGlmaWNhdGlvbnNcbiAgICovXG4gIHJlYWRvbmx5IG5vdGlmeURlbGF5QWZ0ZXI/OiBjZGsuRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIHRpbWUgdGhhdCBhIGpvYiBydW4gY2FuIGNvbnN1bWUgcmVzb3VyY2VzIGJlZm9yZSBpdCBpcyB0ZXJtaW5hdGVkIGFuZCBlbnRlcnMgVElNRU9VVCBzdGF0dXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IGNkay5EdXJhdGlvbi5ob3Vycyg0OClcbiAgICovXG4gIHJlYWRvbmx5IHRpbWVvdXQ/OiBjZGsuRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSB0eXBlIG9mIHByZWRlZmluZWQgd29ya2VyIHRoYXQgaXMgYWxsb2NhdGVkIHdoZW4gYSBqb2IgcnVucy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBkaWZmZXJzIGJhc2VkIG9uIHNwZWNpZmljIEdsdWUgdmVyc2lvblxuICAgKi9cbiAgcmVhZG9ubHkgd29ya2VyVHlwZT86IFdvcmtlclR5cGU7XG5cbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2Ygd29ya2VycyBvZiBhIGRlZmluZWQgYFdvcmtlclR5cGVgIHRoYXQgYXJlIGFsbG9jYXRlZCB3aGVuIGEgam9iIHJ1bnMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZGlmZmVycyBiYXNlZCBvbiBzcGVjaWZpYyBHbHVlIHZlcnNpb24vd29ya2VyIHR5cGVcbiAgICovXG4gIHJlYWRvbmx5IHdvcmtlckNvdW50PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgYENvbm5lY3Rpb25gcyB1c2VkIGZvciB0aGlzIGpvYi5cbiAgICpcbiAgICogQ29ubmVjdGlvbnMgYXJlIHVzZWQgdG8gY29ubmVjdCB0byBvdGhlciBBV1MgU2VydmljZSBvciByZXNvdXJjZXMgd2l0aGluIGEgVlBDLlxuICAgKlxuICAgKiBAZGVmYXVsdCBbXSAtIG5vIGNvbm5lY3Rpb25zIGFyZSBhZGRlZCB0byB0aGUgam9iXG4gICAqL1xuICByZWFkb25seSBjb25uZWN0aW9ucz86IElDb25uZWN0aW9uW107XG5cbiAgLyoqXG4gICAqIFRoZSBgU2VjdXJpdHlDb25maWd1cmF0aW9uYCB0byB1c2UgZm9yIHRoaXMgam9iLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHNlY3VyaXR5IGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICByZWFkb25seSBzZWN1cml0eUNvbmZpZ3VyYXRpb24/OiBJU2VjdXJpdHlDb25maWd1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBUaGUgZGVmYXVsdCBhcmd1bWVudHMgZm9yIHRoaXMgam9iLCBzcGVjaWZpZWQgYXMgbmFtZS12YWx1ZSBwYWlycy5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZ2x1ZS9sYXRlc3QvZGcvYXdzLWdsdWUtcHJvZ3JhbW1pbmctZXRsLWdsdWUtYXJndW1lbnRzLmh0bWxcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBhcmd1bWVudHNcbiAgICovXG4gIHJlYWRvbmx5IGRlZmF1bHRBcmd1bWVudHM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBUaGUgdGFncyB0byBhZGQgdG8gdGhlIHJlc291cmNlcyBvbiB3aGljaCB0aGUgam9iIHJ1bnNcbiAgICpcbiAgICogQGRlZmF1bHQge30gLSBubyB0YWdzXG4gICAqL1xuICByZWFkb25seSB0YWdzPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogVGhlIElBTSByb2xlIGFzc3VtZWQgYnkgR2x1ZSB0byBydW4gdGhpcyBqb2IuXG4gICAqXG4gICAqIElmIHByb3ZpZGluZyBhIGN1c3RvbSByb2xlLCBpdCBuZWVkcyB0byB0cnVzdCB0aGUgR2x1ZSBzZXJ2aWNlIHByaW5jaXBhbCAoZ2x1ZS5hbWF6b25hd3MuY29tKSBhbmQgYmUgZ3JhbnRlZCBzdWZmaWNpZW50IHBlcm1pc3Npb25zLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy9nZXR0aW5nLXN0YXJ0ZWQtYWNjZXNzLmh0bWxcbiAgICpcbiAgICogQGRlZmF1bHQgLSBhIHJvbGUgaXMgYXV0b21hdGljYWxseSBnZW5lcmF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IHJvbGU/OiBpYW0uSVJvbGU7XG5cbiAgLyoqXG4gICAqIEVuYWJsZXMgdGhlIGNvbGxlY3Rpb24gb2YgbWV0cmljcyBmb3Igam9iIHByb2ZpbGluZy5cbiAgICogRXF1aXZhbGVudCB0byBhIGpvYiBwYXJhbWV0ZXIgYC0tZW5hYmxlLW1ldHJpY3NgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHByb2ZpbGluZyBtZXRyaWNzIGVtaXR0ZWQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL2F3cy1nbHVlLXByb2dyYW1taW5nLWV0bC1nbHVlLWFyZ3VtZW50cy5odG1sXG4gICAqL1xuICByZWFkb25seSBlbmFibGVQcm9maWxpbmdNZXRyaWNzPyA6Ym9vbGVhbjtcblxuICAvKipcbiAgICogRW5hYmxlcyB0aGUgU3BhcmsgVUkgZGVidWdnaW5nIGFuZCBtb25pdG9yaW5nIHdpdGggdGhlIHNwZWNpZmllZCBwcm9wcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBTcGFyayBVSSBkZWJ1Z2dpbmcgYW5kIG1vbml0b3JpbmcgaXMgZGlzYWJsZWQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL21vbml0b3Itc3BhcmstdWktam9icy5odG1sXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL2F3cy1nbHVlLXByb2dyYW1taW5nLWV0bC1nbHVlLWFyZ3VtZW50cy5odG1sXG4gICAqL1xuICByZWFkb25seSBzcGFya1VJPzogU3BhcmtVSVByb3BzO1xuXG4gIC8qKlxuICAgKiBFbmFibGVzIGNvbnRpbnVvdXMgbG9nZ2luZyB3aXRoIHRoZSBzcGVjaWZpZWQgcHJvcHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gY29udGludW91cyBsb2dnaW5nIGlzIGRpc2FibGVkLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy9tb25pdG9yLWNvbnRpbnVvdXMtbG9nZ2luZy1lbmFibGUuaHRtbFxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy9hd3MtZ2x1ZS1wcm9ncmFtbWluZy1ldGwtZ2x1ZS1hcmd1bWVudHMuaHRtbFxuICAgKi9cbiAgcmVhZG9ubHkgY29udGludW91c0xvZ2dpbmc/OiBDb250aW51b3VzTG9nZ2luZ1Byb3BzO1xuXG4gIC8qKlxuICAgKiBUaGUgRXhlY3V0aW9uQ2xhc3Mgd2hldGhlciB0aGUgam9iIGlzIHJ1biB3aXRoIGEgc3RhbmRhcmQgb3IgZmxleGlibGUgZXhlY3V0aW9uIGNsYXNzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFNUQU5EQVJEXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2dsdWUvbGF0ZXN0L2RnL2F3cy1nbHVlLWFwaS1qb2JzLWpvYi5odG1sI2F3cy1nbHVlLWFwaS1qb2JzLWpvYi1Kb2JcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZ2x1ZS9sYXRlc3QvZGcvYWRkLWpvYi5odG1sXG4gICAqL1xuICByZWFkb25seSBleGVjdXRpb25DbGFzcz86IEV4ZWN1dGlvbkNsYXNzO1xufVxuXG4vKipcbiAqIEEgR2x1ZSBKb2IuXG4gKi9cbmV4cG9ydCBjbGFzcyBKb2IgZXh0ZW5kcyBKb2JCYXNlIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBHbHVlIEpvYlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgVGhlIHNjb3BlIGNyZWF0aW5nIGNvbnN0cnVjdCAodXN1YWxseSBgdGhpc2ApLlxuICAgKiBAcGFyYW0gaWQgVGhlIGNvbnN0cnVjdCdzIGlkLlxuICAgKiBAcGFyYW0gYXR0cnMgSW1wb3J0IGF0dHJpYnV0ZXNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUpvYkF0dHJpYnV0ZXMoc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LCBpZDogc3RyaW5nLCBhdHRyczogSm9iQXR0cmlidXRlcyk6IElKb2Ige1xuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIEpvYkJhc2Uge1xuICAgICAgcHVibGljIHJlYWRvbmx5IGpvYk5hbWUgPSBhdHRycy5qb2JOYW1lO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGpvYkFybiA9IGpvYkFybihzY29wZSwgYXR0cnMuam9iTmFtZSk7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZ3JhbnRQcmluY2lwYWwgPSBhdHRycy5yb2xlID8/IG5ldyBpYW0uVW5rbm93blByaW5jaXBhbCh7IHJlc291cmNlOiB0aGlzIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgSW1wb3J0KHNjb3BlLCBpZCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgam9iLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGpvYkFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgam9iLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGpvYk5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIElBTSByb2xlIEdsdWUgYXNzdW1lcyB0byBydW4gdGhpcyBqb2IuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcm9sZTogaWFtLklSb2xlO1xuXG4gIC8qKlxuICAgKiBUaGUgcHJpbmNpcGFsIHRoaXMgR2x1ZSBKb2IgaXMgcnVubmluZyBhcy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBncmFudFByaW5jaXBhbDogaWFtLklQcmluY2lwYWw7XG5cbiAgLyoqXG4gICAqIFRoZSBTcGFyayBVSSBsb2dzIGxvY2F0aW9uIGlmIFNwYXJrIFVJIG1vbml0b3JpbmcgYW5kIGRlYnVnZ2luZyBpcyBlbmFibGVkLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy9tb25pdG9yLXNwYXJrLXVpLWpvYnMuaHRtbFxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9nbHVlL2xhdGVzdC9kZy9hd3MtZ2x1ZS1wcm9ncmFtbWluZy1ldGwtZ2x1ZS1hcmd1bWVudHMuaHRtbFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHNwYXJrVUlMb2dnaW5nTG9jYXRpb24/OiBTcGFya1VJTG9nZ2luZ0xvY2F0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBjb25zdHJ1Y3RzLkNvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEpvYlByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBwaHlzaWNhbE5hbWU6IHByb3BzLmpvYk5hbWUsXG4gICAgfSk7XG5cbiAgICBjb25zdCBleGVjdXRhYmxlID0gcHJvcHMuZXhlY3V0YWJsZS5iaW5kKCk7XG5cbiAgICB0aGlzLnJvbGUgPSBwcm9wcy5yb2xlID8/IG5ldyBpYW0uUm9sZSh0aGlzLCAnU2VydmljZVJvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnZ2x1ZS5hbWF6b25hd3MuY29tJyksXG4gICAgICBtYW5hZ2VkUG9saWNpZXM6IFtpYW0uTWFuYWdlZFBvbGljeS5mcm9tQXdzTWFuYWdlZFBvbGljeU5hbWUoJ3NlcnZpY2Utcm9sZS9BV1NHbHVlU2VydmljZVJvbGUnKV0sXG4gICAgfSk7XG4gICAgdGhpcy5ncmFudFByaW5jaXBhbCA9IHRoaXMucm9sZTtcblxuICAgIGNvbnN0IHNwYXJrVUkgPSBwcm9wcy5zcGFya1VJPy5lbmFibGVkID8gdGhpcy5zZXR1cFNwYXJrVUkoZXhlY3V0YWJsZSwgdGhpcy5yb2xlLCBwcm9wcy5zcGFya1VJKSA6IHVuZGVmaW5lZDtcbiAgICB0aGlzLnNwYXJrVUlMb2dnaW5nTG9jYXRpb24gPSBzcGFya1VJPy5sb2NhdGlvbjtcbiAgICBjb25zdCBjb250aW51b3VzTG9nZ2luZ0FyZ3MgPSBwcm9wcy5jb250aW51b3VzTG9nZ2luZz8uZW5hYmxlZCA/IHRoaXMuc2V0dXBDb250aW51b3VzTG9nZ2luZyh0aGlzLnJvbGUsIHByb3BzLmNvbnRpbnVvdXNMb2dnaW5nKSA6IHt9O1xuICAgIGNvbnN0IHByb2ZpbGluZ01ldHJpY3NBcmdzID0gcHJvcHMuZW5hYmxlUHJvZmlsaW5nTWV0cmljcyA/IHsgJy0tZW5hYmxlLW1ldHJpY3MnOiAnJyB9IDoge307XG5cbiAgICBjb25zdCBkZWZhdWx0QXJndW1lbnRzID0ge1xuICAgICAgLi4udGhpcy5leGVjdXRhYmxlQXJndW1lbnRzKGV4ZWN1dGFibGUpLFxuICAgICAgLi4uY29udGludW91c0xvZ2dpbmdBcmdzLFxuICAgICAgLi4ucHJvZmlsaW5nTWV0cmljc0FyZ3MsXG4gICAgICAuLi5zcGFya1VJPy5hcmdzLFxuICAgICAgLi4udGhpcy5jaGVja05vUmVzZXJ2ZWRBcmdzKHByb3BzLmRlZmF1bHRBcmd1bWVudHMpLFxuICAgIH07XG5cbiAgICBpZiAocHJvcHMuZXhlY3V0aW9uQ2xhc3MgPT09IEV4ZWN1dGlvbkNsYXNzLkZMRVgpIHtcbiAgICAgIGlmIChleGVjdXRhYmxlLnR5cGUgIT09IEpvYlR5cGUuRVRMKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRkxFWCBFeGVjdXRpb25DbGFzcyBpcyBvbmx5IGF2YWlsYWJsZSBmb3IgSm9iVHlwZS5FVEwgam9icycpO1xuICAgICAgfVxuICAgICAgaWYgKFtHbHVlVmVyc2lvbi5WMF85LCBHbHVlVmVyc2lvbi5WMV8wLCBHbHVlVmVyc2lvbi5WMl8wXS5pbmNsdWRlcyhleGVjdXRhYmxlLmdsdWVWZXJzaW9uKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZMRVggRXhlY3V0aW9uQ2xhc3MgaXMgb25seSBhdmFpbGFibGUgZm9yIEdsdWVWZXJzaW9uIDMuMCBvciBsYXRlcicpO1xuICAgICAgfVxuICAgICAgaWYgKHByb3BzLndvcmtlclR5cGUgJiYgKHByb3BzLndvcmtlclR5cGUgIT09IFdvcmtlclR5cGUuR18xWCAmJiBwcm9wcy53b3JrZXJUeXBlICE9PSBXb3JrZXJUeXBlLkdfMlgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRkxFWCBFeGVjdXRpb25DbGFzcyBpcyBvbmx5IGF2YWlsYWJsZSBmb3IgV29ya2VyVHlwZSBHXzFYIG9yIEdfMlgnKTtcbiAgICAgIH1cbiAgICAgIGlmIChwcm9wcy5qb2JSdW5RdWV1aW5nRW5hYmxlZCA9PT0gdHJ1ZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZMRVggRXhlY3V0aW9uQ2xhc3MgaXMgb25seSBhdmFpbGFibGUgaWYgam9iIHJ1biBxdWV1aW5nIGlzIGRpc2FibGVkJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgUmF5IGpvYiBwcm9wZXJ0aWVzXG4gICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9pc3N1ZXMvMjk2MTJcbiAgICBpZiAoZXhlY3V0YWJsZS50eXBlLm5hbWUgPT09IEpvYlR5cGUuUkFZLm5hbWUpIHtcbiAgICAgIGlmIChwcm9wcy53b3JrZXJUeXBlICE9PSBXb3JrZXJUeXBlLlpfMlgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBXb3JrZXJUeXBlIG11c3QgYmUgWl8yWCBmb3IgUmF5IGpvYnMsIGdvdDogJHtwcm9wcy53b3JrZXJUeXBlfWApO1xuICAgICAgfVxuICAgICAgaWYgKHByb3BzLnRpbWVvdXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RpbWVvdXQgY2Fubm90IGJlIHNldCBmb3IgUmF5IGpvYnMnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgbWF4Q2FwYWNpdHkgPSBwcm9wcy5tYXhDYXBhY2l0eTtcbiAgICBpZiAobWF4Q2FwYWNpdHkgIT09IHVuZGVmaW5lZCAmJiAocHJvcHMud29ya2VyVHlwZSAmJiBwcm9wcy53b3JrZXJDb3VudCAhPT0gdW5kZWZpbmVkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtYXhDYXBhY2l0eSBjYW5ub3QgYmUgdXNlZCB3aGVuIHNldHRpbmcgd29ya2VyVHlwZSBhbmQgd29ya2VyQ291bnQnKTtcbiAgICB9XG4gICAgaWYgKGV4ZWN1dGFibGUudHlwZSAhPT0gSm9iVHlwZS5QWVRIT05fU0hFTEwpIHtcbiAgICAgIGlmIChtYXhDYXBhY2l0eSAhPT0gdW5kZWZpbmVkICYmICFbR2x1ZVZlcnNpb24uVjBfOSwgR2x1ZVZlcnNpb24uVjFfMF0uaW5jbHVkZXMoZXhlY3V0YWJsZS5nbHVlVmVyc2lvbikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtYXhDYXBhY2l0eSBjYW5ub3QgYmUgdXNlZCB3aGVuIEdsdWVWZXJzaW9uIDIuMCBvciBsYXRlcicpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBtYXggY2FwYWNpdHkgdmFsaWRhdGlvbiBmb3IgcHl0aG9uIHNoZWxsIGpvYnMgKGRlZmF1bHRzIHRvIDAuMDYyNSlcbiAgICAgIG1heENhcGFjaXR5ID0gbWF4Q2FwYWNpdHkgPz8gMC4wNjI1O1xuICAgICAgaWYgKG1heENhcGFjaXR5ICE9PSAwLjA2MjUgJiYgbWF4Q2FwYWNpdHkgIT09IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBtYXhDYXBhY2l0eSB2YWx1ZSBtdXN0IGJlIGVpdGhlciAwLjA2MjUgb3IgMSBmb3IgSm9iVHlwZS5QWVRIT05fU0hFTEwgam9icywgcmVjZWl2ZWQgJHttYXhDYXBhY2l0eX1gKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCghcHJvcHMud29ya2VyVHlwZSAmJiBwcm9wcy53b3JrZXJDb3VudCAhPT0gdW5kZWZpbmVkKSB8fCAocHJvcHMud29ya2VyVHlwZSAmJiBwcm9wcy53b3JrZXJDb3VudCA9PT0gdW5kZWZpbmVkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdCb3RoIHdvcmtlclR5cGUgYW5kIHdvcmtlckNvdW50IG11c3QgYmUgc2V0Jyk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmpvYlJ1blF1ZXVpbmdFbmFibGVkID09PSB0cnVlICYmIHByb3BzLm1heFJldHJpZXMgIT09IHVuZGVmaW5lZCAmJiAhY2RrLlRva2VuLmlzVW5yZXNvbHZlZChwcm9wcy5tYXhSZXRyaWVzKSAmJiBwcm9wcy5tYXhSZXRyaWVzID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBNYXhpbXVtIHJldHJpZXMgd2FzIHNldCB0byAke3Byb3BzLm1heFJldHJpZXN9LCBtdXN0IGJlIHNldCB0byAwIHdpdGggam9iIHJ1biBxdWV1aW5nIGVuYWJsZWRgKTtcbiAgICB9XG5cbiAgICBjb25zdCBqb2JSZXNvdXJjZSA9IG5ldyBDZm5Kb2IodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgbmFtZTogcHJvcHMuam9iTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiBwcm9wcy5kZXNjcmlwdGlvbixcbiAgICAgIHJvbGU6IHRoaXMucm9sZS5yb2xlQXJuLFxuICAgICAgY29tbWFuZDoge1xuICAgICAgICBuYW1lOiBleGVjdXRhYmxlLnR5cGUubmFtZSxcbiAgICAgICAgc2NyaXB0TG9jYXRpb246IHRoaXMuY29kZVMzT2JqZWN0VXJsKGV4ZWN1dGFibGUuc2NyaXB0KSxcbiAgICAgICAgcHl0aG9uVmVyc2lvbjogZXhlY3V0YWJsZS5weXRob25WZXJzaW9uLFxuICAgICAgICBydW50aW1lOiBleGVjdXRhYmxlLnJ1bnRpbWUgPyBleGVjdXRhYmxlLnJ1bnRpbWUubmFtZSA6IHVuZGVmaW5lZCxcbiAgICAgIH0sXG4gICAgICBnbHVlVmVyc2lvbjogZXhlY3V0YWJsZS5nbHVlVmVyc2lvbi5uYW1lLFxuICAgICAgd29ya2VyVHlwZTogcHJvcHMud29ya2VyVHlwZT8ubmFtZSxcbiAgICAgIG51bWJlck9mV29ya2VyczogcHJvcHMud29ya2VyQ291bnQsXG4gICAgICBqb2JSdW5RdWV1aW5nRW5hYmxlZDogcHJvcHMuam9iUnVuUXVldWluZ0VuYWJsZWQsXG4gICAgICBtYXhDYXBhY2l0eTogcHJvcHMubWF4Q2FwYWNpdHksXG4gICAgICBtYXhSZXRyaWVzOiBwcm9wcy5tYXhSZXRyaWVzLFxuICAgICAgZXhlY3V0aW9uQ2xhc3M6IHByb3BzLmV4ZWN1dGlvbkNsYXNzLFxuICAgICAgZXhlY3V0aW9uUHJvcGVydHk6IHByb3BzLm1heENvbmN1cnJlbnRSdW5zID8geyBtYXhDb25jdXJyZW50UnVuczogcHJvcHMubWF4Q29uY3VycmVudFJ1bnMgfSA6IHVuZGVmaW5lZCxcbiAgICAgIG5vdGlmaWNhdGlvblByb3BlcnR5OiBwcm9wcy5ub3RpZnlEZWxheUFmdGVyID8geyBub3RpZnlEZWxheUFmdGVyOiBwcm9wcy5ub3RpZnlEZWxheUFmdGVyLnRvTWludXRlcygpIH0gOiB1bmRlZmluZWQsXG4gICAgICB0aW1lb3V0OiBwcm9wcy50aW1lb3V0Py50b01pbnV0ZXMoKSxcbiAgICAgIGNvbm5lY3Rpb25zOiBwcm9wcy5jb25uZWN0aW9ucyA/IHsgY29ubmVjdGlvbnM6IHByb3BzLmNvbm5lY3Rpb25zLm1hcCgoY29ubmVjdGlvbikgPT4gY29ubmVjdGlvbi5jb25uZWN0aW9uTmFtZSkgfSA6IHVuZGVmaW5lZCxcbiAgICAgIHNlY3VyaXR5Q29uZmlndXJhdGlvbjogcHJvcHMuc2VjdXJpdHlDb25maWd1cmF0aW9uPy5zZWN1cml0eUNvbmZpZ3VyYXRpb25OYW1lLFxuICAgICAgdGFnczogcHJvcHMudGFncyxcbiAgICAgIGRlZmF1bHRBcmd1bWVudHMsXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXNvdXJjZU5hbWUgPSB0aGlzLmdldFJlc291cmNlTmFtZUF0dHJpYnV0ZShqb2JSZXNvdXJjZS5yZWYpO1xuICAgIHRoaXMuam9iQXJuID0gam9iQXJuKHRoaXMsIHJlc291cmNlTmFtZSk7XG4gICAgdGhpcy5qb2JOYW1lID0gcmVzb3VyY2VOYW1lO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIG5vIHVzYWdlIG9mIHJlc2VydmVkIGFyZ3VtZW50cy5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZ2x1ZS9sYXRlc3QvZGcvYXdzLWdsdWUtcHJvZ3JhbW1pbmctZXRsLWdsdWUtYXJndW1lbnRzLmh0bWxcbiAgICovXG4gIHByaXZhdGUgY2hlY2tOb1Jlc2VydmVkQXJncyhkZWZhdWx0QXJndW1lbnRzPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSkge1xuICAgIGlmIChkZWZhdWx0QXJndW1lbnRzKSB7XG4gICAgICBjb25zdCByZXNlcnZlZEFyZ3MgPSBuZXcgU2V0KFsnLS1kZWJ1ZycsICctLW1vZGUnLCAnLS1KT0JfTkFNRSddKTtcbiAgICAgIE9iamVjdC5rZXlzKGRlZmF1bHRBcmd1bWVudHMpLmZvckVhY2goKGFyZykgPT4ge1xuICAgICAgICBpZiAocmVzZXJ2ZWRBcmdzLmhhcyhhcmcpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgJHthcmd9IGFyZ3VtZW50IGlzIHJlc2VydmVkIGJ5IEdsdWUuIERvbid0IHNldCBpdGApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGRlZmF1bHRBcmd1bWVudHM7XG4gIH1cblxuICBwcml2YXRlIGV4ZWN1dGFibGVBcmd1bWVudHMoY29uZmlnOiBKb2JFeGVjdXRhYmxlQ29uZmlnKSB7XG4gICAgY29uc3QgYXJnczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICAgIGFyZ3NbJy0tam9iLWxhbmd1YWdlJ10gPSBjb25maWcubGFuZ3VhZ2U7XG4gICAgaWYgKGNvbmZpZy5jbGFzc05hbWUpIHtcbiAgICAgIGFyZ3NbJy0tY2xhc3MnXSA9IGNvbmZpZy5jbGFzc05hbWU7XG4gICAgfVxuICAgIGlmIChjb25maWcuZXh0cmFKYXJzICYmIGNvbmZpZy5leHRyYUphcnM/Lmxlbmd0aCA+IDApIHtcbiAgICAgIGFyZ3NbJy0tZXh0cmEtamFycyddID0gY29uZmlnLmV4dHJhSmFycy5tYXAoY29kZSA9PiB0aGlzLmNvZGVTM09iamVjdFVybChjb2RlKSkuam9pbignLCcpO1xuICAgIH1cbiAgICBpZiAoY29uZmlnLmV4dHJhUHl0aG9uRmlsZXMgJiYgY29uZmlnLmV4dHJhUHl0aG9uRmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgYXJnc1snLS1leHRyYS1weS1maWxlcyddID0gY29uZmlnLmV4dHJhUHl0aG9uRmlsZXMubWFwKGNvZGUgPT4gdGhpcy5jb2RlUzNPYmplY3RVcmwoY29kZSkpLmpvaW4oJywnKTtcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5zM1B5dGhvbk1vZHVsZXMgJiYgY29uZmlnLnMzUHl0aG9uTW9kdWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICBhcmdzWyctLXMzLXB5LW1vZHVsZXMnXSA9IGNvbmZpZy5zM1B5dGhvbk1vZHVsZXMubWFwKGNvZGUgPT4gdGhpcy5jb2RlUzNPYmplY3RVcmwoY29kZSkpLmpvaW4oJywnKTtcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5leHRyYUZpbGVzICYmIGNvbmZpZy5leHRyYUZpbGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIGFyZ3NbJy0tZXh0cmEtZmlsZXMnXSA9IGNvbmZpZy5leHRyYUZpbGVzLm1hcChjb2RlID0+IHRoaXMuY29kZVMzT2JqZWN0VXJsKGNvZGUpKS5qb2luKCcsJyk7XG4gICAgfVxuICAgIGlmIChjb25maWcuZXh0cmFKYXJzRmlyc3QpIHtcbiAgICAgIGFyZ3NbJy0tdXNlci1qYXJzLWZpcnN0J10gPSAndHJ1ZSc7XG4gICAgfVxuICAgIHJldHVybiBhcmdzO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cFNwYXJrVUkoZXhlY3V0YWJsZTogSm9iRXhlY3V0YWJsZUNvbmZpZywgcm9sZTogaWFtLklSb2xlLCBwcm9wczogU3BhcmtVSVByb3BzKSB7XG4gICAgaWYgKEpvYlR5cGUuUFlUSE9OX1NIRUxMID09PSBleGVjdXRhYmxlLnR5cGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignU3BhcmsgVUkgaXMgbm90IGF2YWlsYWJsZSBmb3IgSm9iVHlwZS5QWVRIT05fU0hFTEwgam9icycpO1xuICAgIH0gZWxzZSBpZiAoSm9iVHlwZS5SQVkgPT09IGV4ZWN1dGFibGUudHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdTcGFyayBVSSBpcyBub3QgYXZhaWxhYmxlIGZvciBKb2JUeXBlLlJBWSBqb2JzJyk7XG4gICAgfVxuXG4gICAgdGhpcy52YWxpZGF0ZVByZWZpeChwcm9wcy5wcmVmaXgpO1xuICAgIGNvbnN0IGJ1Y2tldCA9IHByb3BzLmJ1Y2tldCA/PyBuZXcgczMuQnVja2V0KHRoaXMsICdTcGFya1VJQnVja2V0Jyk7XG4gICAgYnVja2V0LmdyYW50UmVhZFdyaXRlKHJvbGUsIHRoaXMuY2xlYW5QcmVmaXhGb3JHcmFudChwcm9wcy5wcmVmaXgpKTtcbiAgICBjb25zdCBhcmdzID0ge1xuICAgICAgJy0tZW5hYmxlLXNwYXJrLXVpJzogJ3RydWUnLFxuICAgICAgJy0tc3BhcmstZXZlbnQtbG9ncy1wYXRoJzogYnVja2V0LnMzVXJsRm9yT2JqZWN0KHByb3BzLnByZWZpeCkucmVwbGFjZSgvXFwvPyQvLCAnLycpLCAvLyBwYXRoIHdpbGwgYWx3YXlzIGVuZCB3aXRoIGEgc2xhc2hcbiAgICB9O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGxvY2F0aW9uOiB7XG4gICAgICAgIHByZWZpeDogcHJvcHMucHJlZml4LFxuICAgICAgICBidWNrZXQsXG4gICAgICB9LFxuICAgICAgYXJncyxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZVByZWZpeChwcmVmaXg/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIXByZWZpeCB8fCBjZGsuVG9rZW4uaXNVbnJlc29sdmVkKHByZWZpeCkpIHtcbiAgICAgIC8vIHNraXAgdmFsaWRhdGlvbiBpZiBwcmVmaXggaXMgbm90IHNwZWNpZmllZCBvciBpcyBhIHRva2VuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgaWYgKHByZWZpeC5zdGFydHNXaXRoKCcvJykpIHtcbiAgICAgIGVycm9ycy5wdXNoKCdQcmVmaXggbXVzdCBub3QgYmVnaW4gd2l0aCBcXCcvXFwnJyk7XG4gICAgfVxuXG4gICAgaWYgKCFwcmVmaXguZW5kc1dpdGgoJy8nKSkge1xuICAgICAgZXJyb3JzLnB1c2goJ1ByZWZpeCBtdXN0IGVuZCB3aXRoIFxcJy9cXCcnKTtcbiAgICB9XG5cbiAgICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBwcmVmaXggZm9ybWF0ICh2YWx1ZTogJHtwcmVmaXh9KSR7RU9MfSR7ZXJyb3JzLmpvaW4oRU9MKX1gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNsZWFuUHJlZml4Rm9yR3JhbnQocHJlZml4Pzogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gcHJlZml4ICE9PSB1bmRlZmluZWQgPyBgJHtwcmVmaXh9KmAgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIHNldHVwQ29udGludW91c0xvZ2dpbmcocm9sZTogaWFtLklSb2xlLCBwcm9wczogQ29udGludW91c0xvZ2dpbmdQcm9wcykge1xuICAgIGNvbnN0IGFyZ3M6IHtba2V5OiBzdHJpbmddOiBzdHJpbmd9ID0ge1xuICAgICAgJy0tZW5hYmxlLWNvbnRpbnVvdXMtY2xvdWR3YXRjaC1sb2cnOiAndHJ1ZScsXG4gICAgICAnLS1lbmFibGUtY29udGludW91cy1sb2ctZmlsdGVyJzogKHByb3BzLnF1aWV0ID8/IHRydWUpLnRvU3RyaW5nKCksXG4gICAgfTtcblxuICAgIGlmIChwcm9wcy5sb2dHcm91cCkge1xuICAgICAgYXJnc1snLS1jb250aW51b3VzLWxvZy1sb2dHcm91cCddID0gcHJvcHMubG9nR3JvdXAubG9nR3JvdXBOYW1lO1xuICAgICAgcHJvcHMubG9nR3JvdXAuZ3JhbnRXcml0ZShyb2xlKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMubG9nU3RyZWFtUHJlZml4KSB7XG4gICAgICBhcmdzWyctLWNvbnRpbnVvdXMtbG9nLWxvZ1N0cmVhbVByZWZpeCddID0gcHJvcHMubG9nU3RyZWFtUHJlZml4O1xuICAgIH1cbiAgICBpZiAocHJvcHMuY29udmVyc2lvblBhdHRlcm4pIHtcbiAgICAgIGFyZ3NbJy0tY29udGludW91cy1sb2ctY29udmVyc2lvblBhdHRlcm4nXSA9IHByb3BzLmNvbnZlcnNpb25QYXR0ZXJuO1xuICAgIH1cbiAgICByZXR1cm4gYXJncztcbiAgfVxuXG4gIHByaXZhdGUgY29kZVMzT2JqZWN0VXJsKGNvZGU6IENvZGUpIHtcbiAgICBjb25zdCBzM0xvY2F0aW9uID0gY29kZS5iaW5kKHRoaXMsIHRoaXMucm9sZSkuczNMb2NhdGlvbjtcbiAgICByZXR1cm4gYHMzOi8vJHtzM0xvY2F0aW9uLmJ1Y2tldE5hbWV9LyR7czNMb2NhdGlvbi5vYmplY3RLZXl9YDtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZSBhIENsb3VkV2F0Y2ggTWV0cmljIHRoYXQncyBiYXNlZCBvbiBHbHVlIEpvYiBldmVudHMuXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZFdhdGNoL2xhdGVzdC9ldmVudHMvRXZlbnRUeXBlcy5odG1sI2dsdWUtZXZlbnQtdHlwZXNcbiAqIFRoZSBtZXRyaWMgaGFzIG5hbWVzcGFjZSA9ICdBV1MvRXZlbnRzJywgbWV0cmljTmFtZSA9ICdUcmlnZ2VyZWRSdWxlcycgYW5kIFJ1bGVOYW1lID0gcnVsZS5ydWxlTmFtZSBkaW1lbnNpb24uXG4gKlxuICogQHBhcmFtIHJ1bGUgZm9yIHVzZSBpbiBzZXR0aW5nIFJ1bGVOYW1lIGRpbWVuc2lvbiB2YWx1ZVxuICogQHBhcmFtIHByb3BzIG1ldHJpYyBwcm9wZXJ0aWVzXG4gKi9cbmZ1bmN0aW9uIG1ldHJpY1J1bGUocnVsZTogZXZlbnRzLklSdWxlLCBwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgcmV0dXJuIG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgbmFtZXNwYWNlOiAnQVdTL0V2ZW50cycsXG4gICAgbWV0cmljTmFtZTogJ1RyaWdnZXJlZFJ1bGVzJyxcbiAgICBkaW1lbnNpb25zTWFwOiB7IFJ1bGVOYW1lOiBydWxlLnJ1bGVOYW1lIH0sXG4gICAgc3RhdGlzdGljOiBjbG91ZHdhdGNoLlN0YXRpc3RpYy5TVU0sXG4gICAgLi4ucHJvcHMsXG4gIH0pLmF0dGFjaFRvKHJ1bGUpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGpvYiBhcm5cbiAqIEBwYXJhbSBzY29wZVxuICogQHBhcmFtIGpvYk5hbWVcbiAqL1xuZnVuY3Rpb24gam9iQXJuKHNjb3BlOiBjb25zdHJ1Y3RzLkNvbnN0cnVjdCwgam9iTmFtZTogc3RyaW5nKSA6IHN0cmluZyB7XG4gIHJldHVybiBjZGsuU3RhY2sub2Yoc2NvcGUpLmZvcm1hdEFybih7XG4gICAgc2VydmljZTogJ2dsdWUnLFxuICAgIHJlc291cmNlOiAnam9iJyxcbiAgICByZXNvdXJjZU5hbWU6IGpvYk5hbWUsXG4gIH0pO1xufVxuIl19
|