1 | ;
|
2 | var _a, _b;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.AsgCapacityProvider = exports.ExecuteCommandLogging = exports.Cluster = exports.MachineImageType = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const autoscaling = require("@aws-cdk/aws-autoscaling");
|
8 | const cloudwatch = require("@aws-cdk/aws-cloudwatch");
|
9 | const ec2 = require("@aws-cdk/aws-ec2");
|
10 | const iam = require("@aws-cdk/aws-iam");
|
11 | const cloudmap = require("@aws-cdk/aws-servicediscovery");
|
12 | const core_1 = require("@aws-cdk/core");
|
13 | const amis_1 = require("./amis");
|
14 | const instance_drain_hook_1 = require("./drain-hook/instance-drain-hook");
|
15 | const ecs_canned_metrics_generated_1 = require("./ecs-canned-metrics.generated");
|
16 | const 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
|
19 | const core_2 = require("@aws-cdk/core");
|
20 | /**
|
21 | * The machine image type
|
22 | */
|
23 | var 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 | */
|
37 | class 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 | }
|
525 | exports.Cluster = Cluster;
|
526 | _a = JSII_RTTI_SYMBOL_1;
|
527 | Cluster[_a] = { fqn: "@aws-cdk/aws-ecs.Cluster", version: "1.197.0" };
|
528 | /**
|
529 | * An Cluster that has been imported
|
530 | */
|
531 | class 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 | }
|
562 | var 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 | */
|
577 | var 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 | */
|
599 | class 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 | }
|
640 | exports.AsgCapacityProvider = AsgCapacityProvider;
|
641 | _b = JSII_RTTI_SYMBOL_1;
|
642 | AsgCapacityProvider[_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 | */
|
647 | class 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 | }
|
666 | function 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 |