1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.Pipeline = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const notifications = require("@aws-cdk/aws-codestarnotifications");
|
8 | const events = require("@aws-cdk/aws-events");
|
9 | const iam = require("@aws-cdk/aws-iam");
|
10 | const kms = require("@aws-cdk/aws-kms");
|
11 | const s3 = require("@aws-cdk/aws-s3");
|
12 | const core_1 = require("@aws-cdk/core");
|
13 | const action_1 = require("./action");
|
14 | const codepipeline_generated_1 = require("./codepipeline.generated");
|
15 | const cross_region_support_stack_1 = require("./private/cross-region-support-stack");
|
16 | const full_action_descriptor_1 = require("./private/full-action-descriptor");
|
17 | const rich_action_1 = require("./private/rich-action");
|
18 | const stage_1 = require("./private/stage");
|
19 | const validation_1 = require("./private/validation");
|
20 | class PipelineBase extends core_1.Resource {
|
21 | /**
|
22 | * Defines an event rule triggered by this CodePipeline.
|
23 | *
|
24 | * @param id Identifier for this event handler.
|
25 | * @param options Additional options to pass to the event rule.
|
26 | */
|
27 | onEvent(id, options = {}) {
|
28 | const rule = new events.Rule(this, id, options);
|
29 | rule.addTarget(options.target);
|
30 | rule.addEventPattern({
|
31 | source: ['aws.codepipeline'],
|
32 | resources: [this.pipelineArn],
|
33 | });
|
34 | return rule;
|
35 | }
|
36 | /**
|
37 | * Defines an event rule triggered by the "CodePipeline Pipeline Execution
|
38 | * State Change" event emitted from this pipeline.
|
39 | *
|
40 | * @param id Identifier for this event handler.
|
41 | * @param options Additional options to pass to the event rule.
|
42 | */
|
43 | onStateChange(id, options = {}) {
|
44 | const rule = this.onEvent(id, options);
|
45 | rule.addEventPattern({
|
46 | detailType: ['CodePipeline Pipeline Execution State Change'],
|
47 | });
|
48 | return rule;
|
49 | }
|
50 | bindAsNotificationRuleSource(_scope) {
|
51 | return {
|
52 | sourceArn: this.pipelineArn,
|
53 | };
|
54 | }
|
55 | notifyOn(id, target, options) {
|
56 | return new notifications.NotificationRule(this, id, {
|
57 | ...options,
|
58 | source: this,
|
59 | targets: [target],
|
60 | });
|
61 | }
|
62 | notifyOnExecutionStateChange(id, target, options) {
|
63 | return this.notifyOn(id, target, {
|
64 | ...options,
|
65 | events: [
|
66 | action_1.PipelineNotificationEvents.PIPELINE_EXECUTION_FAILED,
|
67 | action_1.PipelineNotificationEvents.PIPELINE_EXECUTION_CANCELED,
|
68 | action_1.PipelineNotificationEvents.PIPELINE_EXECUTION_STARTED,
|
69 | action_1.PipelineNotificationEvents.PIPELINE_EXECUTION_RESUMED,
|
70 | action_1.PipelineNotificationEvents.PIPELINE_EXECUTION_SUCCEEDED,
|
71 | action_1.PipelineNotificationEvents.PIPELINE_EXECUTION_SUPERSEDED,
|
72 | ],
|
73 | });
|
74 | }
|
75 | notifyOnAnyStageStateChange(id, target, options) {
|
76 | return this.notifyOn(id, target, {
|
77 | ...options,
|
78 | events: [
|
79 | action_1.PipelineNotificationEvents.STAGE_EXECUTION_CANCELED,
|
80 | action_1.PipelineNotificationEvents.STAGE_EXECUTION_FAILED,
|
81 | action_1.PipelineNotificationEvents.STAGE_EXECUTION_RESUMED,
|
82 | action_1.PipelineNotificationEvents.STAGE_EXECUTION_STARTED,
|
83 | action_1.PipelineNotificationEvents.STAGE_EXECUTION_SUCCEEDED,
|
84 | ],
|
85 | });
|
86 | }
|
87 | notifyOnAnyActionStateChange(id, target, options) {
|
88 | return this.notifyOn(id, target, {
|
89 | ...options,
|
90 | events: [
|
91 | action_1.PipelineNotificationEvents.ACTION_EXECUTION_CANCELED,
|
92 | action_1.PipelineNotificationEvents.ACTION_EXECUTION_FAILED,
|
93 | action_1.PipelineNotificationEvents.ACTION_EXECUTION_STARTED,
|
94 | action_1.PipelineNotificationEvents.ACTION_EXECUTION_SUCCEEDED,
|
95 | ],
|
96 | });
|
97 | }
|
98 | notifyOnAnyManualApprovalStateChange(id, target, options) {
|
99 | return this.notifyOn(id, target, {
|
100 | ...options,
|
101 | events: [
|
102 | action_1.PipelineNotificationEvents.MANUAL_APPROVAL_FAILED,
|
103 | action_1.PipelineNotificationEvents.MANUAL_APPROVAL_NEEDED,
|
104 | action_1.PipelineNotificationEvents.MANUAL_APPROVAL_SUCCEEDED,
|
105 | ],
|
106 | });
|
107 | }
|
108 | }
|
109 | /**
|
110 | * An AWS CodePipeline pipeline with its associated IAM role and S3 bucket.
|
111 | *
|
112 | * @example
|
113 | * // create a pipeline
|
114 | * import * as codecommit from '@aws-cdk/aws-codecommit';
|
115 | *
|
116 | * const pipeline = new codepipeline.Pipeline(this, 'Pipeline');
|
117 | *
|
118 | * // add a stage
|
119 | * const sourceStage = pipeline.addStage({ stageName: 'Source' });
|
120 | *
|
121 | * // add a source action to the stage
|
122 | * declare const repo: codecommit.Repository;
|
123 | * declare const sourceArtifact: codepipeline.Artifact;
|
124 | * sourceStage.addAction(new codepipeline_actions.CodeCommitSourceAction({
|
125 | * actionName: 'Source',
|
126 | * output: sourceArtifact,
|
127 | * repository: repo,
|
128 | * }));
|
129 | *
|
130 | * // ... add more stages
|
131 | */
|
132 | class Pipeline extends PipelineBase {
|
133 | constructor(scope, id, props = {}) {
|
134 | super(scope, id, {
|
135 | physicalName: props.pipelineName,
|
136 | });
|
137 | this._stages = new Array();
|
138 | this._crossRegionSupport = {};
|
139 | this._crossAccountSupport = {};
|
140 | try {
|
141 | jsiiDeprecationWarnings._aws_cdk_aws_codepipeline_PipelineProps(props);
|
142 | }
|
143 | catch (error) {
|
144 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
145 | Error.captureStackTrace(error, Pipeline);
|
146 | }
|
147 | throw error;
|
148 | }
|
149 | validation_1.validateName('Pipeline', this.physicalName);
|
150 | // only one of artifactBucket and crossRegionReplicationBuckets can be supplied
|
151 | if (props.artifactBucket && props.crossRegionReplicationBuckets) {
|
152 | throw new Error('Only one of artifactBucket and crossRegionReplicationBuckets can be specified!');
|
153 | }
|
154 | // @deprecated(v2): switch to default false
|
155 | this.crossAccountKeys = props.crossAccountKeys ?? true;
|
156 | this.enableKeyRotation = props.enableKeyRotation;
|
157 | // Cross account keys must be set for key rotation to be enabled
|
158 | if (this.enableKeyRotation && !this.crossAccountKeys) {
|
159 | throw new Error("Setting 'enableKeyRotation' to true also requires 'crossAccountKeys' to be enabled");
|
160 | }
|
161 | this.reuseCrossRegionSupportStacks = props.reuseCrossRegionSupportStacks ?? true;
|
162 | // If a bucket has been provided, use it - otherwise, create a bucket.
|
163 | let propsBucket = this.getArtifactBucketFromProps(props);
|
164 | if (!propsBucket) {
|
165 | let encryptionKey;
|
166 | if (this.crossAccountKeys) {
|
167 | encryptionKey = new kms.Key(this, 'ArtifactsBucketEncryptionKey', {
|
168 | // remove the key - there is a grace period of a few days before it's gone for good,
|
169 | // that should be enough for any emergency access to the bucket artifacts
|
170 | removalPolicy: core_1.RemovalPolicy.DESTROY,
|
171 | enableKeyRotation: this.enableKeyRotation,
|
172 | });
|
173 | // add an alias to make finding the key in the console easier
|
174 | new kms.Alias(this, 'ArtifactsBucketEncryptionKeyAlias', {
|
175 | aliasName: this.generateNameForDefaultBucketKeyAlias(),
|
176 | targetKey: encryptionKey,
|
177 | removalPolicy: core_1.RemovalPolicy.DESTROY,
|
178 | });
|
179 | }
|
180 | propsBucket = new s3.Bucket(this, 'ArtifactsBucket', {
|
181 | bucketName: core_1.PhysicalName.GENERATE_IF_NEEDED,
|
182 | encryptionKey,
|
183 | encryption: encryptionKey ? s3.BucketEncryption.KMS : s3.BucketEncryption.KMS_MANAGED,
|
184 | enforceSSL: true,
|
185 | blockPublicAccess: new s3.BlockPublicAccess(s3.BlockPublicAccess.BLOCK_ALL),
|
186 | removalPolicy: core_1.RemovalPolicy.RETAIN,
|
187 | });
|
188 | }
|
189 | this.artifactBucket = propsBucket;
|
190 | // If a role has been provided, use it - otherwise, create a role.
|
191 | this.role = props.role || new iam.Role(this, 'Role', {
|
192 | assumedBy: new iam.ServicePrincipal('codepipeline.amazonaws.com'),
|
193 | });
|
194 | this.codePipeline = new codepipeline_generated_1.CfnPipeline(this, 'Resource', {
|
195 | artifactStore: core_1.Lazy.any({ produce: () => this.renderArtifactStoreProperty() }),
|
196 | artifactStores: core_1.Lazy.any({ produce: () => this.renderArtifactStoresProperty() }),
|
197 | stages: core_1.Lazy.any({ produce: () => this.renderStages() }),
|
198 | disableInboundStageTransitions: core_1.Lazy.any({ produce: () => this.renderDisabledTransitions() }, { omitEmptyArray: true }),
|
199 | roleArn: this.role.roleArn,
|
200 | restartExecutionOnUpdate: props && props.restartExecutionOnUpdate,
|
201 | name: this.physicalName,
|
202 | });
|
203 | // this will produce a DependsOn for both the role and the policy resources.
|
204 | this.codePipeline.node.addDependency(this.role);
|
205 | this.artifactBucket.grantReadWrite(this.role);
|
206 | this.pipelineName = this.getResourceNameAttribute(this.codePipeline.ref);
|
207 | this.pipelineVersion = this.codePipeline.attrVersion;
|
208 | this.crossRegionBucketsPassed = !!props.crossRegionReplicationBuckets;
|
209 | for (const [region, replicationBucket] of Object.entries(props.crossRegionReplicationBuckets || {})) {
|
210 | this._crossRegionSupport[region] = {
|
211 | replicationBucket,
|
212 | stack: core_1.Stack.of(replicationBucket),
|
213 | };
|
214 | }
|
215 | // Does not expose a Fn::GetAtt for the ARN so we'll have to make it ourselves
|
216 | this.pipelineArn = core_1.Stack.of(this).formatArn({
|
217 | service: 'codepipeline',
|
218 | resource: this.pipelineName,
|
219 | });
|
220 | for (const stage of props.stages || []) {
|
221 | this.addStage(stage);
|
222 | }
|
223 | }
|
224 | /**
|
225 | * Import a pipeline into this app.
|
226 | *
|
227 | * @param scope the scope into which to import this pipeline
|
228 | * @param id the logical ID of the returned pipeline construct
|
229 | * @param pipelineArn The ARN of the pipeline (e.g. `arn:aws:codepipeline:us-east-1:123456789012:MyDemoPipeline`)
|
230 | */
|
231 | static fromPipelineArn(scope, id, pipelineArn) {
|
232 | class Import extends PipelineBase {
|
233 | constructor() {
|
234 | super(...arguments);
|
235 | this.pipelineName = core_1.Stack.of(scope).splitArn(pipelineArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).resource;
|
236 | this.pipelineArn = pipelineArn;
|
237 | }
|
238 | }
|
239 | return new Import(scope, id);
|
240 | }
|
241 | /**
|
242 | * Creates a new Stage, and adds it to this Pipeline.
|
243 | *
|
244 | * @param props the creation properties of the new Stage
|
245 | * @returns the newly created Stage
|
246 | */
|
247 | addStage(props) {
|
248 | try {
|
249 | jsiiDeprecationWarnings._aws_cdk_aws_codepipeline_StageOptions(props);
|
250 | }
|
251 | catch (error) {
|
252 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
253 | Error.captureStackTrace(error, this.addStage);
|
254 | }
|
255 | throw error;
|
256 | }
|
257 | // check for duplicate Stages and names
|
258 | if (this._stages.find(s => s.stageName === props.stageName)) {
|
259 | throw new Error(`Stage with duplicate name '${props.stageName}' added to the Pipeline`);
|
260 | }
|
261 | const stage = new stage_1.Stage(props, this);
|
262 | const index = props.placement
|
263 | ? this.calculateInsertIndexFromPlacement(props.placement)
|
264 | : this.stageCount;
|
265 | this._stages.splice(index, 0, stage);
|
266 | return stage;
|
267 | }
|
268 | /**
|
269 | * Adds a statement to the pipeline role.
|
270 | */
|
271 | addToRolePolicy(statement) {
|
272 | this.role.addToPrincipalPolicy(statement);
|
273 | }
|
274 | /**
|
275 | * Get the number of Stages in this Pipeline.
|
276 | */
|
277 | get stageCount() {
|
278 | return this._stages.length;
|
279 | }
|
280 | /**
|
281 | * Returns the stages that comprise the pipeline.
|
282 | *
|
283 | * **Note**: the returned array is a defensive copy,
|
284 | * so adding elements to it has no effect.
|
285 | * Instead, use the {@link addStage} method if you want to add more stages
|
286 | * to the pipeline.
|
287 | */
|
288 | get stages() {
|
289 | return this._stages.slice();
|
290 | }
|
291 | /**
|
292 | * Access one of the pipeline's stages by stage name
|
293 | */
|
294 | stage(stageName) {
|
295 | for (const stage of this._stages) {
|
296 | if (stage.stageName === stageName) {
|
297 | return stage;
|
298 | }
|
299 | }
|
300 | throw new Error(`Pipeline does not contain a stage named '${stageName}'. Available stages: ${this._stages.map(s => s.stageName).join(', ')}`);
|
301 | }
|
302 | /**
|
303 | * Returns all of the {@link CrossRegionSupportStack}s that were generated automatically
|
304 | * when dealing with Actions that reside in a different region than the Pipeline itself.
|
305 | *
|
306 | */
|
307 | get crossRegionSupport() {
|
308 | const ret = {};
|
309 | Object.keys(this._crossRegionSupport).forEach((key) => {
|
310 | ret[key] = this._crossRegionSupport[key];
|
311 | });
|
312 | return ret;
|
313 | }
|
314 | /** @internal */
|
315 | _attachActionToPipeline(stage, action, actionScope) {
|
316 | const richAction = new rich_action_1.RichAction(action, this);
|
317 | // handle cross-region actions here
|
318 | const crossRegionInfo = this.ensureReplicationResourcesExistFor(richAction);
|
319 | // get the role for the given action, handling if it's cross-account
|
320 | const actionRole = this.getRoleForAction(stage, richAction, actionScope);
|
321 | // // CodePipeline Variables
|
322 | validation_1.validateNamespaceName(richAction.actionProperties.variablesNamespace);
|
323 | // bind the Action (type h4x)
|
324 | const actionConfig = richAction.bind(actionScope, stage, {
|
325 | role: actionRole ? actionRole : this.role,
|
326 | bucket: crossRegionInfo.artifactBucket,
|
327 | });
|
328 | return new full_action_descriptor_1.FullActionDescriptor({
|
329 | // must be 'action', not 'richAction',
|
330 | // as those are returned by the IStage.actions property,
|
331 | // and it's important customers of Pipeline get the same instance
|
332 | // back as they added to the pipeline
|
333 | action,
|
334 | actionConfig,
|
335 | actionRole,
|
336 | actionRegion: crossRegionInfo.region,
|
337 | });
|
338 | }
|
339 | /**
|
340 | * Validate the pipeline structure
|
341 | *
|
342 | * Validation happens according to the rules documented at
|
343 | *
|
344 | * https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#pipeline-requirements
|
345 | * @override
|
346 | */
|
347 | validate() {
|
348 | return [
|
349 | ...this.validateSourceActionLocations(),
|
350 | ...this.validateHasStages(),
|
351 | ...this.validateStages(),
|
352 | ...this.validateArtifacts(),
|
353 | ];
|
354 | }
|
355 | ensureReplicationResourcesExistFor(action) {
|
356 | if (!action.isCrossRegion) {
|
357 | return {
|
358 | artifactBucket: this.artifactBucket,
|
359 | };
|
360 | }
|
361 | // The action has a specific region,
|
362 | // require the pipeline to have a known region as well.
|
363 | this.requireRegion();
|
364 | // source actions have to be in the same region as the pipeline
|
365 | if (action.actionProperties.category === action_1.ActionCategory.SOURCE) {
|
366 | throw new Error(`Source action '${action.actionProperties.actionName}' must be in the same region as the pipeline`);
|
367 | }
|
368 | // check whether we already have a bucket in that region,
|
369 | // either passed from the outside or previously created
|
370 | const crossRegionSupport = this.obtainCrossRegionSupportFor(action);
|
371 | // the stack containing the replication bucket must be deployed before the pipeline
|
372 | core_1.Stack.of(this).addDependency(crossRegionSupport.stack);
|
373 | // The Pipeline role must be able to replicate to that bucket
|
374 | crossRegionSupport.replicationBucket.grantReadWrite(this.role);
|
375 | return {
|
376 | artifactBucket: crossRegionSupport.replicationBucket,
|
377 | region: action.effectiveRegion,
|
378 | };
|
379 | }
|
380 | /**
|
381 | * Get or create the cross-region support construct for the given action
|
382 | */
|
383 | obtainCrossRegionSupportFor(action) {
|
384 | // this method is never called for non cross-region actions
|
385 | const actionRegion = action.effectiveRegion;
|
386 | let crossRegionSupport = this._crossRegionSupport[actionRegion];
|
387 | if (!crossRegionSupport) {
|
388 | // we need to create scaffolding resources for this region
|
389 | const otherStack = action.resourceStack;
|
390 | crossRegionSupport = this.createSupportResourcesForRegion(otherStack, actionRegion);
|
391 | this._crossRegionSupport[actionRegion] = crossRegionSupport;
|
392 | }
|
393 | return crossRegionSupport;
|
394 | }
|
395 | createSupportResourcesForRegion(otherStack, actionRegion) {
|
396 | // if we have a stack from the resource passed - use that!
|
397 | if (otherStack) {
|
398 | // check if the stack doesn't have this magic construct already
|
399 | const id = `CrossRegionReplicationSupport-d823f1d8-a990-4e5c-be18-4ac698532e65-${actionRegion}`;
|
400 | let crossRegionSupportConstruct = otherStack.node.tryFindChild(id);
|
401 | if (!crossRegionSupportConstruct) {
|
402 | crossRegionSupportConstruct = new cross_region_support_stack_1.CrossRegionSupportConstruct(otherStack, id, {
|
403 | createKmsKey: this.crossAccountKeys,
|
404 | enableKeyRotation: this.enableKeyRotation,
|
405 | });
|
406 | }
|
407 | return {
|
408 | replicationBucket: crossRegionSupportConstruct.replicationBucket,
|
409 | stack: otherStack,
|
410 | };
|
411 | }
|
412 | // otherwise - create a stack with the resources needed for replication across regions
|
413 | const pipelineStack = core_1.Stack.of(this);
|
414 | const pipelineAccount = pipelineStack.account;
|
415 | if (core_1.Token.isUnresolved(pipelineAccount)) {
|
416 | throw new Error("You need to specify an explicit account when using CodePipeline's cross-region support");
|
417 | }
|
418 | const app = this.supportScope();
|
419 | const supportStackId = `cross-region-stack-${this.reuseCrossRegionSupportStacks ? pipelineAccount : pipelineStack.stackName}:${actionRegion}`;
|
420 | let supportStack = app.node.tryFindChild(supportStackId);
|
421 | if (!supportStack) {
|
422 | supportStack = new cross_region_support_stack_1.CrossRegionSupportStack(app, supportStackId, {
|
423 | pipelineStackName: pipelineStack.stackName,
|
424 | region: actionRegion,
|
425 | account: pipelineAccount,
|
426 | synthesizer: this.getCrossRegionSupportSynthesizer(),
|
427 | createKmsKey: this.crossAccountKeys,
|
428 | enableKeyRotation: this.enableKeyRotation,
|
429 | });
|
430 | }
|
431 | return {
|
432 | stack: supportStack,
|
433 | replicationBucket: supportStack.replicationBucket,
|
434 | };
|
435 | }
|
436 | getCrossRegionSupportSynthesizer() {
|
437 | if (this.stack.synthesizer instanceof core_1.DefaultStackSynthesizer) {
|
438 | // if we have the new synthesizer,
|
439 | // we need a bootstrapless copy of it,
|
440 | // because we don't want to require bootstrapping the environment
|
441 | // of the pipeline account in this replication region
|
442 | return new core_1.BootstraplessSynthesizer({
|
443 | deployRoleArn: this.stack.synthesizer.deployRoleArn,
|
444 | cloudFormationExecutionRoleArn: this.stack.synthesizer.cloudFormationExecutionRoleArn,
|
445 | });
|
446 | }
|
447 | else {
|
448 | // any other synthesizer: just return undefined
|
449 | // (ie., use the default based on the context settings)
|
450 | return undefined;
|
451 | }
|
452 | }
|
453 | generateNameForDefaultBucketKeyAlias() {
|
454 | const prefix = 'alias/codepipeline-';
|
455 | const maxAliasLength = 256;
|
456 | const uniqueId = core_1.Names.uniqueId(this);
|
457 | // take the last 256 - (prefix length) characters of uniqueId
|
458 | const startIndex = Math.max(0, uniqueId.length - (maxAliasLength - prefix.length));
|
459 | return prefix + uniqueId.substring(startIndex).toLowerCase();
|
460 | }
|
461 | /**
|
462 | * Gets the role used for this action,
|
463 | * including handling the case when the action is supposed to be cross-account.
|
464 | *
|
465 | * @param stage the stage the action belongs to
|
466 | * @param action the action to return/create a role for
|
467 | * @param actionScope the scope, unique to the action, to create new resources in
|
468 | */
|
469 | getRoleForAction(stage, action, actionScope) {
|
470 | const pipelineStack = core_1.Stack.of(this);
|
471 | let actionRole = this.getRoleFromActionPropsOrGenerateIfCrossAccount(stage, action);
|
472 | if (!actionRole && this.isAwsOwned(action)) {
|
473 | // generate a Role for this specific Action
|
474 | actionRole = new iam.Role(actionScope, 'CodePipelineActionRole', {
|
475 | assumedBy: new iam.AccountPrincipal(pipelineStack.account),
|
476 | });
|
477 | }
|
478 | // the pipeline role needs assumeRole permissions to the action role
|
479 | const grant = actionRole?.grantAssumeRole(this.role);
|
480 | grant?.applyBefore(this.codePipeline);
|
481 | return actionRole;
|
482 | }
|
483 | getRoleFromActionPropsOrGenerateIfCrossAccount(stage, action) {
|
484 | const pipelineStack = core_1.Stack.of(this);
|
485 | // if we have a cross-account action, the pipeline's bucket must have a KMS key
|
486 | // (otherwise we can't configure cross-account trust policies)
|
487 | if (action.isCrossAccount) {
|
488 | const artifactBucket = this.ensureReplicationResourcesExistFor(action).artifactBucket;
|
489 | if (!artifactBucket.encryptionKey) {
|
490 | throw new Error(`Artifact Bucket must have a KMS Key to add cross-account action '${action.actionProperties.actionName}' ` +
|
491 | `(pipeline account: '${renderEnvDimension(this.env.account)}', action account: '${renderEnvDimension(action.effectiveAccount)}'). ` +
|
492 | 'Create Pipeline with \'crossAccountKeys: true\' (or pass an existing Bucket with a key)');
|
493 | }
|
494 | }
|
495 | // if a Role has been passed explicitly, always use it
|
496 | // (even if the backing resource is from a different account -
|
497 | // this is how the user can override our default support logic)
|
498 | if (action.actionProperties.role) {
|
499 | if (this.isAwsOwned(action)) {
|
500 | // the role has to be deployed before the pipeline
|
501 | // (our magical cross-stack dependencies will not work,
|
502 | // because the role might be from a different environment),
|
503 | // but _only_ if it's a new Role -
|
504 | // an imported Role should not add the dependency
|
505 | if (action.actionProperties.role instanceof iam.Role) {
|
506 | const roleStack = core_1.Stack.of(action.actionProperties.role);
|
507 | pipelineStack.addDependency(roleStack);
|
508 | }
|
509 | return action.actionProperties.role;
|
510 | }
|
511 | else {
|
512 | // ...except if the Action is not owned by 'AWS',
|
513 | // as that would be rejected by CodePipeline at deploy time
|
514 | throw new Error("Specifying a Role is not supported for actions with an owner different than 'AWS' - " +
|
515 | `got '${action.actionProperties.owner}' (Action: '${action.actionProperties.actionName}' in Stage: '${stage.stageName}')`);
|
516 | }
|
517 | }
|
518 | // if we don't have a Role passed,
|
519 | // and the action is cross-account,
|
520 | // generate a Role in that other account stack
|
521 | const otherAccountStack = this.getOtherStackIfActionIsCrossAccount(action);
|
522 | if (!otherAccountStack) {
|
523 | return undefined;
|
524 | }
|
525 | // generate a role in the other stack, that the Pipeline will assume for executing this action
|
526 | const ret = new iam.Role(otherAccountStack, `${core_1.Names.uniqueId(this)}-${stage.stageName}-${action.actionProperties.actionName}-ActionRole`, {
|
527 | assumedBy: new iam.AccountPrincipal(pipelineStack.account),
|
528 | roleName: core_1.PhysicalName.GENERATE_IF_NEEDED,
|
529 | });
|
530 | // the other stack with the role has to be deployed before the pipeline stack
|
531 | // (CodePipeline verifies you can assume the action Role on creation)
|
532 | pipelineStack.addDependency(otherAccountStack);
|
533 | return ret;
|
534 | }
|
535 | /**
|
536 | * Returns the Stack this Action belongs to if this is a cross-account Action.
|
537 | * If this Action is not cross-account (i.e., it lives in the same account as the Pipeline),
|
538 | * it returns undefined.
|
539 | *
|
540 | * @param action the Action to return the Stack for
|
541 | */
|
542 | getOtherStackIfActionIsCrossAccount(action) {
|
543 | const targetAccount = action.actionProperties.resource
|
544 | ? action.actionProperties.resource.env.account
|
545 | : action.actionProperties.account;
|
546 | if (targetAccount === undefined) {
|
547 | // if the account of the Action is not specified,
|
548 | // then it defaults to the same account the pipeline itself is in
|
549 | return undefined;
|
550 | }
|
551 | // check whether the action's account is a static string
|
552 | if (core_1.Token.isUnresolved(targetAccount)) {
|
553 | if (core_1.Token.isUnresolved(this.env.account)) {
|
554 | // the pipeline is also env-agnostic, so that's fine
|
555 | return undefined;
|
556 | }
|
557 | else {
|
558 | throw new Error(`The 'account' property must be a concrete value (action: '${action.actionProperties.actionName}')`);
|
559 | }
|
560 | }
|
561 | // At this point, we know that the action's account is a static string.
|
562 | // In this case, the pipeline's account must also be a static string.
|
563 | if (core_1.Token.isUnresolved(this.env.account)) {
|
564 | throw new Error('Pipeline stack which uses cross-environment actions must have an explicitly set account');
|
565 | }
|
566 | // at this point, we know that both the Pipeline's account,
|
567 | // and the action-backing resource's account are static strings
|
568 | // if they are identical - nothing to do (the action is not cross-account)
|
569 | if (this.env.account === targetAccount) {
|
570 | return undefined;
|
571 | }
|
572 | // at this point, we know that the action is certainly cross-account,
|
573 | // so we need to return a Stack in its account to create the helper Role in
|
574 | const candidateActionResourceStack = action.actionProperties.resource
|
575 | ? core_1.Stack.of(action.actionProperties.resource)
|
576 | : undefined;
|
577 | if (candidateActionResourceStack?.account === targetAccount) {
|
578 | // we always use the "latest" action-backing resource's Stack for this account,
|
579 | // even if a different one was used earlier
|
580 | this._crossAccountSupport[targetAccount] = candidateActionResourceStack;
|
581 | return candidateActionResourceStack;
|
582 | }
|
583 | let targetAccountStack = this._crossAccountSupport[targetAccount];
|
584 | if (!targetAccountStack) {
|
585 | const stackId = `cross-account-support-stack-${targetAccount}`;
|
586 | const app = this.supportScope();
|
587 | targetAccountStack = app.node.tryFindChild(stackId);
|
588 | if (!targetAccountStack) {
|
589 | const actionRegion = action.actionProperties.resource
|
590 | ? action.actionProperties.resource.env.region
|
591 | : action.actionProperties.region;
|
592 | const pipelineStack = core_1.Stack.of(this);
|
593 | targetAccountStack = new core_1.Stack(app, stackId, {
|
594 | stackName: `${pipelineStack.stackName}-support-${targetAccount}`,
|
595 | env: {
|
596 | account: targetAccount,
|
597 | region: actionRegion ?? pipelineStack.region,
|
598 | },
|
599 | });
|
600 | }
|
601 | this._crossAccountSupport[targetAccount] = targetAccountStack;
|
602 | }
|
603 | return targetAccountStack;
|
604 | }
|
605 | isAwsOwned(action) {
|
606 | const owner = action.actionProperties.owner;
|
607 | return !owner || owner === 'AWS';
|
608 | }
|
609 | getArtifactBucketFromProps(props) {
|
610 | if (props.artifactBucket) {
|
611 | return props.artifactBucket;
|
612 | }
|
613 | if (props.crossRegionReplicationBuckets) {
|
614 | const pipelineRegion = this.requireRegion();
|
615 | return props.crossRegionReplicationBuckets[pipelineRegion];
|
616 | }
|
617 | return undefined;
|
618 | }
|
619 | calculateInsertIndexFromPlacement(placement) {
|
620 | // check if at most one placement property was provided
|
621 | const providedPlacementProps = ['rightBefore', 'justAfter', 'atIndex']
|
622 | .filter((prop) => placement[prop] !== undefined);
|
623 | if (providedPlacementProps.length > 1) {
|
624 | throw new Error('Error adding Stage to the Pipeline: ' +
|
625 | 'you can only provide at most one placement property, but ' +
|
626 | `'${providedPlacementProps.join(', ')}' were given`);
|
627 | }
|
628 | if (placement.rightBefore !== undefined) {
|
629 | const targetIndex = this.findStageIndex(placement.rightBefore);
|
630 | if (targetIndex === -1) {
|
631 | throw new Error('Error adding Stage to the Pipeline: ' +
|
632 | `the requested Stage to add it before, '${placement.rightBefore.stageName}', was not found`);
|
633 | }
|
634 | return targetIndex;
|
635 | }
|
636 | if (placement.justAfter !== undefined) {
|
637 | const targetIndex = this.findStageIndex(placement.justAfter);
|
638 | if (targetIndex === -1) {
|
639 | throw new Error('Error adding Stage to the Pipeline: ' +
|
640 | `the requested Stage to add it after, '${placement.justAfter.stageName}', was not found`);
|
641 | }
|
642 | return targetIndex + 1;
|
643 | }
|
644 | return this.stageCount;
|
645 | }
|
646 | findStageIndex(targetStage) {
|
647 | return this._stages.findIndex(stage => stage === targetStage);
|
648 | }
|
649 | validateSourceActionLocations() {
|
650 | const errors = new Array();
|
651 | let firstStage = true;
|
652 | for (const stage of this._stages) {
|
653 | const onlySourceActionsPermitted = firstStage;
|
654 | for (const action of stage.actionDescriptors) {
|
655 | errors.push(...validation_1.validateSourceAction(onlySourceActionsPermitted, action.category, action.actionName, stage.stageName));
|
656 | }
|
657 | firstStage = false;
|
658 | }
|
659 | return errors;
|
660 | }
|
661 | validateHasStages() {
|
662 | if (this.stageCount < 2) {
|
663 | return ['Pipeline must have at least two stages'];
|
664 | }
|
665 | return [];
|
666 | }
|
667 | validateStages() {
|
668 | const ret = new Array();
|
669 | for (const stage of this._stages) {
|
670 | ret.push(...stage.validate());
|
671 | }
|
672 | return ret;
|
673 | }
|
674 | validateArtifacts() {
|
675 | const ret = new Array();
|
676 | const producers = {};
|
677 | const firstConsumers = {};
|
678 | for (const [stageIndex, stage] of enumerate(this._stages)) {
|
679 | // For every output artifact, get the producer
|
680 | for (const action of stage.actionDescriptors) {
|
681 | const actionLoc = new PipelineLocation(stageIndex, stage, action);
|
682 | for (const outputArtifact of action.outputs) {
|
683 | // output Artifacts always have a name set
|
684 | const name = outputArtifact.artifactName;
|
685 | if (producers[name]) {
|
686 | ret.push(`Both Actions '${producers[name].actionName}' and '${action.actionName}' are producting Artifact '${name}'. Every artifact can only be produced once.`);
|
687 | continue;
|
688 | }
|
689 | producers[name] = actionLoc;
|
690 | }
|
691 | // For every input artifact, get the first consumer
|
692 | for (const inputArtifact of action.inputs) {
|
693 | const name = inputArtifact.artifactName;
|
694 | if (!name) {
|
695 | ret.push(`Action '${action.actionName}' is using an unnamed input Artifact, which is not being produced in this pipeline`);
|
696 | continue;
|
697 | }
|
698 | firstConsumers[name] = firstConsumers[name] ? firstConsumers[name].first(actionLoc) : actionLoc;
|
699 | }
|
700 | }
|
701 | }
|
702 | // Now validate that every input artifact is produced before it's
|
703 | // being consumed.
|
704 | for (const [artifactName, consumerLoc] of Object.entries(firstConsumers)) {
|
705 | const producerLoc = producers[artifactName];
|
706 | if (!producerLoc) {
|
707 | ret.push(`Action '${consumerLoc.actionName}' is using input Artifact '${artifactName}', which is not being produced in this pipeline`);
|
708 | continue;
|
709 | }
|
710 | if (consumerLoc.beforeOrEqual(producerLoc)) {
|
711 | ret.push(`${consumerLoc} is consuming input Artifact '${artifactName}' before it is being produced at ${producerLoc}`);
|
712 | }
|
713 | }
|
714 | return ret;
|
715 | }
|
716 | renderArtifactStoresProperty() {
|
717 | if (!this.crossRegion) {
|
718 | return undefined;
|
719 | }
|
720 | // add the Pipeline's artifact store
|
721 | const primaryRegion = this.requireRegion();
|
722 | this._crossRegionSupport[primaryRegion] = {
|
723 | replicationBucket: this.artifactBucket,
|
724 | stack: core_1.Stack.of(this),
|
725 | };
|
726 | return Object.entries(this._crossRegionSupport).map(([region, support]) => ({
|
727 | region,
|
728 | artifactStore: this.renderArtifactStore(support.replicationBucket),
|
729 | }));
|
730 | }
|
731 | renderArtifactStoreProperty() {
|
732 | if (this.crossRegion) {
|
733 | return undefined;
|
734 | }
|
735 | return this.renderPrimaryArtifactStore();
|
736 | }
|
737 | renderPrimaryArtifactStore() {
|
738 | return this.renderArtifactStore(this.artifactBucket);
|
739 | }
|
740 | renderArtifactStore(bucket) {
|
741 | let encryptionKey;
|
742 | const bucketKey = bucket.encryptionKey;
|
743 | if (bucketKey) {
|
744 | encryptionKey = {
|
745 | type: 'KMS',
|
746 | id: bucketKey.keyArn,
|
747 | };
|
748 | }
|
749 | return {
|
750 | type: 'S3',
|
751 | location: bucket.bucketName,
|
752 | encryptionKey,
|
753 | };
|
754 | }
|
755 | get crossRegion() {
|
756 | if (this.crossRegionBucketsPassed) {
|
757 | return true;
|
758 | }
|
759 | return this._stages.some(stage => stage.actionDescriptors.some(action => action.region !== undefined));
|
760 | }
|
761 | renderStages() {
|
762 | return this._stages.map(stage => stage.render());
|
763 | }
|
764 | renderDisabledTransitions() {
|
765 | return this._stages
|
766 | .filter(stage => !stage.transitionToEnabled)
|
767 | .map(stage => ({
|
768 | reason: stage.transitionDisabledReason,
|
769 | stageName: stage.stageName,
|
770 | }));
|
771 | }
|
772 | requireRegion() {
|
773 | const region = this.env.region;
|
774 | if (core_1.Token.isUnresolved(region)) {
|
775 | throw new Error('Pipeline stack which uses cross-environment actions must have an explicitly set region');
|
776 | }
|
777 | return region;
|
778 | }
|
779 | supportScope() {
|
780 | const scope = core_1.Stage.of(this);
|
781 | if (!scope) {
|
782 | throw new Error('Pipeline stack which uses cross-environment actions must be part of a CDK App or Stage');
|
783 | }
|
784 | return scope;
|
785 | }
|
786 | }
|
787 | exports.Pipeline = Pipeline;
|
788 | _a = JSII_RTTI_SYMBOL_1;
|
789 | Pipeline[_a] = { fqn: "@aws-cdk/aws-codepipeline.Pipeline", version: "1.204.0" };
|
790 | function enumerate(xs) {
|
791 | const ret = new Array();
|
792 | for (let i = 0; i < xs.length; i++) {
|
793 | ret.push([i, xs[i]]);
|
794 | }
|
795 | return ret;
|
796 | }
|
797 | class PipelineLocation {
|
798 | constructor(stageIndex, stage, action) {
|
799 | this.stageIndex = stageIndex;
|
800 | this.stage = stage;
|
801 | this.action = action;
|
802 | }
|
803 | get stageName() {
|
804 | return this.stage.stageName;
|
805 | }
|
806 | get actionName() {
|
807 | return this.action.actionName;
|
808 | }
|
809 | /**
|
810 | * Returns whether a is before or the same order as b
|
811 | */
|
812 | beforeOrEqual(rhs) {
|
813 | if (this.stageIndex !== rhs.stageIndex) {
|
814 | return rhs.stageIndex < rhs.stageIndex;
|
815 | }
|
816 | return this.action.runOrder <= rhs.action.runOrder;
|
817 | }
|
818 | /**
|
819 | * Returns the first location between this and the other one
|
820 | */
|
821 | first(rhs) {
|
822 | return this.beforeOrEqual(rhs) ? this : rhs;
|
823 | }
|
824 | toString() {
|
825 | // runOrders are 1-based, so make the stageIndex also 1-based otherwise it's going to be confusing.
|
826 | return `Stage ${this.stageIndex + 1} Action ${this.action.runOrder} ('${this.stageName}'/'${this.actionName}')`;
|
827 | }
|
828 | }
|
829 | /**
|
830 | * Render an env dimension without showing the ugly stringified tokens
|
831 | */
|
832 | function renderEnvDimension(s) {
|
833 | return core_1.Token.isUnresolved(s) ? '(current)' : s;
|
834 | }
|
835 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGlwZWxpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwaXBlbGluZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxvRUFBb0U7QUFDcEUsOENBQThDO0FBQzlDLHdDQUF3QztBQUN4Qyx3Q0FBd0M7QUFDeEMsc0NBQXNDO0FBQ3RDLHdDQWF1QjtBQUV2QixxQ0FBMkg7QUFDM0gscUVBQXVEO0FBQ3ZELHFGQUE0RztBQUM1Ryw2RUFBd0U7QUFDeEUsdURBQW1EO0FBQ25ELDJDQUF3QztBQUN4QyxxREFBaUc7QUFrSmpHLE1BQWUsWUFBYSxTQUFRLGVBQVE7SUFJMUM7Ozs7O09BS0c7SUFDSSxPQUFPLENBQUMsRUFBVSxFQUFFLFVBQWlDLEVBQUU7UUFDNUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLGVBQWUsQ0FBQztZQUNuQixNQUFNLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQztZQUM1QixTQUFTLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDO1NBQzlCLENBQUMsQ0FBQztRQUNILE9BQU8sSUFBSSxDQUFDO0tBQ2I7SUFFRDs7Ozs7O09BTUc7SUFDSSxhQUFhLENBQUMsRUFBVSxFQUFFLFVBQWlDLEVBQUU7UUFDbEUsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDdkMsSUFBSSxDQUFDLGVBQWUsQ0FBQztZQUNuQixVQUFVLEVBQUUsQ0FBQyw4Q0FBOEMsQ0FBQztTQUM3RCxDQUFDLENBQUM7UUFDSCxPQUFPLElBQUksQ0FBQztLQUNiO0lBRU0sNEJBQTRCLENBQUMsTUFBaUI7UUFDbkQsT0FBTztZQUNMLFNBQVMsRUFBRSxJQUFJLENBQUMs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QUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNqRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgbm90aWZpY2F0aW9ucyBmcm9tICdAYXdzLWNkay9hd3MtY29kZXN0YXJub3RpZmljYXRpb25zJztcbmltcG9ydCAqIGFzIGV2ZW50cyBmcm9tICdAYXdzLWNkay9hd3MtZXZlbnRzJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGttcyBmcm9tICdAYXdzLWNkay9hd3Mta21zJztcbmltcG9ydCAqIGFzIHMzIGZyb20gJ0Bhd3MtY2RrL2F3cy1zMyc7XG5pbXBvcnQge1xuICBBcm5Gb3JtYXQsXG4gIEJvb3RzdHJhcGxlc3NTeW50aGVzaXplcixcbiAgRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIsXG4gIElTdGFja1N5bnRoZXNpemVyLFxuICBMYXp5LFxuICBOYW1lcyxcbiAgUGh5c2ljYWxOYW1lLFxuICBSZW1vdmFsUG9saWN5LFxuICBSZXNvdXJjZSxcbiAgU3RhY2ssXG4gIFN0YWdlIGFzIENka1N0YWdlLFxuICBUb2tlbixcbn0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEFjdGlvbkNhdGVnb3J5LCBJQWN0aW9uLCBJUGlwZWxpbmUsIElTdGFnZSwgUGlwZWxpbmVOb3RpZmljYXRpb25FdmVudHMsIFBpcGVsaW5lTm90aWZ5T25PcHRpb25zIH0gZnJvbSAnLi9hY3Rpb24nO1xuaW1wb3J0IHsgQ2ZuUGlwZWxpbmUgfSBmcm9tICcuL2NvZGVwaXBlbGluZS5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgQ3Jvc3NSZWdpb25TdXBwb3J0Q29uc3RydWN0LCBDcm9zc1JlZ2lvblN1cHBvcnRTdGFjayB9IGZyb20gJy4vcHJpdmF0ZS9jcm9zcy1yZWdpb24tc3VwcG9ydC1zdGFjayc7XG5pbXBvcnQgeyBGdWxsQWN0aW9uRGVzY3JpcHRvciB9IGZyb20gJy4vcHJpdmF0ZS9mdWxsLWFjdGlvbi1kZXNjcmlwdG9yJztcbmltcG9ydCB7IFJpY2hBY3Rpb24gfSBmcm9tICcuL3ByaXZhdGUvcmljaC1hY3Rpb24nO1xuaW1wb3J0IHsgU3RhZ2UgfSBmcm9tICcuL3ByaXZhdGUvc3RhZ2UnO1xuaW1wb3J0IHsgdmFsaWRhdGVOYW1lLCB2YWxpZGF0ZU5hbWVzcGFjZU5hbWUsIHZhbGlkYXRlU291cmNlQWN0aW9uIH0gZnJvbSAnLi9wcml2YXRlL3ZhbGlkYXRpb24nO1xuXG4vLyBrZWVwIHRoaXMgaW1wb3J0IHNlcGFyYXRlIGZyb20gb3RoZXIgaW1wb3J0cyB0byByZWR1Y2UgY2hhbmNlIGZvciBtZXJnZSBjb25mbGljdHMgd2l0aCB2Mi1tYWluXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZHVwbGljYXRlLWltcG9ydHMsIGltcG9ydC9vcmRlclxuaW1wb3J0IHsgQ29uc3RydWN0IGFzIENvcmVDb25zdHJ1Y3QgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcblxuLyoqXG4gKiBBbGxvd3MgeW91IHRvIGNvbnRyb2wgd2hlcmUgdG8gcGxhY2UgYSBuZXcgU3RhZ2Ugd2hlbiBpdCdzIGFkZGVkIHRvIHRoZSBQaXBlbGluZS5cbiAqIE5vdGUgdGhhdCB5b3UgY2FuIHByb3ZpZGUgb25seSBvbmUgb2YgdGhlIGJlbG93IHByb3BlcnRpZXMgLVxuICogc3BlY2lmeWluZyBtb3JlIHRoYW4gb25lIHdpbGwgcmVzdWx0IGluIGEgdmFsaWRhdGlvbiBlcnJvci5cbiAqXG4gKiBAc2VlICNyaWdodEJlZm9yZVxuICogQHNlZSAjanVzdEFmdGVyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RhZ2VQbGFjZW1lbnQge1xuICAvKipcbiAgICogSW5zZXJ0cyB0aGUgbmV3IFN0YWdlIGFzIGEgcGFyZW50IG9mIHRoZSBnaXZlbiBTdGFnZVxuICAgKiAoY2hhbmdpbmcgaXRzIGN1cnJlbnQgcGFyZW50IFN0YWdlLCBpZiBpdCBoYWQgb25lKS5cbiAgICovXG4gIHJlYWRvbmx5IHJpZ2h0QmVmb3JlPzogSVN0YWdlO1xuXG4gIC8qKlxuICAgKiBJbnNlcnRzIHRoZSBuZXcgU3RhZ2UgYXMgYSBjaGlsZCBvZiB0aGUgZ2l2ZW4gU3RhZ2VcbiAgICogKGNoYW5naW5nIGl0cyBjdXJyZW50IGNoaWxkIFN0YWdlLCBpZiBpdCBoYWQgb25lKS5cbiAgICovXG4gIHJlYWRvbmx5IGp1c3RBZnRlcj86IElTdGFnZTtcbn1cblxuLyoqXG4gKiBDb25zdHJ1Y3Rpb24gcHJvcGVydGllcyBvZiBhIFBpcGVsaW5lIFN0YWdlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YWdlUHJvcHMge1xuICAvKipcbiAgICogVGhlIHBoeXNpY2FsLCBodW1hbi1yZWFkYWJsZSBuYW1lIHRvIGFzc2lnbiB0byB0aGlzIFBpcGVsaW5lIFN0YWdlLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhZ2VOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBsaXN0IG9mIEFjdGlvbnMgdG8gY3JlYXRlIHRoaXMgU3RhZ2Ugd2l0aC5cbiAgICogWW91IGNhbiBhbHdheXMgYWRkIG1vcmUgQWN0aW9ucyBsYXRlciBieSBjYWxsaW5nIHtAbGluayBJU3RhZ2UjYWRkQWN0aW9ufS5cbiAgICovXG4gIHJlYWRvbmx5IGFjdGlvbnM/OiBJQWN0aW9uW107XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZW5hYmxlIHRyYW5zaXRpb24gdG8gdGhpcyBzdGFnZS5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgdHJhbnNpdGlvblRvRW5hYmxlZD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSByZWFzb24gZm9yIGRpc2FibGluZyB0cmFuc2l0aW9uIHRvIHRoaXMgc3RhZ2UuIE9ubHkgYXBwbGljYWJsZVxuICAgKiBpZiBgdHJhbnNpdGlvblRvRW5hYmxlZGAgaXMgc2V0IHRvIGBmYWxzZWAuXG4gICAqXG4gICAqIEBkZWZhdWx0ICdUcmFuc2l0aW9uIGRpc2FibGVkJ1xuICAgKi9cbiAgcmVhZG9ubHkgdHJhbnNpdGlvbkRpc2FibGVkUmVhc29uPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFN0YWdlT3B0aW9ucyBleHRlbmRzIFN0YWdlUHJvcHMge1xuICByZWFkb25seSBwbGFjZW1lbnQ/OiBTdGFnZVBsYWNlbWVudDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQaXBlbGluZVByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBTMyBidWNrZXQgdXNlZCBieSB0aGlzIFBpcGVsaW5lIHRvIHN0b3JlIGFydGlmYWN0cy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBIG5ldyBTMyBidWNrZXQgd2lsbCBiZSBjcmVhdGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgYXJ0aWZhY3RCdWNrZXQ/OiBzMy5JQnVja2V0O1xuXG4gIC8qKlxuICAgKiBUaGUgSUFNIHJvbGUgdG8gYmUgYXNzdW1lZCBieSB0aGlzIFBpcGVsaW5lLlxuICAgKlxuICAgKiBAZGVmYXVsdCBhIG5ldyBJQU0gcm9sZSB3aWxsIGJlIGNyZWF0ZWQuXG4gICAqL1xuICByZWFkb25seSByb2xlPzogaWFtLklSb2xlO1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciB0byByZXJ1biB0aGUgQVdTIENvZGVQaXBlbGluZSBwaXBlbGluZSBhZnRlciB5b3UgdXBkYXRlIGl0LlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzdGFydEV4ZWN1dGlvbk9uVXBkYXRlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogTmFtZSBvZiB0aGUgcGlwZWxpbmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQVdTIENsb3VkRm9ybWF0aW9uIGdlbmVyYXRlcyBhbiBJRCBhbmQgdXNlcyB0aGF0IGZvciB0aGUgcGlwZWxpbmUgbmFtZS5cbiAgICovXG4gIHJlYWRvbmx5IHBpcGVsaW5lTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogQSBtYXAgb2YgcmVnaW9uIHRvIFMzIGJ1Y2tldCBuYW1lIHVzZWQgZm9yIGNyb3NzLXJlZ2lvbiBDb2RlUGlwZWxpbmUuXG4gICAqIEZvciBldmVyeSBBY3Rpb24gdGhhdCB5b3Ugc3BlY2lmeSB0YXJnZXRpbmcgYSBkaWZmZXJlbnQgcmVnaW9uIHRoYW4gdGhlIFBpcGVsaW5lIGl0c2VsZixcbiAgICogaWYgeW91IGRvbid0IHByb3ZpZGUgYW4gZXhwbGljaXQgQnVja2V0IGZvciB0aGF0IHJlZ2lvbiB1c2luZyB0aGlzIHByb3BlcnR5LFxuICAgKiB0aGUgY29uc3RydWN0IHdpbGwgYXV0b21hdGljYWxseSBjcmVhdGUgYSBTdGFjayBjb250YWluaW5nIGFuIFMzIEJ1Y2tldCBpbiB0aGF0IHJlZ2lvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBOb25lLlxuICAgKi9cbiAgcmVhZG9ubHkgY3Jvc3NSZWdpb25SZXBsaWNhdGlvbkJ1Y2tldHM/OiB7IFtyZWdpb246IHN0cmluZ106IHMzLklCdWNrZXQgfTtcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2YgU3RhZ2VzLCBpbiBvcmRlcixcbiAgICogdG8gY3JlYXRlIHRoaXMgUGlwZWxpbmUgd2l0aC5cbiAgICogWW91IGNhbiBhbHdheXMgYWRkIG1vcmUgU3RhZ2VzIGxhdGVyIGJ5IGNhbGxpbmcge0BsaW5rIFBpcGVsaW5lI2FkZFN0YWdlfS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBOb25lLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhZ2VzPzogU3RhZ2VQcm9wc1tdO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgS01TIGtleXMgZm9yIGNyb3NzLWFjY291bnQgZGVwbG95bWVudHMuXG4gICAqXG4gICAqIFRoaXMgY29udHJvbHMgd2hldGhlciB0aGUgcGlwZWxpbmUgaXMgZW5hYmxlZCBmb3IgY3Jvc3MtYWNjb3VudCBkZXBsb3ltZW50cy5cbiAgICpcbiAgICogQnkgZGVmYXVsdCBjcm9zcy1hY2NvdW50IGRlcGxveW1lbnRzIGFyZSBlbmFibGVkLCBidXQgdGhpcyBmZWF0dXJlIHJlcXVpcmVzXG4gICAqIHRoYXQgS01TIEN1c3RvbWVyIE1hc3RlciBLZXlzIGFyZSBjcmVhdGVkIHdoaWNoIGhhdmUgYSBjb3N0IG9mICQxL21vbnRoLlxuICAgKlxuICAgKiBJZiB5b3UgZG8gbm90IG5lZWQgY3Jvc3MtYWNjb3VudCBkZXBsb3ltZW50cywgeW91IGNhbiBzZXQgdGhpcyB0byBgZmFsc2VgIHRvXG4gICAqIG5vdCBjcmVhdGUgdGhvc2Uga2V5cyBhbmQgc2F2ZSBvbiB0aGF0IGNvc3QgKHRoZSBhcnRpZmFjdCBidWNrZXQgd2lsbCBiZVxuICAgKiBlbmNyeXB0ZWQgd2l0aCBhbiBBV1MtbWFuYWdlZCBrZXkpLiBIb3dldmVyLCBjcm9zcy1hY2NvdW50IGRlcGxveW1lbnRzIHdpbGxcbiAgICogbm8gbG9uZ2VyIGJlIHBvc3NpYmxlLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBjcm9zc0FjY291bnRLZXlzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRW5hYmxlIEtNUyBrZXkgcm90YXRpb24gZm9yIHRoZSBnZW5lcmF0ZWQgS01TIGtleXMuXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQgS01TIGtleSByb3RhdGlvbiBpcyBkaXNhYmxlZCwgYnV0IHdpbGwgYWRkIGFuIGFkZGl0aW9uYWwgJDEvbW9udGhcbiAgICogZm9yIGVhY2ggeWVhciB0aGUga2V5IGV4aXN0cyB3aGVuIGVuYWJsZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZmFsc2UgKGtleSByb3RhdGlvbiBpcyBkaXNhYmxlZClcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZUtleVJvdGF0aW9uPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogUmV1c2UgdGhlIHNhbWUgY3Jvc3MgcmVnaW9uIHN1cHBvcnQgc3RhY2sgZm9yIGFsbCBwaXBlbGluZXMgaW4gdGhlIEFwcC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0cnVlIChVc2UgdGhlIHNhbWUgc3VwcG9ydCBzdGFjayBmb3IgYWxsIHBpcGVsaW5lcyBpbiBBcHApXG4gICAqL1xuICByZWFkb25seSByZXVzZUNyb3NzUmVnaW9uU3VwcG9ydFN0YWNrcz86IGJvb2xlYW47XG59XG5cbmFic3RyYWN0IGNsYXNzIFBpcGVsaW5lQmFzZSBleHRlbmRzIFJlc291cmNlIGltcGxlbWVudHMgSVBpcGVsaW5lIHtcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHBpcGVsaW5lTmFtZTogc3RyaW5nO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgcGlwZWxpbmVBcm46IHN0cmluZztcblxuICAvKipcbiAgICogRGVmaW5lcyBhbiBldmVudCBydWxlIHRyaWdnZXJlZCBieSB0aGlzIENvZGVQaXBlbGluZS5cbiAgICpcbiAgICogQHBhcmFtIGlkIElkZW50aWZpZXIgZm9yIHRoaXMgZXZlbnQgaGFuZGxlci5cbiAgICogQHBhcmFtIG9wdGlvbnMgQWRkaXRpb25hbCBvcHRpb25zIHRvIHBhc3MgdG8gdGhlIGV2ZW50IHJ1bGUuXG4gICAqL1xuICBwdWJsaWMgb25FdmVudChpZDogc3RyaW5nLCBvcHRpb25zOiBldmVudHMuT25FdmVudE9wdGlvbnMgPSB7fSk6IGV2ZW50cy5SdWxlIHtcbiAgICBjb25zdCBydWxlID0gbmV3IGV2ZW50cy5SdWxlKHRoaXMsIGlkLCBvcHRpb25zKTtcbiAgICBydWxlLmFkZFRhcmdldChvcHRpb25zLnRhcmdldCk7XG4gICAgcnVsZS5hZGRFdmVudFBhdHRlcm4oe1xuICAgICAgc291cmNlOiBbJ2F3cy5jb2RlcGlwZWxpbmUnXSxcbiAgICAgIHJlc291cmNlczogW3RoaXMucGlwZWxpbmVBcm5dLFxuICAgIH0pO1xuICAgIHJldHVybiBydWxlO1xuICB9XG5cbiAgLyoqXG4gICAqIERlZmluZXMgYW4gZXZlbnQgcnVsZSB0cmlnZ2VyZWQgYnkgdGhlIFwiQ29kZVBpcGVsaW5lIFBpcGVsaW5lIEV4ZWN1dGlvblxuICAgKiBTdGF0ZSBDaGFuZ2VcIiBldmVudCBlbWl0dGVkIGZyb20gdGhpcyBwaXBlbGluZS5cbiAgICpcbiAgICogQHBhcmFtIGlkIElkZW50aWZpZXIgZm9yIHRoaXMgZXZlbnQgaGFuZGxlci5cbiAgICogQHBhcmFtIG9wdGlvbnMgQWRkaXRpb25hbCBvcHRpb25zIHRvIHBhc3MgdG8gdGhlIGV2ZW50IHJ1bGUuXG4gICAqL1xuICBwdWJsaWMgb25TdGF0ZUNoYW5nZShpZDogc3RyaW5nLCBvcHRpb25zOiBldmVudHMuT25FdmVudE9wdGlvbnMgPSB7fSk6IGV2ZW50cy5SdWxlIHtcbiAgICBjb25zdCBydWxlID0gdGhpcy5vbkV2ZW50KGlkLCBvcHRpb25zKTtcbiAgICBydWxlLmFkZEV2ZW50UGF0dGVybih7XG4gICAgICBkZXRhaWxUeXBlOiBbJ0NvZGVQaXBlbGluZSBQaXBlbGluZSBFeGVjdXRpb24gU3RhdGUgQ2hhbmdlJ10sXG4gICAgfSk7XG4gICAgcmV0dXJuIHJ1bGU7XG4gIH1cblxuICBwdWJsaWMgYmluZEFzTm90aWZpY2F0aW9uUnVsZVNvdXJjZShfc2NvcGU6IENvbnN0cnVjdCk6IG5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uUnVsZVNvdXJjZUNvbmZpZyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNvdXJjZUFybjogdGhpcy5waXBlbGluZUFybixcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIG5vdGlmeU9uKFxuICAgIGlkOiBzdHJpbmcsXG4gICAgdGFyZ2V0OiBub3RpZmljYXRpb25zLklOb3RpZmljYXRpb25SdWxlVGFyZ2V0LFxuICAgIG9wdGlvbnM6IFBpcGVsaW5lTm90aWZ5T25PcHRpb25zLFxuICApOiBub3RpZmljYXRpb25zLklOb3RpZmljYXRpb25SdWxlIHtcbiAgICByZXR1cm4gbmV3IG5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uUnVsZSh0aGlzLCBpZCwge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIHNvdXJjZTogdGhpcyxcbiAgICAgIHRhcmdldHM6IFt0YXJnZXRdLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG5vdGlmeU9uRXhlY3V0aW9uU3RhdGVDaGFuZ2UoXG4gICAgaWQ6IHN0cmluZyxcbiAgICB0YXJnZXQ6IG5vdGlmaWNhdGlvbnMuSU5vdGlmaWNhdGlvblJ1bGVUYXJnZXQsXG4gICAgb3B0aW9ucz86IG5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uUnVsZU9wdGlvbnMsXG4gICk6IG5vdGlmaWNhdGlvbnMuSU5vdGlmaWNhdGlvblJ1bGUge1xuICAgIHJldHVybiB0aGlzLm5vdGlmeU9uKGlkLCB0YXJnZXQsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBldmVudHM6IFtcbiAgICAgICAgUGlwZWxpbmVOb3RpZmljYXRpb25FdmVudHMuUElQRUxJTkVfRVhFQ1VUSU9OX0ZBSUxFRCxcbiAgICAgICAgUGlwZWxpbmVOb3RpZmljYXRpb25FdmVudHMuUElQRUxJTkVfRVhFQ1VUSU9OX0NBTkNFTEVELFxuICAgICAgICBQaXBlbGluZU5vdGlmaWNhdGlvbkV2ZW50cy5QSVBFTElORV9FWEVDVVRJT05fU1RBUlRFRCxcbiAgICAgICAgUGlwZWxpbmVOb3RpZmljYXRpb25FdmVudHMuUElQRUxJTkVfRVhFQ1VUSU9OX1JFU1VNRUQsXG4gICAgICAgIFBpcGVsaW5lTm90aWZpY2F0aW9uRXZlbnRzLlBJUEVMSU5FX0VYRUNVVElPTl9TVUNDRUVERUQsXG4gICAgICAgIFBpcGVsaW5lTm90aWZpY2F0aW9uRXZlbnRzLlBJUEVMSU5FX0VYRUNVVElPTl9TVVBFUlNFREVELFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBub3RpZnlPbkFueVN0YWdlU3RhdGVDaGFuZ2UoXG4gICAgaWQ6IHN0cmluZyxcbiAgICB0YXJnZXQ6IG5vdGlmaWNhdGlvbnMuSU5vdGlmaWNhdGlvblJ1bGVUYXJnZXQsXG4gICAgb3B0aW9ucz86IG5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uUnVsZU9wdGlvbnMsXG4gICk6IG5vdGlmaWNhdGlvbnMuSU5vdGlmaWNhdGlvblJ1bGUge1xuICAgIHJldHVybiB0aGlzLm5vdGlmeU9uKGlkLCB0YXJnZXQsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBldmVudHM6IFtcbiAgICAgICAgUGlwZWxpbmVOb3RpZmljYXRpb25FdmVudHMuU1RBR0VfRVhFQ1VUSU9OX0NBTkNFTEVELFxuICAgICAgICBQaXBlbGluZU5vdGlmaWNhdGlvbkV2ZW50cy5TVEFHRV9FWEVDVVRJT05fRkFJTEVELFxuICAgICAgICBQaXBlbGluZU5vdGlmaWNhdGlvbkV2ZW50cy5TVEFHRV9FWEVDVVRJT05fUkVTVU1FRCxcbiAgICAgICAgUGlwZWxpbmVOb3RpZmljYXRpb25FdmVudHMuU1RBR0VfRVhFQ1VUSU9OX1NUQVJURUQsXG4gICAgICAgIFBpcGVsaW5lTm90aWZpY2F0aW9uRXZlbnRzLlNUQUdFX0VYRUNVVElPTl9TVUNDRUVERUQsXG4gICAgICBdLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG5vdGlmeU9uQW55QWN0aW9uU3RhdGVDaGFuZ2UoXG4gICAgaWQ6IHN0cmluZyxcbiAgICB0YXJnZXQ6IG5vdGlmaWNhdGlvbnMuSU5vdGlmaWNhdGlvblJ1bGVUYXJnZXQsXG4gICAgb3B0aW9ucz86IG5vdGlmaWNhdGlvbnMuTm90aWZpY2F0aW9uUnVsZU9wdGlvbnMsXG4gICk6IG5vdGlmaWNhdGlvbnMuSU5vdGlmaWNhdGlvblJ1bGUge1xuICAgIHJldHVybiB0aGlzLm5vdGlmeU9uKGlkLCB0YXJnZXQsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBldmVudHM6IFtcbiAgICAgICAgUGlwZWxpbmVOb3RpZmljYXRpb25FdmVudHMuQUNUSU9OX0VYRUNVVElPTl9DQU5DRUxFRCxcbiAgICAgICAgUGlwZWxpbmVOb3RpZmljYXRpb25FdmVudHMuQUNUSU9OX0VYRUNVVElPTl9GQUlMRUQsXG4gICAgICAgIFBpcGVsaW5lTm90aWZpY2F0aW9uRXZlbnRzLkFDVElPTl9FWEVDVVRJT05fU1RBUlRFRCxcbiAgICAgICAgUGlwZWxpbmVOb3RpZmljYXRpb25FdmVudHMuQUNUSU9OX0VYRUNVVElPTl9TVUNDRUVERUQsXG4gICAgICBdLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG5vdGlmeU9uQW55TWFudWFsQXBwcm92YWxTdGF0ZUNoYW5nZShcbiAgICBpZDogc3RyaW5nLFxuICAgIHRhcmdldDogbm90aWZpY2F0aW9ucy5JTm90aWZpY2F0aW9uUnVsZVRhcmdldCxcbiAgICBvcHRpb25zPzogbm90aWZpY2F0aW9ucy5Ob3RpZmljYXRpb25SdWxlT3B0aW9ucyxcbiAgKTogbm90aWZpY2F0aW9ucy5JTm90aWZpY2F0aW9uUnVsZSB7XG4gICAgcmV0dXJuIHRoaXMubm90aWZ5T24oaWQsIHRhcmdldCwge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIGV2ZW50czogW1xuICAgICAgICBQaXBlbGluZU5vdGlmaWNhdGlvbkV2ZW50cy5NQU5VQUxfQVBQUk9WQUxfRkFJTEVELFxuICAgICAgICBQaXBlbGluZU5vdGlmaWNhdGlvbkV2ZW50cy5NQU5VQUxfQVBQUk9WQUxfTkVFREVELFxuICAgICAgICBQaXBlbGluZU5vdGlmaWNhdGlvbkV2ZW50cy5NQU5VQUxfQVBQUk9WQUxfU1VDQ0VFREVELFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIEFuIEFXUyBDb2RlUGlwZWxpbmUgcGlwZWxpbmUgd2l0aCBpdHMgYXNzb2NpYXRlZCBJQU0gcm9sZSBhbmQgUzMgYnVja2V0LlxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBjcmVhdGUgYSBwaXBlbGluZVxuICogaW1wb3J0ICogYXMgY29kZWNvbW1pdCBmcm9tICdAYXdzLWNkay9hd3MtY29kZWNvbW1pdCc7XG4gKlxuICogY29uc3QgcGlwZWxpbmUgPSBuZXcgY29kZXBpcGVsaW5lLlBpcGVsaW5lKHRoaXMsICdQaXBlbGluZScpO1xuICpcbiAqIC8vIGFkZCBhIHN0YWdlXG4gKiBjb25zdCBzb3VyY2VTdGFnZSA9IHBpcGVsaW5lLmFkZFN0YWdlKHsgc3RhZ2VOYW1lOiAnU291cmNlJyB9KTtcbiAqXG4gKiAvLyBhZGQgYSBzb3VyY2UgYWN0aW9uIHRvIHRoZSBzdGFnZVxuICogZGVjbGFyZSBjb25zdCByZXBvOiBjb2RlY29tbWl0LlJlcG9zaXRvcnk7XG4gKiBkZWNsYXJlIGNvbnN0IHNvdXJjZUFydGlmYWN0OiBjb2RlcGlwZWxpbmUuQXJ0aWZhY3Q7XG4gKiBzb3VyY2VTdGFnZS5hZGRBY3Rpb24obmV3IGNvZGVwaXBlbGluZV9hY3Rpb25zLkNvZGVDb21taXRTb3VyY2VBY3Rpb24oe1xuICogICBhY3Rpb25OYW1lOiAnU291cmNlJyxcbiAqICAgb3V0cHV0OiBzb3VyY2VBcnRpZmFjdCxcbiAqICAgcmVwb3NpdG9yeTogcmVwbyxcbiAqIH0pKTtcbiAqXG4gKiAvLyAuLi4gYWRkIG1vcmUgc3RhZ2VzXG4gKi9cbmV4cG9ydCBjbGFzcyBQaXBlbGluZSBleHRlbmRzIFBpcGVsaW5lQmFzZSB7XG4gIC8qKlxuICAgKiBJbXBvcnQgYSBwaXBlbGluZSBpbnRvIHRoaXMgYXBwLlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgdGhlIHNjb3BlIGludG8gd2hpY2ggdG8gaW1wb3J0IHRoaXMgcGlwZWxpbmVcbiAgICogQHBhcmFtIGlkIHRoZSBsb2dpY2FsIElEIG9mIHRoZSByZXR1cm5lZCBwaXBlbGluZSBjb25zdHJ1Y3RcbiAgICogQHBhcmFtIHBpcGVsaW5lQXJuIFRoZSBBUk4gb2YgdGhlIHBpcGVsaW5lIChlLmcuIGBhcm46YXdzOmNvZGVwaXBlbGluZTp1cy1lYXN0LTE6MTIzNDU2Nzg5MDEyOk15RGVtb1BpcGVsaW5lYClcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVBpcGVsaW5lQXJuKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHBpcGVsaW5lQXJuOiBzdHJpbmcpOiBJUGlwZWxpbmUge1xuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIFBpcGVsaW5lQmFzZSB7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgcGlwZWxpbmVOYW1lID0gU3RhY2sub2Yoc2NvcGUpLnNwbGl0QXJuKHBpcGVsaW5lQXJuLCBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfTkFNRSkucmVzb3VyY2U7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgcGlwZWxpbmVBcm4gPSBwaXBlbGluZUFybjtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEltcG9ydChzY29wZSwgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBJQU0gcm9sZSBBV1MgQ29kZVBpcGVsaW5lIHdpbGwgdXNlIHRvIHBlcmZvcm0gYWN0aW9ucyBvciBhc3N1bWUgcm9sZXMgZm9yIGFjdGlvbnMgd2l0aFxuICAgKiBhIG1vcmUgc3BlY2lmaWMgSUFNIHJvbGUuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcm9sZTogaWFtLklSb2xlO1xuXG4gIC8qKlxuICAgKiBBUk4gb2YgdGhpcyBwaXBlbGluZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBpcGVsaW5lQXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBwaXBlbGluZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBpcGVsaW5lTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgdmVyc2lvbiBvZiB0aGUgcGlwZWxpbmVcbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBpcGVsaW5lVmVyc2lvbjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBCdWNrZXQgdXNlZCB0byBzdG9yZSBvdXRwdXQgYXJ0aWZhY3RzXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgYXJ0aWZhY3RCdWNrZXQ6IHMzLklCdWNrZXQ7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfc3RhZ2VzID0gbmV3IEFycmF5PFN0YWdlPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGNyb3NzUmVnaW9uQnVja2V0c1Bhc3NlZDogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBfY3Jvc3NSZWdpb25TdXBwb3J0OiB7IFtyZWdpb246IHN0cmluZ106IENyb3NzUmVnaW9uU3VwcG9ydCB9ID0ge307XG4gIHByaXZhdGUgcmVhZG9ubHkgX2Nyb3NzQWNjb3VudFN1cHBvcnQ6IHsgW2FjY291bnQ6IHN0cmluZ106IFN0YWNrIH0gPSB7fTtcbiAgcHJpdmF0ZSByZWFkb25seSBjcm9zc0FjY291bnRLZXlzOiBib29sZWFuO1xuICBwcml2YXRlIHJlYWRvbmx5IGVuYWJsZUtleVJvdGF0aW9uPzogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSByZXVzZUNyb3NzUmVnaW9uU3VwcG9ydFN0YWNrczogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBjb2RlUGlwZWxpbmU6IENmblBpcGVsaW5lO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBQaXBlbGluZVByb3BzID0ge30pIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIHBoeXNpY2FsTmFtZTogcHJvcHMucGlwZWxpbmVOYW1lLFxuICAgIH0pO1xuXG4gICAgdmFsaWRhdGVOYW1lKCdQaXBlbGluZScsIHRoaXMucGh5c2ljYWxOYW1lKTtcblxuICAgIC8vIG9ubHkgb25lIG9mIGFydGlmYWN0QnVja2V0IGFuZCBjcm9zc1JlZ2lvblJlcGxpY2F0aW9uQnVja2V0cyBjYW4gYmUgc3VwcGxpZWRcbiAgICBpZiAocHJvcHMuYXJ0aWZhY3RCdWNrZXQgJiYgcHJvcHMuY3Jvc3NSZWdpb25SZXBsaWNhdGlvbkJ1Y2tldHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT25seSBvbmUgb2YgYXJ0aWZhY3RCdWNrZXQgYW5kIGNyb3NzUmVnaW9uUmVwbGljYXRpb25CdWNrZXRzIGNhbiBiZSBzcGVjaWZpZWQhJyk7XG4gICAgfVxuXG4gICAgLy8gQGRlcHJlY2F0ZWQodjIpOiBzd2l0Y2ggdG8gZGVmYXVsdCBmYWxzZVxuICAgIHRoaXMuY3Jvc3NBY2NvdW50S2V5cyA9IHByb3BzLmNyb3NzQWNjb3VudEtleXMgPz8gdHJ1ZTtcbiAgICB0aGlzLmVuYWJsZUtleVJvdGF0aW9uID0gcHJvcHMuZW5hYmxlS2V5Um90YXRpb247XG5cbiAgICAvLyBDcm9zcyBhY2NvdW50IGtleXMgbXVzdCBiZSBzZXQgZm9yIGtleSByb3RhdGlvbiB0byBiZSBlbmFibGVkXG4gICAgaWYgKHRoaXMuZW5hYmxlS2V5Um90YXRpb24gJiYgIXRoaXMuY3Jvc3NBY2NvdW50S2V5cykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU2V0dGluZyAnZW5hYmxlS2V5Um90YXRpb24nIHRvIHRydWUgYWxzbyByZXF1aXJlcyAnY3Jvc3NBY2NvdW50S2V5cycgdG8gYmUgZW5hYmxlZFwiKTtcbiAgICB9XG5cbiAgICB0aGlzLnJldXNlQ3Jvc3NSZWdpb25TdXBwb3J0U3RhY2tzID0gcHJvcHMucmV1c2VDcm9zc1JlZ2lvblN1cHBvcnRTdGFja3MgPz8gdHJ1ZTtcblxuICAgIC8vIElmIGEgYnVja2V0IGhhcyBiZWVuIHByb3ZpZGVkLCB1c2UgaXQgLSBvdGhlcndpc2UsIGNyZWF0ZSBhIGJ1Y2tldC5cbiAgICBsZXQgcHJvcHNCdWNrZXQgPSB0aGlzLmdldEFydGlmYWN0QnVja2V0RnJvbVByb3BzKHByb3BzKTtcblxuICAgIGlmICghcHJvcHNCdWNrZXQpIHtcbiAgICAgIGxldCBlbmNyeXB0aW9uS2V5O1xuXG4gICAgICBpZiAodGhpcy5jcm9zc0FjY291bnRLZXlzKSB7XG4gICAgICAgIGVuY3J5cHRpb25LZXkgPSBuZXcga21zLktleSh0aGlzLCAnQXJ0aWZhY3RzQnVja2V0RW5jcnlwdGlvbktleScsIHtcbiAgICAgICAgICAvLyByZW1vdmUgdGhlIGtleSAtIHRoZXJlIGlzIGEgZ3JhY2UgcGVyaW9kIG9mIGEgZmV3IGRheXMgYmVmb3JlIGl0J3MgZ29uZSBmb3IgZ29vZCxcbiAgICAgICAgICAvLyB0aGF0IHNob3VsZCBiZSBlbm91Z2ggZm9yIGFueSBlbWVyZ2VuY3kgYWNjZXNzIHRvIHRoZSBidWNrZXQgYXJ0aWZhY3RzXG4gICAgICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICAgIGVuYWJsZUtleVJvdGF0aW9uOiB0aGlzLmVuYWJsZUtleVJvdGF0aW9uLFxuICAgICAgICB9KTtcbiAgICAgICAgLy8gYWRkIGFuIGFsaWFzIHRvIG1ha2UgZmluZGluZyB0aGUga2V5IGluIHRoZSBjb25zb2xlIGVhc2llclxuICAgICAgICBuZXcga21zLkFsaWFzKHRoaXMsICdBcnRpZmFjdHNCdWNrZXRFbmNyeXB0aW9uS2V5QWxpYXMnLCB7XG4gICAgICAgICAgYWxpYXNOYW1lOiB0aGlzLmdlbmVyYXRlTmFtZUZvckRlZmF1bHRCdWNrZXRLZXlBbGlhcygpLFxuICAgICAgICAgIHRhcmdldEtleTogZW5jcnlwdGlvbktleSxcbiAgICAgICAgICByZW1vdmFsUG9saWN5OiBSZW1vdmFsUG9saWN5LkRFU1RST1ksIC8vIGRlc3Ryb3kgdGhlIGFsaWFzIGFsb25nIHdpdGggdGhlIGtleVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcHJvcHNCdWNrZXQgPSBuZXcgczMuQnVja2V0KHRoaXMsICdBcnRpZmFjdHNCdWNrZXQnLCB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IFBoeXNpY2FsTmFtZS5HRU5FUkFURV9JRl9ORUVERUQsXG4gICAgICAgIGVuY3J5cHRpb25LZXksXG4gICAgICAgIGVuY3J5cHRpb246IGVuY3J5cHRpb25LZXkgPyBzMy5CdWNrZXRFbmNyeXB0aW9uLktNUyA6IHMzLkJ1Y2tldEVuY3J5cHRpb24uS01TX01BTkFHRUQsXG4gICAgICAgIGVuZm9yY2VTU0w6IHRydWUsXG4gICAgICAgIGJsb2NrUHVibGljQWNjZXNzOiBuZXcgczMuQmxvY2tQdWJsaWNBY2Nlc3MoczMuQmxvY2tQdWJsaWNBY2Nlc3MuQkxPQ0tfQUxMKSxcbiAgICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5SRVRBSU4sXG4gICAgICB9KTtcbiAgICB9XG4gICAgdGhpcy5hcnRpZmFjdEJ1Y2tldCA9IHByb3BzQnVja2V0O1xuXG4gICAgLy8gSWYgYSByb2xlIGhhcyBiZWVuIHByb3ZpZGVkLCB1c2UgaXQgLSBvdGhlcndpc2UsIGNyZWF0ZSBhIHJvbGUuXG4gICAgdGhpcy5yb2xlID0gcHJvcHMucm9sZSB8fCBuZXcgaWFtLlJvbGUodGhpcywgJ1JvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnY29kZXBpcGVsaW5lLmFtYXpvbmF3cy5jb20nKSxcbiAgICB9KTtcblxuICAgIHRoaXMuY29kZVBpcGVsaW5lID0gbmV3IENmblBpcGVsaW5lKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIGFydGlmYWN0U3RvcmU6IExhenkuYW55KHsgcHJvZHVjZTogKCkgPT4gdGhpcy5yZW5kZXJBcnRpZmFjdFN0b3JlUHJvcGVydHkoKSB9KSxcbiAgICAgIGFydGlmYWN0U3RvcmVzOiBMYXp5LmFueSh7IHByb2R1Y2U6ICgpID0+IHRoaXMucmVuZGVyQXJ0aWZhY3RTdG9yZXNQcm9wZXJ0eSgpIH0pLFxuICAgICAgc3RhZ2VzOiBMYXp5LmFueSh7IHByb2R1Y2U6ICgpID0+IHRoaXMucmVuZGVyU3RhZ2VzKCkgfSksXG4gICAgICBkaXNhYmxlSW5ib3VuZFN0YWdlVHJhbnNpdGlvbnM6IExhenkuYW55KHsgcHJvZHVjZTogKCkgPT4gdGhpcy5yZW5kZXJEaXNhYmxlZFRyYW5zaXRpb25zKCkgfSwgeyBvbWl0RW1wdHlBcnJheTogdHJ1ZSB9KSxcbiAgICAgIHJvbGVBcm46IHRoaXMucm9sZS5yb2xlQXJuLFxuICAgICAgcmVzdGFydEV4ZWN1dGlvbk9uVXBkYXRlOiBwcm9wcyAmJiBwcm9wcy5yZXN0YXJ0RXhlY3V0aW9uT25VcGRhdGUsXG4gICAgICBuYW1lOiB0aGlzLnBoeXNpY2FsTmFtZSxcbiAgICB9KTtcblxuICAgIC8vIHRoaXMgd2lsbCBwcm9kdWNlIGEgRGVwZW5kc09uIGZvciBib3RoIHRoZSByb2xlIGFuZCB0aGUgcG9saWN5IHJlc291cmNlcy5cbiAgICB0aGlzLmNvZGVQaXBlbGluZS5ub2RlLmFkZERlcGVuZGVuY3kodGhpcy5yb2xlKTtcblxuICAgIHRoaXMuYXJ0aWZhY3RCdWNrZXQuZ3JhbnRSZWFkV3JpdGUodGhpcy5yb2xlKTtcbiAgICB0aGlzLnBpcGVsaW5lTmFtZSA9IHRoaXMuZ2V0UmVzb3VyY2VOYW1lQXR0cmlidXRlKHRoaXMuY29kZVBpcGVsaW5lLnJlZik7XG4gICAgdGhpcy5waXBlbGluZVZlcnNpb24gPSB0aGlzLmNvZGVQaXBlbGluZS5hdHRyVmVyc2lvbjtcbiAgICB0aGlzLmNyb3NzUmVnaW9uQnVja2V0c1Bhc3NlZCA9ICEhcHJvcHMuY3Jvc3NSZWdpb25SZXBsaWNhdGlvbkJ1Y2tldHM7XG5cbiAgICBmb3IgKGNvbnN0IFtyZWdpb24sIHJlcGxpY2F0aW9uQnVja2V0XSBvZiBPYmplY3QuZW50cmllcyhwcm9wcy5jcm9zc1JlZ2lvblJlcGxpY2F0aW9uQnVja2V0cyB8fCB7fSkpIHtcbiAgICAgIHRoaXMuX2Nyb3NzUmVnaW9uU3VwcG9ydFtyZWdpb25dID0ge1xuICAgICAgICByZXBsaWNhdGlvbkJ1Y2tldCxcbiAgICAgICAgc3RhY2s6IFN0YWNrLm9mKHJlcGxpY2F0aW9uQnVja2V0KSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRG9lcyBub3QgZXhwb3NlIGEgRm46OkdldEF0dCBmb3IgdGhlIEFSTiBzbyB3ZSdsbCBoYXZlIHRvIG1ha2UgaXQgb3Vyc2VsdmVzXG4gICAgdGhpcy5waXBlbGluZUFybiA9IFN0YWNrLm9mKHRoaXMpLmZvcm1hdEFybih7XG4gICAgICBzZXJ2aWNlOiAnY29kZXBpcGVsaW5lJyxcbiAgICAgIHJlc291cmNlOiB0aGlzLnBpcGVsaW5lTmFtZSxcbiAgICB9KTtcblxuICAgIGZvciAoY29uc3Qgc3RhZ2Ugb2YgcHJvcHMuc3RhZ2VzIHx8IFtdKSB7XG4gICAgICB0aGlzLmFkZFN0YWdlKHN0YWdlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBTdGFnZSwgYW5kIGFkZHMgaXQgdG8gdGhpcyBQaXBlbGluZS5cbiAgICpcbiAgICogQHBhcmFtIHByb3BzIHRoZSBjcmVhdGlvbiBwcm9wZXJ0aWVzIG9mIHRoZSBuZXcgU3RhZ2VcbiAgICogQHJldHVybnMgdGhlIG5ld2x5IGNyZWF0ZWQgU3RhZ2VcbiAgICovXG4gIHB1YmxpYyBhZGRTdGFnZShwcm9wczogU3RhZ2VPcHRpb25zKTogSVN0YWdlIHtcbiAgICAvLyBjaGVjayBmb3IgZHVwbGljYXRlIFN0YWdlcyBhbmQgbmFtZXNcbiAgICBpZiAodGhpcy5fc3RhZ2VzLmZpbmQocyA9PiBzLnN0YWdlTmFtZSA9PT0gcHJvcHMuc3RhZ2VOYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdGFnZSB3aXRoIGR1cGxpY2F0ZSBuYW1lICcke3Byb3BzLnN0YWdlTmFtZX0nIGFkZGVkIHRvIHRoZSBQaXBlbGluZWApO1xuICAgIH1cblxuICAgIGNvbnN0IHN0YWdlID0gbmV3IFN0YWdlKHByb3BzLCB0aGlzKTtcblxuICAgIGNvbnN0IGluZGV4ID0gcHJvcHMucGxhY2VtZW50XG4gICAgICA/IHRoaXMuY2FsY3VsYXRlSW5zZXJ0SW5kZXhGcm9tUGxhY2VtZW50KHByb3BzLnBsYWNlbWVudClcbiAgICAgIDogdGhpcy5zdGFnZUNvdW50O1xuXG4gICAgdGhpcy5fc3RhZ2VzLnNwbGljZShpbmRleCwgMCwgc3RhZ2UpO1xuXG4gICAgcmV0dXJuIHN0YWdlO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBzdGF0ZW1lbnQgdG8gdGhlIHBpcGVsaW5lIHJvbGUuXG4gICAqL1xuICBwdWJsaWMgYWRkVG9Sb2xlUG9saWN5KHN0YXRlbWVudDogaWFtLlBvbGljeVN0YXRlbWVudCkge1xuICAgIHRoaXMucm9sZS5hZGRUb1ByaW5jaXBhbFBvbGljeShzdGF0ZW1lbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbnVtYmVyIG9mIFN0YWdlcyBpbiB0aGlzIFBpcGVsaW5lLlxuICAgKi9cbiAgcHVibGljIGdldCBzdGFnZUNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YWdlcy5sZW5ndGg7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc3RhZ2VzIHRoYXQgY29tcHJpc2UgdGhlIHBpcGVsaW5lLlxuICAgKlxuICAgKiAqKk5vdGUqKjogdGhlIHJldHVybmVkIGFycmF5IGlzIGEgZGVmZW5zaXZlIGNvcHksXG4gICAqIHNvIGFkZGluZyBlbGVtZW50cyB0byBpdCBoYXMgbm8gZWZmZWN0LlxuICAgKiBJbnN0ZWFkLCB1c2UgdGhlIHtAbGluayBhZGRTdGFnZX0gbWV0aG9kIGlmIHlvdSB3YW50IHRvIGFkZCBtb3JlIHN0YWdlc1xuICAgKiB0byB0aGUgcGlwZWxpbmUuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN0YWdlcygpOiBJU3RhZ2VbXSB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YWdlcy5zbGljZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFjY2VzcyBvbmUgb2YgdGhlIHBpcGVsaW5lJ3Mgc3RhZ2VzIGJ5IHN0YWdlIG5hbWVcbiAgICovXG4gIHB1YmxpYyBzdGFnZShzdGFnZU5hbWU6IHN0cmluZyk6IElTdGFnZSB7XG4gICAgZm9yIChjb25zdCBzdGFnZSBvZiB0aGlzLl9zdGFnZXMpIHtcbiAgICAgIGlmIChzdGFnZS5zdGFnZU5hbWUgPT09IHN0YWdlTmFtZSkge1xuICAgICAgICByZXR1cm4gc3RhZ2U7XG4gICAgICB9XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgUGlwZWxpbmUgZG9lcyBub3QgY29udGFpbiBhIHN0YWdlIG5hbWVkICcke3N0YWdlTmFtZX0nLiBBdmFpbGFibGUgc3RhZ2VzOiAke3RoaXMuX3N0YWdlcy5tYXAocyA9PiBzLnN0YWdlTmFtZSkuam9pbignLCAnKX1gKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBvZiB0aGUge0BsaW5rIENyb3NzUmVnaW9uU3VwcG9ydFN0YWNrfXMgdGhhdCB3ZXJlIGdlbmVyYXRlZCBhdXRvbWF0aWNhbGx5XG4gICAqIHdoZW4gZGVhbGluZyB3aXRoIEFjdGlvbnMgdGhhdCByZXNpZGUgaW4gYSBkaWZmZXJlbnQgcmVnaW9uIHRoYW4gdGhlIFBpcGVsaW5lIGl0c2VsZi5cbiAgICpcbiAgICovXG4gIHB1YmxpYyBnZXQgY3Jvc3NSZWdpb25TdXBwb3J0KCk6IHsgW3JlZ2lvbjogc3RyaW5nXTogQ3Jvc3NSZWdpb25TdXBwb3J0IH0ge1xuICAgIGNvbnN0IHJldDogeyBbcmVnaW9uOiBzdHJpbmddOiBDcm9zc1JlZ2lvblN1cHBvcnQgfSA9IHt9O1xuICAgIE9iamVjdC5rZXlzKHRoaXMuX2Nyb3NzUmVnaW9uU3VwcG9ydCkuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICByZXRba2V5XSA9IHRoaXMuX2Nyb3NzUmVnaW9uU3VwcG9ydFtrZXldO1xuICAgIH0pO1xuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHB1YmxpYyBfYXR0YWNoQWN0aW9uVG9QaXBlbGluZShzdGFnZTogU3RhZ2UsIGFjdGlvbjogSUFjdGlvbiwgYWN0aW9uU2NvcGU6IENvbnN0cnVjdCk6IEZ1bGxBY3Rpb25EZXNjcmlwdG9yIHtcbiAgICBjb25zdCByaWNoQWN0aW9uID0gbmV3IFJpY2hBY3Rpb24oYWN0aW9uLCB0aGlzKTtcblxuICAgIC8vIGhhbmRsZSBjcm9zcy1yZWdpb24gYWN0aW9ucyBoZXJlXG4gICAgY29uc3QgY3Jvc3NSZWdpb25JbmZvID0gdGhpcy5lbnN1cmVSZXBsaWNhdGlvblJlc291cmNlc0V4aXN0Rm9yKHJpY2hBY3Rpb24pO1xuXG4gICAgLy8gZ2V0IHRoZSByb2xlIGZvciB0aGUgZ2l2ZW4gYWN0aW9uLCBoYW5kbGluZyBpZiBpdCdzIGNyb3NzLWFjY291bnRcbiAgICBjb25zdCBhY3Rpb25Sb2xlID0gdGhpcy5nZXRSb2xlRm9yQWN0aW9uKHN0YWdlLCByaWNoQWN0aW9uLCBhY3Rpb25TY29wZSk7XG5cbiAgICAvLyAvLyBDb2RlUGlwZWxpbmUgVmFyaWFibGVzXG4gICAgdmFsaWRhdGVOYW1lc3BhY2VOYW1lKHJpY2hBY3Rpb24uYWN0aW9uUHJvcGVydGllcy52YXJpYWJsZXNOYW1lc3BhY2UpO1xuXG4gICAgLy8gYmluZCB0aGUgQWN0aW9uICh0eXBlIGg0eClcbiAgICBjb25zdCBhY3Rpb25Db25maWcgPSByaWNoQWN0aW9uLmJpbmQoYWN0aW9uU2NvcGUgYXMgQ29yZUNvbnN0cnVjdCwgc3RhZ2UsIHtcbiAgICAgIHJvbGU6IGFjdGlvblJvbGUgPyBhY3Rpb25Sb2xlIDogdGhpcy5yb2xlLFxuICAgICAgYnVja2V0OiBjcm9zc1JlZ2lvbkluZm8uYXJ0aWZhY3RCdWNrZXQsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gbmV3IEZ1bGxBY3Rpb25EZXNjcmlwdG9yKHtcbiAgICAgIC8vIG11c3QgYmUgJ2FjdGlvbicsIG5vdCAncmljaEFjdGlvbicsXG4gICAgICAvLyBhcyB0aG9zZSBhcmUgcmV0dXJuZWQgYnkgdGhlIElTdGFnZS5hY3Rpb25zIHByb3BlcnR5LFxuICAgICAgLy8gYW5kIGl0J3MgaW1wb3J0YW50IGN1c3RvbWVycyBvZiBQaXBlbGluZSBnZXQgdGhlIHNhbWUgaW5zdGFuY2VcbiAgICAgIC8vIGJhY2sgYXMgdGhleSBhZGRlZCB0byB0aGUgcGlwZWxpbmVcbiAgICAgIGFjdGlvbixcbiAgICAgIGFjdGlvbkNvbmZpZyxcbiAgICAgIGFjdGlvblJvbGUsXG4gICAgICBhY3Rpb25SZWdpb246IGNyb3NzUmVnaW9uSW5mby5yZWdpb24sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhlIHBpcGVsaW5lIHN0cnVjdHVyZVxuICAgKlxuICAgKiBWYWxpZGF0aW9uIGhhcHBlbnMgYWNjb3JkaW5nIHRvIHRoZSBydWxlcyBkb2N1bWVudGVkIGF0XG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jb2RlcGlwZWxpbmUvbGF0ZXN0L3VzZXJndWlkZS9yZWZlcmVuY2UtcGlwZWxpbmUtc3RydWN0dXJlLmh0bWwjcGlwZWxpbmUtcmVxdWlyZW1lbnRzXG4gICAqIEBvdmVycmlkZVxuICAgKi9cbiAgcHJvdGVjdGVkIHZhbGlkYXRlKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gW1xuICAgICAgLi4udGhpcy52YWxpZGF0ZVNvdXJjZUFjdGlvbkxvY2F0aW9ucygpLFxuICAgICAgLi4udGhpcy52YWxpZGF0ZUhhc1N0YWdlcygpLFxuICAgICAgLi4udGhpcy52YWxpZGF0ZVN0YWdlcygpLFxuICAgICAgLi4udGhpcy52YWxpZGF0ZUFydGlmYWN0cygpLFxuICAgIF07XG4gIH1cblxuICBwcml2YXRlIGVuc3VyZVJlcGxpY2F0aW9uUmVzb3VyY2VzRXhpc3RGb3IoYWN0aW9uOiBSaWNoQWN0aW9uKTogQ3Jvc3NSZWdpb25JbmZvIHtcbiAgICBpZiAoIWFjdGlvbi5pc0Nyb3NzUmVnaW9uKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhcnRpZmFjdEJ1Y2tldDogdGhpcy5hcnRpZmFjdEJ1Y2tldCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gVGhlIGFjdGlvbiBoYXMgYSBzcGVjaWZpYyByZWdpb24sXG4gICAgLy8gcmVxdWlyZSB0aGUgcGlwZWxpbmUgdG8gaGF2ZSBhIGtub3duIHJlZ2lvbiBhcyB3ZWxsLlxuICAgIHRoaXMucmVxdWlyZVJlZ2lvbigpO1xuXG4gICAgLy8gc291cmNlIGFjdGlvbnMgaGF2ZSB0byBiZSBpbiB0aGUgc2FtZSByZWdpb24gYXMgdGhlIHBpcGVsaW5lXG4gICAgaWYgKGFjdGlvbi5hY3Rpb25Qcm9wZXJ0aWVzLmNhdGVnb3J5ID09PSBBY3Rpb25DYXRlZ29yeS5TT1VSQ0UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU291cmNlIGFjdGlvbiAnJHthY3Rpb24uYWN0aW9uUHJvcGVydGllcy5hY3Rpb25OYW1lfScgbXVzdCBiZSBpbiB0aGUgc2FtZSByZWdpb24gYXMgdGhlIHBpcGVsaW5lYCk7XG4gICAgfVxuXG4gICAgLy8gY2hlY2sgd2hldGhlciB3ZSBhbHJlYWR5IGhhdmUgYSBidWNrZXQgaW4gdGhhdCByZWdpb24sXG4gICAgLy8gZWl0aGVyIHBhc3NlZCBmcm9tIHRoZSBvdXRzaWRlIG9yIHByZXZpb3VzbHkgY3JlYXRlZFxuICAgIGNvbnN0IGNyb3NzUmVnaW9uU3VwcG9ydCA9IHRoaXMub2J0YWluQ3Jvc3NSZWdpb25TdXBwb3J0Rm9yKGFjdGlvbik7XG5cbiAgICAvLyB0aGUgc3RhY2sgY29udGFpbmluZyB0aGUgcmVwbGljYXRpb24gYnVja2V0IG11c3QgYmUgZGVwbG95ZWQgYmVmb3JlIHRoZSBwaXBlbGluZVxuICAgIFN0YWNrLm9mKHRoaXMpLmFkZERlcGVuZGVuY3koY3Jvc3NSZWdpb25TdXBwb3J0LnN0YWNrKTtcbiAgICAvLyBUaGUgUGlwZWxpbmUgcm9sZSBtdXN0IGJlIGFibGUgdG8gcmVwbGljYXRlIHRvIHRoYXQgYnVja2V0XG4gICAgY3Jvc3NSZWdpb25TdXBwb3J0LnJlcGxpY2F0aW9uQnVja2V0LmdyYW50UmVhZFdyaXRlKHRoaXMucm9sZSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgYXJ0aWZhY3RCdWNrZXQ6IGNyb3NzUmVnaW9uU3VwcG9ydC5yZXBsaWNhdGlvbkJ1Y2tldCxcbiAgICAgIHJlZ2lvbjogYWN0aW9uLmVmZmVjdGl2ZVJlZ2lvbixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBvciBjcmVhdGUgdGhlIGNyb3NzLXJlZ2lvbiBzdXBwb3J0IGNvbnN0cnVjdCBmb3IgdGhlIGdpdmVuIGFjdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBvYnRhaW5Dcm9zc1JlZ2lvblN1cHBvcnRGb3IoYWN0aW9uOiBSaWNoQWN0aW9uKSB7XG4gICAgLy8gdGhpcyBtZXRob2QgaXMgbmV2ZXIgY2FsbGVkIGZvciBub24gY3Jvc3MtcmVnaW9uIGFjdGlvbnNcbiAgICBjb25zdCBhY3Rpb25SZWdpb24gPSBhY3Rpb24uZWZmZWN0aXZlUmVnaW9uITtcbiAgICBsZXQgY3Jvc3NSZWdpb25TdXBwb3J0ID0gdGhpcy5fY3Jvc3NSZWdpb25TdXBwb3J0W2FjdGlvblJlZ2lvbl07XG4gICAgaWYgKCFjcm9zc1JlZ2lvblN1cHBvcnQpIHtcbiAgICAgIC8vIHdlIG5lZWQgdG8gY3JlYXRlIHNjYWZmb2xkaW5nIHJlc291cmNlcyBmb3IgdGhpcyByZWdpb25cbiAgICAgIGNvbnN0IG90aGVyU3RhY2sgPSBhY3Rpb24ucmVzb3VyY2VTdGFjaztcbiAgICAgIGNyb3NzUmVnaW9uU3VwcG9ydCA9IHRoaXMuY3JlYXRlU3VwcG9ydFJlc291cmNlc0ZvclJlZ2lvbihvdGhlclN0YWNrLCBhY3Rpb25SZWdpb24pO1xuICAgICAgdGhpcy5fY3Jvc3NSZWdpb25TdXBwb3J0W2FjdGlvblJlZ2lvbl0gPSBjcm9zc1JlZ2lvblN1cHBvcnQ7XG4gICAgfVxuICAgIHJldHVybiBjcm9zc1JlZ2lvblN1cHBvcnQ7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVN1cHBvcnRSZXNvdXJjZXNGb3JSZWdpb24ob3RoZXJTdGFjazogU3RhY2sgfCB1bmRlZmluZWQsIGFjdGlvblJlZ2lvbjogc3RyaW5nKTogQ3Jvc3NSZWdpb25TdXBwb3J0IHtcbiAgICAvLyBpZiB3ZSBoYXZlIGEgc3RhY2sgZnJvbSB0aGUgcmVzb3VyY2UgcGFzc2VkIC0gdXNlIHRoYXQhXG4gICAgaWYgKG90aGVyU3RhY2spIHtcbiAgICAgIC8vIGNoZWNrIGlmIHRoZSBzdGFjayBkb2Vzbid0IGhhdmUgdGhpcyBtYWdpYyBjb25zdHJ1Y3QgYWxyZWFkeVxuICAgICAgY29uc3QgaWQgPSBgQ3Jvc3NSZWdpb25SZXBsaWNhdGlvblN1cHBvcnQtZDgyM2YxZDgtYTk5MC00ZTVjLWJlMTgtNGFjNjk4NTMyZTY1LSR7YWN0aW9uUmVnaW9ufWA7XG4gICAgICBsZXQgY3Jvc3NSZWdpb25TdXBwb3J0Q29uc3RydWN0ID0gb3RoZXJTdGFjay5ub2RlLnRyeUZpbmRDaGlsZChpZCkgYXMgQ3Jvc3NSZWdpb25TdXBwb3J0Q29uc3RydWN0O1xuICAgICAgaWYgKCFjcm9zc1JlZ2lvblN1cHBvcnRDb25zdHJ1Y3QpIHtcbiAgICAgICAgY3Jvc3NSZWdpb25TdXBwb3J0Q29uc3RydWN0ID0gbmV3IENyb3NzUmVnaW9uU3VwcG9ydENvbnN0cnVjdChvdGhlclN0YWNrLCBpZCwge1xuICAgICAgICAgIGNyZWF0ZUttc0tleTogdGhpcy5jcm9zc0FjY291bnRLZXlzLFxuICAgICAgICAgIGVuYWJsZUtleVJvdGF0aW9uOiB0aGlzLmVuYWJsZUtleVJvdGF0aW9uLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcmVwbGljYXRpb25CdWNrZXQ6IGNyb3NzUmVnaW9uU3VwcG9ydENvbnN0cnVjdC5yZXBsaWNhdGlvbkJ1Y2tldCxcbiAgICAgICAgc3RhY2s6IG90aGVyU3RhY2ssXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIG90aGVyd2lzZSAtIGNyZWF0ZSBhIHN0YWNrIHdpdGggdGhlIHJlc291cmNlcyBuZWVkZWQgZm9yIHJlcGxpY2F0aW9uIGFjcm9zcyByZWdpb25zXG4gICAgY29uc3QgcGlwZWxpbmVTdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIGNvbnN0IHBpcGVsaW5lQWNjb3VudCA9IHBpcGVsaW5lU3RhY2suYWNjb3VudDtcbiAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKHBpcGVsaW5lQWNjb3VudCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIllvdSBuZWVkIHRvIHNwZWNpZnkgYW4gZXhwbGljaXQgYWNjb3VudCB3aGVuIHVzaW5nIENvZGVQaXBlbGluZSdzIGNyb3NzLXJlZ2lvbiBzdXBwb3J0XCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGFwcCA9IHRoaXMuc3VwcG9ydFNjb3BlKCk7XG4gICAgY29uc3Qgc3VwcG9ydFN0YWNrSWQgPSBgY3Jvc3MtcmVnaW9uLXN0YWNrLSR7dGhpcy5yZXVzZUNyb3NzUmVnaW9uU3VwcG9ydFN0YWNrcyA/IHBpcGVsaW5lQWNjb3VudCA6IHBpcGVsaW5lU3RhY2suc3RhY2tOYW1lfToke2FjdGlvblJlZ2lvbn1gO1xuICAgIGxldCBzdXBwb3J0U3RhY2sgPSBhcHAubm9kZS50cnlGaW5kQ2hpbGQoc3VwcG9ydFN0YWNrSWQpIGFzIENyb3NzUmVnaW9uU3VwcG9ydFN0YWNrO1xuICAgIGlmICghc3VwcG9ydFN0YWNrKSB7XG4gICAgICBzdXBwb3J0U3RhY2sgPSBuZXcgQ3Jvc3NSZWdpb25TdXBwb3J0U3RhY2soYXBwLCBzdXBwb3J0U3RhY2tJZCwge1xuICAgICAgICBwaXBlbGluZVN0YWNrTmFtZTogcGlwZWxpbmVTdGFjay5zdGFja05hbWUsXG4gICAgICAgIHJlZ2lvbjogYWN0aW9uUmVnaW9uLFxuICAgICAgICBhY2NvdW50OiBwaXBlbGluZUFjY291bnQsXG4gICAgICAgIHN5bnRoZXNpemVyOiB0aGlzLmdldENyb3NzUmVnaW9uU3VwcG9ydFN5bnRoZXNpemVyKCksXG4gICAgICAgIGNyZWF0ZUttc0tleTogdGhpcy5jcm9zc0FjY291bnRLZXlzLFxuICAgICAgICBlbmFibGVLZXlSb3RhdGlvbjogdGhpcy5lbmFibGVLZXlSb3RhdGlvbixcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBzdGFjazogc3VwcG9ydFN0YWNrLFxuICAgICAgcmVwbGljYXRpb25CdWNrZXQ6IHN1cHBvcnRTdGFjay5yZXBsaWNhdGlvbkJ1Y2tldCxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDcm9zc1JlZ2lvblN1cHBvcnRTeW50aGVzaXplcigpOiBJU3RhY2tTeW50aGVzaXplciB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHRoaXMuc3RhY2suc3ludGhlc2l6ZXIgaW5zdGFuY2VvZiBEZWZhdWx0U3RhY2tTeW50aGVzaXplcikge1xuICAgICAgLy8gaWYgd2UgaGF2ZSB0aGUgbmV3IHN5bnRoZXNpemVyLFxuICAgICAgLy8gd2UgbmVlZCBhIGJvb3RzdHJhcGxlc3MgY29weSBvZiBpdCxcbiAgICAgIC8vIGJlY2F1c2Ugd2UgZG9uJ3Qgd2FudCB0byByZXF1aXJlIGJvb3RzdHJhcHBpbmcgdGhlIGVudmlyb25tZW50XG4gICAgICAvLyBvZiB0aGUgcGlwZWxpbmUgYWNjb3VudCBpbiB0aGlzIHJlcGxpY2F0aW9uIHJlZ2lvblxuICAgICAgcmV0dXJuIG5ldyBCb290c3RyYXBsZXNzU3ludGhlc2l6ZXIoe1xuICAgICAgICBkZXBsb3lSb2xlQXJuOiB0aGlzLnN0YWNrLnN5bnRoZXNpemVyLmRlcGxveVJvbGVBcm4sXG4gICAgICAgIGNsb3VkRm9ybWF0aW9uRXhlY3V0aW9uUm9sZUFybjogdGhpcy5zdGFjay5zeW50aGVzaXplci5jbG91ZEZvcm1hdGlvbkV4ZWN1dGlvblJvbGVBcm4sXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gYW55IG90aGVyIHN5bnRoZXNpemVyOiBqdXN0IHJldHVybiB1bmRlZmluZWRcbiAgICAgIC8vIChpZS4sIHVzZSB0aGUgZGVmYXVsdCBiYXNlZCBvbiB0aGUgY29udGV4dCBzZXR0aW5ncylcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZU5hbWVGb3JEZWZhdWx0QnVja2V0S2V5QWxpYXMoKTogc3RyaW5nIHtcbiAgICBjb25zdCBwcmVmaXggPSAnYWxpYXMvY29kZXBpcGVsaW5lLSc7XG4gICAgY29uc3QgbWF4QWxpYXNMZW5ndGggPSAyNTY7XG4gICAgY29uc3QgdW5pcXVlSWQgPSBOYW1lcy51bmlxdWVJZCh0aGlzKTtcbiAgICAvLyB0YWtlIHRoZSBsYXN0IDI1NiAtIChwcmVmaXggbGVuZ3RoKSBjaGFyYWN0ZXJzIG9mIHVuaXF1ZUlkXG4gICAgY29uc3Qgc3RhcnRJbmRleCA9IE1hdGgubWF4KDAsIHVuaXF1ZUlkLmxlbmd0aCAtIChtYXhBbGlhc0xlbmd0aCAtIHByZWZpeC5sZW5ndGgpKTtcbiAgICByZXR1cm4gcHJlZml4ICsgdW5pcXVlSWQuc3Vic3RyaW5nKHN0YXJ0SW5kZXgpLnRvTG93ZXJDYXNlKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgcm9sZSB1c2VkIGZvciB0aGlzIGFjdGlvbixcbiAgICogaW5jbHVkaW5nIGhhbmRsaW5nIHRoZSBjYXNlIHdoZW4gdGhlIGFjdGlvbiBpcyBzdXBwb3NlZCB0byBiZSBjcm9zcy1hY2NvdW50LlxuICAgKlxuICAgKiBAcGFyYW0gc3RhZ2UgdGhlIHN0YWdlIHRoZSBhY3Rpb24gYmVsb25ncyB0b1xuICAgKiBAcGFyYW0gYWN0aW9uIHRoZSBhY3Rpb24gdG8gcmV0dXJuL2NyZWF0ZSBhIHJvbGUgZm9yXG4gICAqIEBwYXJhbSBhY3Rpb25TY29wZSB0aGUgc2NvcGUsIHVuaXF1ZSB0byB0aGUgYWN0aW9uLCB0byBjcmVhdGUgbmV3IHJlc291cmNlcyBpblxuICAgKi9cbiAgcHJpdmF0ZSBnZXRSb2xlRm9yQWN0aW9uKHN0YWdlOiBTdGFnZSwgYWN0aW9uOiBSaWNoQWN0aW9uLCBhY3Rpb25TY29wZTogQ29uc3RydWN0KTogaWFtLklSb2xlIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBwaXBlbGluZVN0YWNrID0gU3RhY2sub2YodGhpcyk7XG5cbiAgICBsZXQgYWN0aW9uUm9sZSA9IHRoaXMuZ2V0Um9sZUZyb21BY3Rpb25Qcm9wc09yR2VuZXJhdGVJZkNyb3NzQWNjb3VudChzdGFnZSwgYWN0aW9uKTtcblxuICAgIGlmICghYWN0aW9uUm9sZSAmJiB0aGlzLmlzQXdzT3duZWQoYWN0aW9uKSkge1xuICAgICAgLy8gZ2VuZXJhdGUgYSBSb2xlIGZvciB0aGlzIHNwZWNpZmljIEFjdGlvblxuICAgICAgYWN0aW9uUm9sZSA9IG5ldyBpYW0uUm9sZShhY3Rpb25TY29wZSwgJ0NvZGVQaXBlbGluZUFjdGlvblJvbGUnLCB7XG4gICAgICAgIGFzc3VtZWRCeTogbmV3IGlhbS5BY2NvdW50UHJpbmNpcGFsKHBpcGVsaW5lU3RhY2suYWNjb3VudCksXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyB0aGUgcGlwZWxpbmUgcm9sZSBuZWVkcyBhc3N1bWVSb2xlIHBlcm1pc3Npb25zIHRvIHRoZSBhY3Rpb24gcm9sZVxuICAgIGNvbnN0IGdyYW50ID0gYWN0aW9uUm9sZT8uZ3JhbnRBc3N1bWVSb2xlKHRoaXMucm9sZSk7XG4gICAgZ3JhbnQ/LmFwcGx5QmVmb3JlKHRoaXMuY29kZVBpcGVsaW5lKTtcbiAgICByZXR1cm4gYWN0aW9uUm9sZTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0Um9sZUZyb21BY3Rpb25Qcm9wc09yR2VuZXJhdGVJZkNyb3NzQWNjb3VudChzdGFnZTogU3RhZ2UsIGFjdGlvbjogUmljaEFjdGlvbik6IGlhbS5JUm9sZSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgcGlwZWxpbmVTdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgLy8gaWYgd2UgaGF2ZSBhIGNyb3NzLWFjY291bnQgYWN0aW9uLCB0aGUgcGlwZWxpbmUncyBidWNrZXQgbXVzdCBoYXZlIGEgS01TIGtleVxuICAgIC8vIChvdGhlcndpc2Ugd2UgY2FuJ3QgY29uZmlndXJlIGNyb3NzLWFjY291bnQgdHJ1c3QgcG9saWNpZXMpXG4gICAgaWYgKGFjdGlvbi5pc0Nyb3NzQWNjb3VudCkge1xuICAgICAgY29uc3QgYXJ0aWZhY3RCdWNrZXQgPSB0aGlzLmVuc3VyZVJlcGxpY2F0aW9uUmVzb3VyY2VzRXhpc3RGb3IoYWN0aW9uKS5hcnRpZmFjdEJ1Y2tldDtcbiAgICAgIGlmICghYXJ0aWZhY3RCdWNrZXQuZW5jcnlwdGlvbktleSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEFydGlmYWN0IEJ1Y2tldCBtdXN0IGhhdmUgYSBLTVMgS2V5IHRvIGFkZCBjcm9zcy1hY2NvdW50IGFjdGlvbiAnJHthY3Rpb24uYWN0aW9uUHJvcGVydGllcy5hY3Rpb25OYW1lfScgYCArXG4gICAgICAgICAgYChwaXBlbGluZSBhY2NvdW50OiAnJHtyZW5kZXJFbnZEaW1lbnNpb24odGhpcy5lbnYuYWNjb3VudCl9JywgYWN0aW9uIGFjY291bnQ6ICcke3JlbmRlckVudkRpbWVuc2lvbihhY3Rpb24uZWZmZWN0aXZlQWNjb3VudCl9JykuIGAgK1xuICAgICAgICAgICdDcmVhdGUgUGlwZWxpbmUgd2l0aCBcXCdjcm9zc0FjY291bnRLZXlzOiB0cnVlXFwnIChvciBwYXNzIGFuIGV4aXN0aW5nIEJ1Y2tldCB3aXRoIGEga2V5KScsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gaWYgYSBSb2xlIGhhcyBiZWVuIHBhc3NlZCBleHBsaWNpdGx5LCBhbHdheXMgdXNlIGl0XG4gICAgLy8gKGV2ZW4gaWYgdGhlIGJhY2tpbmcgcmVzb3VyY2UgaXMgZnJvbSBhIGRpZmZlcmVudCBhY2NvdW50IC1cbiAgICAvLyB0aGlzIGlzIGhvdyB0aGUgdXNlciBjYW4gb3ZlcnJpZGUgb3VyIGRlZmF1bHQgc3VwcG9ydCBsb2dpYylcbiAgICBpZiAoYWN0aW9uLmFjdGlvblByb3BlcnRpZXMucm9sZSkge1xuICAgICAgaWYgKHRoaXMuaXNBd3NPd25lZChhY3Rpb24pKSB7XG4gICAgICAgIC8vIHRoZSByb2xlIGhhcyB0byBiZSBkZXBsb3llZCBiZWZvcmUgdGhlIHBpcGVsaW5lXG4gICAgICAgIC8vIChvdXIgbWFnaWNhbCBjcm9zcy1zdGFjayBkZXBlbmRlbmNpZXMgd2lsbCBub3Qgd29yayxcbiAgICAgICAgLy8gYmVjYXVzZSB0aGUgcm9sZSBtaWdodCBiZSBmcm9tIGEgZGlmZmVyZW50IGVudmlyb25tZW50KSxcbiAgICAgICAgLy8gYnV0IF9vbmx5XyBpZiBpdCdzIGEgbmV3IFJvbGUgLVxuICAgICAgICAvLyBhbiBpbXBvcnRlZCBSb2xlIHNob3VsZCBub3QgYWRkIHRoZSBkZXBlbmRlbmN5XG4gICAgICAgIGlmIChhY3Rpb24uYWN0aW9uUHJvcGVydGllcy5yb2xlIGluc3RhbmNlb2YgaWFtLlJvbGUpIHtcbiAgICAgICAgICBjb25zdCByb2xlU3RhY2sgPSBTdGFjay5vZihhY3Rpb24uYWN0aW9uUHJvcGVydGllcy5yb2xlKTtcbiAgICAgICAgICBwaXBlbGluZVN0YWNrLmFkZERlcGVuZGVuY3kocm9sZVN0YWNrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhY3Rpb24uYWN0aW9uUHJvcGVydGllcy5yb2xlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gLi4uZXhjZXB0IGlmIHRoZSBBY3Rpb24gaXMgbm90IG93bmVkIGJ5ICdBV1MnLFxuICAgICAgICAvLyBhcyB0aGF0IHdvdWxkIGJlIHJlamVjdGVkIGJ5IENvZGVQaXBlbGluZSBhdCBkZXBsb3kgdGltZVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTcGVjaWZ5aW5nIGEgUm9sZSBpcyBub3Qgc3VwcG9ydGVkIGZvciBhY3Rpb25zIHdpdGggYW4gb3duZXIgZGlmZmVyZW50IHRoYW4gJ0FXUycgLSBcIiArXG4gICAgICAgICAgYGdvdCAnJHthY3Rpb24uYWN0aW9uUHJvcGVydGllcy5vd25lcn0nIChBY3Rpb246ICcke2FjdGlvbi5hY3Rpb25Qcm9wZXJ0aWVzLmFjdGlvbk5hbWV9JyBpbiBTdGFnZTogJyR7c3RhZ2Uuc3RhZ2VOYW1lfScpYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gaWYgd2UgZG9uJ3QgaGF2ZSBhIFJvbGUgcGFzc2VkLFxuICAgIC8vIGFuZCB0aGUgYWN0aW9uIGlzIGNyb3NzLWFjY291bnQsXG4gICAgLy8gZ2VuZXJhdGUgYSBSb2xlIGluIHRoYXQgb3RoZXIgYWNjb3VudCBzdGFja1xuICAgIGNvbnN0IG90aGVyQWNjb3VudFN0YWNrID0gdGhpcy5nZXRPdGhlclN0YWNrSWZBY3Rpb25Jc0Nyb3NzQWNjb3VudChhY3Rpb24pO1xuICAgIGlmICghb3RoZXJBY2NvdW50U3RhY2spIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8gZ2VuZXJhdGUgYSByb2xlIGluIHRoZSBvdGhlciBzdGFjaywgdGhhdCB0aGUgUGlwZWxpbmUgd2lsbCBhc3N1bWUgZm9yIGV4ZWN1dGluZyB0aGlzIGFjdGlvblxuICAgIGNvbnN0IHJldCA9IG5ldyBpYW0uUm9sZShvdGhlckFjY291bnRTdGFjayxcbiAgICAgIGAke05hbWVzLnVuaXF1ZUlkKHRoaXMpfS0ke3N0YWdlLnN0YWdlTmFtZX0tJHthY3Rpb24uYWN0aW9uUHJvcGVydGllcy5hY3Rpb25OYW1lfS1BY3Rpb25Sb2xlYCwge1xuICAgICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uQWNjb3VudFByaW5jaXBhbChwaXBlbGluZVN0YWNrLmFjY291bnQpLFxuICAgICAgICByb2xlTmFtZTogUGh5c2ljYWxOYW1lLkdFTkVSQVRFX0lGX05FRURFRCxcbiAgICAgIH0pO1xuICAgIC8vIHRoZSBvdGhlciBzdGFjayB3aXRoIHRoZSByb2xlIGhhcyB0byBiZSBkZXBsb3llZCBiZWZvcmUgdGhlIHBpcGVsaW5lIHN0YWNrXG4gICAgLy8gKENvZGVQaXBlbGluZSB2ZXJpZmllcyB5b3UgY2FuIGFzc3VtZSB0aGUgYWN0aW9uIFJvbGUgb24gY3JlYXRpb24pXG4gICAgcGlwZWxpbmVTdGFjay5hZGREZXBlbmRlbmN5KG90aGVyQWNjb3VudFN0YWNrKTtcblxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgU3RhY2sgdGhpcyBBY3Rpb24gYmVsb25ncyB0byBpZiB0aGlzIGlzIGEgY3Jvc3MtYWNjb3VudCBBY3Rpb24uXG4gICAqIElmIHRoaXMgQWN0aW9uIGlzIG5vdCBjcm9zcy1hY2NvdW50IChpLmUuLCBpdCBsaXZlcyBpbiB0aGUgc2FtZSBhY2NvdW50IGFzIHRoZSBQaXBlbGluZSksXG4gICAqIGl0IHJldHVybnMgdW5kZWZpbmVkLlxuICAgKlxuICAgKiBAcGFyYW0gYWN0aW9uIHRoZSBBY3Rpb24gdG8gcmV0dXJuIHRoZSBTdGFjayBmb3JcbiAgICovXG4gIHByaXZhdGUgZ2V0T3RoZXJTdGFja0lmQWN0aW9uSXNDcm9zc0FjY291bnQoYWN0aW9uOiBJQWN0aW9uKTogU3RhY2sgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHRhcmdldEFjY291bnQgPSBhY3Rpb24uYWN0aW9uUHJvcGVydGllcy5yZXNvdXJjZVxuICAgICAgPyBhY3Rpb24uYWN0aW9uUHJvcGVydGllcy5yZXNvdXJjZS5lbnYuYWNjb3VudFxuICAgICAgOiBhY3Rpb24uYWN0aW9uUHJvcGVydGllcy5hY2NvdW50O1xuXG4gICAgaWYgKHRhcmdldEFjY291bnQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgLy8gaWYgdGhlIGFjY291bnQgb2YgdGhlIEFjdGlvbiBpcyBub3Qgc3BlY2lmaWVkLFxuICAgICAgLy8gdGhlbiBpdCBkZWZhdWx0cyB0byB0aGUgc2FtZSBhY2NvdW50IHRoZSBwaXBlbGluZSBpdHNlbGYgaXMgaW5cbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8gY2hlY2sgd2hldGhlciB0aGUgYWN0aW9uJ3MgYWNjb3VudCBpcyBhIHN0YXRpYyBzdHJpbmdcbiAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKHRhcmdldEFjY291bnQpKSB7XG4gICAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKHRoaXMuZW52LmFjY291bnQpKSB7XG4gICAgICAgIC8vIHRoZSBwaXBlbGluZSBpcyBhbHNvIGVudi1hZ25vc3RpYywgc28gdGhhdCdzIGZpbmVcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVGhlICdhY2NvdW50JyBwcm9wZXJ0eSBtdXN0IGJlIGEgY29uY3JldGUgdmFsdWUgKGFjdGlvbjogJyR7YWN0aW9uLmFjdGlvblByb3BlcnRpZXMuYWN0aW9uTmFtZX0nKWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEF0IHRoaXMgcG9pbnQsIHdlIGtub3cgdGhhdCB0aGUgYWN0aW9uJ3MgYWNjb3VudCBpcyBhIHN0YXRpYyBzdHJpbmcuXG4gICAgLy8gSW4gdGhpcyBjYXNlLCB0aGUgcGlwZWxpbmUncyBhY2NvdW50IG11c3QgYWxzbyBiZSBhIHN0YXRpYyBzdHJpbmcuXG4gICAgaWYgKFRva2VuLmlzVW5yZXNvbHZlZCh0aGlzLmVudi5hY2NvdW50KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdQaXBlbGluZSBzdGFjayB3aGljaCB1c2VzIGNyb3NzLWVudmlyb25tZW50IGFjdGlvbnMgbXVzdCBoYXZlIGFuIGV4cGxpY2l0bHkgc2V0IGFjY291bnQnKTtcbiAgICB9XG5cbiAgICAvLyBhdCB0aGlzIHBvaW50LCB3ZSBrbm93IHRoYXQgYm90aCB0aGUgUGlwZWxpbmUncyBhY2NvdW50LFxuICAgIC8vIGFuZCB0aGUgYWN0aW9uLWJhY2tpbmcgcmVzb3VyY2UncyBhY2NvdW50IGFyZSBzdGF0aWMgc3RyaW5nc1xuXG4gICAgLy8gaWYgdGhleSBhcmUgaWRlbnRpY2FsIC0gbm90aGluZyB0byBkbyAodGhlIGFjdGlvbiBpcyBub3QgY3Jvc3MtYWNjb3VudClcbiAgICBpZiAodGhpcy5lbnYuYWNjb3VudCA9PT0gdGFyZ2V0QWNjb3VudCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICAvLyBhdCB0aGlzIHBvaW50LCB3ZSBrbm93IHRoYXQgdGhlIGFjdGlvbiBpcyBjZXJ0YWlubHkgY3Jvc3MtYWNjb3VudCxcbiAgICAvLyBzbyB3ZSBuZWVkIHRvIHJldHVybiBhIFN0YWNrIGluIGl0cyBhY2NvdW50IHRvIGNyZWF0ZSB0aGUgaGVscGVyIFJvbGUgaW5cblxuICAgIGNvbnN0IGNhbmRpZGF0ZUFjdGlvblJlc291cmNlU3RhY2sgPSBhY3Rpb24uYWN0aW9uUHJvcGVydGllcy5yZXNvdXJjZVxuICAgICAgPyBTdGFjay5vZihhY3Rpb24uYWN0aW9uUHJvcGVydGllcy5yZXNvdXJjZSlcbiAgICAgIDogdW5kZWZpbmVkO1xuICAgIGlmIChjYW5kaWRhdGVBY3Rpb25SZXNvdXJjZVN0YWNrPy5hY2NvdW50ID09PSB0YXJnZXRBY2NvdW50KSB7XG4gICAgICAvLyB3ZSBhbHdheXMgdXNlIHRoZSBcImxhdGVzdFwiIGFjdGlvbi1iYWNraW5nIHJlc291cmNlJ3MgU3RhY2sgZm9yIHRoaXMgYWNjb3VudCxcbiAgICAgIC8vIGV2ZW4gaWYgYSBkaWZmZXJlbnQgb25lIHdhcyB1c2VkIGVhcmxpZXJcbiAgICAgIHRoaXMuX2Nyb3NzQWNjb3VudFN1cHBvcnRbdGFyZ2V0QWNjb3VudF0gPSBjYW5kaWRhdGVBY3Rpb25SZXNvdXJjZVN0YWNrO1xuICAgICAgcmV0dXJuIGNhbmRpZGF0ZUFjdGlvblJlc291cmNlU3RhY2s7XG4gICAgfVxuXG4gICAgbGV0IHRhcmdldEFjY291bnRTdGFjazogU3RhY2sgfCB1bmRlZmluZWQgPSB0aGlzLl9jcm9zc0FjY291bnRTdXBwb3J0W3RhcmdldEFjY291bnRdO1xuICAgIGlmICghdGFyZ2V0QWNjb3VudFN0YWNrKSB7XG4gICAgICBjb25zdCBzdGFja0lkID0gYGNyb3NzLWFjY291bnQtc3VwcG9ydC1zdGFjay0ke3RhcmdldEFjY291bnR9YDtcbiAgICAgIGNvbnN0IGFwcCA9IHRoaXMuc3VwcG9ydFNjb3BlKCk7XG4gICAgICB0YXJnZXRBY2NvdW50U3RhY2sgPSBhcHAubm9kZS50cnlGaW5kQ2hpbGQoc3RhY2tJZCkgYXMgU3RhY2s7XG4gICAgICBpZiAoIXRhcmdldEFjY291bnRTdGFjaykge1xuICAgICAgICBjb25zdCBhY3Rpb25SZWdpb24gPSBhY3Rpb24uYWN0aW9uUHJvcGVydGllcy5yZXNvdXJjZVxuICAgICAgICAgID8gYWN0aW9uLmFjdGlvblByb3BlcnRpZXMucmVzb3VyY2UuZW52LnJlZ2lvblxuICAgICAgICAgIDogYWN0aW9uLmFjdGlvblByb3BlcnRpZXMucmVnaW9uO1xuICAgICAgICBjb25zdCBwaXBlbGluZVN0YWNrID0gU3RhY2sub2YodGhpcyk7XG4gICAgICAgIHRhcmdldEFjY291bnRTdGFjayA9IG5ldyBTdGFjayhhcHAsIHN0YWNrSWQsIHtcbiAgICAgICAgICBzdGFja05hbWU6IGAke3BpcGVsaW5lU3RhY2suc3RhY2tOYW1lfS1zdXBwb3J0LSR7dGFyZ2V0QWNjb3VudH1gLFxuICAgICAgICAgIGVudjoge1xuICAgICAgICAgICAgYWNjb3VudDogdGFyZ2V0QWNjb3VudCxcbiAgICAgICAgICAgIHJlZ2lvbjogYWN0aW9uUmVnaW9uID8/IHBpcGVsaW5lU3RhY2sucmVnaW9uLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgdGhpcy5fY3Jvc3NBY2NvdW50U3VwcG9ydFt0YXJnZXRBY2NvdW50XSA9IHRhcmdldEFjY291bnRTdGFjaztcbiAgICB9XG4gICAgcmV0dXJuIHRhcmdldEFjY291bnRTdGFjaztcbiAgfVxuXG4gIHByaXZhdGUgaXNBd3NPd25lZChhY3Rpb246IElBY3Rpb24pIHtcbiAgICBjb25zdCBvd25lciA9IGFjdGlvbi5hY3Rpb25Qcm9wZXJ0aWVzLm93bmVyO1xuICAgIHJldHVybiAhb3duZXIgfHwgb3duZXIgPT09ICdBV1MnO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRBcnRpZmFjdEJ1Y2tldEZyb21Qcm9wcyhwcm9wczogUGlwZWxpbmVQcm9wcyk6IHMzLklCdWNrZXQgfCB1bmRlZmluZWQge1xuICAgIGlmIChwcm9wcy5hcnRpZmFjdEJ1Y2tldCkge1xuICAgICAgcmV0dXJuIHByb3BzLmFydGlmYWN0QnVja2V0O1xuICAgIH1cbiAgICBpZiAocHJvcHMuY3Jvc3NSZWdpb25SZXBsaWNhdGlvbkJ1Y2tldHMpIHtcbiAgICAgIGNvbnN0IHBpcGVsaW5lUmVnaW9uID0gdGhpcy5yZXF1aXJlUmVnaW9uKCk7XG4gICAgICByZXR1cm4gcHJvcHMuY3Jvc3NSZWdpb25SZXBsaWNhdGlvbkJ1Y2tldHNbcGlwZWxpbmVSZWdpb25dO1xuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJpdmF0ZSBjYWxjdWxhdGVJbnNlcnRJbmRleEZyb21QbGFjZW1lbnQocGxhY2VtZW50OiBTdGFnZVBsYWNlbWVudCk6IG51bWJlciB7XG4gICAgLy8gY2hlY2sgaWYgYXQgbW9zdCBvbmUgcGxhY2VtZW50IHByb3BlcnR5IHdhcyBwcm92aWRlZFxuICAgIGNvbnN0IHByb3ZpZGVkUGxhY2VtZW50UHJvcHMgPSBbJ3JpZ2h0QmVmb3JlJywgJ2p1c3RBZnRlcicsICdhdEluZGV4J11cbiAgICAgIC5maWx0ZXIoKHByb3ApID0+IChwbGFjZW1lbnQgYXMgYW55KVtwcm9wXSAhPT0gdW5kZWZpbmVkKTtcbiAgICBpZiAocHJvdmlkZWRQbGFjZW1lbnRQcm9wcy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Vycm9yIGFkZGluZyBTdGFnZSB0byB0aGUgUGlwZWxpbmU6ICcgK1xuICAgICAgICAneW91IGNhbiBvbmx5IHByb3ZpZGUgYXQgbW9zdCBvbmUgcGxhY2VtZW50IHByb3BlcnR5LCBidXQgJyArXG4gICAgICAgIGAnJHtwcm92aWRlZFBsYWNlbWVudFByb3BzLmpvaW4oJywgJyl9JyB3ZXJlIGdpdmVuYCk7XG4gICAgfVxuXG4gICAgaWYgKHBsYWNlbWVudC5yaWdodEJlZm9yZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCB0YXJnZXRJbmRleCA9IHRoaXMuZmluZFN0YWdlSW5kZXgocGxhY2VtZW50LnJpZ2h0QmVmb3JlKTtcbiAgICAgIGlmICh0YXJnZXRJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFcnJvciBhZGRpbmcgU3RhZ2UgdG8gdGhlIFBpcGVsaW5lOiAnICtcbiAgICAgICAgICBgdGhlIHJlcXVlc3RlZCBTdGFnZSB0byBhZGQgaXQgYmVmb3JlLCAnJHtwbGFjZW1lbnQucmlnaHRCZWZvcmUuc3RhZ2VOYW1lfScsIHdhcyBub3QgZm91bmRgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0YXJnZXRJbmRleDtcbiAgICB9XG5cbiAgICBpZiAocGxhY2VtZW50Lmp1c3RBZnRlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCB0YXJnZXRJbmRleCA9IHRoaXMuZmluZFN0YWdlSW5kZXgocGxhY2VtZW50Lmp1c3RBZnRlcik7XG4gICAgICBpZiAodGFyZ2V0SW5kZXggPT09IC0xKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXJyb3IgYWRkaW5nIFN0YWdlIHRvIHRoZSBQaXBlbGluZTogJyArXG4gICAgICAgICAgYHRoZSByZXF1ZXN0ZWQgU3RhZ2UgdG8gYWRkIGl0IGFmdGVyLCAnJHtwbGFjZW1lbnQuanVzdEFmdGVyLnN0YWdlTmFtZX0nLCB3YXMgbm90IGZvdW5kYCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGFyZ2V0SW5kZXggKyAxO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnN0YWdlQ291bnQ7XG4gIH1cblxuICBwcml2YXRlIGZpbmRTdGFnZUluZGV4KHRhcmdldFN0YWdlOiBJU3RhZ2UpIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhZ2VzLmZpbmRJbmRleChzdGFnZSA9PiBzdGFnZSA9PT0gdGFyZ2V0U3RhZ2UpO1xuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZVNvdXJjZUFjdGlvbkxvY2F0aW9ucygpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgICBsZXQgZmlyc3RTdGFnZSA9IHRydWU7XG4gICAgZm9yIChjb25zdCBzdGFnZSBvZiB0aGlzLl9zdGFnZXMpIHtcbiAgICAgIGNvbnN0IG9ubHlTb3VyY2VBY3Rpb25zUGVybWl0dGVkID0gZmlyc3RTdGFnZTtcbiAgICAgIGZvciAoY29uc3QgYWN0aW9uIG9mIHN0YWdlLmFjdGlvbkRlc2NyaXB0b3JzKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKC4uLnZhbGlkYXRlU291cmNlQWN0aW9uKG9ubHlTb3VyY2VBY3Rpb25zUGVybWl0dGVkLCBhY3Rpb24uY2F0ZWdvcnksIGFjdGlvbi5hY3Rpb25OYW1lLCBzdGFnZS5zdGFnZU5hbWUpKTtcbiAgICAgIH1cbiAgICAgIGZpcnN0U3RhZ2UgPSBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9ycztcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVIYXNTdGFnZXMoKTogc3RyaW5nW10ge1xuICAgIGlmICh0aGlzLnN0YWdlQ291bnQgPCAyKSB7XG4gICAgICByZXR1cm4gWydQaXBlbGluZSBtdXN0IGhhdmUgYXQgbGVhc3QgdHdvIHN0YWdlcyddO1xuICAgIH1cbiAgICByZXR1cm4gW107XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlU3RhZ2VzKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCByZXQgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuICAgIGZvciAoY29uc3Qgc3RhZ2Ugb2YgdGhpcy5fc3RhZ2VzKSB7XG4gICAgICByZXQucHVzaCguLi5zdGFnZS52YWxpZGF0ZSgpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVBcnRpZmFjdHMoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHJldCA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG5cbiAgICBjb25zdCBwcm9kdWNlcnM6IFJlY29yZDxzdHJpbmcsIFBpcGVsaW5lTG9jYXRpb24+ID0ge307XG4gICAgY29uc3QgZmlyc3RDb25zdW1lcnM6IFJlY29yZDxzdHJpbmcsIFBpcGVsaW5lTG9jYXRpb24+ID0ge307XG5cbiAgICBmb3IgKGNvbnN0IFtzdGFnZUluZGV4LCBzdGFnZV0gb2YgZW51bWVyYXRlKHRoaXMuX3N0YWdlcykpIHtcbiAgICAgIC8vIEZvciBldmVyeSBvdXRwdXQgYXJ0aWZhY3QsIGdldCB0aGUgcHJvZHVjZXJcbiAgICAgIGZvciAoY29uc3QgYWN0aW9uIG9mIHN0YWdlLmFjdGlvbkRlc2NyaXB0b3JzKSB7XG4gICAgICAgIGNvbnN0IGFjdGlvbkxvYyA9IG5ldyBQaXBlbGluZUxvY2F0aW9uKHN0YWdlSW5kZXgsIHN0YWdlLCBhY3Rpb24pO1xuXG4gICAgICAgIGZvciAoY29uc3Qgb3V0cHV0QXJ0aWZhY3Qgb2YgYWN0aW9uLm91dHB1dHMpIHtcbiAgICAgICAgICAvLyBvdXRwdXQgQXJ0aWZhY3RzIGFsd2F5cyBoYXZlIGEgbmFtZSBzZXRcbiAgICAgICAgICBjb25zdCBuYW1lID0gb3V0cHV0QXJ0aWZhY3QuYXJ0aWZhY3ROYW1lITtcbiAgICAgICAgICBpZiAocHJvZHVjZXJzW25hbWVdKSB7XG4gICAgICAgICAgICByZXQucHVzaChgQm90aCBBY3Rpb25zICcke3Byb2R1Y2Vyc1tuYW1lXS5hY3Rpb25OYW1lfScgYW5kICcke2FjdGlvbi5hY3Rpb25OYW1lfScgYXJlIHByb2R1Y3RpbmcgQXJ0aWZhY3QgJyR7bmFtZX0nLiBFdmVyeSBhcnRpZmFjdCBjYW4gb25seSBiZSBwcm9kdWNlZCBvbmNlLmApO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcHJvZHVjZXJzW25hbWVdID0gYWN0aW9uTG9jO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRm9yIGV2ZXJ5IGlucHV0IGFydGlmYWN0LCBnZXQgdGhlIGZpcnN0IGNvbnN1bWVyXG4gICAgICAgIGZvciAoY29uc3QgaW5wdXRBcnRpZmFjdCBvZiBhY3Rpb24uaW5wdXRzKSB7XG4gICAgICAgICAgY29uc3QgbmFtZSA9IGlucHV0QXJ0aWZhY3QuYXJ0aWZhY3ROYW1lO1xuICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgcmV0LnB1c2goYEFjdGlvbiAnJHthY3Rpb24uYWN0aW9uTmFtZX0nIGlzIHVzaW5nIGFuIHVubmFtZWQgaW5wdXQgQXJ0aWZhY3QsIHdoaWNoIGlzIG5vdCBiZWluZyBwcm9kdWNlZCBpbiB0aGlzIHBpcGVsaW5lYCk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmaXJzdENvbnN1bWVyc1tuYW1lXSA9IGZpcnN0Q29uc3VtZXJzW25hbWVdID8gZmlyc3RDb25zdW1lcnNbbmFtZV0uZmlyc3QoYWN0aW9uTG9jKSA6IGFjdGlvbkxvYztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vdyB2YWxpZGF0ZSB0aGF0IGV2ZXJ5IGlucHV0IGFydGlmYWN0IGlzIHByb2R1Y2VkIGJlZm9yZSBpdCdzXG4gICAgLy8gYmVpbmcgY29uc3VtZWQuXG4gICAgZm9yIChjb25zdCBbYXJ0aWZhY3ROYW1lLCBjb25zdW1lckxvY10gb2YgT2JqZWN0LmVudHJpZXMoZmlyc3RDb25zdW1lcnMpKSB7XG4gICAgICBjb25zdCBwcm9kdWNlckxvYyA9IHByb2R1Y2Vyc1thcnRpZmFjdE5hbWVdO1xuICAgICAgaWYgKCFwcm9kdWNlckxvYykge1xuICAgICAgICByZXQucHVzaChgQWN0aW9uICcke2NvbnN1bWVyTG9jLmFjdGlvbk5hbWV9JyBpcyB1c2luZyBpbnB1dCBBcnRpZmFjdCAnJHthcnRpZmFjdE5hbWV9Jywgd2hpY2ggaXMgbm90IGJlaW5nIHByb2R1Y2VkIGluIHRoaXMgcGlwZWxpbmVgKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb25zdW1lckxvYy5iZWZvcmVPckVxdWFsKHByb2R1Y2VyTG9jKSkge1xuICAgICAgICByZXQucHVzaChgJHtjb25zdW1lckxvY30gaXMgY29uc3VtaW5nIGlucHV0IEFydGlmYWN0ICcke2FydGlmYWN0TmFtZX0nIGJlZm9yZSBpdCBpcyBiZWluZyBwcm9kdWNlZCBhdCAke3Byb2R1Y2VyTG9jfWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlckFydGlmYWN0U3RvcmVzUHJvcGVydHkoKTogQ2ZuUGlwZWxpbmUuQXJ0aWZhY3RTdG9yZU1hcFByb3BlcnR5W10gfCB1bmRlZmluZWQge1xuICAgIGlmICghdGhpcy5jcm9zc1JlZ2lvbikgeyByZXR1cm4gdW5kZWZpbmVkOyB9XG5cbiAgICAvLyBhZGQgdGhlIFBpcGVsaW5lJ3MgYXJ0aWZhY3Qgc3RvcmVcbiAgICBjb25zdCBwcmltYXJ5UmVnaW9uID0gdGhpcy5yZXF1aXJlUmVnaW9uKCk7XG4gICAgdGhpcy5fY3Jvc3NSZWdpb25TdXBwb3J0W3ByaW1hcnlSZWdpb25dID0ge1xuICAgICAgcmVwbGljYXRpb25CdWNrZXQ6IHRoaXMuYXJ0aWZhY3RCdWNrZXQsXG4gICAgICBzdGFjazogU3RhY2sub2YodGhpcyksXG4gICAgfTtcblxuICAgIHJldHVybiBPYmplY3QuZW50cmllcyh0aGlzLl9jcm9zc1JlZ2lvblN1cHBvcnQpLm1hcCgoW3JlZ2lvbiwgc3VwcG9ydF0pID0+ICh7XG4gICAgICByZWdpb24sXG4gICAgICBhcnRpZmFjdFN0b3JlOiB0aGlzLnJlbmRlckFydGlmYWN0U3RvcmUoc3VwcG9ydC5yZXBsaWNhdGlvbkJ1Y2tldCksXG4gICAgfSkpO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJBcnRpZmFjdFN0b3JlUHJvcGVydHkoKTogQ2ZuUGlwZWxpbmUuQXJ0aWZhY3RTdG9yZVByb3BlcnR5IHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodGhpcy5jcm9zc1JlZ2lvbikgeyByZXR1cm4gdW5kZWZpbmVkOyB9XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyUHJpbWFyeUFydGlmYWN0U3RvcmUoKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyUHJpbWFyeUFydGlmYWN0U3RvcmUoKTogQ2ZuUGlwZWxpbmUuQXJ0aWZhY3RTdG9yZVByb3BlcnR5IHtcbiAgICByZXR1cm4gdGhpcy5yZW5kZXJBcnRpZmFjdFN0b3JlKHRoaXMuYXJ0aWZhY3RCdWNrZXQpO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJBcnRpZmFjdFN0b3JlKGJ1Y2tldDogczMuSUJ1Y2tldCk6IENmblBpcGVsaW5lLkFydGlmYWN0U3RvcmVQcm9wZXJ0eSB7XG4gICAgbGV0IGVuY3J5cHRpb25LZXk6IENmblBpcGVsaW5lLkVuY3J5cHRpb25LZXlQcm9wZXJ0eSB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCBidWNrZXRLZXkgPSBidWNrZXQuZW5jcnlwdGlvbktleTtcbiAgICBpZiAoYnVja2V0S2V5KSB7XG4gICAgICBlbmNyeXB0aW9uS2V5ID0ge1xuICAgICAgICB0eXBlOiAnS01TJyxcbiAgICAgICAgaWQ6IGJ1Y2tldEtleS5rZXlBcm4sXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAnUzMnLFxuICAgICAgbG9jYXRpb246IGJ1Y2tldC5idWNrZXROYW1lLFxuICAgICAgZW5jcnlwdGlvbktleSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgY3Jvc3NSZWdpb24oKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuY3Jvc3NSZWdpb25CdWNrZXRzUGFzc2VkKSB7IHJldHVybiB0cnVlOyB9XG4gICAgcmV0dXJuIHRoaXMuX3N0YWdlcy5zb21lKHN0YWdlID0+IHN0YWdlLmFjdGlvbkRlc2NyaXB0b3JzLnNvbWUoYWN0aW9uID0+IGFjdGlvbi5yZWdpb24gIT09IHVuZGVmaW5lZCkpO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJTdGFnZXMoKTogQ2ZuUGlwZWxpbmUuU3RhZ2VEZWNsYXJhdGlvblByb3BlcnR5W10ge1xuICAgIHJldHVybiB0aGlzLl9zdGFnZXMubWFwKHN0YWdlID0+IHN0YWdlLnJlbmRlcigpKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyRGlzYWJsZWRUcmFuc2l0aW9ucygpOiBDZm5QaXBlbGluZS5TdGFnZVRyYW5zaXRpb25Qcm9wZXJ0eVtdIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhZ2VzXG4gICAgICAuZmlsdGVyKHN0YWdlID0+ICFzdGFnZS50cmFuc2l0aW9uVG9FbmFibGVkKVxuICAgICAgLm1hcChzdGFnZSA9PiAoe1xuICAgICAgICByZWFzb246IHN0YWdlLnRyYW5zaXRpb25EaXNhYmxlZFJlYXNvbixcbiAgICAgICAgc3RhZ2VOYW1lOiBzdGFnZS5zdGFnZU5hbWUsXG4gICAgICB9KSk7XG4gIH1cblxuICBwcml2YXRlIHJlcXVpcmVSZWdpb24oKTogc3RyaW5nIHtcbiAgICBjb25zdCByZWdpb24gPSB0aGlzLmVudi5yZWdpb247XG4gICAgaWYgKFRva2VuLmlzVW5yZXNvbHZlZChyZWdpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BpcGVsaW5lIHN0YWNrIHdoaWNoIHVzZXMgY3Jvc3MtZW52aXJvbm1lbnQgYWN0aW9ucyBtdXN0IGhhdmUgYW4gZXhwbGljaXRseSBzZXQgcmVnaW9uJyk7XG4gICAgfVxuICAgIHJldHVybiByZWdpb247XG4gIH1cblxuICBwcml2YXRlIHN1cHBvcnRTY29wZSgpOiBDZGtTdGFnZSB7XG4gICAgY29uc3Qgc2NvcGUgPSBDZGtTdGFnZS5vZih0aGlzKTtcbiAgICBpZiAoIXNjb3BlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BpcGVsaW5lIHN0YWNrIHdoaWNoIHVzZXMgY3Jvc3MtZW52aXJvbm1lbnQgYWN0aW9ucyBtdXN0IGJlIHBhcnQgb2YgYSBDREsgQXBwIG9yIFN0YWdlJyk7XG4gICAgfVxuICAgIHJldHVybiBzY29wZTtcbiAgfVxufVxuXG4vKipcbiAqIEFuIGludGVyZmFjZSByZXByZXNlbnRpbmcgcmVzb3VyY2VzIGdlbmVyYXRlZCBpbiBvcmRlciB0byBzdXBwb3J0XG4gKiB0aGUgY3Jvc3MtcmVnaW9uIGNhcGFiaWxpdGllcyBvZiBDb2RlUGlwZWxpbmUuXG4gKiBZb3UgZ2V0IGluc3RhbmNlcyBvZiB0aGlzIGludGVyZmFjZSBmcm9tIHRoZSB7QGxpbmsgUGlwZWxpbmUjY3Jvc3NSZWdpb25TdXBwb3J0fSBwcm9wZXJ0eS5cbiAqXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ3Jvc3NSZWdpb25TdXBwb3J0IHtcbiAgLyoqXG4gICAqIFRoZSBTdGFjayB0aGF0IGhhcyBiZWVuIGNyZWF0ZWQgdG8gaG91c2UgdGhlIHJlcGxpY2F0aW9uIEJ1Y2tldFxuICAgKiByZXF1aXJlZCBmb3IgdGhpcyAgcmVnaW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhY2s6IFN0YWNrO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVwbGljYXRpb24gQnVja2V0IHVzZWQgYnkgQ29kZVBpcGVsaW5lIHRvIG9wZXJhdGUgaW4gdGhpcyByZWdpb24uXG4gICAqIEJlbG9uZ3MgdG8ge0BsaW5rIHN0YWNrfS5cbiAgICovXG4gIHJlYWRvbmx5IHJlcGxpY2F0aW9uQnVja2V0OiBzMy5JQnVja2V0O1xufVxuXG5pbnRlcmZhY2UgQ3Jvc3NSZWdpb25JbmZvIHtcbiAgcmVhZG9ubHkgYXJ0aWZhY3RCdWNrZXQ6IHMzLklCdWNrZXQ7XG5cbiAgcmVhZG9ubHkgcmVnaW9uPzogc3RyaW5nO1xufVxuXG5mdW5jdGlvbiBlbnVtZXJhdGU8QT4oeHM6IEFbXSk6IEFycmF5PFtudW1iZXIsIEFdPiB7XG4gIGNvbnN0IHJldCA9IG5ldyBBcnJheTxbbnVtYmVyLCBBXT4oKTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB4cy5sZW5ndGg7IGkrKykge1xuICAgIHJldC5wdXNoKFtpLCB4c1tpXV0pO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbmNsYXNzIFBpcGVsaW5lTG9jYXRpb24ge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHN0YWdlSW5kZXg6IG51bWJlciwgcHJpdmF0ZSByZWFkb25seSBzdGFnZTogSVN0YWdlLCBwcml2YXRlIHJlYWRvbmx5IGFjdGlvbjogRnVsbEFjdGlvbkRlc2NyaXB0b3IpIHtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgc3RhZ2VOYW1lKCkge1xuICAgIHJldHVybiB0aGlzLnN0YWdlLnN0YWdlTmFtZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYWN0aW9uTmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5hY3Rpb24uYWN0aW9uTmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgYSBpcyBiZWZvcmUgb3IgdGhlIHNhbWUgb3JkZXIgYXMgYlxuICAgKi9cbiAgcHVibGljIGJlZm9yZU9yRXF1YWwocmhzOiBQaXBlbGluZUxvY2F0aW9uKSB7XG4gICAgaWYgKHRoaXMuc3RhZ2VJbmRleCAhPT0gcmhzLnN0YWdlSW5kZXgpIHsgcmV0dXJuIHJocy5zdGFnZUluZGV4IDwgcmhzLnN0YWdlSW5kZXg7IH1cbiAgICByZXR1cm4gdGhpcy5hY3Rpb24ucnVuT3JkZXIgPD0gcmhzLmFjdGlvbi5ydW5PcmRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBmaXJzdCBsb2NhdGlvbiBiZXR3ZWVuIHRoaXMgYW5kIHRoZSBvdGhlciBvbmVcbiAgICovXG4gIHB1YmxpYyBmaXJzdChyaHM6IFBpcGVsaW5lTG9jYXRpb24pIHtcbiAgICByZXR1cm4gdGhpcy5iZWZvcmVPckVxdWFsKHJocykgPyB0aGlzIDogcmhzO1xuICB9XG5cbiAgcHVibGljIHRvU3RyaW5nKCkge1xuICAgIC8vIHJ1bk9yZGVycyBhcmUgMS1iYXNlZCwgc28gbWFrZSB0aGUgc3RhZ2VJbmRleCBhbHNvIDEtYmFzZWQgb3RoZXJ3aXNlIGl0J3MgZ29pbmcgdG8gYmUgY29uZnVzaW5nLlxuICAgIHJldHVybiBgU3RhZ2UgJHt0aGlzLnN0YWdlSW5kZXggKyAxfSBBY3Rpb24gJHt0aGlzLmFjdGlvbi5ydW5PcmRlcn0gKCcke3RoaXMuc3RhZ2VOYW1lfScvJyR7dGhpcy5hY3Rpb25OYW1lfScpYDtcbiAgfVxufVxuXG4vKipcbiAqIFJlbmRlciBhbiBlbnYgZGltZW5zaW9uIHdpdGhvdXQgc2hvd2luZyB0aGUgdWdseSBzdHJpbmdpZmllZCB0b2tlbnNcbiAqL1xuZnVuY3Rpb24gcmVuZGVyRW52RGltZW5zaW9uKHM6IHN0cmluZyB8IHVuZGVmaW5lZCkge1xuICByZXR1cm4gVG9rZW4uaXNVbnJlc29sdmVkKHMpID8gJyhjdXJyZW50KScgOiBzO1xufVxuIl19 |
\ | No newline at end of file |