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