UNPKG

106 kBJavaScriptView Raw
1"use strict";
2var _a, _b;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.AsgCapacityProvider = exports.ExecuteCommandLogging = exports.Cluster = exports.MachineImageType = void 0;
5const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const autoscaling = require("@aws-cdk/aws-autoscaling");
8const cloudwatch = require("@aws-cdk/aws-cloudwatch");
9const ec2 = require("@aws-cdk/aws-ec2");
10const iam = require("@aws-cdk/aws-iam");
11const cloudmap = require("@aws-cdk/aws-servicediscovery");
12const core_1 = require("@aws-cdk/core");
13const amis_1 = require("./amis");
14const instance_drain_hook_1 = require("./drain-hook/instance-drain-hook");
15const ecs_canned_metrics_generated_1 = require("./ecs-canned-metrics.generated");
16const ecs_generated_1 = require("./ecs.generated");
17// v2 - keep this import as a separate section to reduce merge conflict when forward merging with the v2 branch.
18// eslint-disable-next-line
19const core_2 = require("@aws-cdk/core");
20/**
21 * The machine image type
22 */
23var MachineImageType;
24(function (MachineImageType) {
25 /**
26 * Amazon ECS-optimized Amazon Linux 2 AMI
27 */
28 MachineImageType[MachineImageType["AMAZON_LINUX_2"] = 0] = "AMAZON_LINUX_2";
29 /**
30 * Bottlerocket AMI
31 */
32 MachineImageType[MachineImageType["BOTTLEROCKET"] = 1] = "BOTTLEROCKET";
33})(MachineImageType = exports.MachineImageType || (exports.MachineImageType = {}));
34/**
35 * A regional grouping of one or more container instances on which you can run tasks and services.
36 */
37class Cluster extends core_1.Resource {
38 /**
39 * Constructs a new instance of the Cluster class.
40 */
41 constructor(scope, id, props = {}) {
42 var _c;
43 super(scope, id, {
44 physicalName: props.clusterName,
45 });
46 /**
47 * Manage the allowed network connections for the cluster with Security Groups.
48 */
49 this.connections = new ec2.Connections();
50 /**
51 * The names of both ASG and Fargate capacity providers associated with the cluster.
52 */
53 this._capacityProviderNames = [];
54 /**
55 * Specifies whether the cluster has EC2 instance capacity.
56 */
57 this._hasEc2Capacity = false;
58 try {
59 jsiiDeprecationWarnings._aws_cdk_aws_ecs_ClusterProps(props);
60 }
61 catch (error) {
62 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
63 Error.captureStackTrace(error, this.constructor);
64 }
65 throw error;
66 }
67 /**
68 * clusterSettings needs to be undefined if containerInsights is not explicitly set in order to allow any
69 * containerInsights settings on the account to apply. See:
70 * https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-clustersettings.html#cfn-ecs-cluster-clustersettings-value
71 */
72 let clusterSettings = undefined;
73 if (props.containerInsights !== undefined) {
74 clusterSettings = [{ name: 'containerInsights', value: props.containerInsights ? ContainerInsights.ENABLED : ContainerInsights.DISABLED }];
75 }
76 this._capacityProviderNames = (_c = props.capacityProviders) !== null && _c !== void 0 ? _c : [];
77 if (props.enableFargateCapacityProviders) {
78 this.enableFargateCapacityProviders();
79 }
80 if (props.executeCommandConfiguration) {
81 if ((props.executeCommandConfiguration.logging === ExecuteCommandLogging.OVERRIDE) !==
82 (props.executeCommandConfiguration.logConfiguration !== undefined)) {
83 throw new Error('Execute command log configuration must only be specified when logging is OVERRIDE.');
84 }
85 this._executeCommandConfiguration = props.executeCommandConfiguration;
86 }
87 const cluster = new ecs_generated_1.CfnCluster(this, 'Resource', {
88 clusterName: this.physicalName,
89 clusterSettings,
90 configuration: this._executeCommandConfiguration && this.renderExecuteCommandConfiguration(),
91 });
92 this.clusterArn = this.getResourceArnAttribute(cluster.attrArn, {
93 service: 'ecs',
94 resource: 'cluster',
95 resourceName: this.physicalName,
96 });
97 this.clusterName = this.getResourceNameAttribute(cluster.ref);
98 this.vpc = props.vpc || new ec2.Vpc(this, 'Vpc', { maxAzs: 2 });
99 this._defaultCloudMapNamespace = props.defaultCloudMapNamespace !== undefined
100 ? this.addDefaultCloudMapNamespace(props.defaultCloudMapNamespace)
101 : undefined;
102 this._autoscalingGroup = props.capacity !== undefined
103 ? this.addCapacity('DefaultAutoScalingGroup', props.capacity)
104 : undefined;
105 // Only create cluster capacity provider associations if there are any EC2
106 // capacity providers. Ordinarily we'd just add the construct to the tree
107 // since it's harmless, but we'd prefer not to add unexpected new
108 // resources to the stack which could surprise users working with
109 // brown-field CDK apps and stacks.
110 core_1.Aspects.of(this).add(new MaybeCreateCapacityProviderAssociations(this, id, this._capacityProviderNames));
111 }
112 /**
113 * Import an existing cluster to the stack from its attributes.
114 */
115 static fromClusterAttributes(scope, id, attrs) {
116 try {
117 jsiiDeprecationWarnings._aws_cdk_aws_ecs_ClusterAttributes(attrs);
118 }
119 catch (error) {
120 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
121 Error.captureStackTrace(error, this.fromClusterAttributes);
122 }
123 throw error;
124 }
125 return new ImportedCluster(scope, id, attrs);
126 }
127 /**
128 * Import an existing cluster to the stack from the cluster ARN.
129 * This does not provide access to the vpc, hasEc2Capacity, or connections -
130 * use the `fromClusterAttributes` method to access those properties.
131 */
132 static fromClusterArn(scope, id, clusterArn) {
133 const stack = core_1.Stack.of(scope);
134 const arn = stack.splitArn(clusterArn, core_1.ArnFormat.SLASH_RESOURCE_NAME);
135 const clusterName = arn.resourceName;
136 if (!clusterName) {
137 throw new Error(`Missing required Cluster Name from Cluster ARN: ${clusterArn}`);
138 }
139 const errorSuffix = 'is not available for a Cluster imported using fromClusterArn(), please use fromClusterAttributes() instead.';
140 class Import extends core_1.Resource {
141 constructor() {
142 super(...arguments);
143 this.clusterArn = clusterArn;
144 this.clusterName = clusterName;
145 }
146 get hasEc2Capacity() {
147 throw new Error(`hasEc2Capacity ${errorSuffix}`);
148 }
149 get connections() {
150 throw new Error(`connections ${errorSuffix}`);
151 }
152 get vpc() {
153 throw new Error(`vpc ${errorSuffix}`);
154 }
155 }
156 return new Import(scope, id, {
157 environmentFromArn: clusterArn,
158 });
159 }
160 /**
161 * Enable the Fargate capacity providers for this cluster.
162 */
163 enableFargateCapacityProviders() {
164 for (const provider of ['FARGATE', 'FARGATE_SPOT']) {
165 if (!this._capacityProviderNames.includes(provider)) {
166 this._capacityProviderNames.push(provider);
167 }
168 }
169 }
170 renderExecuteCommandConfiguration() {
171 var _c, _d, _e, _f;
172 return {
173 executeCommandConfiguration: {
174 kmsKeyId: (_d = (_c = this._executeCommandConfiguration) === null || _c === void 0 ? void 0 : _c.kmsKey) === null || _d === void 0 ? void 0 : _d.keyArn,
175 logConfiguration: ((_e = this._executeCommandConfiguration) === null || _e === void 0 ? void 0 : _e.logConfiguration) && this.renderExecuteCommandLogConfiguration(),
176 logging: (_f = this._executeCommandConfiguration) === null || _f === void 0 ? void 0 : _f.logging,
177 },
178 };
179 }
180 renderExecuteCommandLogConfiguration() {
181 var _c, _d, _e;
182 const logConfiguration = (_c = this._executeCommandConfiguration) === null || _c === void 0 ? void 0 : _c.logConfiguration;
183 if ((logConfiguration === null || logConfiguration === void 0 ? void 0 : logConfiguration.s3EncryptionEnabled) && !(logConfiguration === null || logConfiguration === void 0 ? void 0 : logConfiguration.s3Bucket)) {
184 throw new Error('You must specify an S3 bucket name in the execute command log configuration to enable S3 encryption.');
185 }
186 if ((logConfiguration === null || logConfiguration === void 0 ? void 0 : logConfiguration.cloudWatchEncryptionEnabled) && !(logConfiguration === null || logConfiguration === void 0 ? void 0 : logConfiguration.cloudWatchLogGroup)) {
187 throw new Error('You must specify a CloudWatch log group in the execute command log configuration to enable CloudWatch encryption.');
188 }
189 return {
190 cloudWatchEncryptionEnabled: logConfiguration === null || logConfiguration === void 0 ? void 0 : logConfiguration.cloudWatchEncryptionEnabled,
191 cloudWatchLogGroupName: (_d = logConfiguration === null || logConfiguration === void 0 ? void 0 : logConfiguration.cloudWatchLogGroup) === null || _d === void 0 ? void 0 : _d.logGroupName,
192 s3BucketName: (_e = logConfiguration === null || logConfiguration === void 0 ? void 0 : logConfiguration.s3Bucket) === null || _e === void 0 ? void 0 : _e.bucketName,
193 s3EncryptionEnabled: logConfiguration === null || logConfiguration === void 0 ? void 0 : logConfiguration.s3EncryptionEnabled,
194 s3KeyPrefix: logConfiguration === null || logConfiguration === void 0 ? void 0 : logConfiguration.s3KeyPrefix,
195 };
196 }
197 /**
198 * Add an AWS Cloud Map DNS namespace for this cluster.
199 * NOTE: HttpNamespaces are not supported, as ECS always requires a DNSConfig when registering an instance to a Cloud
200 * Map service.
201 */
202 addDefaultCloudMapNamespace(options) {
203 try {
204 jsiiDeprecationWarnings._aws_cdk_aws_ecs_CloudMapNamespaceOptions(options);
205 }
206 catch (error) {
207 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
208 Error.captureStackTrace(error, this.addDefaultCloudMapNamespace);
209 }
210 throw error;
211 }
212 if (this._defaultCloudMapNamespace !== undefined) {
213 throw new Error('Can only add default namespace once.');
214 }
215 const namespaceType = options.type !== undefined
216 ? options.type
217 : cloudmap.NamespaceType.DNS_PRIVATE;
218 const sdNamespace = namespaceType === cloudmap.NamespaceType.DNS_PRIVATE ?
219 new cloudmap.PrivateDnsNamespace(this, 'DefaultServiceDiscoveryNamespace', {
220 name: options.name,
221 vpc: this.vpc,
222 }) :
223 new cloudmap.PublicDnsNamespace(this, 'DefaultServiceDiscoveryNamespace', {
224 name: options.name,
225 });
226 this._defaultCloudMapNamespace = sdNamespace;
227 return sdNamespace;
228 }
229 /**
230 * Getter for namespace added to cluster
231 */
232 get defaultCloudMapNamespace() {
233 return this._defaultCloudMapNamespace;
234 }
235 /**
236 * It is highly recommended to use {@link Cluster.addAsgCapacityProvider} instead of this method.
237 *
238 * This method adds compute capacity to a cluster by creating an AutoScalingGroup with the specified options.
239 *
240 * Returns the AutoScalingGroup so you can add autoscaling settings to it.
241 */
242 addCapacity(id, options) {
243 var _c, _d;
244 try {
245 jsiiDeprecationWarnings._aws_cdk_aws_ecs_AddCapacityOptions(options);
246 }
247 catch (error) {
248 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
249 Error.captureStackTrace(error, this.addCapacity);
250 }
251 throw error;
252 }
253 // Do 2-way defaulting here: if the machineImageType is BOTTLEROCKET, pick the right AMI.
254 // Otherwise, determine the machineImageType from the given AMI.
255 const machineImage = (_c = options.machineImage) !== null && _c !== void 0 ? _c : (options.machineImageType === MachineImageType.BOTTLEROCKET ? new amis_1.BottleRocketImage({
256 architecture: options.instanceType.architecture,
257 }) : new amis_1.EcsOptimizedAmi());
258 const machineImageType = (_d = options.machineImageType) !== null && _d !== void 0 ? _d : (isBottleRocketImage(machineImage) ? MachineImageType.BOTTLEROCKET : MachineImageType.AMAZON_LINUX_2);
259 const autoScalingGroup = new autoscaling.AutoScalingGroup(this, id, {
260 vpc: this.vpc,
261 machineImage,
262 updateType: options.updateType || autoscaling.UpdateType.REPLACING_UPDATE,
263 ...options,
264 });
265 this.addAutoScalingGroup(autoScalingGroup, {
266 machineImageType: machineImageType,
267 ...options,
268 });
269 return autoScalingGroup;
270 }
271 /**
272 * This method adds an Auto Scaling Group Capacity Provider to a cluster.
273 *
274 * @param provider the capacity provider to add to this cluster.
275 */
276 addAsgCapacityProvider(provider, options = {}) {
277 try {
278 jsiiDeprecationWarnings._aws_cdk_aws_ecs_AsgCapacityProvider(provider);
279 jsiiDeprecationWarnings._aws_cdk_aws_ecs_AddAutoScalingGroupCapacityOptions(options);
280 }
281 catch (error) {
282 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
283 Error.captureStackTrace(error, this.addAsgCapacityProvider);
284 }
285 throw error;
286 }
287 // Don't add the same capacity provider more than once.
288 if (this._capacityProviderNames.includes(provider.capacityProviderName)) {
289 return;
290 }
291 this._hasEc2Capacity = true;
292 this.configureAutoScalingGroup(provider.autoScalingGroup, {
293 ...options,
294 machineImageType: provider.machineImageType,
295 // Don't enable the instance-draining lifecycle hook if managed termination protection is enabled
296 taskDrainTime: provider.enableManagedTerminationProtection ? core_1.Duration.seconds(0) : options.taskDrainTime,
297 });
298 this._capacityProviderNames.push(provider.capacityProviderName);
299 }
300 /**
301 * This method adds compute capacity to a cluster using the specified AutoScalingGroup.
302 *
303 * @deprecated Use {@link Cluster.addAsgCapacityProvider} instead.
304 * @param autoScalingGroup the ASG to add to this cluster.
305 * [disable-awslint:ref-via-interface] is needed in order to install the ECS
306 * agent by updating the ASGs user data.
307 */
308 addAutoScalingGroup(autoScalingGroup, options = {}) {
309 try {
310 jsiiDeprecationWarnings.print("@aws-cdk/aws-ecs.Cluster#addAutoScalingGroup", "Use {@link Cluster.addAsgCapacityProvider} instead.");
311 jsiiDeprecationWarnings._aws_cdk_aws_ecs_AddAutoScalingGroupCapacityOptions(options);
312 }
313 catch (error) {
314 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
315 Error.captureStackTrace(error, this.addAutoScalingGroup);
316 }
317 throw error;
318 }
319 this._hasEc2Capacity = true;
320 this.connections.connections.addSecurityGroup(...autoScalingGroup.connections.securityGroups);
321 this.configureAutoScalingGroup(autoScalingGroup, options);
322 }
323 configureAutoScalingGroup(autoScalingGroup, options = {}) {
324 if (autoScalingGroup.osType === ec2.OperatingSystemType.WINDOWS) {
325 this.configureWindowsAutoScalingGroup(autoScalingGroup, options);
326 }
327 else {
328 // Tie instances to cluster
329 switch (options.machineImageType) {
330 // Bottlerocket AMI
331 case MachineImageType.BOTTLEROCKET: {
332 autoScalingGroup.addUserData(
333 // Connect to the cluster
334 // Source: https://github.com/bottlerocket-os/bottlerocket/blob/develop/QUICKSTART-ECS.md#connecting-to-your-cluster
335 '[settings.ecs]', `cluster = "${this.clusterName}"`);
336 // Enabling SSM
337 // Source: https://github.com/bottlerocket-os/bottlerocket/blob/develop/QUICKSTART-ECS.md#enabling-ssm
338 autoScalingGroup.role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'));
339 // required managed policy
340 autoScalingGroup.role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2ContainerServiceforEC2Role'));
341 break;
342 }
343 default:
344 // Amazon ECS-optimized AMI for Amazon Linux 2
345 autoScalingGroup.addUserData(`echo ECS_CLUSTER=${this.clusterName} >> /etc/ecs/ecs.config`);
346 if (!options.canContainersAccessInstanceRole) {
347 // Deny containers access to instance metadata service
348 // Source: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html
349 autoScalingGroup.addUserData('sudo iptables --insert FORWARD 1 --in-interface docker+ --destination 169.254.169.254/32 --jump DROP');
350 autoScalingGroup.addUserData('sudo service iptables save');
351 // The following is only for AwsVpc networking mode, but doesn't hurt for the other modes.
352 autoScalingGroup.addUserData('echo ECS_AWSVPC_BLOCK_IMDS=true >> /etc/ecs/ecs.config');
353 }
354 if (autoScalingGroup.spotPrice && options.spotInstanceDraining) {
355 autoScalingGroup.addUserData('echo ECS_ENABLE_SPOT_INSTANCE_DRAINING=true >> /etc/ecs/ecs.config');
356 }
357 }
358 }
359 // ECS instances must be able to do these things
360 // Source: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html
361 // But, scoped down to minimal permissions required.
362 // Notes:
363 // - 'ecs:CreateCluster' removed. The cluster already exists.
364 autoScalingGroup.addToRolePolicy(new iam.PolicyStatement({
365 actions: [
366 'ecs:DeregisterContainerInstance',
367 'ecs:RegisterContainerInstance',
368 'ecs:Submit*',
369 ],
370 resources: [
371 this.clusterArn,
372 ],
373 }));
374 autoScalingGroup.addToRolePolicy(new iam.PolicyStatement({
375 actions: [
376 // These act on a cluster instance, and the instance doesn't exist until the service starts.
377 // Thus, scope to the cluster using a condition.
378 // See: https://docs.aws.amazon.com/IAM/latest/UserGuide/list_amazonelasticcontainerservice.html
379 'ecs:Poll',
380 'ecs:StartTelemetrySession',
381 ],
382 resources: ['*'],
383 conditions: {
384 ArnEquals: { 'ecs:cluster': this.clusterArn },
385 },
386 }));
387 autoScalingGroup.addToRolePolicy(new iam.PolicyStatement({
388 actions: [
389 // These do not support resource constraints, and must be resource '*'
390 'ecs:DiscoverPollEndpoint',
391 'ecr:GetAuthorizationToken',
392 // Preserved for backwards compatibility.
393 // Users are able to enable cloudwatch agent using CDK. Existing
394 // customers might be installing CW agent as part of user-data so if we
395 // remove these permissions we will break that customer use cases.
396 'logs:CreateLogStream',
397 'logs:PutLogEvents',
398 ],
399 resources: ['*'],
400 }));
401 // 0 disables, otherwise forward to underlying implementation which picks the sane default
402 if (!options.taskDrainTime || options.taskDrainTime.toSeconds() !== 0) {
403 new instance_drain_hook_1.InstanceDrainHook(autoScalingGroup, 'DrainECSHook', {
404 autoScalingGroup,
405 cluster: this,
406 drainTime: options.taskDrainTime,
407 topicEncryptionKey: options.topicEncryptionKey,
408 });
409 }
410 }
411 /**
412 * This method enables the Fargate or Fargate Spot capacity providers on the cluster.
413 *
414 * @param provider the capacity provider to add to this cluster.
415 * @deprecated Use {@link enableFargateCapacityProviders} instead.
416 * @see {@link addAsgCapacityProvider} to add an Auto Scaling Group capacity provider to the cluster.
417 */
418 addCapacityProvider(provider) {
419 try {
420 jsiiDeprecationWarnings.print("@aws-cdk/aws-ecs.Cluster#addCapacityProvider", "Use {@link enableFargateCapacityProviders} instead.");
421 }
422 catch (error) {
423 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
424 Error.captureStackTrace(error, this.addCapacityProvider);
425 }
426 throw error;
427 }
428 if (!(provider === 'FARGATE' || provider === 'FARGATE_SPOT')) {
429 throw new Error('CapacityProvider not supported');
430 }
431 if (!this._capacityProviderNames.includes(provider)) {
432 this._capacityProviderNames.push(provider);
433 }
434 }
435 configureWindowsAutoScalingGroup(autoScalingGroup, options = {}) {
436 // clear the cache of the agent
437 autoScalingGroup.addUserData('Remove-Item -Recurse C:\\ProgramData\\Amazon\\ECS\\Cache');
438 // pull the latest ECS Tools
439 autoScalingGroup.addUserData('Import-Module ECSTools');
440 // set the cluster name environment variable
441 autoScalingGroup.addUserData(`[Environment]::SetEnvironmentVariable("ECS_CLUSTER", "${this.clusterName}", "Machine")`);
442 autoScalingGroup.addUserData('[Environment]::SetEnvironmentVariable("ECS_ENABLE_AWSLOGS_EXECUTIONROLE_OVERRIDE", "true", "Machine")');
443 // tslint:disable-next-line: max-line-length
444 autoScalingGroup.addUserData('[Environment]::SetEnvironmentVariable("ECS_AVAILABLE_LOGGING_DRIVERS", \'["json-file","awslogs"]\', "Machine")');
445 // enable instance draining
446 if (autoScalingGroup.spotPrice && options.spotInstanceDraining) {
447 autoScalingGroup.addUserData('[Environment]::SetEnvironmentVariable("ECS_ENABLE_SPOT_INSTANCE_DRAINING", "true", "Machine")');
448 }
449 // enable task iam role
450 if (!options.canContainersAccessInstanceRole) {
451 autoScalingGroup.addUserData('[Environment]::SetEnvironmentVariable("ECS_ENABLE_TASK_IAM_ROLE", "true", "Machine")');
452 autoScalingGroup.addUserData(`Initialize-ECSAgent -Cluster '${this.clusterName}' -EnableTaskIAMRole`);
453 }
454 else {
455 autoScalingGroup.addUserData(`Initialize-ECSAgent -Cluster '${this.clusterName}'`);
456 }
457 }
458 /**
459 * Getter for autoscaling group added to cluster
460 */
461 get autoscalingGroup() {
462 return this._autoscalingGroup;
463 }
464 /**
465 * Whether the cluster has EC2 capacity associated with it
466 */
467 get hasEc2Capacity() {
468 return this._hasEc2Capacity;
469 }
470 /**
471 * Getter for execute command configuration associated with the cluster.
472 */
473 get executeCommandConfiguration() {
474 return this._executeCommandConfiguration;
475 }
476 /**
477 * This method returns the CloudWatch metric for this clusters CPU reservation.
478 *
479 * @default average over 5 minutes
480 */
481 metricCpuReservation(props) {
482 return this.cannedMetric(ecs_canned_metrics_generated_1.ECSMetrics.cpuReservationAverage, props);
483 }
484 /**
485 * This method returns the CloudWatch metric for this clusters CPU utilization.
486 *
487 * @default average over 5 minutes
488 */
489 metricCpuUtilization(props) {
490 return this.cannedMetric(ecs_canned_metrics_generated_1.ECSMetrics.cpuUtilizationAverage, props);
491 }
492 /**
493 * This method returns the CloudWatch metric for this clusters memory reservation.
494 *
495 * @default average over 5 minutes
496 */
497 metricMemoryReservation(props) {
498 return this.cannedMetric(ecs_canned_metrics_generated_1.ECSMetrics.memoryReservationAverage, props);
499 }
500 /**
501 * This method returns the CloudWatch metric for this clusters memory utilization.
502 *
503 * @default average over 5 minutes
504 */
505 metricMemoryUtilization(props) {
506 return this.cannedMetric(ecs_canned_metrics_generated_1.ECSMetrics.memoryUtilizationAverage, props);
507 }
508 /**
509 * This method returns the specifed CloudWatch metric for this cluster.
510 */
511 metric(metricName, props) {
512 return new cloudwatch.Metric({
513 namespace: 'AWS/ECS',
514 metricName,
515 dimensionsMap: { ClusterName: this.clusterName },
516 ...props,
517 }).attachTo(this);
518 }
519 cannedMetric(fn, props) {
520 return new cloudwatch.Metric({
521 ...fn({ ClusterName: this.clusterName }),
522 ...props,
523 }).attachTo(this);
524 }
525}
526exports.Cluster = Cluster;
527_a = JSII_RTTI_SYMBOL_1;
528Cluster[_a] = { fqn: "@aws-cdk/aws-ecs.Cluster", version: "1.156.1" };
529/**
530 * An Cluster that has been imported
531 */
532class ImportedCluster extends core_1.Resource {
533 /**
534 * Constructs a new instance of the ImportedCluster class.
535 */
536 constructor(scope, id, props) {
537 var _c;
538 super(scope, id);
539 /**
540 * Security group of the cluster instances
541 */
542 this.connections = new ec2.Connections();
543 this.clusterName = props.clusterName;
544 this.vpc = props.vpc;
545 this.hasEc2Capacity = props.hasEc2Capacity !== false;
546 this._defaultCloudMapNamespace = props.defaultCloudMapNamespace;
547 this._executeCommandConfiguration = props.executeCommandConfiguration;
548 this.clusterArn = (_c = props.clusterArn) !== null && _c !== void 0 ? _c : core_1.Stack.of(this).formatArn({
549 service: 'ecs',
550 resource: 'cluster',
551 resourceName: props.clusterName,
552 });
553 this.connections = new ec2.Connections({
554 securityGroups: props.securityGroups,
555 });
556 }
557 get defaultCloudMapNamespace() {
558 return this._defaultCloudMapNamespace;
559 }
560 get executeCommandConfiguration() {
561 return this._executeCommandConfiguration;
562 }
563}
564var ContainerInsights;
565(function (ContainerInsights) {
566 /**
567 * Enable CloudWatch Container Insights for the cluster
568 */
569 ContainerInsights["ENABLED"] = "enabled";
570 /**
571 * Disable CloudWatch Container Insights for the cluster
572 */
573 ContainerInsights["DISABLED"] = "disabled";
574})(ContainerInsights || (ContainerInsights = {}));
575/**
576 * The log settings to use to for logging the execute command session. For more information, see
577 * [Logging] https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-cluster-executecommandconfiguration.html#cfn-ecs-cluster-executecommandconfiguration-logging
578 */
579var ExecuteCommandLogging;
580(function (ExecuteCommandLogging) {
581 /**
582 * The execute command session is not logged.
583 */
584 ExecuteCommandLogging["NONE"] = "NONE";
585 /**
586 * The awslogs configuration in the task definition is used. If no logging parameter is specified, it defaults to this value. If no awslogs log driver is configured in the task definition, the output won't be logged.
587 */
588 ExecuteCommandLogging["DEFAULT"] = "DEFAULT";
589 /**
590 * Specify the logging details as a part of logConfiguration.
591 */
592 ExecuteCommandLogging["OVERRIDE"] = "OVERRIDE";
593})(ExecuteCommandLogging = exports.ExecuteCommandLogging || (exports.ExecuteCommandLogging = {}));
594/**
595 * An Auto Scaling Group Capacity Provider. This allows an ECS cluster to target
596 * a specific EC2 Auto Scaling Group for the placement of tasks. Optionally (and
597 * recommended), ECS can manage the number of instances in the ASG to fit the
598 * tasks, and can ensure that instances are not prematurely terminated while
599 * there are still tasks running on them.
600 */
601class AsgCapacityProvider extends core_2.Construct {
602 constructor(scope, id, props) {
603 var _c;
604 super(scope, id);
605 try {
606 jsiiDeprecationWarnings._aws_cdk_aws_ecs_AsgCapacityProviderProps(props);
607 }
608 catch (error) {
609 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
610 Error.captureStackTrace(error, this.constructor);
611 }
612 throw error;
613 }
614 this.autoScalingGroup = props.autoScalingGroup;
615 this.machineImageType = (_c = props.machineImageType) !== null && _c !== void 0 ? _c : MachineImageType.AMAZON_LINUX_2;
616 this.enableManagedTerminationProtection =
617 props.enableManagedTerminationProtection === undefined ? true : props.enableManagedTerminationProtection;
618 if (this.enableManagedTerminationProtection) {
619 this.autoScalingGroup.protectNewInstancesFromScaleIn();
620 }
621 if (props.capacityProviderName) {
622 if (!(/^(?!aws|ecs|fargate).+/gm.test(props.capacityProviderName))) {
623 throw new Error(`Invalid Capacity Provider Name: ${props.capacityProviderName}, If a name is specified, it cannot start with aws, ecs, or fargate.`);
624 }
625 }
626 const capacityProvider = new ecs_generated_1.CfnCapacityProvider(this, id, {
627 name: props.capacityProviderName,
628 autoScalingGroupProvider: {
629 autoScalingGroupArn: this.autoScalingGroup.autoScalingGroupName,
630 managedScaling: props.enableManagedScaling === false ? undefined : {
631 status: 'ENABLED',
632 targetCapacity: props.targetCapacityPercent || 100,
633 maximumScalingStepSize: props.maximumScalingStepSize,
634 minimumScalingStepSize: props.minimumScalingStepSize,
635 },
636 managedTerminationProtection: this.enableManagedTerminationProtection ? 'ENABLED' : 'DISABLED',
637 },
638 });
639 this.capacityProviderName = capacityProvider.ref;
640 }
641}
642exports.AsgCapacityProvider = AsgCapacityProvider;
643_b = JSII_RTTI_SYMBOL_1;
644AsgCapacityProvider[_b] = { fqn: "@aws-cdk/aws-ecs.AsgCapacityProvider", version: "1.156.1" };
645/**
646 * A visitor that adds a capacity provider association to a Cluster only if
647 * the caller created any EC2 Capacity Providers.
648 */
649class MaybeCreateCapacityProviderAssociations {
650 constructor(scope, id, capacityProviders) {
651 this.scope = scope;
652 this.id = id;
653 this.capacityProviders = capacityProviders;
654 }
655 visit(node) {
656 if (node instanceof Cluster) {
657 if (this.capacityProviders.length > 0 && !this.resource) {
658 const resource = new ecs_generated_1.CfnClusterCapacityProviderAssociations(this.scope, this.id, {
659 cluster: node.clusterName,
660 defaultCapacityProviderStrategy: [],
661 capacityProviders: core_1.Lazy.list({ produce: () => this.capacityProviders }),
662 });
663 this.resource = resource;
664 }
665 }
666 }
667}
668function isBottleRocketImage(image) {
669 return image instanceof amis_1.BottleRocketImage;
670}
671//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsd0RBQXdEO0FBQ3hELHNEQUFzRDtBQUN0RCx3Q0FBd0M7QUFDeEMsd0NBQXdDO0FBSXhDLDBEQUEwRDtBQUMxRCx3Q0FBb0g7QUFFcEgsaUNBQTREO0FBQzVELDBFQUFxRTtBQUNyRSxpRkFBNEQ7QUFDNUQsbURBQTBHO0FBRTFHLGdIQUFnSDtBQUNoSCwyQkFBMkI7QUFDM0Isd0NBQTJEO0FBaUUzRDs7R0FFRztBQUNILElBQVksZ0JBU1g7QUFURCxXQUFZLGdCQUFnQjtJQUMxQjs7T0FFRztJQUNILDJFQUFjLENBQUE7SUFDZDs7T0FFRztJQUNILHVFQUFZLENBQUE7QUFDZCxDQUFDLEVBVFcsZ0JBQWdCLEdBQWhCLHdCQUFnQixLQUFoQix3QkFBZ0IsUUFTM0I7QUFFRDs7R0FFRztBQUNILE1BQWEsT0FBUSxTQUFRLGVBQVE7SUF3Rm5DOztPQUVHO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxRQUFzQixFQUFFOztRQUNoRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLFlBQVksRUFBRSxLQUFLLENBQUMsV0FBVztTQUNoQyxDQUFDLENBQUM7UUFuREw7O1dBRUc7UUFDYSxnQkFBVyxHQUFvQixJQUFJLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQWlCckU7O1dBRUc7UUFDSywyQkFBc0IsR0FBYSxFQUFFLENBQUM7UUFPOUM7O1dBRUc7UUFDSyxvQkFBZSxHQUFZLEtBQUssQ0FBQzs7Ozs7Ozs7OztRQW9CdkM7Ozs7VUFJRTtRQUNGLElBQUksZUFBZSxHQUFHLFNBQVMsQ0FBQztRQUNoQyxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsS0FBSyxTQUFTLEVBQUU7WUFDekMsZUFBZSxHQUFHLENBQUMsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1NBQzVJO1FBRUQsSUFBSSxDQUFDLHNCQUFzQixTQUFHLEtBQUssQ0FBQyxpQkFBaUIsbUNBQUksRUFBRSxDQUFDO1FBQzVELElBQUksS0FBSyxDQUFDLDhCQUE4QixFQUFFO1lBQ3hDLElBQUksQ0FBQyw4QkFBOEIsRUFBRSxDQUFDO1NBQ3ZDO1FBRUQsSUFBSSxLQUFLLENBQUMsMkJBQTJCLEVBQUU7WUFDckMsSUFBSSxDQUFDLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxPQUFPLEtBQUsscUJBQXFCLENBQUMsUUFBUSxDQUFDO2dCQUNoRixDQUFDLEtBQUssQ0FBQywyQkFBMkIsQ0FBQyxnQkFBZ0IsS0FBSyxTQUFTLENBQUMsRUFBRTtnQkFDcEUsTUFBTSxJQUFJLEtBQUssQ0FBQyxvRkFBb0YsQ0FBQyxDQUFDO2FBQ3ZHO1lBQ0QsSUFBSSxDQUFDLDRCQUE0QixHQUFHLEtBQUssQ0FBQywyQkFBMkIsQ0FBQztTQUN2RTtRQUVELE1BQU0sT0FBTyxHQUFHLElBQUksMEJBQVUsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBQy9DLFdBQVcsRUFBRSxJQUFJLENBQUMsWUFBWTtZQUM5QixlQUFlO1lBQ2YsYUFBYSxFQUFFLElBQUksQ0FBQyw0QkFBNEIsSUFBSSxJQUFJLENBQUMsaUNBQWlDLEVBQUU7U0FDN0YsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRTtZQUM5RCxPQUFPLEVBQUUsS0FBSztZQUNkLFFBQVEsRUFBRSxTQUFTO1lBQ25CLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtTQUNoQyxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFFOUQsSUFBSSxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUMsR0FBRyxJQUFJLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFHaEUsSUFBSSxDQUFDLHlCQUF5QixHQUFHLEtBQUssQ0FBQyx3QkFBd0IsS0FBSyxTQUFTO1lBQzNFLENBQUMsQ0FBQyxJQUFJLENBQUMsMkJBQTJCLENBQUMsS0FBSyxDQUFDLHdCQUF3QixDQUFDO1lBQ2xFLENBQUMsQ0FBQyxTQUFTLENBQUM7UUFFZCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDLFFBQVEsS0FBSyxTQUFTO1lBQ25ELENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLHlCQUF5QixFQUFFLEtBQUssQ0FBQyxRQUFRLENBQUM7WUFDN0QsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUVkLDBFQUEwRTtRQUMxRSx5RUFBeUU7UUFDekUsaUVBQWlFO1FBQ2pFLGlFQUFpRTtRQUNqRSxtQ0FBbUM7UUFDbkMsY0FBTyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSx1Q0FBdUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUM7S0FDMUc7SUFwSkQ7O09BRUc7SUFDSSxNQUFNLENBQUMscUJBQXFCLENBQUMsS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBd0I7Ozs7Ozs7Ozs7UUFDeEYsT0FBTyxJQUFJLGVBQWUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO0tBQzlDO0lBRUQ7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyxjQUFjLENBQUMsS0FBZ0IsRUFBRSxFQUFVLEVBQUUsVUFBa0I7UUFDM0UsTUFBTSxLQUFLLEdBQUcsWUFBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM5QixNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxnQkFBUyxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDdEUsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQztRQUVyQyxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsbURBQW1ELFVBQVUsRUFBRSxDQUFDLENBQUM7U0FDbEY7UUFFRCxNQUFNLFdBQVcsR0FBRyw2R0FBNkcsQ0FBQztRQUVsSSxNQUFNLE1BQU8sU0FBUSxlQUFRO1lBQTdCOztnQkFDa0IsZUFBVSxHQUFHLFVBQVUsQ0FBQztnQkFDeEIsZ0JBQVcsR0FBRyxXQUFZLENBQUM7WUFVN0MsQ0FBQztZQVRDLElBQUksY0FBYztnQkFDaEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUNuRCxDQUFDO1lBQ0QsSUFBSSxXQUFXO2dCQUNiLE1BQU0sSUFBSSxLQUFLLENBQUMsZUFBZSxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQ2hELENBQUM7WUFDRCxJQUFJLEdBQUc7Z0JBQ0wsTUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLFdBQVcsRUFBRSxDQUFDLENBQUM7WUFDeEMsQ0FBQztTQUNGO1FBRUQsT0FBTyxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQzNCLGtCQUFrQixFQUFFLFVBQVU7U0FDL0IsQ0FBQyxDQUFDO0tBQ0o7SUE4R0Q7O09BRUc7SUFDSSw4QkFBOEI7UUFDbkMsS0FBSyxNQUFNLFFBQVEsSUFBSSxDQUFDLFNBQVMsRUFBRSxjQUFjLENBQUMsRUFBRTtZQUNsRCxJQUFJLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRTtnQkFDbkQsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUM1QztTQUNGO0tBQ0Y7SUFFTyxpQ0FBaUM7O1FBQ3ZDLE9BQU87WUFDTCwyQkFBMkIsRUFBRTtnQkFDM0IsUUFBUSxjQUFFLElBQUksQ0FBQyw0QkFBNEIsMENBQUUsTUFBTSwwQ0FBRSxNQUFNO2dCQUMzRCxnQkFBZ0IsRUFBRSxPQUFBLElBQUksQ0FBQyw0QkFBNEIsMENBQUUsZ0JBQWdCLEtBQUksSUFBSSxDQUFDLG9DQUFvQyxFQUFFO2dCQUNwSCxPQUFPLFFBQUUsSUFBSSxDQUFDLDRCQUE0QiwwQ0FBRSxPQUFPO2FBQ3BEO1NBQ0YsQ0FBQztLQUNIO0lBRU8sb0NBQW9DOztRQUMxQyxNQUFNLGdCQUFnQixTQUFHLElBQUksQ0FBQyw0QkFBNEIsMENBQUUsZ0JBQWdCLENBQUM7UUFDN0UsSUFBSSxDQUFBLGdCQUFnQixhQUFoQixnQkFBZ0IsdUJBQWhCLGdCQUFnQixDQUFFLG1CQUFtQixLQUFJLEVBQUMsZ0JBQWdCLGFBQWhCLGdCQUFnQix1QkFBaEIsZ0JBQWdCLENBQUUsUUFBUSxDQUFBLEVBQUU7WUFDeEUsTUFBTSxJQUFJLEtBQUssQ0FBQyxzR0FBc0csQ0FBQyxDQUFDO1NBQ3pIO1FBQ0QsSUFBSSxDQUFBLGdCQUFnQixhQUFoQixnQkFBZ0IsdUJBQWhCLGdCQUFnQixDQUFFLDJCQUEyQixLQUFJLEVBQUMsZ0JBQWdCLGFBQWhCLGdCQUFnQix1QkFBaEIsZ0JBQWdCLENBQUUsa0JBQWtCLENBQUEsRUFBRTtZQUMxRixNQUFNLElBQUksS0FBSyxDQUFDLG1IQUFtSCxDQUFDLENBQUM7U0FDdEk7UUFDRCxPQUFPO1lBQ0wsMkJBQTJCLEVBQUUsZ0JBQWdCLGFBQWhCLGdCQUFnQix1QkFBaEIsZ0JBQWdCLENBQUUsMkJBQTJCO1lBQzFFLHNCQUFzQixRQUFFLGdCQUFnQixhQUFoQixnQkFBZ0IsdUJBQWhCLGdCQUFnQixDQUFFLGtCQUFrQiwwQ0FBRSxZQUFZO1lBQzFFLFlBQVksUUFBRSxnQkFBZ0IsYUFBaEIsZ0JBQWdCLHVCQUFoQixnQkFBZ0IsQ0FBRSxRQUFRLDBDQUFFLFVBQVU7WUFDcEQsbUJBQW1CLEVBQUUsZ0JBQWdCLGFBQWhCLGdCQUFnQix1QkFBaEIsZ0JBQWdCLENBQUUsbUJBQW1CO1lBQzFELFdBQVcsRUFBRSxnQkFBZ0IsYUFBaEIsZ0JBQWdCLHVCQUFoQixnQkFBZ0IsQ0FBRSxXQUFXO1NBQzNDLENBQUM7S0FDSDtJQUVEOzs7O09BSUc7SUFDSSwyQkFBMkIsQ0FBQyxPQUFpQzs7Ozs7Ozs7OztRQUNsRSxJQUFJLElBQUksQ0FBQyx5QkFBeUIsS0FBSyxTQUFTLEVBQUU7WUFDaEQsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO1NBQ3pEO1FBRUQsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLElBQUksS0FBSyxTQUFTO1lBQzlDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSTtZQUNkLENBQUMsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQztRQUV2QyxNQUFNLFdBQVcsR0FBRyxhQUFhLEtBQUssUUFBUSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN4RSxJQUFJLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsa0NBQWtDLEVBQUU7Z0JBQ3pFLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtnQkFDbEIsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO2FBQ2QsQ0FBQyxDQUFDLENBQUM7WUFDSixJQUFJLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsa0NBQWtDLEVBQUU7Z0JBQ3hFLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTthQUNuQixDQUFDLENBQUM7UUFFTCxJQUFJLENBQUMseUJBQXlCLEdBQUcsV0FBVyxDQUFDO1FBRTdDLE9BQU8sV0FBVyxDQUFDO0tBQ3BCO0lBRUQ7O09BRUc7SUFDSCxJQUFXLHdCQUF3QjtRQUNqQyxPQUFPLElBQUksQ0FBQyx5QkFBeUIsQ0FBQztLQUN2QztJQUVEOzs7Ozs7T0FNRztJQUNJLFdBQVcsQ0FBQyxFQUFVLEVBQUUsT0FBMkI7Ozs7Ozs7Ozs7O1FBQ3hELHlGQUF5RjtRQUN6RixnRUFBZ0U7UUFDaEUsTUFBTSxZQUFZLFNBQUcsT0FBTyxDQUFDLFlBQVksbUNBQ3ZDLENBQUMsT0FBTyxDQUFDLGdCQUFnQixLQUFLLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSSx3QkFBaUIsQ0FBQztZQUNsRixZQUFZLEVBQUUsT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZO1NBQ2hELENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxzQkFBZSxFQUFFLENBQUMsQ0FBQztRQUU5QixNQUFNLGdCQUFnQixTQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsbUNBQy9DLENBQUMsbUJBQW1CLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsZ0JBQWdCLENBQUMsY0FBYyxDQUFDLENBQUM7UUFFeEcsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFO1lBQ2xFLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRztZQUNiLFlBQVk7WUFDWixVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVUsSUFBSSxXQUFXLENBQUMsVUFBVSxDQUFDLGdCQUFnQjtZQUN6RSxHQUFHLE9BQU87U0FDWCxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsbUJBQW1CLENBQUMsZ0JBQWdCLEVBQUU7WUFDekMsZ0JBQWdCLEVBQUUsZ0JBQWdCO1lBQ2xDLEdBQUcsT0FBTztTQUNYLENBQUMsQ0FBQztRQUVILE9BQU8sZ0JBQWdCLENBQUM7S0FDekI7SUFFRDs7OztPQUlHO0lBQ0ksc0JBQXNCLENBQUMsUUFBNkIsRUFBRSxVQUE2QyxFQUFFOzs7Ozs7Ozs7OztRQUMxRyx1REFBdUQ7UUFDdkQsSUFBSSxJQUFJLENBQUMsc0JBQXNCLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFO1lBQ3ZFLE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDO1FBQzVCLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUU7WUFDeEQsR0FBRyxPQUFPO1lBQ1YsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLGdCQUFnQjtZQUMzQyxpR0FBaUc7WUFDakcsYUFBYSxFQUFFLFFBQVEsQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDLENBQUMsZUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLGFBQWE7U0FDekcsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLHNCQUFzQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsb0JBQW9CLENBQUMsQ0FBQztLQUNqRTtJQUVEOzs7Ozs7O09BT0c7SUFDSSxtQkFBbUIsQ0FBQyxnQkFBOEMsRUFBRSxVQUE4QyxFQUFFOzs7Ozs7Ozs7OztRQUN6SCxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQztRQUM1QixJQUFJLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUM5RixJQUFJLENBQUMseUJBQXlCLENBQUMsZ0JBQWdCLEVBQUUsT0FBTyxDQUFDLENBQUM7S0FDM0Q7SUFFTyx5QkFBeUIsQ0FBQyxnQkFBOEMsRUFBRSxVQUE4QyxFQUFFO1FBQ2hJLElBQUksZ0JBQWdCLENBQUMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUU7WUFDL0QsSUFBSSxDQUFDLGdDQUFnQyxDQUFDLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxDQUFDO1NBQ2xFO2FBQU07WUFDTCwyQkFBMkI7WUFDM0IsUUFBUSxPQUFPLENBQUMsZ0JBQWdCLEVBQUU7Z0JBQ2hDLG1CQUFtQjtnQkFDbkIsS0FBSyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztvQkFDbEMsZ0JBQWdCLENBQUMsV0FBVztvQkFDMUIseUJBQXlCO29CQUN6QixvSEFBb0g7b0JBQ3BILGdCQUFnQixFQUNoQixjQUFjLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FDbEMsQ0FBQztvQkFDRixlQUFlO29CQUNmLHNHQUFzRztvQkFDdEcsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsd0JBQXdCLENBQUMsOEJBQThCLENBQUMsQ0FBQyxDQUFDO29CQUNuSCwwQkFBMEI7b0JBQzFCLGdCQUFnQixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsYUFBYSxDQUFDLHdCQUF3QixDQUFDLGtEQUFrRCxDQUFDLENBQUMsQ0FBQztvQkFDdkksTUFBTTtpQkFDUDtnQkFDRDtvQkFDRSw4Q0FBOEM7b0JBQzlDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxvQkFBb0IsSUFBSSxDQUFDLFdBQVcseUJBQXlCLENBQUMsQ0FBQztvQkFDNUYsSUFBSSxDQUFDLE9BQU8sQ0FBQywrQkFBK0IsRUFBRTt3QkFDNUMsc0RBQXNEO3dCQUN0RCw2RkFBNkY7d0JBQzdGLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxzR0FBc0csQ0FBQyxDQUFDO3dCQUNySSxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsNEJBQTRCLENBQUMsQ0FBQzt3QkFDM0QsMEZBQTBGO3dCQUMxRixnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsd0RBQXdELENBQUMsQ0FBQztxQkFDeEY7b0JBRUQsSUFBSSxnQkFBZ0IsQ0FBQyxTQUFTLElBQUksT0FBTyxDQUFDLG9CQUFvQixFQUFFO3dCQUM5RCxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsb0VBQW9FLENBQUMsQ0FBQztxQkFDcEc7YUFDSjtTQUNGO1FBRUQsZ0RBQWdEO1FBQ2hELDZGQUE2RjtRQUM3RixvREFBb0Q7UUFDcEQsVUFBVTtRQUNWLCtEQUErRDtRQUMvRCxnQkFBZ0IsQ0FBQyxlQUFlLENBQUMsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO1lBQ3ZELE9BQU8sRUFBRTtnQkFDUCxpQ0FBaUM7Z0JBQ2pDLCtCQUErQjtnQkFDL0IsYUFBYTthQUNkO1lBQ0QsU0FBUyxFQUFFO2dCQUNULElBQUksQ0FBQyxVQUFVO2FBQ2hCO1NBQ0YsQ0FBQyxDQUFDLENBQUM7UUFDSixnQkFBZ0IsQ0FBQyxlQUFlLENBQUMsSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDO1lBQ3ZELE9BQU8sRUFBRTtnQkFDUCw0RkFBNEY7Z0JBQzVGLGdEQUFnRDtnQkFDaEQsZ0dBQWdHO2dCQUNoRyxVQUFVO2dCQUNWLDJCQUEyQjthQUM1QjtZQUNELFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQztZQUNoQixVQUFVLEVBQUU7Z0JBQ1YsU0FBUyxFQUFFLEVBQUUsYUFBYSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUU7YUFDOUM7U0FDRixDQUFDLENBQUMsQ0FBQztRQUNKLGdCQUFnQixDQUFDLGVBQWUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7WUFDdkQsT0FBTyxFQUFFO2dCQUNQLHNFQUFzRTtnQkFDdEUsMEJBQTBCO2dCQUMxQiwyQkFBMkI7Z0JBQzNCLHlDQUF5QztnQkFDekMsZ0VBQWdFO2dCQUNoRSx1RUFBdUU7Z0JBQ3ZFLGtFQUFrRTtnQkFDbEUsc0JBQXNCO2dCQUN0QixtQkFBbUI7YUFDcEI7WUFDRCxTQUFTLEVBQUUsQ0FBQyxHQUFHLENBQUM7U0FDakIsQ0FBQyxDQUFDLENBQUM7UUFFSiwwRkFBMEY7UUFDMUYsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLElBQUksT0FBTyxDQUFDLGFBQWEsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLEVBQUU7WUFDckUsSUFBSSx1Q0FBaUIsQ0FBQyxnQkFBZ0IsRUFBRSxjQUFjLEVBQUU7Z0JBQ3RELGdCQUFnQjtnQkFDaEIsT0FBTyxFQUFFLElBQUk7Z0JBQ2IsU0FBUyxFQUFFLE9BQU8sQ0FBQyxhQUFhO2dCQUNoQyxrQkFBa0IsRUFBRSxPQUFPLENBQUMsa0JBQWtCO2FBQy9DLENBQUMsQ0FBQztTQUNKO0tBQ0Y7SUFFRDs7Ozs7O09BTUc7SUFDSSxtQkFBbUIsQ0FBQyxRQUFnQjs7Ozs7Ozs7OztRQUN6QyxJQUFJLENBQUMsQ0FBQyxRQUFRLEtBQUssU0FBUyxJQUFJLFFBQVEsS0FBSyxjQUFjLENBQUMsRUFBRTtZQUM1RCxNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7U0FDbkQ7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRTtZQUNuRCxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQzVDO0tBQ0Y7SUFFTyxnQ0FBZ0MsQ0FBQyxnQkFBOEMsRUFBRSxVQUE4QyxFQUFFO1FBQ3ZJLCtCQUErQjtRQUMvQixnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsMERBQTBELENBQUMsQ0FBQztRQUV6Riw0QkFBNEI7UUFDNUIsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLHdCQUF3QixDQUFDLENBQUM7UUFFdkQsNENBQTRDO1FBQzVDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyx5REFBeUQsSUFBSSxDQUFDLFdBQVcsZUFBZSxDQUFDLENBQUM7UUFDdkgsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLHVHQUF1RyxDQUFDLENBQUM7UUFDdEksNENBQTRDO1FBQzVDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxnSEFBZ0gsQ0FBQyxDQUFDO1FBRS9JLDJCQUEyQjtRQUMzQixJQUFJLGdCQUFnQixDQUFDLFNBQVMsSUFBSSxPQUFPLENBQUMsb0JBQW9CLEVBQUU7WUFDOUQsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLCtGQUErRixDQUFDLENBQUM7U0FDL0g7UUFFRCx1QkFBdUI7UUFDdkIsSUFBSSxDQUFDLE9BQU8sQ0FBQywrQkFBK0IsRUFBRTtZQUM1QyxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsc0ZBQXNGLENBQUMsQ0FBQztZQUNySCxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsaUNBQWlDLElBQUksQ0FBQyxXQUFXLHNCQUFzQixDQUFDLENBQUM7U0FDdkc7YUFBTTtZQUNMLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxpQ0FBaUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUM7U0FDcEY7S0FDRjtJQUVEOztPQUVHO0lBQ0gsSUFBVyxnQkFBZ0I7UUFDekIsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUM7S0FDL0I7SUFFRDs7T0FFRztJQUNILElBQVcsY0FBYztRQUN2QixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUM7S0FDN0I7SUFFRDs7T0FFRztJQUNILElBQVcsMkJBQTJCO1FBQ3BDLE9BQU8sSUFBSSxDQUFDLDRCQUE0QixDQUFDO0tBQzFDO0lBRUQ7Ozs7T0FJRztJQUNJLG9CQUFvQixDQUFDLEtBQWdDO1FBQzFELE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyx5Q0FBVSxDQUFDLHFCQUFxQixFQUFFLEtBQUssQ0FBQyxDQUFDO0tBQ25FO0lBRUQ7Ozs7T0FJRztJQUNJLG9CQUFvQixDQUFDLEtBQWdDO1FBQzFELE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyx5Q0FBVSxDQUFDLHFCQUFxQixFQUFFLEtBQUssQ0FBQyxDQUFDO0tBQ25FO0lBRUQ7Ozs7T0FJRztJQUNJLHVCQUF1QixDQUFDLEtBQWdDO1FBQzdELE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyx5Q0FBVSxDQUFDLHdCQUF3QixFQUFFLEtBQUssQ0FBQyxDQUFDO0tBQ3RFO0lBRUQ7Ozs7T0FJRztJQUNJLHVCQUF1QixDQUFDLEtBQWdDO1FBQzdELE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyx5Q0FBVSxDQUFDLHdCQUF3QixFQUFFLEtBQUssQ0FBQyxDQUFDO0tBQ3RFO0lBRUQ7O09BRUc7SUFDSSxNQUFNLENBQUMsVUFBa0IsRUFBRSxLQUFnQztRQUNoRSxPQUFPLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQztZQUMzQixTQUFTLEVBQUUsU0FBUztZQUNwQixVQUFVO1lBQ1YsYUFBYSxFQUFFLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDaEQsR0FBRyxLQUFLO1NBQ1QsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUNuQjtJQUVPLFlBQVksQ0FDbEIsRUFBNkQsRUFDN0QsS0FBZ0M7UUFDaEMsT0FBTyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUM7WUFDM0IsR0FBRyxFQUFFLENBQUMsRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3hDLEdBQUcsS0FBSztTQUNULENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDbkI7O0FBemZILDBCQTBmQzs7O0FBd0dEOztHQUVHO0FBQ0gsTUFBTSxlQUFnQixTQUFRLGVBQVE7SUFvQ3BDOztPQUVHO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUF3Qjs7UUFDaEUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQXhCbkI7O1dBRUc7UUFDYSxnQkFBVyxHQUFHLElBQUksR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBc0JsRCxJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQyxXQUFXLENBQUM7UUFDckMsSUFBSSxDQUFDLEdBQUcsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDO1FBQ3JCLElBQUksQ0FBQyxjQUFjLEdBQUcsS0FBSyxDQUFDLGNBQWMsS0FBSyxLQUFLLENBQUM7UUFDckQsSUFBSSxDQUFDLHlCQUF5QixHQUFHLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQztRQUNoRSxJQUFJLENBQUMsNEJBQTRCLEdBQUcsS0FBSyxDQUFDLDJCQUEyQixDQUFDO1FBRXRFLElBQUksQ0FBQyxVQUFVLFNBQUcsS0FBSyxDQUFDLFVBQVUsbUNBQUksWUFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUM7WUFDN0QsT0FBTyxFQUFFLEtBQUs7WUFDZCxRQUFRLEVBQUUsU0FBUztZQUNuQixZQUFZLEVBQUUsS0FBSyxDQUFDLFdBQVc7U0FDaEMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxXQUFXLENBQUM7WUFDckMsY0FBYyxFQUFFLEtBQUssQ0FBQyxjQUFjO1NBQ3JDLENBQUMsQ0FBQztLQUNKO0lBRUQsSUFBVyx3QkFBd0I7UUFDakMsT0FBTyxJQUFJLENBQUMseUJBQXlCLENBQUM7S0FDdkM7SUFFRCxJQUFXLDJCQUEyQjtRQUNwQyxPQUFPLElBQUksQ0FBQyw0QkFBNEIsQ0FBQztLQUMxQztDQUNGO0FBd0hELElBQUssaUJBV0o7QUFYRCxXQUFLLGlCQUFpQjtJQUNwQjs7T0FFRztJQUVILHdDQUFtQixDQUFBO0lBRW5COztPQUVHO0lBQ0gsMENBQXFCLENBQUE7QUFDdkIsQ0FBQyxFQVhJLGlCQUFpQixLQUFqQixpQkFBaUIsUUFXckI7QUEyREQ7OztHQUdHO0FBQ0gsSUFBWSxxQkFlWDtBQWZELFdBQVkscUJBQXFCO0lBQy9COztPQUVHO0lBQ0gsc0NBQWEsQ0FBQTtJQUViOztPQUVHO0lBQ0gsNENBQW1CLENBQUE7SUFFbkI7O09BRUc7SUFDSCw4Q0FBcUIsQ0FBQTtBQUN2QixDQUFDLEVBZlcscUJBQXFCLEdBQXJCLDZCQUFxQixLQUFyQiw2QkFBcUIsUUFlaEM7QUFnR0Q7Ozs7OztHQU1HO0FBQ0gsTUFBYSxtQkFBb0IsU0FBUSxnQkFBYTtJQXNCcEQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUErQjs7UUFDdkUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQzs7Ozs7Ozs7OztRQUVqQixJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLGdCQUFnRCxDQUFDO1FBRS9FLElBQUksQ0FBQyxnQkFBZ0IsU0FBRyxLQUFLLENBQUMsZ0JBQWdCLG1DQUFJLGdCQUFnQixDQUFDLGNBQWMsQ0FBQztRQUVsRixJQUFJLENBQUMsa0NBQWtDO1lBQ3JDLEtBQUssQ0FBQyxrQ0FBa0MsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGtDQUFrQyxDQUFDO1FBRTNHLElBQUksSUFBSSxDQUFDLGtDQUFrQyxFQUFFO1lBQzNDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyw4QkFBOEIsRUFBRSxDQUFDO1NBQ3hEO1FBQ0QsSUFBSSxLQUFLLENBQUMsb0JBQW9CLEVBQUU7WUFDOUIsSUFBSSxDQUFDLENBQUMsMEJBQTBCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLEVBQUU7Z0JBQ2xFLE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLEtBQUssQ0FBQyxvQkFBb0Isc0VBQXNFLENBQUMsQ0FBQzthQUN0SjtTQUNGO1FBQ0QsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLG1DQUFtQixDQUFDLElBQUksRUFBRSxFQUFFLEVBQUU7WUFDekQsSUFBSSxFQUFFLEtBQUssQ0FBQyxvQkFBb0I7WUFDaEMsd0JBQXdCLEVBQUU7Z0JBQ3hCLG1CQUFtQixFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxvQkFBb0I7Z0JBQy9ELGNBQWMsRUFBRSxLQUFLLENBQUMsb0JBQW9CLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO29CQUNqRSxNQUFNLEVBQUUsU0FBUztvQkFDakIsY0FBYyxFQUFFLEtBQUssQ0FBQyxxQkFBcUIsSUFBSSxHQUFHO29CQUNsRCxzQkFBc0IsRUFBRSxLQUFLLENBQUMsc0JBQXNCO29CQUNwRCxzQkFBc0IsRUFBRSxLQUFLLENBQUMsc0JBQXNCO2lCQUNyRDtnQkFDRCw0QkFBNEIsRUFBRSxJQUFJLENBQUMsa0NBQWtDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsVUFBVTthQUMvRjtTQUNGLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxvQkFBb0IsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUM7S0FDbEQ7O0FBdkRILGtEQXdEQzs7O0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSx1Q0FBdUM7SUFNM0MsWUFBWSxLQUFvQixFQUFFLEVBQVUsRUFBRSxpQkFBMkI7UUFDdkUsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbkIsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7UUFDYixJQUFJLENBQUMsaUJBQWlCLEdBQUcsaUJBQWlCLENBQUM7S0FDNUM7SUFFTSxLQUFLLENBQUMsSUFBZ0I7UUFDM0IsSUFBSSxJQUFJLFlBQVksT0FBTyxFQUFFO1lBQzNCLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUN2RCxNQUFNLFFBQVEsR0FBRyxJQUFJLHNEQUFzQyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtvQkFDL0UsT0FBTyxFQUFFLElBQUksQ0FBQyxXQUFXO29CQUN6QiwrQkFBK0IsRUFBRSxFQUFFO29CQUNuQyxpQkFBaUIsRUFBRSxXQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO2lCQUN4RSxDQUFDLENBQUM7Z0JBQ0gsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7YUFDMUI7U0FDRjtLQUNGO0NBQ0Y7QUFHRCxTQUFTLG1CQUFtQixDQUFDLEtBQXdCO0lBQ25ELE9BQU8sS0FBSyxZQUFZLHdCQUFpQixDQUFDO0FBQzVDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhdXRvc2NhbGluZyBmcm9tICdAYXdzLWNkay9hd3MtYXV0b3NjYWxpbmcnO1xuaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tICdAYXdzLWNkay9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQgKiBhcyBlYzIgZnJvbSAnQGF3cy1jZGsvYXdzLWVjMic7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnQGF3cy1jZGsvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBrbXMgZnJvbSAnQGF3cy1jZGsvYXdzLWttcyc7XG5pbXBvcnQgKiBhcyBsb2dzIGZyb20gJ0Bhd3MtY2RrL2F3cy1sb2dzJztcbmltcG9ydCAqIGFzIHMzIGZyb20gJ0Bhd3MtY2RrL2F3cy1zMyc7XG5pbXBvcnQgKiBhcyBjbG91ZG1hcCBmcm9tICdAYXdzLWNkay9hd3Mtc2VydmljZWRpc2NvdmVyeSc7XG5pbXBvcnQgeyBEdXJhdGlvbiwgTGF6eSwgSVJlc291cmNlLCBSZXNvdXJjZSwgU3RhY2ssIEFzcGVjdHMsIElBc3BlY3QsIElDb25zdHJ1Y3QsIEFybkZvcm1hdCB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBCb3R0bGVSb2NrZXRJbWFnZSwgRWNzT3B0aW1pemVkQW1pIH0gZnJvbSAnLi9hbWlzJztcbmltcG9ydCB7IEluc3RhbmNlRHJhaW5Ib29rIH0gZnJvbSAnLi9kcmFpbi1ob29rL2luc3RhbmNlLWRyYWluLWhvb2snO1xuaW1wb3J0IHsgRUNTTWV0cmljcyB9IGZyb20gJy4vZWNzLWNhbm5lZC1tZXRyaWNzLmdlbmVyYXRlZCc7XG5pbXBvcnQgeyBDZm5DbHVzdGVyLCBDZm5DYXBhY2l0eVByb3ZpZGVyLCBDZm5DbHVzdGVyQ2FwYWNpdHlQcm92aWRlckFzc29jaWF0aW9ucyB9IGZyb20gJy4vZWNzLmdlbmVyYXRlZCc7XG5cbi8vIHYyIC0ga2VlcCB0aGlzIGltcG9ydCBhcyBhIHNlcGFyYXRlIHNlY3Rpb24gdG8gcmVkdWNlIG1lcmdlIGNvbmZsaWN0IHdoZW4gZm9yd2FyZCBtZXJnaW5nIHdpdGggdGhlIHYyIGJyYW5jaC5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuaW1wb3J0IHsgQ29uc3RydWN0IGFzIENvcmVDb25zdHJ1Y3QgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcblxuLyoqXG4gKiBUaGUgcHJvcGVydGllcyB1c2VkIHRvIGRlZmluZSBhbiBFQ1MgY2x1c3Rlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDbHVzdGVyUHJvcHMge1xuICAvKipcbiAgICogVGhlIG5hbWUgZm9yIHRoZSBjbHVzdGVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCBDbG91ZEZvcm1hdGlvbi1nZW5lcmF0ZWQgbmFtZVxuICAgKi9cbiAgcmVhZG9ubHkgY2x1c3Rlck5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBWUEMgd2hlcmUgeW91ciBFQ1MgaW5zdGFuY2VzIHdpbGwgYmUgcnVubmluZyBvciB5b3VyIEVOSXMgd2lsbCBiZSBkZXBsb3llZFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGNyZWF0ZXMgYSBuZXcgVlBDIHdpdGggdHdvIEFac1xuICAgKi9cbiAgcmVhZG9ubHkgdnBjPzogZWMyLklWcGM7XG5cbiAgLyoqXG4gICAqIFRoZSBzZXJ2aWNlIGRpc2NvdmVyeSBuYW1lc3BhY2UgY3JlYXRlZCBpbiB0aGlzIGNsdXN0ZXJcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBzZXJ2aWNlIGRpc2NvdmVyeSBuYW1lc3BhY2UgY3JlYXRlZCwgeW91IGNhbiB1c2UgYGFkZERlZmF1bHRDbG91ZE1hcE5hbWVzcGFjZWAgdG8gYWRkIGFcbiAgICogZGVmYXVsdCBzZXJ2aWNlIGRpc2NvdmVyeSBuYW1lc3BhY2UgbGF0ZXIuXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0Q2xvdWRNYXBOYW1lc3BhY2U/OiBDbG91ZE1hcE5hbWVzcGFjZU9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFRoZSBlYzIgY2FwYWNpdHkgdG8gYWRkIHRvIHRoZSBjbHVzdGVyXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gRUMyIGNhcGFjaXR5IHdpbGwgYmUgYWRkZWQsIHlvdSBjYW4gdXNlIGBhZGRDYXBhY2l0eWAgdG8gYWRkIGNhcGFjaXR5IGxhdGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgY2FwYWNpdHk/OiBBZGRDYXBhY2l0eU9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFRoZSBjYXBhY2l0eSBwcm92aWRlcnMgdG8gYWRkIHRvIHRoZSBjbHVzdGVyXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm9uZS4gQ3VycmVudGx5IG9ubHkgRkFSR0FURSBhbmQgRkFSR0FURV9TUE9UIGFyZSBzdXBwb3J0ZWQuXG4gICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgQ2x1c3RlclByb3BzLmVuYWJsZUZhcmdhdGVDYXBhY2l0eVByb3ZpZGVyc30gaW5zdGVhZC5cbiAgICovXG4gIHJlYWRvbmx5IGNhcGFjaXR5UHJvdmlkZXJzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZW5hYmxlIEZhcmdhdGUgQ2FwYWNpdHkgUHJvdmlkZXJzXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBlbmFibGVGYXJnYXRlQ2FwYWNpdHlQcm92aWRlcnM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJZiB0cnVlIENsb3VkV2F0Y2ggQ29udGFpbmVyIEluc2lnaHRzIHdpbGwgYmUgZW5hYmxlZCBmb3IgdGhlIGNsdXN0ZXJcbiAgICpcbiAgICogQGRlZmF1bHQgLSBDb250YWluZXIgSW5zaWdodHMgd2lsbCBiZSBkaXNhYmxlZCBmb3IgdGhpcyBjbHVzZXIuXG4gICAqL1xuICByZWFkb25seSBjb250YWluZXJJbnNpZ2h0cz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBleGVjdXRlIGNvbW1hbmQgY29uZmlndXJhdGlvbiBmb3IgdGhlIGNsdXN0ZXJcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBjb25maWd1cmF0aW9uIHdpbGwgYmUgcHJvdmlkZWQuXG4gICAqL1xuICByZWFkb25seSBleGVjdXRlQ29tbWFuZENvbmZpZ3VyYXRpb24/OiBFeGVjdXRlQ29tbWFuZENvbmZpZ3VyYXRpb247XG59XG5cbi8qKlxuICogVGhlIG1hY2hpbmUgaW1hZ2UgdHlwZVxuICovXG5leHBvcnQgZW51bSBNYWNoaW5lSW1hZ2VUeXBlIHtcbiAgLyoqXG4gICAqIEFtYXpvbiBFQ1Mtb3B0aW1pemVkIEFtYXpvbiBMaW51eCAyIEFNSVxuICAgKi9cbiAgQU1BWk9OX0xJTlVYXzIsXG4gIC8qKlxuICAgKiBCb3R0bGVyb2NrZXQgQU1JXG4gICAqL1xuICBCT1RUTEVST0NLRVRcbn1cblxuLyoqXG4gKiBBIHJlZ2lvbmFsIGdyb3VwaW5nIG9mIG9uZSBvciBtb3JlIGNvbnRhaW5lciBpbnN0YW5jZXMgb24gd2hpY2ggeW91IGNhbiBydW4gdGFza3MgYW5kIHNlcnZpY2VzLlxuICovXG5leHBvcnQgY2xhc3MgQ2x1c3RlciBleHRlbmRzIFJlc291cmNlIGltcGxlbWVudHMgSUNsdXN0ZXIge1xuICAvKipcbiAgICogSW1wb3J0IGFuIGV4aXN0aW5nIGNsdXN0ZXIgdG8gdGhlIHN0YWNrIGZyb20gaXRzIGF0dHJpYnV0ZXMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21DbHVzdGVyQXR0cmlidXRlcyhzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBhdHRyczogQ2x1c3RlckF0dHJpYnV0ZXMpOiBJQ2x1c3RlciB7XG4gICAgcmV0dXJuIG5ldyBJbXBvcnRlZENsdXN0ZXIoc2NvcGUsIGlkLCBhdHRycyk7XG4gIH1cblxuICAvKipcbiAgICogSW1wb3J0IGFuIGV4aXN0aW5nIGNsdXN0ZXIgdG8gdGhlIHN0YWNrIGZyb20gdGhlIGNsdXN0ZXIgQVJOLlxuICAgKiBUaGlzIGRvZXMgbm90IHByb3ZpZGUgYWNjZXNzIHRvIHRoZSB2cGMsIGhhc0VjMkNhcGFjaXR5LCBvciBjb25uZWN0aW9ucyAtXG4gICAqIHVzZSB0aGUgYGZyb21DbHVzdGVyQXR0cmlidXRlc2AgbWV0aG9kIHRvIGFjY2VzcyB0aG9zZSBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tQ2x1c3RlckFybihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBjbHVzdGVyQXJuOiBzdHJpbmcpOiBJQ2x1c3RlciB7XG4gICAgY29uc3Qgc3RhY2sgPSBTdGFjay5vZihzY29wZSk7XG4gICAgY29uc3QgYXJuID0gc3RhY2suc3BsaXRBcm4oY2x1c3RlckFybiwgQXJuRm9ybWF0LlNMQVNIX1JFU09VUkNFX05BTUUpO1xuICAgIGNvbnN0IGNsdXN0ZXJOYW1lID0gYXJuLnJlc291cmNlTmFtZTtcblxuICAgIGlmICghY2x1c3Rlck5hbWUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyByZXF1aXJlZCBDbHVzdGVyIE5hbWUgZnJvbSBDbHVzdGVyIEFSTjogJHtjbHVzdGVyQXJufWApO1xuICAgIH1cblxuICAgIGNvbnN0IGVycm9yU3VmZml4ID0gJ2lzIG5vdCBhdmFpbGFibGUgZm9yIGEgQ2x1c3RlciBpbXBvcnRlZCB1c2luZyBmcm9tQ2x1c3RlckFybigpLCBwbGVhc2UgdXNlIGZyb21DbHVzdGVyQXR0cmlidXRlcygpIGluc3RlYWQuJztcblxuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIFJlc291cmNlIGltcGxlbWVudHMgSUNsdXN0ZXIge1xuICAgICAgcHVibGljIHJlYWRvbmx5IGNsdXN0ZXJBcm4gPSBjbHVzdGVyQXJuO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGNsdXN0ZXJOYW1lID0gY2x1c3Rlck5hbWUhO1xuICAgICAgZ2V0IGhhc0VjMkNhcGFjaXR5KCk6IGJvb2xlYW4ge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGhhc0VjMkNhcGFjaXR5ICR7ZXJyb3JTdWZmaXh9YCk7XG4gICAgICB9XG4gICAgICBnZXQgY29ubmVjdGlvbnMoKTogZWMyLkNvbm5lY3Rpb25zIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjb25uZWN0aW9ucyAke2Vycm9yU3VmZml4fWApO1xuICAgICAgfVxuICAgICAgZ2V0IHZwYygpOiBlYzIuSVZwYyB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdnBjICR7ZXJyb3JTdWZmaXh9YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoc2NvcGUsIGlkLCB7XG4gICAgICBlbnZpcm9ubWVudEZyb21Bcm46IGNsdXN0ZXJBcm4sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTWFuYWdlIHRoZSBhbGxvd2VkIG5ldHdvcmsgY29ubmVjdGlvbnMgZm9yIHRoZSBjbHVzdGVyIHdpdGggU2VjdXJpdHkgR3JvdXBzLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGNvbm5lY3Rpb25zOiBlYzIuQ29ubmVjdGlvbnMgPSBuZXcgZWMyLkNvbm5lY3Rpb25zKCk7XG5cbiAgLyoqXG4gICAqIFRoZSBWUEMgYXNzb2NpYXRlZCB3aXRoIHRoZSBjbHVzdGVyLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHZwYzogZWMyLklWcGM7XG5cbiAgLyoqXG4gICAqIFRoZSBBbWF6b24gUmVzb3VyY2UgTmFtZSAoQVJOKSB0aGF0IGlkZW50aWZpZXMgdGhlIGNsdXN0ZXIuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgY2x1c3RlckFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgY2x1c3Rlci5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjbHVzdGVyTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZXMgb2YgYm90aCBBU0cgYW5kIEZhcmdhdGUgY2FwYWNpdHkgcHJvdmlkZXJzIGFzc29jaWF0ZWQgd2l0aCB0aGUgY2x1c3Rlci5cbiAgICovXG4gIHByaXZhdGUgX2NhcGFjaXR5UHJvdmlkZXJOYW1lczogc3RyaW5nW10gPSBbXTtcblxuICAvKipcbiAgICogVGhlIEFXUyBDbG91ZCBNYXAgbmFtZXNwYWNlIHRvIGFzc29jaWF0ZSB3aXRoIHRoZSBjbHVzdGVyLlxuICAgKi9cbiAgcHJpdmF0ZSBfZGVmYXVsdENsb3VkTWFwTmFtZXNwYWNlPzogY2xvdWRtYXAuSU5hbWVzcGFjZTtcblxuICAvKipcbiAgICogU3BlY2lmaWVzIHdoZXRoZXIgdGhlIGNsdXN0ZXIgaGFzIEVDMiBpbnN0YW5jZSBjYXBhY2l0eS5cbiAgICovXG4gIHByaXZhdGUgX2hhc0VjMkNhcGFjaXR5OiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIFRoZSBhdXRvc2NhbGluZyBncm91cCBmb3IgYWRkZWQgRWMyIGNhcGFjaXR5XG4gICAqL1xuICBwcml2YXRlIF9hdXRvc2NhbGluZ0dyb3VwPzogYXV0b3NjYWxpbmcuSUF1dG9TY2FsaW5nR3JvdXA7XG5cbiAgLyoqXG4gICAqIFRoZSBleGVjdXRlIGNvbW1hbmQgY29uZmlndXJhdGlvbiBmb3IgdGhlIGNsdXN0ZXJcbiAgICovXG4gIHByaXZhdGUgX2V4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbj86IEV4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgQ2x1c3RlciBjbGFzcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBDbHVzdGVyUHJvcHMgPSB7fSkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge1xuICAgICAgcGh5c2ljYWxOYW1lOiBwcm9wcy5jbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqIGNsdXN0ZXJTZXR0aW5ncyBuZWVkcyB0byBiZSB1bmRlZmluZWQgaWYgY29udGFpbmVySW5zaWdodHMgaXMgbm90IGV4cGxpY2l0bHkgc2V0IGluIG9yZGVyIHRvIGFsbG93IGFueVxuICAgICAqIGNvbnRhaW5lckluc2lnaHRzIHNldHRpbmdzIG9uIHRoZSBhY2NvdW50IHRvIGFwcGx5LiAgU2VlOlxuICAgICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWVjcy1jbHVzdGVyLWNsdXN0ZXJzZXR0aW5ncy5odG1sI2Nmbi1lY3MtY2x1c3Rlci1jbHVzdGVyc2V0dGluZ3MtdmFsdWVcbiAgICAqL1xuICAgIGxldCBjbHVzdGVyU2V0dGluZ3MgPSB1bmRlZmluZWQ7XG4gICAgaWYgKHByb3BzLmNvbnRhaW5lckluc2lnaHRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNsdXN0ZXJTZXR0aW5ncyA9IFt7IG5hbWU6ICdjb250YWluZXJJbnNpZ2h0cycsIHZhbHVlOiBwcm9wcy5jb250YWluZXJJbnNpZ2h0cyA/IENvbnRhaW5lckluc2lnaHRzLkVOQUJMRUQgOiBDb250YWluZXJJbnNpZ2h0cy5ESVNBQkxFRCB9XTtcbiAgICB9XG5cbiAgICB0aGlzLl9jYXBhY2l0eVByb3ZpZGVyTmFtZXMgPSBwcm9wcy5jYXBhY2l0eVByb3ZpZGVycyA/PyBbXTtcbiAgICBpZiAocHJvcHMuZW5hYmxlRmFyZ2F0ZUNhcGFjaXR5UHJvdmlkZXJzKSB7XG4gICAgICB0aGlzLmVuYWJsZUZhcmdhdGVDYXBhY2l0eVByb3ZpZGVycygpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5leGVjdXRlQ29tbWFuZENvbmZpZ3VyYXRpb24pIHtcbiAgICAgIGlmICgocHJvcHMuZXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uLmxvZ2dpbmcgPT09IEV4ZWN1dGVDb21tYW5kTG9nZ2luZy5PVkVSUklERSkgIT09XG4gICAgICAgIChwcm9wcy5leGVjdXRlQ29tbWFuZENvbmZpZ3VyYXRpb24ubG9nQ29uZmlndXJhdGlvbiAhPT0gdW5kZWZpbmVkKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4ZWN1dGUgY29tbWFuZCBsb2cgY29uZmlndXJhdGlvbiBtdXN0IG9ubHkgYmUgc3BlY2lmaWVkIHdoZW4gbG9nZ2luZyBpcyBPVkVSUklERS4nKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX2V4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbiA9IHByb3BzLmV4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbjtcbiAgICB9XG5cbiAgICBjb25zdCBjbHVzdGVyID0gbmV3IENmbkNsdXN0ZXIodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgY2x1c3Rlck5hbWU6IHRoaXMucGh5c2ljYWxOYW1lLFxuICAgICAgY2x1c3RlclNldHRpbmdzLFxuICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5fZXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uICYmIHRoaXMucmVuZGVyRXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uKCksXG4gICAgfSk7XG5cbiAgICB0aGlzLmNsdXN0ZXJBcm4gPSB0aGlzLmdldFJlc291cmNlQXJuQXR0cmlidXRlKGNsdXN0ZXIuYXR0ckFybiwge1xuICAgICAgc2VydmljZTogJ2VjcycsXG4gICAgICByZXNvdXJjZTogJ2NsdXN0ZXInLFxuICAgICAgcmVzb3VyY2VOYW1lOiB0aGlzLnBoeXNpY2FsTmFtZSxcbiAgICB9KTtcbiAgICB0aGlzLmNsdXN0ZXJOYW1lID0gdGhpcy5nZXRSZXNvdXJjZU5hbWVBdHRyaWJ1dGUoY2x1c3Rlci5yZWYpO1xuXG4gICAgdGhpcy52cGMgPSBwcm9wcy52cGMgfHwgbmV3IGVjMi5WcGModGhpcywgJ1ZwYycsIHsgbWF4QXpzOiAyIH0pO1xuXG5cbiAgICB0aGlzLl9kZWZhdWx0Q2xvdWRNYXBOYW1lc3BhY2UgPSBwcm9wcy5kZWZhdWx0Q2xvdWRNYXBOYW1lc3BhY2UgIT09IHVuZGVmaW5lZFxuICAgICAgPyB0aGlzLmFkZERlZmF1bHRDbG91ZE1hcE5hbWVzcGFjZShwcm9wcy5kZWZhdWx0Q2xvdWRNYXBOYW1lc3BhY2UpXG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIHRoaXMuX2F1dG9zY2FsaW5nR3JvdXAgPSBwcm9wcy5jYXBhY2l0eSAhPT0gdW5kZWZpbmVkXG4gICAgICA/IHRoaXMuYWRkQ2FwYWNpdHkoJ0RlZmF1bHRBdXRvU2NhbGluZ0dyb3VwJywgcHJvcHMuY2FwYWNpdHkpXG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIC8vIE9ubHkgY3JlYXRlIGNsdXN0ZXIgY2FwYWNpdHkgcHJvdmlkZXIgYXNzb2NpYXRpb25zIGlmIHRoZXJlIGFyZSBhbnkgRUMyXG4gICAgLy8gY2FwYWNpdHkgcHJvdmlkZXJzLiBPcmRpbmFyaWx5IHdlJ2QganVzdCBhZGQgdGhlIGNvbnN0cnVjdCB0byB0aGUgdHJlZVxuICAgIC8vIHNpbmNlIGl0J3MgaGFybWxlc3MsIGJ1dCB3ZSdkIHByZWZlciBub3QgdG8gYWRkIHVuZXhwZWN0ZWQgbmV3XG4gICAgLy8gcmVzb3VyY2VzIHRvIHRoZSBzdGFjayB3aGljaCBjb3VsZCBzdXJwcmlzZSB1c2VycyB3b3JraW5nIHdpdGhcbiAgICAvLyBicm93bi1maWVsZCBDREsgYXBwcyBhbmQgc3RhY2tzLlxuICAgIEFzcGVjdHMub2YodGhpcykuYWRkKG5ldyBNYXliZUNyZWF0ZUNhcGFjaXR5UHJvdmlkZXJBc3NvY2lhdGlvbnModGhpcywgaWQsIHRoaXMuX2NhcGFjaXR5UHJvdmlkZXJOYW1lcykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZSB0aGUgRmFyZ2F0ZSBjYXBhY2l0eSBwcm92aWRlcnMgZm9yIHRoaXMgY2x1c3Rlci5cbiAgICovXG4gIHB1YmxpYyBlbmFibGVGYXJnYXRlQ2FwYWNpdHlQcm92aWRlcnMoKSB7XG4gICAgZm9yIChjb25zdCBwcm92aWRlciBvZiBbJ0ZBUkdBVEUnLCAnRkFSR0FURV9TUE9UJ10pIHtcbiAgICAgIGlmICghdGhpcy5fY2FwYWNpdHlQcm92aWRlck5hbWVzLmluY2x1ZGVzKHByb3ZpZGVyKSkge1xuICAgICAgICB0aGlzLl9jYXBhY2l0eVByb3ZpZGVyTmFtZXMucHVzaChwcm92aWRlcik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJFeGVjdXRlQ29tbWFuZENvbmZpZ3VyYXRpb24oKSA6IENmbkNsdXN0ZXIuQ2x1c3RlckNvbmZpZ3VyYXRpb25Qcm9wZXJ0eSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGV4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbjoge1xuICAgICAgICBrbXNLZXlJZDogdGhpcy5fZXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uPy5rbXNLZXk/LmtleUFybixcbiAgICAgICAgbG9nQ29uZmlndXJhdGlvbjogdGhpcy5fZXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uPy5sb2dDb25maWd1cmF0aW9uICYmIHRoaXMucmVuZGVyRXhlY3V0ZUNvbW1hbmRMb2dDb25maWd1cmF0aW9uKCksXG4gICAgICAgIGxvZ2dpbmc6IHRoaXMuX2V4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbj8ubG9nZ2luZyxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyRXhlY3V0ZUNvbW1hbmRMb2dDb25maWd1cmF0aW9uKCk6IENmbkNsdXN0ZXIuRXhlY3V0ZUNvbW1hbmRMb2dDb25maWd1cmF0aW9uUHJvcGVydHkge1xuICAgIGNvbnN0IGxvZ0NvbmZpZ3VyYXRpb24gPSB0aGlzLl9leGVjdXRlQ29tbWFuZENvbmZpZ3VyYXRpb24/LmxvZ0NvbmZpZ3VyYXRpb247XG4gICAgaWYgKGxvZ0NvbmZpZ3VyYXRpb24/LnMzRW5jcnlwdGlvbkVuYWJsZWQgJiYgIWxvZ0NvbmZpZ3VyYXRpb24/LnMzQnVja2V0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBtdXN0IHNwZWNpZnkgYW4gUzMgYnVja2V0IG5hbWUgaW4gdGhlIGV4ZWN1dGUgY29tbWFuZCBsb2cgY29uZmlndXJhdGlvbiB0byBlbmFibGUgUzMgZW5jcnlwdGlvbi4nKTtcbiAgICB9XG4gICAgaWYgKGxvZ0NvbmZpZ3VyYXRpb24/LmNsb3VkV2F0Y2hFbmNyeXB0aW9uRW5hYmxlZCAmJiAhbG9nQ29uZmlndXJhdGlvbj8uY2xvdWRXYXRjaExvZ0dyb3VwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1lvdSBtdXN0IHNwZWNpZnkgYSBDbG91ZFdhdGNoIGxvZyBncm91cCBpbiB0aGUgZXhlY3V0ZSBjb21tYW5kIGxvZyBjb25maWd1cmF0aW9uIHRvIGVuYWJsZSBDbG91ZFdhdGNoIGVuY3J5cHRpb24uJyk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBjbG91ZFdhdGNoRW5jcnlwdGlvbkVuYWJsZWQ6IGxvZ0NvbmZpZ3VyYXRpb24/LmNsb3VkV2F0Y2hFbmNyeXB0aW9uRW5hYmxlZCxcbiAgICAgIGNsb3VkV2F0Y2hMb2dHcm91cE5hbWU6IGxvZ0NvbmZpZ3VyYXRpb24/LmNsb3VkV2F0Y2hMb2dHcm91cD8ubG9nR3JvdXBOYW1lLFxuICAgICAgczNCdWNrZXROYW1lOiBsb2dDb25maWd1cmF0aW9uPy5zM0J1Y2tldD8uYnVja2V0TmFtZSxcbiAgICAgIHMzRW5jcnlwdGlvbkVuYWJsZWQ6IGxvZ0NvbmZpZ3VyYXRpb24/LnMzRW5jcnlwdGlvbkVuYWJsZWQsXG4gICAgICBzM0tleVByZWZpeDogbG9nQ29uZmlndXJhdGlvbj8uczNLZXlQcmVmaXgsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYW4gQVdTIENsb3VkIE1hcCBETlMgbmFtZXNwYWNlIGZvciB0aGlzIGNsdXN0ZXIuXG4gICAqIE5PVEU6IEh0dHBOYW1lc3BhY2VzIGFyZSBub3Qgc3VwcG9ydGVkLCBhcyBFQ1MgYWx3YXlzIHJlcXVpcmVzIGEgRE5TQ29uZmlnIHdoZW4gcmVnaXN0ZXJpbmcgYW4gaW5zdGFuY2UgdG8gYSBDbG91ZFxuICAgKiBNYXAgc2VydmljZS5cbiAgICovXG4gIHB1YmxpYyBhZGREZWZhdWx0Q2xvdWRNYXBOYW1lc3BhY2Uob3B0aW9uczogQ2xvdWRNYXBOYW1lc3BhY2VPcHRpb25zKTogY2xvdWRtYXAuSU5hbWVzcGFjZSB7XG4gICAgaWYgKHRoaXMuX2RlZmF1bHRDbG91ZE1hcE5hbWVzcGFjZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBvbmx5IGFkZCBkZWZhdWx0IG5hbWVzcGFjZSBvbmNlLicpO1xuICAgIH1cblxuICAgIGNvbnN0IG5hbWVzcGFjZVR5cGUgPSBvcHRpb25zLnR5cGUgIT09IHVuZGVmaW5lZFxuICAgICAgPyBvcHRpb25zLnR5cGVcbiAgICAgIDogY2xvdWRtYXAuTmFtZXNwYWNlVHlwZS5ETlNfUFJJVkFURTtcblxuICAgIGNvbnN0IHNkTmFtZXNwYWNlID0gbmFtZXNwYWNlVHlwZSA9PT0gY2xvdWRtYXAuTmFtZXNwYWNlVHlwZS5ETlNfUFJJVkFURSA/XG4gICAgICBuZXcgY2xvdWRtYXAuUHJpdmF0ZURuc05hbWVzcGFjZSh0aGlzLCAnRGVmYXVsdFNlcnZpY2VEaXNjb3ZlcnlOYW1lc3BhY2UnLCB7XG4gICAgICAgIG5hbWU6IG9wdGlvbnMubmFtZSxcbiAgICAgICAgdnBjOiB0aGlzLnZwYyxcbiAgICAgIH0pIDpcbiAgICAgIG5ldyBjbG91ZG1hcC5QdWJsaWNEbnNOYW1lc3BhY2UodGhpcywgJ0RlZmF1bHRTZXJ2aWNlRGlzY292ZXJ5TmFtZXNwYWNlJywge1xuICAgICAgICBuYW1lOiBvcHRpb25zLm5hbWUsXG4gICAgICB9KTtcblxuICAgIHRoaXMuX2RlZmF1bHRDbG91ZE1hcE5hbWVzcGFjZSA9IHNkTmFtZXNwYWNlO1xuXG4gICAgcmV0dXJuIHNkTmFtZXNwYWNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHRlciBmb3IgbmFtZXNwYWNlIGFkZGVkIHRvIGNsdXN0ZXJcbiAgICovXG4gIHB1YmxpYyBnZXQgZGVmYXVsdENsb3VkTWFwTmFtZXNwYWNlKCk6IGNsb3VkbWFwLklOYW1lc3BhY2UgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9kZWZhdWx0Q2xvdWRNYXBOYW1lc3BhY2U7XG4gIH1cblxuICAvKipcbiAgICogSXQgaXMgaGlnaGx5IHJlY29tbWVuZGVkIHRvIHVzZSB7QGxpbmsgQ2x1c3Rlci5hZGRBc2dDYXBhY2l0eVByb3ZpZGVyfSBpbnN0ZWFkIG9mIHRoaXMgbWV0aG9kLlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBhZGRzIGNvbXB1dGUgY2FwYWNpdHkgdG8gYSBjbHVzdGVyIGJ5IGNyZWF0aW5nIGFuIEF1dG9TY2FsaW5nR3JvdXAgd2l0aCB0aGUgc3BlY2lmaWVkIG9wdGlvbnMuXG4gICAqXG4gICAqIFJldHVybnMgdGhlIEF1dG9TY2FsaW5nR3JvdXAgc28geW91IGNhbiBhZGQgYXV0b3NjYWxpbmcgc2V0dGluZ3MgdG8gaXQuXG4gICAqL1xuICBwdWJsaWMgYWRkQ2FwYWNpdHkoaWQ6IHN0cmluZywgb3B0aW9uczogQWRkQ2FwYWNpdHlPcHRpb25zKTogYXV0b3NjYWxpbmcuQXV0b1NjYWxpbmdHcm91cCB7XG4gICAgLy8gRG8gMi13YXkgZGVmYXVsdGluZyBoZXJlOiBpZiB0aGUgbWFjaGluZUltYWdlVHlwZSBpcyBCT1RUTEVST0NLRVQsIHBpY2sgdGhlIHJpZ2h0IEFNSS5cbiAgICAvLyBPdGhlcndpc2UsIGRldGVybWluZSB0aGUgbWFjaGluZUltYWdlVHlwZSBmcm9tIHRoZSBnaXZlbiBBTUkuXG4gICAgY29uc3QgbWFjaGluZUltYWdlID0gb3B0aW9ucy5tYWNoaW5lSW1hZ2UgPz9cbiAgICAgIChvcHRpb25zLm1hY2hpbmVJbWFnZVR5cGUgPT09IE1hY2hpbmVJbWFnZVR5cGUuQk9UVExFUk9DS0VUID8gbmV3IEJvdHRsZVJvY2tldEltYWdlKHtcbiAgICAgICAgYXJjaGl0ZWN0dXJlOiBvcHRpb25zLmluc3RhbmNlVHlwZS5hcmNoaXRlY3R1cmUsXG4gICAgICB9KSA6IG5ldyBFY3NPcHRpbWl6ZWRBbWkoKSk7XG5cbiAgICBjb25zdCBtYWNoaW5lSW1hZ2VUeXBlID0gb3B0aW9ucy5tYWNoaW5lSW1hZ2VUeXBlID8/XG4gICAgICAoaXNCb3R0bGVSb2NrZXRJbWFnZShtYWNoaW5lSW1hZ2UpID8gTWFjaGluZUltYWdlVHlwZS5CT1RUTEVST0NLRVQgOiBNYWNoaW5lSW1hZ2VUeXBlLkFNQVpPTl9MSU5VWF8yKTtcblxuICAgIGNvbnN0IGF1dG9TY2FsaW5nR3JvdXAgPSBuZXcgYXV0b3NjYWxpbmcuQXV0b1NjYWxpbmdHcm91cCh0aGlzLCBpZCwge1xuICAgICAgdnBjOiB0aGlzLnZwYyxcbiAgICAgIG1hY2hpbmVJbWFnZSxcbiAgICAgIHVwZGF0ZVR5cGU6IG9wdGlvbnMudXBkYXRlVHlwZSB8fCBhdXRvc2NhbGluZy5VcGRhdGVUeXBlLlJFUExBQ0lOR19VUERBVEUsXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRBdXRvU2NhbGluZ0dyb3VwKGF1dG9TY2FsaW5nR3JvdXAsIHtcbiAgICAgIG1hY2hpbmVJbWFnZVR5cGU6IG1hY2hpbmVJbWFnZVR5cGUsXG4gICAgICAuLi5vcHRpb25zLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGF1dG9TY2FsaW5nR3JvdXA7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgYWRkcyBhbiBBdXRvIFNjYWxpbmcgR3JvdXAgQ2FwYWNpdHkgUHJvdmlkZXIgdG8gYSBjbHVzdGVyLlxuICAgKlxuICAgKiBAcGFyYW0gcHJvdmlkZXIgdGhlIGNhcGFjaXR5IHByb3ZpZGVyIHRvIGFkZCB0byB0aGlzIGNsdXN0ZXIuXG4gICAqL1xuICBwdWJsaWMgYWRkQXNnQ2FwYWNpdHlQcm92aWRlcihwcm92aWRlcjogQXNnQ2FwYWNpdHlQcm92aWRlciwgb3B0aW9uczogQWRkQXV0b1NjYWxpbmdHcm91cENhcGFjaXR5T3B0aW9ucz0ge30pIHtcbiAgICAvLyBEb24ndCBhZGQgdGhlIHNhbWUgY2FwYWNpdHkgcHJvdmlkZXIgbW9yZSB0aGFuIG9uY2UuXG4gICAgaWYgKHRoaXMuX2NhcGFjaXR5UHJvdmlkZXJOYW1lcy5pbmNsdWRlcyhwcm92aWRlci5jYXBhY2l0eVByb3ZpZGVyTmFtZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5faGFzRWMyQ2FwYWNpdHkgPSB0cnVlO1xuICAgIHRoaXMuY29uZmlndXJlQXV0b1NjYWxpbmdHcm91cChwcm92aWRlci5hdXRvU2NhbGluZ0dyb3VwLCB7XG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgbWFjaGluZUltYWdlVHlwZTogcHJvdmlkZXIubWFjaGluZUltYWdlVHlwZSxcbiAgICAgIC8vIERvbid0IGVuYWJsZSB0aGUgaW5zdGFuY2UtZHJhaW5pbmcgbGlmZWN5Y2xlIGhvb2sgaWYgbWFuYWdlZCB0ZXJtaW5hdGlvbiBwcm90ZWN0aW9uIGlzIGVuYWJsZWRcbiAgICAgIHRhc2tEcmFpblRpbWU6IHByb3ZpZGVyLmVuYWJsZU1hbmFnZWRUZXJtaW5hdGlvblByb3RlY3Rpb24gPyBEdXJhdGlvbi5zZWNvbmRzKDApIDogb3B0aW9ucy50YXNrRHJhaW5UaW1lLFxuICAgIH0pO1xuXG4gICAgdGhpcy5fY2FwYWNpdHlQcm92aWRlck5hbWVzLnB1c2gocHJvdmlkZXIuY2FwYWNpdHlQcm92aWRlck5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGFkZHMgY29tcHV0ZSBjYXBhY2l0eSB0byBhIGNsdXN0ZXIgdXNpbmcgdGhlIHNwZWNpZmllZCBBdXRvU2NhbGluZ0dyb3VwLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rIENsdXN0ZXIuYWRkQXNnQ2FwYWNpdHlQcm92aWRlcn0gaW5zdGVhZC5cbiAgICogQHBhcmFtIGF1dG9TY2FsaW5nR3JvdXAgdGhlIEFTRyB0byBhZGQgdG8gdGhpcyBjbHVzdGVyLlxuICAgKiBbZGlzYWJsZS1hd3NsaW50OnJlZi12aWEtaW50ZXJmYWNlXSBpcyBuZWVkZWQgaW4gb3JkZXIgdG8gaW5zdGFsbCB0aGUgRUNTXG4gICAqIGFnZW50IGJ5IHVwZGF0aW5nIHRoZSBBU0dzIHVzZXIgZGF0YS5cbiAgICovXG4gIHB1YmxpYyBhZGRBdXRvU2NhbGluZ0dyb3VwKGF1dG9TY2FsaW5nR3JvdXA6IGF1dG9zY2FsaW5nLkF1dG9TY2FsaW5nR3JvdXAsIG9wdGlvbnM6IEFkZEF1dG9TY2FsaW5nR3JvdXBDYXBhY2l0eU9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMuX2hhc0VjMkNhcGFjaXR5ID0gdHJ1ZTtcbiAgICB0aGlzLmNvbm5lY3Rpb25zLmNvbm5lY3Rpb25zLmFkZFNlY3VyaXR5R3JvdXAoLi4uYXV0b1NjYWxpbmdHcm91cC5jb25uZWN0aW9ucy5zZWN1cml0eUdyb3Vwcyk7XG4gICAgdGhpcy5jb25maWd1cmVBdXRvU2NhbGluZ0dyb3VwKGF1dG9TY2FsaW5nR3JvdXAsIG9wdGlvbnMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb25maWd1cmVBdXRvU2NhbGluZ0dyb3VwKGF1dG9TY2FsaW5nR3JvdXA6IGF1dG9zY2FsaW5nLkF1dG9TY2FsaW5nR3JvdXAsIG9wdGlvbnM6IEFkZEF1dG9TY2FsaW5nR3JvdXBDYXBhY2l0eU9wdGlvbnMgPSB7fSkge1xuICAgIGlmIChhdXRvU2NhbGluZ0dyb3VwLm9zVHlwZSA9PT0gZWMyLk9wZXJhdGluZ1N5c3RlbVR5cGUuV0lORE9XUykge1xuICAgICAgdGhpcy5jb25maWd1cmVXaW5kb3dzQXV0b1NjYWxpbmdHcm91cChhdXRvU2NhbGluZ0dyb3VwLCBvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVGllIGluc3RhbmNlcyB0byBjbHVzdGVyXG4gICAgICBzd2l0Y2ggKG9wdGlvbnMubWFjaGluZUltYWdlVHlwZSkge1xuICAgICAgICAvLyBCb3R0bGVyb2NrZXQgQU1JXG4gICAgICAgIGNhc2UgTWFjaGluZUltYWdlVHlwZS5CT1RUTEVST0NLRVQ6IHtcbiAgICAgICAgICBhdXRvU2NhbGluZ0dyb3VwLmFkZFVzZXJEYXRhKFxuICAgICAgICAgICAgLy8gQ29ubmVjdCB0byB0aGUgY2x1c3RlclxuICAgICAgICAgICAgLy8gU291cmNlOiBodHRwczovL2dpdGh1Yi5jb20vYm90dGxlcm9ja2V0LW9zL2JvdHRsZXJvY2tldC9ibG9iL2RldmVsb3AvUVVJQ0tTVEFSVC1FQ1MubWQjY29ubmVjdGluZy10by15b3VyLWNsdXN0ZXJcbiAgICAgICAgICAgICdbc2V0dGluZ3MuZWNzXScsXG4gICAgICAgICAgICBgY2x1c3RlciA9IFwiJHt0aGlzLmNsdXN0ZXJOYW1lfVwiYCxcbiAgICAgICAgICApO1xuICAgICAgICAgIC8vIEVuYWJsaW5nIFNTTVxuICAgICAgICAgIC8vIFNvdXJjZTogaHR0cHM6Ly9naXRodWIuY29tL2JvdHRsZXJvY2tldC1vcy9ib3R0bGVyb2NrZXQvYmxvYi9kZXZlbG9wL1FVSUNLU1RBUlQtRUNTLm1kI2VuYWJsaW5nLXNzbVxuICAgICAgICAgIGF1dG9TY2FsaW5nR3JvdXAucm9sZS5hZGRNYW5hZ2VkUG9saWN5KGlhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZSgnQW1hem9uU1NNTWFuYWdlZEluc3RhbmNlQ29yZScpKTtcbiAgICAgICAgICAvLyByZXF1aXJlZCBtYW5hZ2VkIHBvbGljeVxuICAgICAgICAgIGF1dG9TY2FsaW5nR3JvdXAucm9sZS5hZGRNYW5hZ2VkUG9saWN5KGlhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZSgnc2VydmljZS1yb2xlL0FtYXpvbkVDMkNvbnRhaW5lclNlcnZpY2Vmb3JFQzJSb2xlJykpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgLy8gQW1hem9uIEVDUy1vcHRpbWl6ZWQgQU1JIGZvciBBbWF6b24gTGludXggMlxuICAgICAgICAgIGF1dG9TY2FsaW5nR3JvdXAuYWRkVXNlckRhdGEoYGVjaG8gRUNTX0NMVVNURVI9JHt0aGlzLmNsdXN0ZXJOYW1lfSA+PiAvZXRjL2Vjcy9lY3MuY29uZmlnYCk7XG4gICAgICAgICAgaWYgKCFvcHRpb25zLmNhbkNvbnRhaW5lcnNBY2Nlc3NJbnN0YW5jZVJvbGUpIHtcbiAgICAgICAgICAgIC8vIERlbnkgY29udGFpbmVycyBhY2Nlc3MgdG8gaW5zdGFuY2UgbWV0YWRhdGEgc2VydmljZVxuICAgICAgICAgICAgLy8gU291cmNlOiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uRUNTL2xhdGVzdC9kZXZlbG9wZXJndWlkZS9pbnN0YW5jZV9JQU1fcm9sZS5odG1sXG4gICAgICAgICAgICBhdXRvU2NhbGluZ0dyb3VwLmFkZFVzZXJEYXRhKCdzdWRvIGlwdGFibGVzIC0taW5zZXJ0IEZPUldBUkQgMSAtLWluLWludGVyZmFjZSBkb2NrZXIrIC0tZGVzdGluYXRpb24gMTY5LjI1NC4xNjkuMjU0LzMyIC0tanVtcCBEUk9QJyk7XG4gICAgICAgICAgICBhdXRvU2NhbGluZ0dyb3VwLmFkZFVzZXJEYXRhKCdzdWRvIHNlcnZpY2UgaXB0YWJsZXMgc2F2ZScpO1xuICAgICAgICAgICAgLy8gVGhlIGZvbGxvd2luZyBpcyBvbmx5IGZvciBBd3NWcGMgbmV0d29ya2luZyBtb2RlLCBidXQgZG9lc24ndCBodXJ0IGZvciB0aGUgb3RoZXIgbW9kZXMuXG4gICAgICAgICAgICBhdXRvU2NhbGluZ0dyb3VwLmFkZFVzZXJEYXRhKCdlY2hvIEVDU19BV1NWUENfQkxPQ0tfSU1EUz10cnVlID4+IC9ldGMvZWNzL2Vjcy5jb25maWcnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoYXV0b1NjYWxpbmdHcm91cC5zcG90UHJpY2UgJiYgb3B0aW9ucy5zcG90SW5zdGFuY2VEcmFpbmluZykge1xuICAgICAgICAgICAgYXV0b1NjYWxpbmdHcm91cC5hZGRVc2VyRGF0YSgnZWNobyBFQ1NfRU5BQkxFX1NQT1RfSU5TVEFOQ0VfRFJBSU5JTkc9dHJ1ZSA+PiAvZXRjL2Vjcy9lY3MuY29uZmlnJyk7XG4gICAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEVDUyBpbnN0YW5jZXMgbXVzdCBiZSBhYmxlIHRvIGRvIHRoZXNlIHRoaW5nc1xuICAgIC8vIFNvdXJjZTogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkVDUy9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvaW5zdGFuY2VfSUFNX3JvbGUuaHRtbFxuICAgIC8vIEJ1dCwgc2NvcGVkIGRvd24gdG8gbWluaW1hbCBwZXJtaXNzaW9ucyByZXF1aXJlZC5cbiAgICAvLyAgTm90ZXM6XG4gICAgLy8gICAtICdlY3M6Q3JlYXRlQ2x1c3RlcicgcmVtb3ZlZC4gVGhlIGNsdXN0ZXIgYWxyZWFkeSBleGlzdHMuXG4gICAgYXV0b1NjYWxpbmdHcm91cC5hZGRUb1JvbGVQb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgYWN0aW9uczogW1xuICAgICAgICAnZWNzOkRlcmVnaXN0ZXJDb250YWluZXJJbnN0YW5jZScsXG4gICAgICAgICdlY3M6UmVnaXN0ZXJDb250YWluZXJJbnN0YW5jZScsXG4gICAgICAgICdlY3M6U3VibWl0KicsXG4gICAgICBdLFxuICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgIHRoaXMuY2x1c3RlckFybixcbiAgICAgIF0sXG4gICAgfSkpO1xuICAgIGF1dG9TY2FsaW5nR3JvdXAuYWRkVG9Sb2xlUG9saWN5KG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgLy8gVGhlc2UgYWN0IG9uIGEgY2x1c3RlciBpbnN0YW5jZSwgYW5kIHRoZSBpbnN0YW5jZSBkb2Vzbid0IGV4aXN0IHVudGlsIHRoZSBzZXJ2aWNlIHN0YXJ0cy5cbiAgICAgICAgLy8gVGh1cywgc2NvcGUgdG8gdGhlIGNsdXN0ZXIgdXNpbmcgYSBjb25kaXRpb24uXG4gICAgICAgIC8vIFNlZTogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL2xpc3RfYW1hem9uZWxhc3RpY2NvbnRhaW5lcnNlcnZpY2UuaHRtbFxuICAgICAgICAnZWNzOlBvbGwnLFxuICAgICAgICAnZWNzOlN0YXJ0VGVsZW1ldHJ5U2Vzc2lvbicsXG4gICAgICBdLFxuICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICAgIGNvbmRpdGlvbnM6IHtcbiAgICAgICAgQXJuRXF1YWxzOiB7ICdlY3M6Y2x1c3Rlcic6IHRoaXMuY2x1c3RlckFybiB9LFxuICAgICAgfSxcbiAgICB9KSk7XG4gICAgYXV0b1NjYWxpbmdHcm91cC5hZGRUb1JvbGVQb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgYWN0aW9uczogW1xuICAgICAgICAvLyBUaGVzZSBkbyBub3Qgc3VwcG9ydCByZXNvdXJjZSBjb25zdHJhaW50cywgYW5kIG11c3QgYmUgcmVzb3VyY2UgJyonXG4gICAgICAgICdlY3M6RGlzY292ZXJQb2xsRW5kcG9pbnQnLFxuICAgICAgICAnZWNyOkdldEF1dGhvcml6YXRpb25Ub2tlbicsXG4gICAgICAgIC8vIFByZXNlcnZlZCBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuXG4gICAgICAgIC8vIFVzZXJzIGFyZSBhYmxlIHRvIGVuYWJsZSBjbG91ZHdhdGNoIGFnZW50IHVzaW5nIENESy4gRXhpc3RpbmdcbiAgICAgICAgLy8gY3VzdG9tZXJzIG1pZ2h0IGJlIGluc3RhbGxpbmcgQ1cgYWdlbnQgYXMgcGFydCBvZiB1c2VyLWRhdGEgc28gaWYgd2VcbiAgICAgICAgLy8gcmVtb3ZlIHRoZXNlIHBlcm1pc3Npb25zIHdlIHdpbGwgYnJlYWsgdGhhdCBjdXN0b21lciB1c2UgY2FzZXMuXG4gICAgICAgICdsb2dzOkNyZWF0ZUxvZ1N0cmVhbScsXG4gICAgICAgICdsb2dzOlB1dExvZ0V2ZW50cycsXG4gICAgICBdLFxuICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICB9KSk7XG5cbiAgICAvLyAwIGRpc2FibGVzLCBvdGhlcndpc2UgZm9yd2FyZCB0byB1bmRlcmx5aW5nIGltcGxlbWVudGF0aW9uIHdoaWNoIHBpY2tzIHRoZSBzYW5lIGRlZmF1bHRcbiAgICBpZiAoIW9wdGlvbnMudGFza0RyYWluVGltZSB8fCBvcHRpb25zLnRhc2tEcmFpblRpbWUudG9TZWNvbmRzKCkgIT09IDApIHtcbiAgICAgIG5ldyBJbnN0YW5jZURyYWluSG9vayhhdXRvU2NhbGluZ0dyb3VwLCAnRHJhaW5FQ1NIb29rJywge1xuICAgICAgICBhdXRvU2NhbGluZ0dyb3VwLFxuICAgICAgICBjbHVzdGVyOiB0aGlzLFxuICAgICAgICBkcmFpblRpbWU6IG9wdGlvbnMudGFza0RyYWluVGltZSxcbiAgICAgICAgdG9waWNFbmNyeXB0aW9uS2V5OiBvcHRpb25zLnRvcGljRW5jcnlwdGlvbktleSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBlbmFibGVzIHRoZSBGYXJnYXRlIG9yIEZhcmdhdGUgU3BvdCBjYXBhY2l0eSBwcm92aWRlcnMgb24gdGhlIGNsdXN0ZXIuXG4gICAqXG4gICAqIEBwYXJhbSBwcm92aWRlciB0aGUgY2FwYWNpdHkgcHJvdmlkZXIgdG8gYWRkIHRvIHRoaXMgY2x1c3Rlci5cbiAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayBlbmFibGVGYXJnYXRlQ2FwYWNpdHlQcm92aWRlcnN9IGluc3RlYWQuXG4gICAqIEBzZWUge0BsaW5rIGFkZEFzZ0NhcGFjaXR5UHJvdmlkZXJ9IHRvIGFkZCBhbiBBdXRvIFNjYWxpbmcgR3JvdXAgY2FwYWNpdHkgcHJvdmlkZXIgdG8gdGhlIGNsdXN0ZXIuXG4gICAqL1xuICBwdWJsaWMgYWRkQ2FwYWNpdHlQcm92aWRlcihwcm92aWRlcjogc3RyaW5nKSB7XG4gICAgaWYgKCEocHJvdmlkZXIgPT09ICdGQVJHQVRFJyB8fCBwcm92aWRlciA9PT0gJ0ZBUkdBVEVfU1BPVCcpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhcGFjaXR5UHJvdmlkZXIgbm90IHN1cHBvcnRlZCcpO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fY2FwYWNpdHlQcm92aWRlck5hbWVzLmluY2x1ZGVzKHByb3ZpZGVyKSkge1xuICAgICAgdGhpcy5fY2FwYWNpdHlQcm92aWRlck5hbWVzLnB1c2gocHJvdmlkZXIpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY29uZmlndXJlV2luZG93c0F1dG9TY2FsaW5nR3JvdXAoYXV0b1NjYWxpbmdHcm91cDogYXV0b3NjYWxpbmcuQXV0b1NjYWxpbmdHcm91cCwgb3B0aW9uczogQWRkQXV0b1NjYWxpbmdHcm91cENhcGFjaXR5T3B0aW9ucyA9IHt9KSB7XG4gICAgLy8gY2xlYXIgdGhlIGNhY2hlIG9mIHRoZSBhZ2VudFxuICAgIGF1dG9TY2FsaW5nR3JvdXAuYWRkVXNlckRhdGEoJ1JlbW92ZS1JdGVtIC1SZWN1cnNlIEM6XFxcXFByb2dyYW1EYXRhXFxcXEFtYXpvblxcXFxFQ1NcXFxcQ2FjaGUnKTtcblxuICAgIC8vIHB1bGwgdGhlIGxhdGVzdCBFQ1MgVG9vbHNcbiAgICBhdXRvU2NhbGluZ0dyb3VwLmFkZFVzZXJEYXRhKCdJbXBvcnQtTW9kdWxlIEVDU1Rvb2xzJyk7XG5cbiAgICAvLyBzZXQgdGhlIGNsdXN0ZXIgbmFtZSBlbnZpcm9ubWVudCB2YXJpYWJsZVxuICAgIGF1dG9TY2FsaW5nR3JvdXAuYWRkVXNlckRhdGEoYFtFbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoXCJFQ1NfQ0xVU1RFUlwiLCBcIiR7dGhpcy5jbHVzdGVyTmFtZX1cIiwgXCJNYWNoaW5lXCIpYCk7XG4gICAgYXV0b1NjYWxpbmdHcm91cC5hZGRVc2VyRGF0YSgnW0Vudmlyb25tZW50XTo6U2V0RW52aXJvbm1lbnRWYXJpYWJsZShcIkVDU19FTkFCTEVfQVdTTE9HU19FWEVDVVRJT05ST0xFX09WRVJSSURFXCIsIFwidHJ1ZVwiLCBcIk1hY2hpbmVcIiknKTtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IG1heC1saW5lLWxlbmd0aFxuICAgIGF1dG9TY2FsaW5nR3JvdXAuYWRkVXNlckRhdGEoJ1tFbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoXCJFQ1NfQVZBSUxBQkxFX0xPR0dJTkdfRFJJVkVSU1wiLCBcXCdbXCJqc29uLWZpbGVcIixcImF3c2xvZ3NcIl1cXCcsIFwiTWFjaGluZVwiKScpO1xuXG4gICAgLy8gZW5hYmxlIGluc3RhbmNlIGRyYWluaW5nXG4gICAgaWYgKGF1dG9TY2FsaW5nR3JvdXAuc3BvdFByaWNlICYmIG9wdGlvbnMuc3BvdEluc3RhbmNlRHJhaW5pbmcpIHtcbiAgICAgIGF1dG9TY2FsaW5nR3JvdXAuYWRkVXNlckRhdGEoJ1tFbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoXCJFQ1NfRU5BQkxFX1NQT1RfSU5TVEFOQ0VfRFJBSU5JTkdcIiwgXCJ0cnVlXCIsIFwiTWFjaGluZVwiKScpO1xuICAgIH1cblxuICAgIC8vIGVuYWJsZSB0YXNrIGlhbSByb2xlXG4gICAgaWYgKCFvcHRpb25zLmNhbkNvbnRhaW5lcnNBY2Nlc3NJbnN0YW5jZVJvbGUpIHtcbiAgICAgIGF1dG9TY2FsaW5nR3JvdXAuYWRkVXNlckRhdGEoJ1tFbnZpcm9ubWVudF06OlNldEVudmlyb25tZW50VmFyaWFibGUoXCJFQ1NfRU5BQkxFX1RBU0tfSUFNX1JPTEVcIiwgXCJ0cnVlXCIsIFwiTWFjaGluZVwiKScpO1xuICAgICAgYXV0b1NjYWxpbmdHcm91cC5hZGRVc2VyRGF0YShgSW5pdGlhbGl6ZS1FQ1NBZ2VudCAtQ2x1c3RlciAnJHt0aGlzLmNsdXN0ZXJOYW1lfScgLUVuYWJsZVRhc2tJQU1Sb2xlYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGF1dG9TY2FsaW5nR3JvdXAuYWRkVXNlckRhdGEoYEluaXRpYWxpemUtRUNTQWdlbnQgLUNsdXN0ZXIgJyR7dGhpcy5jbHVzdGVyTmFtZX0nYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHRlciBmb3IgYXV0b3NjYWxpbmcgZ3JvdXAgYWRkZWQgdG8gY2x1c3RlclxuICAgKi9cbiAgcHVibGljIGdldCBhdXRvc2NhbGluZ0dyb3VwKCk6IGF1dG9zY2FsaW5nLklBdXRvU2NhbGluZ0dyb3VwIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0b3NjYWxpbmdHcm91cDtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBjbHVzdGVyIGhhcyBFQzIgY2FwYWNpdHkgYXNzb2NpYXRlZCB3aXRoIGl0XG4gICAqL1xuICBwdWJsaWMgZ2V0IGhhc0VjMkNhcGFjaXR5KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9oYXNFYzJDYXBhY2l0eTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXR0ZXIgZm9yIGV4ZWN1dGUgY29tbWFuZCBjb25maWd1cmF0aW9uIGFzc29jaWF0ZWQgd2l0aCB0aGUgY2x1c3Rlci5cbiAgICovXG4gIHB1YmxpYyBnZXQgZXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uKCk6IEV4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbiB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX2V4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIHRoZSBDbG91ZFdhdGNoIG1ldHJpYyBmb3IgdGhpcyBjbHVzdGVycyBDUFUgcmVzZXJ2YXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IGF2ZXJhZ2Ugb3ZlciA1IG1pbnV0ZXNcbiAgICovXG4gIHB1YmxpYyBtZXRyaWNDcHVSZXNlcnZhdGlvbihwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5jYW5uZWRNZXRyaWMoRUNTTWV0cmljcy5jcHVSZXNlcnZhdGlvbkF2ZXJhZ2UsIHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIHRoZSBDbG91ZFdhdGNoIG1ldHJpYyBmb3IgdGhpcyBjbHVzdGVycyBDUFUgdXRpbGl6YXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IGF2ZXJhZ2Ugb3ZlciA1IG1pbnV0ZXNcbiAgICovXG4gIHB1YmxpYyBtZXRyaWNDcHVVdGlsaXphdGlvbihwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5jYW5uZWRNZXRyaWMoRUNTTWV0cmljcy5jcHVVdGlsaXphdGlvbkF2ZXJhZ2UsIHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIHRoZSBDbG91ZFdhdGNoIG1ldHJpYyBmb3IgdGhpcyBjbHVzdGVycyBtZW1vcnkgcmVzZXJ2YXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IGF2ZXJhZ2Ugb3ZlciA1IG1pbnV0ZXNcbiAgICovXG4gIHB1YmxpYyBtZXRyaWNNZW1vcnlSZXNlcnZhdGlvbihwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5jYW5uZWRNZXRyaWMoRUNTTWV0cmljcy5tZW1vcnlSZXNlcnZhdGlvbkF2ZXJhZ2UsIHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIHRoZSBDbG91ZFdhdGNoIG1ldHJpYyBmb3IgdGhpcyBjbHVzdGVycyBtZW1vcnkgdXRpbGl6YXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IGF2ZXJhZ2Ugb3ZlciA1IG1pbnV0ZXNcbiAgICovXG4gIHB1YmxpYyBtZXRyaWNNZW1vcnlVdGlsaXphdGlvbihwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5jYW5uZWRNZXRyaWMoRUNTTWV0cmljcy5tZW1vcnlVdGlsaXphdGlvbkF2ZXJhZ2UsIHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCByZXR1cm5zIHRoZSBzcGVjaWZlZCBDbG91ZFdhdGNoIG1ldHJpYyBmb3IgdGhpcyBjbHVzdGVyLlxuICAgKi9cbiAgcHVibGljIG1ldHJpYyhtZXRyaWNOYW1lOiBzdHJpbmcsIHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbmFtZXNwYWNlOiAnQVdTL0VDUycsXG4gICAgICBtZXRyaWNOYW1lLFxuICAgICAgZGltZW5zaW9uc01hcDogeyBDbHVzdGVyTmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9LFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSkuYXR0YWNoVG8odGhpcyk7XG4gIH1cblxuICBwcml2YXRlIGNhbm5lZE1ldHJpYyhcbiAgICBmbjogKGRpbXM6IHsgQ2x1c3Rlck5hbWU6IHN0cmluZyB9KSA9PiBjbG91ZHdhdGNoLk1ldHJpY1Byb3BzLFxuICAgIHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgLi4uZm4oeyBDbHVzdGVyTmFtZTogdGhpcy5jbHVzdGVyTmFtZSB9KSxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pLmF0dGFjaFRvKHRoaXMpO1xuICB9XG59XG5cbi8qKlxuICogQSByZWdpb25hbCBncm91cGluZyBvZiBvbmUgb3IgbW9yZSBjb250YWluZXIgaW5zdGFuY2VzIG9uIHdoaWNoIHlvdSBjYW4gcnVuIHRhc2tzIGFuZCBzZXJ2aWNlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJQ2x1c3RlciBleHRlbmRzIElSZXNvdXJjZSB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgY2x1c3Rlci5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgY2x1c3Rlck5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEFtYXpvbiBSZXNvdXJjZSBOYW1lIChBUk4pIHRoYXQgaWRlbnRpZmllcyB0aGUgY2x1c3Rlci5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgY2x1c3RlckFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgVlBDIGFzc29jaWF0ZWQgd2l0aCB0aGUgY2x1c3Rlci5cbiAgICovXG4gIHJlYWRvbmx5IHZwYzogZWMyLklWcGM7XG5cbiAgLyoqXG4gICAqIE1hbmFnZSB0aGUgYWxsb3dlZCBuZXR3b3JrIGNvbm5lY3Rpb25zIGZvciB0aGUgY2x1c3RlciB3aXRoIFNlY3VyaXR5IEdyb3Vwcy5cbiAgICovXG4gIHJlYWRvbmx5IGNvbm5lY3Rpb25zOiBlYzIuQ29ubmVjdGlvbnM7XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB3aGV0aGVyIHRoZSBjbHVzdGVyIGhhcyBFQzIgaW5zdGFuY2UgY2FwYWNpdHkuXG4gICAqL1xuICByZWFkb25seSBoYXNFYzJDYXBhY2l0eTogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIEFXUyBDbG91ZCBNYXAgbmFtZXNwYWNlIHRvIGFzc29jaWF0ZSB3aXRoIHRoZSBjbHVzdGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgZGVmYXVsdENsb3VkTWFwTmFtZXNwYWNlPzogY2xvdWRtYXAuSU5hbWVzcGFjZTtcblxuICAvKipcbiAgICogVGhlIGF1dG9zY2FsaW5nIGdyb3VwIGFkZGVkIHRvIHRoZSBjbHVzdGVyIGlmIGNhcGFjaXR5IGlzIGFzc29jaWF0ZWQgdG8gdGhlIGNsdXN0ZXJcbiAgICovXG4gIHJlYWRvbmx5IGF1dG9zY2FsaW5nR3JvdXA/OiBhdXRvc2NhbGluZy5JQXV0b1NjYWxpbmdHcm91cDtcblxuICAvKipcbiAgICogVGhlIGV4ZWN1dGUgY29tbWFuZCBjb25maWd1cmF0aW9uIGZvciB0aGUgY2x1c3RlclxuICAgKi9cbiAgcmVhZG9ubHkgZXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uPzogRXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uO1xufVxuXG4vKipcbiAqIFRoZSBwcm9wZXJ0aWVzIHRvIGltcG9ydCBmcm9tIHRoZSBFQ1MgY2x1c3Rlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDbHVzdGVyQXR0cmlidXRlcyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgY2x1c3Rlci5cbiAgICovXG4gIHJlYWRvbmx5IGNsdXN0ZXJOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBBbWF6b24gUmVzb3VyY2UgTmFtZSAoQVJOKSB0aGF0IGlkZW50aWZpZXMgdGhlIGNsdXN0ZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IERlcml2ZWQgZnJvbSBjbHVzdGVyTmFtZVxuICAgKi9cbiAgcmVhZG9ubHkgY2x1c3RlckFybj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIFZQQyBhc3NvY2lhdGVkIHdpdGggdGhlIGNsdXN0ZXIuXG4gICAqL1xuICByZWFkb25seSB2cGM6IGVjMi5JVnBjO1xuXG4gIC8qKlxuICAgKiBUaGUgc2VjdXJpdHkgZ3JvdXBzIGFzc29jaWF0ZWQgd2l0aCB0aGUgY29udGFpbmVyIGluc3RhbmNlcyByZWdpc3RlcmVkIHRvIHRoZSBjbHVzdGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgc2VjdXJpdHlHcm91cHM6IGVjMi5JU2VjdXJpdHlHcm91cFtdO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgd2hldGhlciB0aGUgY2x1c3RlciBoYXMgRUMyIGluc3RhbmNlIGNhcGFjaXR5LlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBoYXNFYzJDYXBhY2l0eT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBBV1MgQ2xvdWQgTWFwIG5hbWVzcGFjZSB0byBhc3NvY2lhdGUgd2l0aCB0aGUgY2x1c3Rlci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBkZWZhdWx0IG5hbWVzcGFjZVxuICAgKi9cbiAgcmVhZG9ubHkgZGVmYXVsdENsb3VkTWFwTmFtZXNwYWNlPzogY2xvdWRtYXAuSU5hbWVzcGFjZTtcblxuICAvKipcbiAgICogQXV0b3NjYWxpbmcgZ3JvdXAgYWRkZWQgdG8gdGhlIGNsdXN0ZXIgaWYgY2FwYWNpdHkgaXMgYWRkZWRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBkZWZhdWx0IGF1dG9zY2FsaW5nIGdyb3VwXG4gICAqL1xuICByZWFkb25seSBhdXRvc2NhbGluZ0dyb3VwPzogYXV0b3NjYWxpbmcuSUF1dG9TY2FsaW5nR3JvdXA7XG5cbiAgLyoqXG4gICAqIFRoZSBleGVjdXRlIGNvbW1hbmQgY29uZmlndXJhdGlvbiBmb3IgdGhlIGNsdXN0ZXJcbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uPzogRXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uO1xufVxuXG4vKipcbiAqIEFuIENsdXN0ZXIgdGhhdCBoYXMgYmVlbiBpbXBvcnRlZFxuICovXG5jbGFzcyBJbXBvcnRlZENsdXN0ZXIgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElDbHVzdGVyIHtcbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIGNsdXN0ZXJcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjbHVzdGVyTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBUk4gb2YgdGhlIGNsdXN0ZXJcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjbHVzdGVyQXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFZQQyB0aGF0IHRoZSBjbHVzdGVyIGluc3RhbmNlcyBhcmUgcnVubmluZyBpblxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHZwYzogZWMyLklWcGM7XG5cbiAgLyoqXG4gICAqIFNlY3VyaXR5IGdyb3VwIG9mIHRoZSBjbHVzdGVyIGluc3RhbmNlc1xuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGNvbm5lY3Rpb25zID0gbmV3IGVjMi5Db25uZWN0aW9ucygpO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBjbHVzdGVyIGhhcyBFQzIgY2FwYWNpdHlcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBoYXNFYzJDYXBhY2l0eTogYm9vbGVhbjtcblxuICAvKipcbiAgICogQ2xvdWRtYXAgbmFtZXNwYWNlIGNyZWF0ZWQgaW4gdGhlIGNsdXN0ZXJcbiAgICovXG4gIHByaXZhdGUgX2RlZmF1bHRDbG91ZE1hcE5hbWVzcGFjZT86IGNsb3VkbWFwLklOYW1lc3BhY2U7XG5cbiAgLyoqXG4gICAqIFRoZSBleGVjdXRlIGNvbW1hbmQgY29uZmlndXJhdGlvbiBmb3IgdGhlIGNsdXN0ZXJcbiAgICovXG4gIHByaXZhdGUgX2V4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbj86IEV4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgSW1wb3J0ZWRDbHVzdGVyIGNsYXNzLlxuICAgKi9cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IENsdXN0ZXJBdHRyaWJ1dGVzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICB0aGlzLmNsdXN0ZXJOYW1lID0gcHJvcHMuY2x1c3Rlck5hbWU7XG4gICAgdGhpcy52cGMgPSBwcm9wcy52cGM7XG4gICAgdGhpcy5oYXNFYzJDYXBhY2l0eSA9IHByb3BzLmhhc0VjMkNhcGFjaXR5ICE9PSBmYWxzZTtcbiAgICB0aGlzLl9kZWZhdWx0Q2xvdWRNYXBOYW1lc3BhY2UgPSBwcm9wcy5kZWZhdWx0Q2xvdWRNYXBOYW1lc3BhY2U7XG4gICAgdGhpcy5fZXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uID0gcHJvcHMuZXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uO1xuXG4gICAgdGhpcy5jbHVzdGVyQXJuID0gcHJvcHMuY2x1c3RlckFybiA/PyBTdGFjay5vZih0aGlzKS5mb3JtYXRBcm4oe1xuICAgICAgc2VydmljZTogJ2VjcycsXG4gICAgICByZXNvdXJjZTogJ2NsdXN0ZXInLFxuICAgICAgcmVzb3VyY2VOYW1lOiBwcm9wcy5jbHVzdGVyTmFtZSxcbiAgICB9KTtcblxuICAgIHRoaXMuY29ubmVjdGlvbnMgPSBuZXcgZWMyLkNvbm5lY3Rpb25zKHtcbiAgICAgIHNlY3VyaXR5R3JvdXBzOiBwcm9wcy5zZWN1cml0eUdyb3VwcyxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgZGVmYXVsdENsb3VkTWFwTmFtZXNwYWNlKCk6IGNsb3VkbWFwLklOYW1lc3BhY2UgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9kZWZhdWx0Q2xvdWRNYXBOYW1lc3BhY2U7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGV4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbigpOiBFeGVjdXRlQ29tbWFuZENvbmZpZ3VyYXRpb24gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9leGVjdXRlQ29tbWFuZENvbmZpZ3VyYXRpb247XG4gIH1cbn1cblxuLyoqXG4gKiBUaGUgcHJvcGVydGllcyBmb3IgYWRkaW5nIGFuIEF1dG9TY2FsaW5nR3JvdXAuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWRkQXV0b1NjYWxpbmdHcm91cENhcGFjaXR5T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgd2hldGhlciB0aGUgY29udGFpbmVycyBjYW4gYWNjZXNzIHRoZSBjb250YWluZXIgaW5zdGFuY2Ugcm9sZS5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGNhbkNvbnRhaW5lcnNBY2Nlc3NJbnN0YW5jZVJvbGU/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgdGltZSBwZXJpb2QgdG8gd2FpdCBiZWZvcmUgZm9yY2UgdGVybWluYXRpbmcgYW4gaW5zdGFuY2UgdGhhdCBpcyBkcmFpbmluZy5cbiAgICpcbiAgICogVGhpcyBjcmVhdGVzIGEgTGFtYmRhIGZ1bmN0aW9uIHRoYXQgaXMgdXNlZCBieSBhIGxpZmVjeWNsZSBob29rIGZvciB0aGVcbiAgICogQXV0b1NjYWxpbmdHcm91cCB0aGF0IHdpbGwgZGVsYXkgaW5zdGFuY2UgdGVybWluYXRpb24gdW50aWwgYWxsIEVDUyB0YXNrc1xuICAgKiBoYXZlIGRyYWluZWQgZnJvbSB0aGUgaW5zdGFuY2UuIFNldCB0byAwIHRvIGRpc2FibGUgdGFzayBkcmFpbmluZy5cbiAgICpcbiAgICogU2V0IHRvIDAgdG8gZGlzYWJsZSB0YXNrIGRyYWluaW5nLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBUaGUgbGlmZWN5Y2xlIGRyYWluaW5nIGhvb2sgaXMgbm90IGNvbmZpZ3VyZWQgaWYgdXNpbmcgdGhlIEVDMiBDYXBhY2l0eSBQcm92aWRlci4gRW5hYmxlIG1hbmFnZWQgdGVybWluYXRpb24gcHJvdGVjdGlvbiBpbnN0ZWFkLlxuICAgKiBAZGVmYXVsdCBEdXJhdGlvbi5taW51dGVzKDUpXG4gICAqL1xuICByZWFkb25seSB0YXNrRHJhaW5UaW1lPzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgd2hldGhlciB0byBlbmFibGUgQXV0b21hdGVkIERyYWluaW5nIGZvciBTcG90IEluc3RhbmNlcyBydW5uaW5nIEFtYXpvbiBFQ1MgU2VydmljZXMuXG4gICAqIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWUgW1VzaW5nIFNwb3QgSW5zdGFuY2VzXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uRUNTL2xhdGVzdC9kZXZlbG9wZXJndWlkZS9jb250YWluZXItaW5zdGFuY2Utc3BvdC5odG1sKS5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHNwb3RJbnN0YW5jZURyYWluaW5nPzogYm9vbGVhblxuXG4gIC8qKlxuICAgKiBJZiB7QGxpbmsgQWRkQXV0b1NjYWxpbmdHcm91cENhcGFjaXR5T3B0aW9ucy50YXNrRHJhaW5UaW1lfSBpcyBub24temVybywgdGhlbiB0aGUgRUNTIGNsdXN0ZXIgY3JlYXRlcyBhblxuICAgKiBTTlMgVG9waWMgdG8gYXMgcGFydCBvZiBhIHN5c3RlbSB0byBkcmFpbiBpbnN0YW5jZXMgb2YgdGFza3Mgd2hlbiB0aGUgaW5zdGFuY2UgaXMgYmVpbmcgc2h1dCBkb3duLlxuICAgKiBJZiB0aGlzIHByb3BlcnR5IGlzIHByb3ZpZGVkLCB0aGVuIHRoaXMga2V5IHdpbGwgYmUgdXNlZCB0byBlbmNyeXB0IHRoZSBjb250ZW50cyBvZiB0aGF0IFNOUyBUb3BpYy5cbiAgICogU2VlIFtTTlMgRGF0YSBFbmNyeXB0aW9uXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vc25zL2xhdGVzdC9kZy9zbnMtZGF0YS1lbmNyeXB0aW9uLmh0bWwpIGZvciBtb3JlIGluZm9ybWF0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBUaGUgU05TIFRvcGljIHdpbGwgbm90IGJlIGVuY3J5cHRlZC5cbiAgICovXG4gIHJlYWRvbmx5IHRvcGljRW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuXG4gIC8qKlxuICAgKiBXaGF0IHR5cGUgb2YgbWFjaGluZSBpbWFnZSB0aGlzIGlzXG4gICAqXG4gICAqIERlcGVuZGluZyBvbiB0aGUgc2V0dGluZywgZGlmZmVyZW50IFVzZXJEYXRhIHdpbGwgYXV0b21hdGljYWxseSBiZSBhZGRlZFxuICAgKiB0byB0aGUgYEF1dG9TY2FsaW5nR3JvdXBgIHRvIGNvbmZpZ3VyZSBpdCBwcm9wZXJseSBmb3IgdXNlIHdpdGggRUNTLlxuICAgKlxuICAgKiBJZiB5b3UgY3JlYXRlIGFuIGBBdXRvU2NhbGluZ0dyb3VwYCB5b3Vyc2VsZiBhbmQgYXJlIGFkZGluZyBpdCB2aWFcbiAgICogYGFkZEF1dG9TY2FsaW5nR3JvdXAoKWAsIHlvdSBtdXN0IHNwZWNpZnkgdGhpcyB2YWx1ZS4gSWYgeW91IGFyZSBhZGRpbmcgYW5cbiAgICogYGF1dG9TY2FsaW5nR3JvdXBgIHZpYSBgYWRkQ2FwYWNpdHlgLCB0aGlzIHZhbHVlIHdpbGwgYmUgZGV0ZXJtaW5lZFxuICAgKiBmcm9tIHRoZSBgbWFjaGluZUltYWdlYCB5b3UgcGFzcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBdXRvbWF0aWNhbGx5IGRldGVybWluZWQgZnJvbSBgbWFjaGluZUltYWdlYCwgaWYgYXZhaWxhYmxlLCBvdGhlcndpc2UgYE1hY2hpbmVJbWFnZVR5cGUuQU1BWk9OX0xJTlVYXzJgLlxuICAgKi9cbiAgcmVhZG9ubHkgbWFjaGluZUltYWdlVHlwZT86IE1hY2hpbmVJbWFnZVR5cGU7XG59XG5cbi8qKlxuICogVGhlIHByb3BlcnRpZXMgZm9yIGFkZGluZyBpbnN0YW5jZSBjYXBhY2l0eSB0byBhbiBBdXRvU2NhbGluZ0dyb3VwLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFkZENhcGFjaXR5T3B0aW9ucyBleHRlbmRzIEFkZEF1dG9TY2FsaW5nR3JvdXBDYXBhY2l0eU9wdGlvbnMsIGF1dG9zY2FsaW5nLkNvbW1vbkF1dG9TY2FsaW5nR3JvdXBQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgRUMyIGluc3RhbmNlIHR5cGUgdG8gdXNlIHdoZW4gbGF1bmNoaW5nIGluc3RhbmNlcyBpbnRvIHRoZSBBdXRvU2NhbGluZ0dyb3VwLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5zdGFuY2VUeXBlOiBlYzIuSW5zdGFuY2VUeXBlO1xuXG4gIC8qKlxuICAgKiBUaGUgRUNTLW9wdGltaXplZCBBTUkgdmFyaWFudCB0byB1c2VcbiAgICpcbiAgICogVGhlIGRlZmF1bHQgaXMgdG8gdXNlIGFuIEVDUy1vcHRpbWl6ZWQgQU1JIG9mIEFtYXpvbiBMaW51eCAyIHdoaWNoIGlzXG4gICAqIGF1dG9tYXRpY2FsbHkgdXBkYXRlZCB0byB0aGUgbGF0ZXN0IHZlcnNpb24gb24gZXZlcnkgZGVwbG95bWVudC4gVGhpcyB3aWxsXG4gICAqIHJlcGxhY2UgdGhlIGluc3RhbmNlcyBpbiB0aGUgQXV0b1NjYWxpbmdHcm91cC4gTWFrZSBzdXJlIHlvdSBoYXZlIG5vdCBkaXNhYmxlZFxuICAgKiB0YXNrIGRyYWluaW5nLCB0byBhdm9pZCBkb3dudGltZSB3aGVuIHRoZSBBTUkgdXBkYXRlcy5cbiAgICpcbiAgICogVG8gdXNlIGFuIGltYWdlIHRoYXQgZG9lcyBub3QgdXBkYXRlIG9uIGV2ZXJ5IGRlcGxveW1lbnQsIHBhc3M6XG4gICAqXG4gICAqIGBgYHRzXG4gICAqIGNvbnN0IG1hY2hpbmVJbWFnZSA9IGVjcy5FY3NPcHRpbWl6ZWRJbWFnZS5hbWF6b25MaW51eDIoZWNzLkFtaUhhcmR3YXJlVHlwZS5TVEFOREFSRCwge1xuICAgKiAgIGNhY2hlZEluQ29udGV4dDogdHJ1ZSxcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlIFtBbWF6b24gRUNTLW9wdGltaXplZFxuICAgKiBBTUlzXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uRUNTL2xhdGVzdC9kZXZlbG9wZXJndWlkZS9lY3Mtb3B0aW1pemVkX0FNSS5odG1sKS5cbiAgICpcbiAgICogWW91IG11c3QgZGVmaW5lIGVpdGhlciBgbWFjaGluZUltYWdlYCBvciBgbWFjaGluZUltYWdlVHlwZWAsIG5vdCBib3RoLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEF1dG9tYXRpY2FsbHkgdXBkYXRlZCwgRUNTLW9wdGltaXplZCBBbWF6b24gTGludXggMlxuICAgKi9cbiAgcmVhZG9ubHkgbWFjaGluZUltYWdlPzogZWMyLklNYWNoaW5lSW1hZ2U7XG59XG5cbi8qKlxuICogVGhlIG9wdGlvbnMgZm9yIGNyZWF0aW5nIGFuIEFXUyBDbG91ZCBNYXAgbmFtZXNwYWNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENsb3VkTWFwTmFtZXNwYWNlT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgbmFtZXNwYWNlLCBzdWNoIGFzIGV4YW1wbGUuY29tLlxuICAgKi9cbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgdHlwZSBvZiBDbG91ZE1hcCBOYW1lc3BhY2UgdG8gY3JlYXRlLlxuICAgKlxuICAgKiBAZGVmYXVsdCBQcml2YXRlRG5zXG4gICAqL1xuICByZWFkb25seSB0eXBlPzogY2xvdWRtYXAuTmFtZXNwYWNlVHlwZTtcblxuICAvKipcbiAgICogVGhlIFZQQyB0byBhc3NvY2lhdGUgdGhlIG5hbWVzcGFjZSB3aXRoLiBUaGlzIHByb3BlcnR5IGlzIHJlcXVpcmVkIGZvciBwcml2YXRlIEROUyBuYW1lc3BhY2VzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBWUEMgb2YgdGhlIGNsdXN0ZXIgZm9yIFByaXZhdGUgRE5TIE5hbWVzcGFjZSwgb3RoZXJ3aXNlIG5vbmVcbiAgICovXG4gIHJlYWRvbmx5IHZwYz86IGVjMi5JVnBjO1xufVxuXG5lbnVtIENvbnRhaW5lckluc2lnaHRzIHtcbiAgLyoqXG4gICAqIEVuYWJsZSBDbG91ZFdhdGNoIENvbnRhaW5lciBJbnNpZ2h0cyBmb3IgdGhlIGNsdXN0ZXJcbiAgICovXG5cbiAgRU5BQkxFRCA9ICdlbmFibGVkJyxcblxuICAvKipcbiAgICogRGlzYWJsZSBDbG91ZFdhdGNoIENvbnRhaW5lciBJbnNpZ2h0cyBmb3IgdGhlIGNsdXN0ZXJcbiAgICovXG4gIERJU0FCTEVEID0gJ2Rpc2FibGVkJyxcbn1cblxuLyoqXG4gKiBBIENhcGFjaXR5IFByb3ZpZGVyIHN0cmF0ZWd5IHRvIHVzZSBmb3IgdGhlIHNlcnZpY2UuXG4gKlxuICogTk9URTogZGVmYXVsdENhcGFjaXR5UHJvdmlkZXJTdHJhdGVneSBvbiBjbHVzdGVyIG5vdCBjdXJyZW50bHkgc3VwcG9ydGVkLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENhcGFjaXR5UHJvdmlkZXJTdHJhdGVneSB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgY2FwYWNpdHkgcHJvdmlkZXIuXG4gICAqL1xuICByZWFkb25seSBjYXBhY2l0eVByb3ZpZGVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBiYXNlIHZhbHVlIGRlc2lnbmF0ZXMgaG93IG1hbnkgdGFza3MsIGF0IGEgbWluaW11bSwgdG8gcnVuIG9uIHRoZSBzcGVjaWZpZWQgY2FwYWNpdHkgcHJvdmlkZXIuIE9ubHkgb25lXG4gICAqIGNhcGFjaXR5IHByb3ZpZGVyIGluIGEgY2FwYWNpdHkgcHJvdmlkZXIgc3RyYXRlZ3kgY2FuIGhhdmUgYSBiYXNlIGRlZmluZWQuIElmIG5vIHZhbHVlIGlzIHNwZWNpZmllZCwgdGhlIGRlZmF1bHRcbiAgICogdmFsdWUgb2YgMCBpcyB1c2VkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIHJlYWRvbmx5IGJhc2U/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSB3ZWlnaHQgdmFsdWUgZGVzaWduYXRlcyB0aGUgcmVsYXRpdmUgcGVyY2VudGFnZSBvZiB0aGUgdG90YWwgbnVtYmVyIG9mIHRhc2tzIGxhdW5jaGVkIHRoYXQgc2hvdWxkIHVzZSB0aGVcbiAgICogc3BlY2lmaWVkXG5jYXBhY2l0eSBwcm92aWRlci4gVGhlIHdlaWdodCB2YWx1ZSBpcyB0YWtlbiBpbnRvIGNvbnNpZGVyYXRpb24gYWZ0ZXIgdGhlIGJhc2UgdmFsdWUsIGlmIGRlZmluZWQsIGlzIHNhdGlzZmllZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSAwXG4gICAqL1xuICByZWFkb25seSB3ZWlnaHQ/OiBudW1iZXI7XG59XG5cbi8qKlxuICogVGhlIGRldGFpbHMgb2YgdGhlIGV4ZWN1dGUgY29tbWFuZCBjb25maWd1cmF0aW9uLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlXG4gKiBbRXhlY3V0ZUNvbW1hbmRDb25maWd1cmF0aW9uXSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1lY3MtY2x1c3Rlci1leGVjdXRlY29tbWFuZGNvbmZpZ3VyYXRpb24uaHRtbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEV4ZWN1dGVDb21tYW5kQ29uZmlndXJhdGlvbiB7XG4gIC8qKlxuICAgKiBUaGUgQVdTIEtleSBNYW5hZ2VtZW50IFNlcnZpY2Uga2V5IElEIHRvIGVuY3J5cHQgdGhlIGRhdGEgYmV0d2VlbiB0aGUgbG9jYWwgY2xpZW50IGFuZCB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIHJlYWRvbmx5IGttc0tleT86IGttcy5JS2V5LFxuXG4gIC8qKlxuICAgKiBUaGUgbG9nIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSByZXN1bHRzIG9mIHRoZSBleGVjdXRlIGNvbW1hbmQgYWN0aW9ucy4gVGhlIGxvZ3MgY2FuIGJlIHNlbnQgdG8gQ2xvdWRXYXRjaCBMb2dzIG9yIGFuIEFtYXpvbiBTMyBidWNrZXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgbG9nQ29uZmlndXJhdGlvbj86IEV4ZWN1dGVDb21tYW5kTG9nQ29uZmlndXJhdGlvbixcblxuICAvKipcbiAgICogVGhlIGxvZyBzZXR0aW5ncyB0byB1c2UgZm9yIGxvZ2dpbmcgdGhlIGV4ZWN1dGUgY29tbWFuZCBzZXNzaW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIHJlYWRvbmx5IGxvZ2dpbmc/OiBFeGVjdXRlQ29tbWFuZExvZ2dpbmcsXG59XG5cbi8qKlxuICogVGhlIGxvZyBzZXR0aW5ncyB0byB1c2UgdG8gZm9yIGxvZ2dpbmcgdGhlIGV4ZWN1dGUgY29tbWFuZCBzZXNzaW9uLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlXG4gKiBbTG9nZ2luZ10gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZWNzLWNsdXN0ZXItZXhlY3V0ZWNvbW1hbmRjb25maWd1cmF0aW9uLmh0bWwjY2ZuLWVjcy1jbHVzdGVyLWV4ZWN1dGVjb21tYW5kY29uZmlndXJhdGlvbi1sb2dnaW5nXG4gKi9cbmV4cG9ydCBlbnVtIEV4ZWN1dGVDb21tYW5kTG9nZ2luZyB7XG4gIC8qKlxuICAgKiBUaGUgZXhlY3V0ZSBjb21tYW5kIHNlc3Npb24gaXMgbm90IGxvZ2dlZC5cbiAgICovXG4gIE5PTkUgPSAnTk9ORScsXG5cbiAgLyoqXG4gICAqIFRoZSBhd3Nsb2dzIGNvbmZpZ3VyYXRpb24gaW4gdGhlIHRhc2sgZGVmaW5pdGlvbiBpcyB1c2VkLiBJZiBubyBsb2dnaW5nIHBhcmFtZXRlciBpcyBzcGVjaWZpZWQsIGl0IGRlZmF1bHRzIHRvIHRoaXMgdmFsdWUuIElmIG5vIGF3c2xvZ3MgbG9nIGRyaXZlciBpcyBjb25maWd1cmVkIGluIHRoZSB0YXNrIGRlZmluaXRpb24sIHRoZSBvdXRwdXQgd29uJ3QgYmUgbG9nZ2VkLlxuICAgKi9cbiAgREVGQVVMVCA9ICdERUZBVUxUJyxcblxuICAvKipcbiAgICogU3BlY2lmeSB0aGUgbG9nZ2luZyBkZXRhaWxzIGFzIGEgcGFydCBvZiBsb2dDb25maWd1cmF0aW9uLlxuICAgKi9cbiAgT1ZFUlJJREUgPSAnT1ZFUlJJREUnLFxufVxuXG4vKipcbiAqIFRoZSBsb2cgY29uZmlndXJhdGlvbiBmb3IgdGhlIHJlc3VsdHMgb2YgdGhlIGV4ZWN1dGUgY29tbWFuZCBhY3Rpb25zLiBUaGUgbG9ncyBjYW4gYmUgc2VudCB0byBDbG91ZFdhdGNoIExvZ3MgYW5kLyBvciBhbiBBbWF6b24gUzMgYnVja2V0LlxuICogRm9yIG1vcmUgaW5mb3JtYXRpb24sIHNlZSBbRXhlY3V0ZUNvbW1hbmRMb2dDb25maWd1cmF0aW9uXSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1lY3MtY2x1c3Rlci1leGVjdXRlY29tbWFuZGxvZ2NvbmZpZ3VyYXRpb24uaHRtbFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEV4ZWN1dGVDb21tYW5kTG9nQ29uZmlndXJhdGlvbiB7XG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0byBlbmFibGUgZW5jcnlwdGlvbiBvbiB0aGUgQ2xvdWRXYXRjaCBsb2dzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGVuY3J5cHRpb24gd2lsbCBiZSBkaXNhYmxlZC5cbiAgICovXG4gIHJlYWRvbmx5IGNsb3VkV2F0Y2hFbmNyeXB0aW9uRW5hYmxlZD86IGJvb2xlYW4sXG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBDbG91ZFdhdGNoIGxvZyBncm91cCB0byBzZW5kIGxvZ3MgdG8uIFRoZSBDbG91ZFdhdGNoIGxvZyBncm91cCBtdXN0IGFscmVhZHkgYmUgY3JlYXRlZC5cbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICByZWFkb25seSBjbG91ZFdhdGNoTG9nR3JvdXA/OiBsb2dzLklMb2dHcm91cCxcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIFMzIGJ1Y2tldCB0byBzZW5kIGxvZ3MgdG8uIFRoZSBTMyBidWNrZXQgbXVzdCBhbHJlYWR5IGJlIGNyZWF0ZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgczNCdWNrZXQ/OiBzMy5JQnVja2V0LFxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0byBlbmFibGUgZW5jcnlwdGlvbiBvbiB0aGUgQ2xvdWRXYXRjaCBsb2dzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGVuY3J5cHRpb24gd2lsbCBiZSBkaXNhYmxlZC5cbiAgICovXG4gIHJlYWRvbmx5IHMzRW5jcnlwdGlvbkVuYWJsZWQ/OiBib29sZWFuLFxuXG4gIC8qKlxuICAgKiBBbiBvcHRpb25hbCBmb2xkZXIgaW4gdGhlIFMzIGJ1Y2tldCB0byBwbGFjZSBsb2dzIGluLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIHJlYWRvbmx5IHMzS2V5UHJlZml4Pzogc3RyaW5nXG59XG5cbi8qKlxuICogVGhlIG9wdGlvbnMgZm9yIGNyZWF0aW5nIGFuIEF1dG8gU2NhbGluZyBHcm91cCBDYXBhY2l0eSBQcm92aWRlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBc2dDYXBhY2l0eVByb3ZpZGVyUHJvcHMgZXh0ZW5kcyBBZGRBdXRvU2NhbGluZ0dyb3VwQ2FwYWNpdHlPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBjYXBhY2l0eSBwcm92aWRlci4gSWYgYSBuYW1lIGlzIHNwZWNpZmllZCxcbiAgICogaXQgY2Fubm90IHN0YXJ0IHdpdGggYGF3c2AsIGBlY3NgLCBvciBgZmFyZ2F0ZWAuIElmIG5vIG5hbWUgaXMgc3BlY2lmaWVkLFxuICAgKiBhIGRlZmF1bHQgbmFtZSBpbiB0aGUgQ0ZOU3RhY2tOYW1lLUNGTlJlc291cmNlTmFtZS1SYW5kb21TdHJpbmcgZm9ybWF0IGlzIHVzZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IENsb3VkRm9ybWF0aW9uLWdlbmVyYXRlZCBuYW1lXG4gICAqL1xuICByZWFkb25seSBjYXBhY2l0eVByb3ZpZGVyTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGF1dG9zY2FsaW5nIGdyb3VwIHRvIGFkZCBhcyBhIENhcGFjaXR5IFByb3ZpZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgYXV0b1NjYWxpbmdHcm91cDogYXV0b3NjYWxpbmcuSUF1dG9TY2FsaW5nR3JvdXA7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZW5hYmxlIG1hbmFnZWQgc2NhbGluZ1xuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBlbmFibGVNYW5hZ2VkU2NhbGluZz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZW5hYmxlIG1hbmFnZWQgdGVybWluYXRpb24gcHJvdGVjdGlvblxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBlbmFibGVNYW5hZ2VkVGVybWluYXRpb25Qcm90ZWN0aW9uPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogTWF4aW11bSBzY2FsaW5nIHN0ZXAgc2l6ZS4gSW4gbW9zdCBjYXNlcyB0aGlzIHNob3VsZCBiZSBsZWZ0IGFsb25lLlxuICAgKlxuICAgKiBAZGVmYXVsdCAxMDAwXG4gICAqL1xuICByZWFkb25seSBtYXhpbXVtU2NhbGluZ1N0ZXBTaXplPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBNaW5pbXVtIHNjYWxpbmcgc3RlcCBzaXplLiBJbiBtb3N0IGNhc2VzIHRoaXMgc2hvdWxkIGJlIGxlZnQgYWxvbmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IDFcbiAgICovXG4gIHJlYWRvbmx5IG1pbmltdW1TY2FsaW5nU3RlcFNpemU/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRhcmdldCBjYXBhY2l0eSBwZXJjZW50LiBJbiBtb3N0IGNhc2VzIHRoaXMgc2hvdWxkIGJlIGxlZnQgYWxvbmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IDEwMFxuICAgKi9cbiAgcmVhZG9ubHkgdGFyZ2V0Q2FwYWNpdHlQZXJjZW50PzogbnVtYmVyO1xufVxuXG4vKipcbiAqIEFuIEF1dG8gU2NhbGluZyBHcm91cCBDYXBhY2l0eSBQcm92aWRlci4gVGhpcyBhbGxvd3MgYW4gRUNTIGNsdXN0ZXIgdG8gdGFyZ2V0XG4gKiBhIHNwZWNpZmljIEVDMiBBdXRvIFNjYWxpbmcgR3JvdXAgZm9yIHRoZSBwbGFjZW1lbnQgb2YgdGFza3MuIE9wdGlvbmFsbHkgKGFuZFxuICogcmVjb21tZW5kZWQpLCBFQ1MgY2FuIG1hbmFnZSB0aGUgbnVtYmVyIG9mIGluc3RhbmNlcyBpbiB0aGUgQVNHIHRvIGZpdCB0aGVcbiAqIHRhc2tzLCBhbmQgY2FuIGVuc3VyZSB0aGF0IGluc3RhbmNlcyBhcmUgbm90IHByZW1hdHVyZWx5IHRlcm1pbmF0ZWQgd2hpbGVcbiAqIHRoZXJlIGFyZSBzdGlsbCB0YXNrcyBydW5uaW5nIG9uIHRoZW0uXG4gKi9cbmV4cG9ydCBjbGFzcyBBc2dDYXBhY2l0eVByb3ZpZGVyIGV4dGVuZHMgQ29yZUNvbnN0cnVjdCB7XG4gIC8qKlxuICAgKiBDYXBhY2l0eSBwcm92aWRlciBuYW1lXG4gICAqIEBkZWZhdWx0IENob3NlbiBieSBDbG91ZEZvcm1hdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgY2FwYWNpdHlQcm92aWRlck5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogQXV0byBTY2FsaW5nIEdyb3VwXG4gICAqL1xuICByZWFkb25seSBhdXRvU2NhbGluZ0dyb3VwOiBhdXRvc2NhbGluZy5BdXRvU2NhbGluZ0dyb3VwO1xuXG4gIC8qKlxuICAgKiBBdXRvIFNjYWxpbmcgR3JvdXAgbWFjaGluZUltYWdlVHlwZS5cbiAgICovXG4gIHJlYWRvbmx5IG1hY2hpbmVJbWFnZVR5cGU6IE1hY2hpbmVJbWFnZVR5cGU7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgbWFuYWdlZCB0ZXJtaW5hdGlvbiBwcm90ZWN0aW9uIGlzIGVuYWJsZWRcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZU1hbmFnZWRUZXJtaW5hdGlvblByb3RlY3Rpb24/OiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBBc2dDYXBhY2l0eVByb3ZpZGVyUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgdGhpcy5hdXRvU2NhbGluZ0dyb3VwID0gcHJvcHMuYXV0b1NjYWxpbmdHcm91cCBhcyBhdXRvc2NhbGluZy5BdXRvU2NhbGluZ0dyb3VwO1xuXG4gICAgdGhpcy5tYWNoaW5lSW1hZ2VUeXBlID0gcHJvcHMubWFjaGluZUltYWdlVHlwZSA/PyBNYWNoaW5lSW1hZ2VUeXBlLkFNQVpPTl9MSU5VWF8yO1xuXG4gICAgdGhpcy5lbmFibGVNYW5hZ2VkVGVybWluYXRpb25Qcm90ZWN0aW9uID1cbiAgICAgIHByb3BzLmVuYWJsZU1hbmFnZWRUZXJtaW5hdGlvblByb3RlY3Rpb24gPT09IHVuZGVmaW5lZCA/IHRydWUgOiBwcm9wcy5lbmFibGVNYW5hZ2VkVGVybWluYXRpb25Qcm90ZWN0aW9uO1xuXG4gICAgaWYgKHRoaXMuZW5hYmxlTWFuYWdlZFRlcm1pbmF0aW9uUHJvdGVjdGlvbikge1xuICAgICAgdGhpcy5hdXRvU2NhbGluZ0dyb3VwLnByb3RlY3ROZXdJbnN0YW5jZXNGcm9tU2NhbGVJbigpO1xuICAgIH1cbiAgICBpZiAocHJvcHMuY2FwYWNpdHlQcm92aWRlck5hbWUpIHtcbiAgICAgIGlmICghKC9eKD8hYXdzfGVjc3xmYXJnYXRlKS4rL2dtLnRlc3QocHJvcHMuY2FwYWNpdHlQcm92aWRlck5hbWUpKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgQ2FwYWNpdHkgUHJvdmlkZXIgTmFtZTogJHtwcm9wcy5jYXBhY2l0eVByb3ZpZGVyTmFtZX0sIElmIGEgbmFtZSBpcyBzcGVjaWZpZWQsIGl0IGNhbm5vdCBzdGFydCB3aXRoIGF3cywgZWNzLCBvciBmYXJnYXRlLmApO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBjYXBhY2l0eVByb3ZpZGVyID0gbmV3IENmbkNhcGFjaXR5UHJvdmlkZXIodGhpcywgaWQsIHtcbiAgICAgIG5hbWU6IHByb3BzLmNhcGFjaXR5UHJvdmlkZXJOYW1lLFxuICAgICAgYXV0b1NjYWxpbmdHcm91cFByb3ZpZGVyOiB7XG4gICAgICAgIGF1dG9TY2FsaW5nR3JvdXBBcm46IHRoaXMuYXV0b1NjYWxpbmdHcm91cC5hdXRvU2NhbGluZ0dyb3VwTmFtZSxcbiAgICAgICAgbWFuYWdlZFNjYWxpbmc6IHByb3BzLmVuYWJsZU1hbmFnZWRTY2FsaW5nID09PSBmYWxzZSA/IHVuZGVmaW5lZCA6IHtcbiAgICAgICAgICBzdGF0dXM6ICdFTkFCTEVEJyxcbiAgICAgICAgICB0YXJnZXRDYXBhY2l0eTogcHJvcHMudGFyZ2V0Q2FwYWNpdHlQZXJjZW50IHx8IDEwMCxcbiAgICAgICAgICBtYXhpbXVtU2NhbGluZ1N0ZXBTaXplOiBwcm9wcy5tYXhpbXVtU2NhbGluZ1N0ZXBTaXplLFxuICAgICAgICAgIG1pbmltdW1TY2FsaW5nU3RlcFNpemU6IHByb3BzLm1pbmltdW1TY2FsaW5nU3RlcFNpemUsXG4gICAgICAgIH0sXG4gICAgICAgIG1hbmFnZWRUZXJtaW5hdGlvblByb3RlY3Rpb246IHRoaXMuZW5hYmxlTWFuYWdlZFRlcm1pbmF0aW9uUHJvdGVjdGlvbiA/ICdFTkFCTEVEJyA6ICdESVNBQkxFRCcsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgdGhpcy5jYXBhY2l0eVByb3ZpZGVyTmFtZSA9IGNhcGFjaXR5UHJvdmlkZXIucmVmO1xuICB9XG59XG5cbi8qKlxuICogQSB2aXNpdG9yIHRoYXQgYWRkcyBhIGNhcGFjaXR5IHByb3ZpZGVyIGFzc29jaWF0aW9uIHRvIGEgQ2x1c3RlciBvbmx5IGlmXG4gKiB0aGUgY2FsbGVyIGNyZWF0ZWQgYW55IEVDMiBDYXBhY2l0eSBQcm92aWRlcnMuXG4gKi9cbmNsYXNzIE1heWJlQ3JlYXRlQ2FwYWNpdHlQcm92aWRlckFzc29jaWF0aW9ucyBpbXBsZW1lbnRzIElBc3BlY3Qge1xuICBwcml2YXRlIHNjb3BlOiBDb3JlQ29uc3RydWN0O1xuICBwcml2YXRlIGlkOiBzdHJpbmc7XG4gIHByaXZhdGUgY2FwYWNpdHlQcm92aWRlcnM6IHN0cmluZ1tdXG4gIHByaXZhdGUgcmVzb3VyY2U/OiBDZm5DbHVzdGVyQ2FwYWNpdHlQcm92aWRlckFzc29jaWF0aW9uc1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb3JlQ29uc3RydWN0LCBpZDogc3RyaW5nLCBjYXBhY2l0eVByb3ZpZGVyczogc3RyaW5nW10gKSB7XG4gICAgdGhpcy5zY29wZSA9IHNjb3BlO1xuICAgIHRoaXMuaWQgPSBpZDtcbiAgICB0aGlzLmNhcGFjaXR5UHJvdmlkZXJzID0gY2FwYWNpdHlQcm92aWRlcnM7XG4gIH1cblxuICBwdWJsaWMgdmlzaXQobm9kZTogSUNvbnN0cnVjdCk6IHZvaWQge1xuICAgIGlmIChub2RlIGluc3RhbmNlb2YgQ2x1c3Rlcikge1xuICAgICAgaWYgKHRoaXMuY2FwYWNpdHlQcm92aWRlcnMubGVuZ3RoID4gMCAmJiAhdGhpcy5yZXNvdXJjZSkge1xuICAgICAgICBjb25zdCByZXNvdXJjZSA9IG5ldyBDZm5DbHVzdGVyQ2FwYWNpdHlQcm92aWRlckFzc29jaWF0aW9ucyh0aGlzLnNjb3BlLCB0aGlzLmlkLCB7XG4gICAgICAgICAgY2x1c3Rlcjogbm9kZS5jbHVzdGVyTmFtZSxcbiAgICAgICAgICBkZWZhdWx0Q2FwYWNpdHlQcm92aWRlclN0cmF0ZWd5OiBbXSxcbiAgICAgICAgICBjYXBhY2l0eVByb3ZpZGVyczogTGF6eS5saXN0KHsgcHJvZHVjZTogKCkgPT4gdGhpcy5jYXBhY2l0eVByb3ZpZGVycyB9KSxcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucmVzb3VyY2UgPSByZXNvdXJjZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBpc0JvdHRsZVJvY2tldEltYWdlKGltYWdlOiBlYzIuSU1hY2hpbmVJbWFnZSkge1xuICByZXR1cm4gaW1hZ2UgaW5zdGFuY2VvZiBCb3R0bGVSb2NrZXRJbWFnZTtcbn1cbiJdfQ==
\No newline at end of file