aws-cdk
Version:
CDK Toolkit, the command line tool for CDK apps
362 lines • 73.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Deployments = void 0;
const crypto_1 = require("crypto");
const cdk_assets = require("cdk-assets");
const chalk = require("chalk");
const asset_manifest_builder_1 = require("./asset-manifest-builder");
const asset_publishing_1 = require("./asset-publishing");
const checks_1 = require("./checks");
const cloudformation_1 = require("./cloudformation");
const deploy_stack_1 = require("./deploy-stack");
const nested_stack_helpers_1 = require("./nested-stack-helpers");
const logging_1 = require("../../logging");
const error_1 = require("../../toolkit/error");
const error_2 = require("../../util/error");
const environment_access_1 = require("../environment-access");
const toolkit_info_1 = require("../toolkit-info");
const stack_activity_monitor_1 = require("../util/cloudformation/stack-activity-monitor");
const stack_event_poller_1 = require("../util/cloudformation/stack-event-poller");
const stack_status_1 = require("../util/cloudformation/stack-status");
const template_body_parameter_1 = require("../util/template-body-parameter");
const BOOTSTRAP_STACK_VERSION_FOR_ROLLBACK = 23;
/**
* Scope for a single set of deployments from a set of Cloud Assembly Artifacts
*
* Manages lookup of SDKs, Bootstrap stacks, etc.
*/
class Deployments {
constructor(props) {
this.props = props;
this.publisherCache = new Map();
this.assetSdkProvider = props.sdkProvider;
this.deployStackSdkProvider = props.sdkProvider;
this.envs = new environment_access_1.EnvironmentAccess(props.sdkProvider, props.toolkitStackName ?? toolkit_info_1.DEFAULT_TOOLKIT_STACK_NAME);
}
/**
* Resolves the environment for a stack.
*/
async resolveEnvironment(stack) {
return this.envs.resolveStackEnvironment(stack);
}
async readCurrentTemplateWithNestedStacks(rootStackArtifact, retrieveProcessedTemplate = false) {
const env = await this.envs.accessStackForLookupBestEffort(rootStackArtifact);
return (0, nested_stack_helpers_1.loadCurrentTemplateWithNestedStacks)(rootStackArtifact, env.sdk, retrieveProcessedTemplate);
}
async readCurrentTemplate(stackArtifact) {
(0, logging_1.debug)(`Reading existing template for stack ${stackArtifact.displayName}.`);
const env = await this.envs.accessStackForLookupBestEffort(stackArtifact);
return (0, nested_stack_helpers_1.loadCurrentTemplate)(stackArtifact, env.sdk);
}
async resourceIdentifierSummaries(stackArtifact) {
(0, logging_1.debug)(`Retrieving template summary for stack ${stackArtifact.displayName}.`);
// Currently, needs to use `deploy-role` since it may need to read templates in the staging
// bucket which have been encrypted with a KMS key (and lookup-role may not read encrypted things)
const env = await this.envs.accessStackForReadOnlyStackOperations(stackArtifact);
const cfn = env.sdk.cloudFormation();
await (0, cloudformation_1.uploadStackTemplateAssets)(stackArtifact, this);
// Upload the template, if necessary, before passing it to CFN
const builder = new asset_manifest_builder_1.AssetManifestBuilder();
const cfnParam = await (0, template_body_parameter_1.makeBodyParameter)(stackArtifact, env.resolvedEnvironment, builder, env.resources);
// If the `makeBodyParameter` before this added assets, make sure to publish them before
// calling the API.
const addedAssets = builder.toManifest(stackArtifact.assembly.directory);
for (const entry of addedAssets.entries) {
await this.buildSingleAsset('no-version-validation', addedAssets, entry, {
stack: stackArtifact,
});
await this.publishSingleAsset(addedAssets, entry, {
stack: stackArtifact,
});
}
const response = await cfn.getTemplateSummary(cfnParam);
if (!response.ResourceIdentifierSummaries) {
(0, logging_1.debug)('GetTemplateSummary API call did not return "ResourceIdentifierSummaries"');
}
return response.ResourceIdentifierSummaries ?? [];
}
async deployStack(options) {
let deploymentMethod = options.deploymentMethod;
if (options.changeSetName || options.execute !== undefined) {
if (deploymentMethod) {
throw new error_1.ToolkitError("You cannot supply both 'deploymentMethod' and 'changeSetName/execute'. Supply one or the other.");
}
deploymentMethod = {
method: 'change-set',
changeSetName: options.changeSetName,
execute: options.execute,
};
}
const env = await this.envs.accessStackForMutableStackOperations(options.stack);
// Do a verification of the bootstrap stack version
await this.validateBootstrapStackVersion(options.stack.stackName, options.stack.requiresBootstrapStackVersion, options.stack.bootstrapStackVersionSsmParameter, env.resources);
const executionRoleArn = await env.replacePlaceholders(options.roleArn ?? options.stack.cloudFormationExecutionRoleArn);
return (0, deploy_stack_1.deployStack)({
stack: options.stack,
resolvedEnvironment: env.resolvedEnvironment,
deployName: options.deployName,
notificationArns: options.notificationArns,
quiet: options.quiet,
sdk: env.sdk,
sdkProvider: this.deployStackSdkProvider,
roleArn: executionRoleArn,
reuseAssets: options.reuseAssets,
envResources: env.resources,
tags: options.tags,
deploymentMethod,
force: options.force,
parameters: options.parameters,
usePreviousParameters: options.usePreviousParameters,
progress: options.progress,
ci: options.ci,
rollback: options.rollback,
hotswap: options.hotswap,
hotswapPropertyOverrides: options.hotswapPropertyOverrides,
extraUserAgent: options.extraUserAgent,
resourcesToImport: options.resourcesToImport,
overrideTemplate: options.overrideTemplate,
assetParallelism: options.assetParallelism,
});
}
async rollbackStack(options) {
let resourcesToSkip = options.orphanLogicalIds ?? [];
if (options.force && resourcesToSkip.length > 0) {
throw new error_1.ToolkitError('Cannot combine --force with --orphan');
}
const env = await this.envs.accessStackForMutableStackOperations(options.stack);
if (options.validateBootstrapStackVersion ?? true) {
// Do a verification of the bootstrap stack version
await this.validateBootstrapStackVersion(options.stack.stackName, BOOTSTRAP_STACK_VERSION_FOR_ROLLBACK, options.stack.bootstrapStackVersionSsmParameter, env.resources);
}
const cfn = env.sdk.cloudFormation();
const deployName = options.stack.stackName;
// We loop in case of `--force` and the stack ends up in `CONTINUE_UPDATE_ROLLBACK`.
let maxLoops = 10;
while (maxLoops--) {
let cloudFormationStack = await cloudformation_1.CloudFormationStack.lookup(cfn, deployName);
const executionRoleArn = await env.replacePlaceholders(options.roleArn ?? options.stack.cloudFormationExecutionRoleArn);
switch (cloudFormationStack.stackStatus.rollbackChoice) {
case stack_status_1.RollbackChoice.NONE:
(0, logging_1.warning)(`Stack ${deployName} does not need a rollback: ${cloudFormationStack.stackStatus}`);
return { notInRollbackableState: true };
case stack_status_1.RollbackChoice.START_ROLLBACK:
(0, logging_1.debug)(`Initiating rollback of stack ${deployName}`);
await cfn.rollbackStack({
StackName: deployName,
RoleARN: executionRoleArn,
ClientRequestToken: (0, crypto_1.randomUUID)(),
// Enabling this is just the better overall default, the only reason it isn't the upstream default is backwards compatibility
RetainExceptOnCreate: true,
});
break;
case stack_status_1.RollbackChoice.CONTINUE_UPDATE_ROLLBACK:
if (options.force) {
// Find the failed resources from the deployment and automatically skip them
// (Using deployment log because we definitely have `DescribeStackEvents` permissions, and we might not have
// `DescribeStackResources` permissions).
const poller = new stack_event_poller_1.StackEventPoller(cfn, {
stackName: deployName,
stackStatuses: ['ROLLBACK_IN_PROGRESS', 'UPDATE_ROLLBACK_IN_PROGRESS'],
});
await poller.poll();
resourcesToSkip = poller.resourceErrors
.filter((r) => !r.isStackEvent && r.parentStackLogicalIds.length === 0)
.map((r) => r.event.LogicalResourceId ?? '');
}
const skipDescription = resourcesToSkip.length > 0 ? ` (orphaning: ${resourcesToSkip.join(', ')})` : '';
(0, logging_1.warning)(`Continuing rollback of stack ${deployName}${skipDescription}`);
await cfn.continueUpdateRollback({
StackName: deployName,
ClientRequestToken: (0, crypto_1.randomUUID)(),
RoleARN: executionRoleArn,
ResourcesToSkip: resourcesToSkip,
});
break;
case stack_status_1.RollbackChoice.ROLLBACK_FAILED:
(0, logging_1.warning)(`Stack ${deployName} failed creation and rollback. This state cannot be rolled back. You can recreate this stack by running 'cdk deploy'.`);
return { notInRollbackableState: true };
default:
throw new error_1.ToolkitError(`Unexpected rollback choice: ${cloudFormationStack.stackStatus.rollbackChoice}`);
}
const monitor = options.quiet
? undefined
: stack_activity_monitor_1.StackActivityMonitor.withDefaultPrinter(cfn, deployName, options.stack, {
ci: options.ci,
}).start();
let stackErrorMessage = undefined;
let finalStackState = cloudFormationStack;
try {
const successStack = await (0, cloudformation_1.stabilizeStack)(cfn, deployName);
// This shouldn't really happen, but catch it anyway. You never know.
if (!successStack) {
throw new error_1.ToolkitError('Stack deploy failed (the stack disappeared while we were rolling it back)');
}
finalStackState = successStack;
const errors = monitor?.errors?.join(', ');
if (errors) {
stackErrorMessage = errors;
}
}
catch (e) {
stackErrorMessage = suffixWithErrors((0, error_2.formatErrorMessage)(e), monitor?.errors);
}
finally {
await monitor?.stop();
}
if (finalStackState.stackStatus.isRollbackSuccess || !stackErrorMessage) {
return { success: true };
}
// Either we need to ignore some resources to continue the rollback, or something went wrong
if (finalStackState.stackStatus.rollbackChoice === stack_status_1.RollbackChoice.CONTINUE_UPDATE_ROLLBACK && options.force) {
// Do another loop-de-loop
continue;
}
throw new error_1.ToolkitError(`${stackErrorMessage} (fix problem and retry, or orphan these resources using --orphan or --force)`);
}
throw new error_1.ToolkitError("Rollback did not finish after a large number of iterations; stopping because it looks like we're not making progress anymore. You can retry if rollback was progressing as expected.");
}
async destroyStack(options) {
const env = await this.envs.accessStackForMutableStackOperations(options.stack);
const executionRoleArn = await env.replacePlaceholders(options.roleArn ?? options.stack.cloudFormationExecutionRoleArn);
return (0, deploy_stack_1.destroyStack)({
sdk: env.sdk,
roleArn: executionRoleArn,
stack: options.stack,
deployName: options.deployName,
quiet: options.quiet,
ci: options.ci,
});
}
async stackExists(options) {
let env;
if (options.tryLookupRole) {
env = await this.envs.accessStackForLookupBestEffort(options.stack);
}
else {
env = await this.envs.accessStackForReadOnlyStackOperations(options.stack);
}
const stack = await cloudformation_1.CloudFormationStack.lookup(env.sdk.cloudFormation(), options.deployName ?? options.stack.stackName);
return stack.exists;
}
async prepareAndValidateAssets(asset, options) {
const env = await this.envs.accessStackForMutableStackOperations(options.stack);
await this.validateBootstrapStackVersion(options.stack.stackName, asset.requiresBootstrapStackVersion, asset.bootstrapStackVersionSsmParameter, env.resources);
const manifest = cdk_assets.AssetManifest.fromFile(asset.file);
return { manifest, stackEnv: env.resolvedEnvironment };
}
/**
* Build all assets in a manifest
*
* @deprecated Use `buildSingleAsset` instead
*/
async buildAssets(asset, options) {
const { manifest, stackEnv } = await this.prepareAndValidateAssets(asset, options);
await (0, asset_publishing_1.buildAssets)(manifest, this.assetSdkProvider, stackEnv, options.buildOptions);
}
/**
* Publish all assets in a manifest
*
* @deprecated Use `publishSingleAsset` instead
*/
async publishAssets(asset, options) {
const { manifest, stackEnv } = await this.prepareAndValidateAssets(asset, options);
await (0, asset_publishing_1.publishAssets)(manifest, this.assetSdkProvider, stackEnv, {
...options.publishOptions,
allowCrossAccount: await this.allowCrossAccountAssetPublishingForEnv(options.stack),
});
}
/**
* Build a single asset from an asset manifest
*
* If an assert manifest artifact is given, the bootstrap stack version
* will be validated according to the constraints in that manifest artifact.
* If that is not necessary, `'no-version-validation'` can be passed.
*/
// eslint-disable-next-line max-len
async buildSingleAsset(assetArtifact, assetManifest, asset, options) {
if (assetArtifact !== 'no-version-validation') {
const env = await this.envs.accessStackForReadOnlyStackOperations(options.stack);
await this.validateBootstrapStackVersion(options.stack.stackName, assetArtifact.requiresBootstrapStackVersion, assetArtifact.bootstrapStackVersionSsmParameter, env.resources);
}
const resolvedEnvironment = await this.envs.resolveStackEnvironment(options.stack);
const publisher = this.cachedPublisher(assetManifest, resolvedEnvironment, options.stackName);
await publisher.buildEntry(asset);
if (publisher.hasFailures) {
throw new error_1.ToolkitError(`Failed to build asset ${asset.id}`);
}
}
/**
* Publish a single asset from an asset manifest
*/
// eslint-disable-next-line max-len
async publishSingleAsset(assetManifest, asset, options) {
const stackEnv = await this.envs.resolveStackEnvironment(options.stack);
// No need to validate anymore, we already did that during build
const publisher = this.cachedPublisher(assetManifest, stackEnv, options.stackName);
await publisher.publishEntry(asset, { allowCrossAccount: await this.allowCrossAccountAssetPublishingForEnv(options.stack) });
if (publisher.hasFailures) {
throw new error_1.ToolkitError(`Failed to publish asset ${asset.id}`);
}
}
async allowCrossAccountAssetPublishingForEnv(stack) {
if (this._allowCrossAccountAssetPublishing === undefined) {
const env = await this.envs.accessStackForReadOnlyStackOperations(stack);
this._allowCrossAccountAssetPublishing = await (0, checks_1.determineAllowCrossAccountAssetPublishing)(env.sdk, this.props.toolkitStackName);
}
return this._allowCrossAccountAssetPublishing;
}
/**
* Return whether a single asset has been published already
*/
async isSingleAssetPublished(assetManifest, asset, options) {
const stackEnv = await this.envs.resolveStackEnvironment(options.stack);
const publisher = this.cachedPublisher(assetManifest, stackEnv, options.stackName);
return publisher.isEntryPublished(asset);
}
/**
* Validate that the bootstrap stack has the right version for this stack
*
* Call into envResources.validateVersion, but prepend the stack name in case of failure.
*/
async validateBootstrapStackVersion(stackName, requiresBootstrapStackVersion, bootstrapStackVersionSsmParameter, envResources) {
try {
await envResources.validateVersion(requiresBootstrapStackVersion, bootstrapStackVersionSsmParameter);
}
catch (e) {
throw new error_1.ToolkitError(`${stackName}: ${(0, error_2.formatErrorMessage)(e)}`);
}
}
cachedPublisher(assetManifest, env, stackName) {
const existing = this.publisherCache.get(assetManifest);
if (existing) {
return existing;
}
const prefix = stackName ? `${chalk.bold(stackName)}: ` : '';
const publisher = new cdk_assets.AssetPublishing(assetManifest, {
// The AssetPublishing class takes care of role assuming etc, so it's okay to
// give it a direct `SdkProvider`.
aws: new asset_publishing_1.PublishingAws(this.assetSdkProvider, env),
progressListener: new ParallelSafeAssetProgress(prefix, this.props.quiet ?? false),
});
this.publisherCache.set(assetManifest, publisher);
return publisher;
}
}
exports.Deployments = Deployments;
/**
* Asset progress that doesn't do anything with percentages (currently)
*/
class ParallelSafeAssetProgress {
constructor(prefix, quiet) {
this.prefix = prefix;
this.quiet = quiet;
}
onPublishEvent(type, event) {
const handler = this.quiet && type !== 'fail' ? logging_1.debug : asset_publishing_1.EVENT_TO_LOGGER[type];
handler(`${this.prefix}${type}: ${event.message}`);
}
}
function suffixWithErrors(msg, errors) {
return errors && errors.length > 0 ? `${msg}: ${errors.join(', ')}` : msg;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwbG95bWVudHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJkZXBsb3ltZW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtQ0FBb0M7QUFFcEMseUNBQXlDO0FBQ3pDLCtCQUErQjtBQUMvQixxRUFBZ0U7QUFDaEUseURBTzRCO0FBQzVCLHFDQUFxRTtBQUNyRSxxREFPMEI7QUFDMUIsaURBQTJEO0FBRzNELGlFQUlnQztBQUNoQywyQ0FBK0M7QUFDL0MsK0NBQW1EO0FBQ25ELDRDQUFzRDtBQUV0RCw4REFBMEQ7QUFJMUQsa0RBQTZEO0FBQzdELDBGQUE0RztBQUM1RyxrRkFBNkU7QUFDN0Usc0VBQXFFO0FBQ3JFLDZFQUFvRTtBQUVwRSxNQUFNLG9DQUFvQyxHQUFHLEVBQUUsQ0FBQztBQTJTaEQ7Ozs7R0FJRztBQUNILE1BQWEsV0FBVztJQTBCdEIsWUFBNkIsS0FBdUI7UUFBdkIsVUFBSyxHQUFMLEtBQUssQ0FBa0I7UUFIbkMsbUJBQWMsR0FBRyxJQUFJLEdBQUcsRUFBd0QsQ0FBQztRQUloRyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztRQUMxQyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztRQUNoRCxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksc0NBQWlCLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsZ0JBQWdCLElBQUkseUNBQTBCLENBQUMsQ0FBQztJQUM3RyxDQUFDO0lBRUQ7O09BRUc7SUFDSSxLQUFLLENBQUMsa0JBQWtCLENBQUMsS0FBd0M7UUFDdEUsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFTSxLQUFLLENBQUMsbUNBQW1DLENBQzlDLGlCQUFvRCxFQUNwRCw0QkFBcUMsS0FBSztRQUUxQyxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQyxJ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cG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0ICogYXMgY3hhcGkgZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCAqIGFzIGNka19hc3NldHMgZnJvbSAnY2RrLWFzc2V0cyc7XG5pbXBvcnQgKiBhcyBjaGFsayBmcm9tICdjaGFsayc7XG5pbXBvcnQgeyBBc3NldE1hbmlmZXN0QnVpbGRlciB9IGZyb20gJy4vYXNzZXQtbWFuaWZlc3QtYnVpbGRlcic7XG5pbXBvcnQge1xuICBidWlsZEFzc2V0cyxcbiAgdHlwZSBCdWlsZEFzc2V0c09wdGlvbnMsXG4gIEVWRU5UX1RPX0xPR0dFUixcbiAgcHVibGlzaEFzc2V0cyxcbiAgdHlwZSBQdWJsaXNoQXNzZXRzT3B0aW9ucyxcbiAgUHVibGlzaGluZ0F3cyxcbn0gZnJvbSAnLi9hc3NldC1wdWJsaXNoaW5nJztcbmltcG9ydCB7IGRldGVybWluZUFsbG93Q3Jvc3NBY2NvdW50QXNzZXRQdWJsaXNoaW5nIH0gZnJvbSAnLi9jaGVja3MnO1xuaW1wb3J0IHtcbiAgQ2xvdWRGb3JtYXRpb25TdGFjayxcbiAgdHlwZSBSZXNvdXJjZUlkZW50aWZpZXJTdW1tYXJpZXMsXG4gIFJlc291cmNlc1RvSW1wb3J0LFxuICBzdGFiaWxpemVTdGFjayxcbiAgVGVtcGxhdGUsXG4gIHVwbG9hZFN0YWNrVGVtcGxhdGVBc3NldHMsXG59IGZyb20gJy4vY2xvdWRmb3JtYXRpb24nO1xuaW1wb3J0IHsgZGVwbG95U3RhY2ssIGRlc3Ryb3lTdGFjayB9IGZyb20gJy4vZGVwbG95LXN0YWNrJztcbmltcG9ydCB7IERlcGxveW1lbnRNZXRob2QgfSBmcm9tICcuL2RlcGxveW1lbnQtbWV0aG9kJztcbmltcG9ydCB7IERlcGxveVN0YWNrUmVzdWx0IH0gZnJvbSAnLi9kZXBsb3ltZW50LXJlc3VsdCc7XG5pbXBvcnQge1xuICBsb2FkQ3VycmVudFRlbXBsYXRlLFxuICBsb2FkQ3VycmVudFRlbXBsYXRlV2l0aE5lc3RlZFN0YWNrcyxcbiAgdHlwZSBSb290VGVtcGxhdGVXaXRoTmVzdGVkU3RhY2tzLFxufSBmcm9tICcuL25lc3RlZC1zdGFjay1oZWxwZXJzJztcbmltcG9ydCB7IGRlYnVnLCB3YXJuaW5nIH0gZnJvbSAnLi4vLi4vbG9nZ2luZyc7XG5pbXBvcnQgeyBUb29sa2l0RXJyb3IgfSBmcm9tICcuLi8uLi90b29sa2l0L2Vycm9yJztcbmltcG9ydCB7IGZvcm1hdEVycm9yTWVzc2FnZSB9IGZyb20gJy4uLy4uL3V0aWwvZXJyb3InO1xuaW1wb3J0IHR5cGUgeyBTZGtQcm92aWRlciB9IGZyb20gJy4uL2F3cy1hdXRoL3Nkay1wcm92aWRlcic7XG5pbXBvcnQgeyBFbnZpcm9ubWVudEFjY2VzcyB9IGZyb20gJy4uL2Vudmlyb25tZW50LWFjY2Vzcyc7XG5pbXBvcnQgeyB0eXBlIEVudmlyb25tZW50UmVzb3VyY2VzIH0gZnJvbSAnLi4vZW52aXJvbm1lbnQtcmVzb3VyY2VzJztcbmltcG9ydCB7IEhvdHN3YXBNb2RlLCBIb3Rzd2FwUHJvcGVydHlPdmVycmlkZXMgfSBmcm9tICcuLi9ob3Rzd2FwL2NvbW1vbic7XG5pbXBvcnQgdHlwZSB7IFRhZyB9IGZyb20gJy4uL3RhZ3MnO1xuaW1wb3J0IHsgREVGQVVMVF9UT09MS0lUX1NUQUNLX05BTUUgfSBmcm9tICcuLi90b29sa2l0LWluZm8nO1xuaW1wb3J0IHsgU3RhY2tBY3Rpdml0eU1vbml0b3IsIFN0YWNrQWN0aXZpdHlQcm9ncmVzcyB9IGZyb20gJy4uL3V0aWwvY2xvdWRmb3JtYXRpb24vc3RhY2stYWN0aXZpdHktbW9uaXRvcic7XG5pbXBvcnQgeyBTdGFja0V2ZW50UG9sbGVyIH0gZnJvbSAnLi4vdXRpbC9jbG91ZGZvcm1hdGlvbi9zdGFjay1ldmVudC1wb2xsZXInO1xuaW1wb3J0IHsgUm9sbGJhY2tDaG9pY2UgfSBmcm9tICcuLi91dGlsL2Nsb3VkZm9ybWF0aW9uL3N0YWNrLXN0YXR1cyc7XG5pbXBvcnQgeyBtYWtlQm9keVBhcmFtZXRlciB9IGZyb20gJy4uL3V0aWwvdGVtcGxhdGUtYm9keS1wYXJhbWV0ZXInO1xuXG5jb25zdCBCT09UU1RSQVBfU1RBQ0tfVkVSU0lPTl9GT1JfUk9MTEJBQ0sgPSAyMztcblxuZXhwb3J0IGludGVyZmFjZSBEZXBsb3lTdGFja09wdGlvbnMge1xuICAvKipcbiAgICogU3RhY2sgdG8gZGVwbG95XG4gICAqL1xuICByZWFkb25seSBzdGFjazogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0O1xuXG4gIC8qKlxuICAgKiBFeGVjdXRpb24gcm9sZSBmb3IgdGhlIGRlcGxveW1lbnQgKHBhc3MgdGhyb3VnaCB0byBDbG91ZEZvcm1hdGlvbilcbiAgICpcbiAgICogQGRlZmF1bHQgLSBDdXJyZW50IHJvbGVcbiAgICovXG4gIHJlYWRvbmx5IHJvbGVBcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRvcGljIEFSTnMgdG8gc2VuZCBhIG1lc3NhZ2Ugd2hlbiBkZXBsb3ltZW50IGZpbmlzaGVzIChwYXNzIHRocm91Z2ggdG8gQ2xvdWRGb3JtYXRpb24pXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gbm90aWZpY2F0aW9uc1xuICAgKi9cbiAgcmVhZG9ubHkgbm90aWZpY2F0aW9uQXJucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBPdmVycmlkZSBuYW1lIHVuZGVyIHdoaWNoIHN0YWNrIHdpbGwgYmUgZGVwbG95ZWRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBVc2UgYXJ0aWZhY3QgZGVmYXVsdFxuICAgKi9cbiAgcmVhZG9ubHkgZGVwbG95TmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogRG9uJ3Qgc2hvdyBzdGFjayBkZXBsb3ltZW50IGV2ZW50cywganVzdCB3YWl0XG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBxdWlldD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIHRvb2xraXQgc3RhY2ssIGlmIG5vdCB0aGUgZGVmYXVsdCBuYW1lXG4gICAqXG4gICAqIEBkZWZhdWx0ICdDREtUb29sa2l0J1xuICAgKi9cbiAgcmVhZG9ubHkgdG9vbGtpdFN0YWNrTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogTGlzdCBvZiBhc3NldCBJRHMgd2hpY2ggc2hvdWxkIE5PVCBiZSBidWlsdCBvciB1cGxvYWRlZFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEJ1aWxkIGFsbCBhc3NldHNcbiAgICovXG4gIHJlYWRvbmx5IHJldXNlQXNzZXRzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFN0YWNrIHRhZ3MgKHBhc3MgdGhyb3VnaCB0byBDbG91ZEZvcm1hdGlvbilcbiAgICovXG4gIHJlYWRvbmx5IHRhZ3M/OiBUYWdbXTtcblxuICAvKipcbiAgICogU3RhZ2UgdGhlIGNoYW5nZSBzZXQgYnV0IGRvbid0IGV4ZWN1dGUgaXRcbiAgICpcbiAgICogQGRlZmF1bHQgLSB0cnVlXG4gICAqIEBkZXByZWNhdGVkIFVzZSAnZGVwbG95bWVudE1ldGhvZCcgaW5zdGVhZFxuICAgKi9cbiAgcmVhZG9ubHkgZXhlY3V0ZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIG5hbWUgdG8gdXNlIGZvciB0aGUgQ2xvdWRGb3JtYXRpb24gY2hhbmdlIHNldC5cbiAgICogSWYgbm90IHByb3ZpZGVkLCBhIG5hbWUgd2lsbCBiZSBnZW5lcmF0ZWQgYXV0b21hdGljYWxseS5cbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgVXNlICdkZXBsb3ltZW50TWV0aG9kJyBpbnN0ZWFkXG4gICAqL1xuICByZWFkb25seSBjaGFuZ2VTZXROYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTZWxlY3QgdGhlIGRlcGxveW1lbnQgbWV0aG9kIChkaXJlY3Qgb3IgdXNpbmcgYSBjaGFuZ2Ugc2V0KVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIENoYW5nZSBzZXQgd2l0aCBkZWZhdWx0IG9wdGlvbnNcbiAgICovXG4gIHJlYWRvbmx5IGRlcGxveW1lbnRNZXRob2Q/OiBEZXBsb3ltZW50TWV0aG9kO1xuXG4gIC8qKlxuICAgKiBGb3JjZSBkZXBsb3ltZW50LCBldmVuIGlmIHRoZSBkZXBsb3llZCB0ZW1wbGF0ZSBpcyBpZGVudGljYWwgdG8gdGhlIG9uZSB3ZSBhcmUgYWJvdXQgdG8gZGVwbG95LlxuICAgKiBAZGVmYXVsdCBmYWxzZSBkZXBsb3ltZW50IHdpbGwgYmUgc2tpcHBlZCBpZiB0aGUgdGVtcGxhdGUgaXMgaWRlbnRpY2FsXG4gICAqL1xuICByZWFkb25seSBmb3JjZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEV4dHJhIHBhcmFtZXRlcnMgZm9yIENsb3VkRm9ybWF0aW9uXG4gICAqIEBkZWZhdWx0IC0gbm8gYWRkaXRpb25hbCBwYXJhbWV0ZXJzIHdpbGwgYmUgcGFzc2VkIHRvIHRoZSB0ZW1wbGF0ZVxuICAgKi9cbiAgcmVhZG9ubHkgcGFyYW1ldGVycz86IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB8IHVuZGVmaW5lZCB9O1xuXG4gIC8qKlxuICAgKiBVc2UgcHJldmlvdXMgdmFsdWVzIGZvciB1bnNwZWNpZmllZCBwYXJhbWV0ZXJzXG4gICAqXG4gICAqIElmIG5vdCBzZXQsIGFsbCBwYXJhbWV0ZXJzIG11c3QgYmUgc3BlY2lmaWVkIGZvciBldmVyeSBkZXBsb3ltZW50LlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSB1c2VQcmV2aW91c1BhcmFtZXRlcnM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBEaXNwbGF5IG1vZGUgZm9yIHN0YWNrIGRlcGxveW1lbnQgcHJvZ3Jlc3MuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gU3RhY2tBY3Rpdml0eVByb2dyZXNzLkJhciAtIHN0YWNrIGV2ZW50cyB3aWxsIGJlIGRpc3BsYXllZCBmb3JcbiAgICogICB0aGUgcmVzb3VyY2UgY3VycmVudGx5IGJlaW5nIGRlcGxveWVkLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvZ3Jlc3M/OiBTdGFja0FjdGl2aXR5UHJvZ3Jlc3M7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgd2UgYXJlIG9uIGEgQ0kgc3lzdGVtXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBjaT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFJvbGxiYWNrIGZhaWxlZCBkZXBsb3ltZW50c1xuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSByb2xsYmFjaz86IGJvb2xlYW47XG5cbiAgLypcbiAgICogV2hldGhlciB0byBwZXJmb3JtIGEgJ2hvdHN3YXAnIGRlcGxveW1lbnQuXG4gICAqIEEgJ2hvdHN3YXAnIGRlcGxveW1lbnQgd2lsbCBhdHRlbXB0IHRvIHNob3J0LWNpcmN1aXQgQ2xvdWRGb3JtYXRpb25cbiAgICogYW5kIHVwZGF0ZSB0aGUgYWZmZWN0ZWQgcmVzb3VyY2VzIGxpa2UgTGFtYmRhIGZ1bmN0aW9ucyBkaXJlY3RseS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBgSG90c3dhcE1vZGUuRlVMTF9ERVBMT1lNRU5UYCBmb3IgcmVndWxhciBkZXBsb3ltZW50cywgYEhvdHN3YXBNb2RlLkhPVFNXQVBfT05MWWAgZm9yICd3YXRjaCcgZGVwbG95bWVudHNcbiAgICovXG4gIHJlYWRvbmx5IGhvdHN3YXA/OiBIb3Rzd2FwTW9kZTtcblxuICAvKipcbiAgKiBQcm9wZXJ0aWVzIHRoYXQgY29uZmlndXJlIGhvdHN3YXAgYmVoYXZpb3JcbiAgKi9cbiAgcmVhZG9ubHkgaG90c3dhcFByb3BlcnR5T3ZlcnJpZGVzPzogSG90c3dhcFByb3BlcnR5T3ZlcnJpZGVzO1xuXG4gIC8qKlxuICAgKiBUaGUgZXh0cmEgc3RyaW5nIHRvIGFwcGVuZCB0byB0aGUgVXNlci1BZ2VudCBoZWFkZXIgd2hlbiBwZXJmb3JtaW5nIEFXUyBTREsgY2FsbHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm90aGluZyBleHRyYSBpcyBhcHBlbmRlZCB0byB0aGUgVXNlci1BZ2VudCBoZWFkZXJcbiAgICovXG4gIHJlYWRvbmx5IGV4dHJhVXNlckFnZW50Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIGV4aXN0aW5nIHJlc291cmNlcyB0byBiZSBJTVBPUlRFRCBpbnRvIHRoZSBzdGFjaywgaW5zdGVhZCBvZiBiZWluZyBDUkVBVEVEXG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZXNUb0ltcG9ydD86IFJlc291cmNlc1RvSW1wb3J0O1xuXG4gIC8qKlxuICAgKiBJZiBwcmVzZW50LCB1c2UgdGhpcyBnaXZlbiB0ZW1wbGF0ZSBpbnN0ZWFkIG9mIHRoZSBzdG9yZWQgb25lXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVXNlIHRoZSBzdG9yZWQgdGVtcGxhdGVcbiAgICovXG4gIHJlYWRvbmx5IG92ZXJyaWRlVGVtcGxhdGU/OiBhbnk7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gYnVpbGQvcHVibGlzaCBhc3NldHMgaW4gcGFyYWxsZWxcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZSBUbyByZW1haW4gYmFja3dhcmQgY29tcGF0aWJsZS5cbiAgICovXG4gIHJlYWRvbmx5IGFzc2V0UGFyYWxsZWxpc20/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGRlcGxveSBpZiB0aGUgYXBwIGNvbnRhaW5zIG5vIHN0YWNrcy5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIGlnbm9yZU5vU3RhY2tzPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSb2xsYmFja1N0YWNrT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBTdGFjayB0byByb2xsIGJhY2tcbiAgICovXG4gIHJlYWRvbmx5IHN0YWNrOiBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3Q7XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGlvbiByb2xlIGZvciB0aGUgZGVwbG95bWVudCAocGFzcyB0aHJvdWdoIHRvIENsb3VkRm9ybWF0aW9uKVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEN1cnJlbnQgcm9sZVxuICAgKi9cbiAgcmVhZG9ubHkgcm9sZUFybj86IHN0cmluZztcblxuICAvKipcbiAgICogRG9uJ3Qgc2hvdyBzdGFjayBkZXBsb3ltZW50IGV2ZW50cywganVzdCB3YWl0XG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBxdWlldD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgd2UgYXJlIG9uIGEgQ0kgc3lzdGVtXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBjaT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIHRvb2xraXQgc3RhY2ssIGlmIG5vdCB0aGUgZGVmYXVsdCBuYW1lXG4gICAqXG4gICAqIEBkZWZhdWx0ICdDREtUb29sa2l0J1xuICAgKi9cbiAgcmVhZG9ubHkgdG9vbGtpdFN0YWNrTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0byBmb3JjZSBhIHJvbGxiYWNrIG9yIG5vdFxuICAgKlxuICAgKiBGb3JjaW5nIGEgcm9sbGJhY2sgd2lsbCBvcnBoYW4gYWxsIHVuZGVsZXRhYmxlIHJlc291cmNlcy5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGZvcmNlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogT3JwaGFuIHRoZSByZXNvdXJjZXMgd2l0aCB0aGUgZ2l2ZW4gbG9naWNhbCBJRHNcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBvcnBoYW5pbmdcbiAgICovXG4gIHJlYWRvbmx5IG9ycGhhbkxvZ2ljYWxJZHM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogRGlzcGxheSBtb2RlIGZvciBzdGFjayBkZXBsb3ltZW50IHByb2dyZXNzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFN0YWNrQWN0aXZpdHlQcm9ncmVzcy5CYXIgLSBzdGFjayBldmVudHMgd2lsbCBiZSBkaXNwbGF5ZWQgZm9yXG4gICAqICAgdGhlIHJlc291cmNlIGN1cnJlbnRseSBiZWluZyBkZXBsb3llZC5cbiAgICovXG4gIHJlYWRvbmx5IHByb2dyZXNzPzogU3RhY2tBY3Rpdml0eVByb2dyZXNzO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHZhbGlkYXRlIHRoZSB2ZXJzaW9uIG9mIHRoZSBib290c3RyYXAgc3RhY2sgcGVybWlzc2lvbnNcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgdmFsaWRhdGVCb290c3RyYXBTdGFja1ZlcnNpb24/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJvbGxiYWNrU3RhY2tSZXN1bHQge1xuICByZWFkb25seSBub3RJblJvbGxiYWNrYWJsZVN0YXRlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3VjY2Vzcz86IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBBc3NldE9wdGlvbnMge1xuICAvKipcbiAgICogU3RhY2sgd2l0aCBhc3NldHMgdG8gYnVpbGQuXG4gICAqL1xuICByZWFkb25seSBzdGFjazogY3hhcGkuQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0O1xuXG4gIC8qKlxuICAgKiBFeGVjdXRpb24gcm9sZSBmb3IgdGhlIGJ1aWxkaW5nLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEN1cnJlbnQgcm9sZVxuICAgKi9cbiAgcmVhZG9ubHkgcm9sZUFybj86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCdWlsZFN0YWNrQXNzZXRzT3B0aW9ucyBleHRlbmRzIEFzc2V0T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBPcHRpb25zIHRvIHBhc3Mgb24gdG8gYGJ1aWxkQXNzZXRzKClgIGZ1bmN0aW9uXG4gICAqL1xuICByZWFkb25seSBidWlsZE9wdGlvbnM/OiBCdWlsZEFzc2V0c09wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFN0YWNrIG5hbWUgdGhpcyBhc3NldCBpcyBmb3JcbiAgICovXG4gIHJlYWRvbmx5IHN0YWNrTmFtZT86IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIFB1Ymxpc2hTdGFja0Fzc2V0c09wdGlvbnMgZXh0ZW5kcyBBc3NldE9wdGlvbnMge1xuICAvKipcbiAgICogT3B0aW9ucyB0byBwYXNzIG9uIHRvIGBwdWJsaXNoQXNlc3RzKClgIGZ1bmN0aW9uXG4gICAqL1xuICByZWFkb25seSBwdWJsaXNoT3B0aW9ucz86IE9taXQ8UHVibGlzaEFzc2V0c09wdGlvbnMsICdidWlsZEFzc2V0cyc+O1xuXG4gIC8qKlxuICAgKiBTdGFjayBuYW1lIHRoaXMgYXNzZXQgaXMgZm9yXG4gICAqL1xuICByZWFkb25seSBzdGFja05hbWU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVzdHJveVN0YWNrT3B0aW9ucyB7XG4gIHN0YWNrOiBjeGFwaS5DbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3Q7XG4gIGRlcGxveU5hbWU/OiBzdHJpbmc7XG4gIHJvbGVBcm4/OiBzdHJpbmc7XG4gIHF1aWV0PzogYm9vbGVhbjtcbiAgZm9yY2U/OiBib29sZWFuO1xuICBjaT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RhY2tFeGlzdHNPcHRpb25zIHtcbiAgc3RhY2s6IGN4YXBpLkNsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdDtcbiAgZGVwbG95TmFtZT86IHN0cmluZztcbiAgdHJ5TG9va3VwUm9sZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVwbG95bWVudHNQcm9wcyB7XG4gIHNka1Byb3ZpZGVyOiBTZGtQcm92aWRlcjtcbiAgcmVhZG9ubHkgdG9vbGtpdFN0YWNrTmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgcXVpZXQ/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFNjb3BlIGZvciBhIHNpbmdsZSBzZXQgb2YgZGVwbG95bWVudHMgZnJvbSBhIHNldCBvZiBDbG91ZCBBc3NlbWJseSBBcnRpZmFjdHNcbiAqXG4gKiBNYW5hZ2VzIGxvb2t1cCBvZiBTREtzLCBCb290c3RyYXAgc3RhY2tzLCBldGMuXG4gKi9cbmV4cG9ydCBjbGFzcyBEZXBsb3ltZW50cyB7XG4gIHB1YmxpYyByZWFkb25seSBlbnZzOiBFbnZpcm9ubWVudEFjY2VzcztcblxuICAvKipcbiAgICogU0RLIHByb3ZpZGVyIGZvciBhc3NldCBwdWJsaXNoaW5nIChkbyBub3QgdXNlIGZvciBhbnl0aGluZyBlbHNlKS5cbiAgICpcbiAgICogVGhpcyBTREsgcHJvdmlkZXIgaXMgb25seSBhbGxvd2VkIHRvIGJlIHVzZWQgZm9yIHRoYXQgcHVycG9zZSwgbm90aGluZyBlbHNlLlxuICAgKlxuICAgKiBJdCdzIG5vdCBhIGRpZmZlcmVudCBvYmplY3QsIGJ1dCB0aGUgZmllbGQgbmFtZSBzaG91bGQgaW1wbHkgdGhhdCB0aGlzXG4gICAqIG9iamVjdCBzaG91bGQgbm90IGJlIHVzZWQgZGlyZWN0bHksIGV4Y2VwdCB0byBwYXNzIHRvIGFzc2V0IGhhbmRsaW5nIHJvdXRpbmVzLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBhc3NldFNka1Byb3ZpZGVyOiBTZGtQcm92aWRlcjtcblxuICAvKipcbiAgICogU0RLIHByb3ZpZGVyIGZvciBwYXNzaW5nIHRvIGRlcGxveVN0YWNrXG4gICAqXG4gICAqIFRoaXMgU0RLIHByb3ZpZGVyIGlzIG9ubHkgYWxsb3dlZCB0byBiZSB1c2VkIGZvciB0aGF0IHB1cnBvc2UsIG5vdGhpbmcgZWxzZS5cbiAgICpcbiAgICogSXQncyBub3QgYSBkaWZmZXJlbnQgb2JqZWN0LCBidXQgdGhlIGZpZWxkIG5hbWUgc2hvdWxkIGltcGx5IHRoYXQgdGhpc1xuICAgKiBvYmplY3Qgc2hvdWxkIG5vdCBiZSB1c2VkIGRpcmVjdGx5LCBleGNlcHQgdG8gcGFzcyB0byBgZGVwbG95U3RhY2tgLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBkZXBsb3lTdGFja1Nka1Byb3ZpZGVyOiBTZGtQcm92aWRlcjtcblxuICBwcml2YXRlIHJlYWRvbmx5IHB1Ymxpc2hlckNhY2hlID0gbmV3IE1hcDxjZGtfYXNzZXRzLkFzc2V0TWFuaWZlc3QsIGNka19hc3NldHMuQXNzZXRQdWJsaXNoaW5nPigpO1xuXG4gIHByaXZhdGUgX2FsbG93Q3Jvc3NBY2NvdW50QXNzZXRQdWJsaXNoaW5nOiBib29sZWFuIHwgdW5kZWZpbmVkO1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHByb3BzOiBEZXBsb3ltZW50c1Byb3BzKSB7XG4gICAgdGhpcy5hc3NldFNka1Byb3ZpZGVyID0gcHJvcHMuc2RrUHJvdmlkZXI7XG4gICAgdGhpcy5kZXBsb3lTdGFja1Nka1Byb3ZpZGVyID0gcHJvcHMuc2RrUHJvdmlkZXI7XG4gICAgdGhpcy5lbnZzID0gbmV3IEVudmlyb25tZW50QWNjZXNzKHByb3BzLnNka1Byb3ZpZGVyLCBwcm9wcy50b29sa2l0U3RhY2tOYW1lID8/IERFRkFVTFRfVE9PTEtJVF9TVEFDS19OQU1FKTtcbiAgfVxuXG4gIC8qKlxuICAgKiB