UNPKG

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