UNPKG

49.3 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.DefaultStackSynthesizer = exports.BOOTSTRAP_QUALIFIER_CONTEXT = void 0;
5const jsiiDeprecationWarnings = require("../../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const cxapi = require("@aws-cdk/cx-api");
8const cfn_fn_1 = require("../cfn-fn");
9const cfn_parameter_1 = require("../cfn-parameter");
10const cfn_rule_1 = require("../cfn-rule");
11const token_1 = require("../token");
12const _asset_manifest_builder_1 = require("./_asset-manifest-builder");
13const _shared_1 = require("./_shared");
14const stack_synthesizer_1 = require("./stack-synthesizer");
15exports.BOOTSTRAP_QUALIFIER_CONTEXT = '@aws-cdk/core:bootstrapQualifier';
16/* eslint-disable max-len */
17/**
18 * The minimum bootstrap stack version required by this app.
19 */
20const MIN_BOOTSTRAP_STACK_VERSION = 6;
21/**
22 * The minimum bootstrap stack version required
23 * to use the lookup role.
24 */
25const MIN_LOOKUP_ROLE_BOOTSTRAP_STACK_VERSION = 8;
26/**
27 * Uses conventionally named roles and asset storage locations
28 *
29 * This synthesizer:
30 *
31 * - Supports cross-account deployments (the CLI can have credentials to one
32 * account, and you can still deploy to another account by assuming roles with
33 * well-known names in the other account).
34 * - Supports the **CDK Pipelines** library.
35 *
36 * Requires the environment to have been bootstrapped with Bootstrap Stack V2
37 * (also known as "modern bootstrap stack"). The synthesizer adds a version
38 * check to the template, to make sure the bootstrap stack is recent enough
39 * to support all features expected by this synthesizer.
40 */
41class DefaultStackSynthesizer extends stack_synthesizer_1.StackSynthesizer {
42 constructor(props = {}) {
43 super();
44 this.props = props;
45 this.assetManifest = new _asset_manifest_builder_1.AssetManifestBuilder();
46 try {
47 jsiiDeprecationWarnings._aws_cdk_core_DefaultStackSynthesizerProps(props);
48 }
49 catch (error) {
50 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
51 Error.captureStackTrace(error, DefaultStackSynthesizer);
52 }
53 throw error;
54 }
55 this.useLookupRoleForStackOperations = props.useLookupRoleForStackOperations ?? true;
56 for (const key in props) {
57 if (props.hasOwnProperty(key)) {
58 validateNoToken(key);
59 }
60 }
61 function validateNoToken(key) {
62 const prop = props[key];
63 if (typeof prop === 'string' && token_1.Token.isUnresolved(prop)) {
64 throw new Error(`DefaultSynthesizer property '${key}' cannot contain tokens; only the following placeholder strings are allowed: ` + [
65 '${Qualifier}',
66 cxapi.EnvironmentPlaceholders.CURRENT_REGION,
67 cxapi.EnvironmentPlaceholders.CURRENT_ACCOUNT,
68 cxapi.EnvironmentPlaceholders.CURRENT_PARTITION,
69 ].join(', '));
70 }
71 }
72 }
73 bind(stack) {
74 try {
75 jsiiDeprecationWarnings._aws_cdk_core_Stack(stack);
76 }
77 catch (error) {
78 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
79 Error.captureStackTrace(error, this.bind);
80 }
81 throw error;
82 }
83 if (this._stack !== undefined) {
84 throw new Error('A StackSynthesizer can only be used for one Stack: create a new instance to use with a different Stack');
85 }
86 this._stack = stack;
87 const qualifier = this.props.qualifier ?? stack.node.tryGetContext(exports.BOOTSTRAP_QUALIFIER_CONTEXT) ?? DefaultStackSynthesizer.DEFAULT_QUALIFIER;
88 this.qualifier = qualifier;
89 const spec = new _shared_1.StringSpecializer(stack, qualifier);
90 /* eslint-disable max-len */
91 this.bucketName = spec.specialize(this.props.fileAssetsBucketName ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSETS_BUCKET_NAME);
92 this.repositoryName = spec.specialize(this.props.imageAssetsRepositoryName ?? DefaultStackSynthesizer.DEFAULT_IMAGE_ASSETS_REPOSITORY_NAME);
93 this._deployRoleArn = spec.specialize(this.props.deployRoleArn ?? DefaultStackSynthesizer.DEFAULT_DEPLOY_ROLE_ARN);
94 this._cloudFormationExecutionRoleArn = spec.specialize(this.props.cloudFormationExecutionRole ?? DefaultStackSynthesizer.DEFAULT_CLOUDFORMATION_ROLE_ARN);
95 this.fileAssetPublishingRoleArn = spec.specialize(this.props.fileAssetPublishingRoleArn ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PUBLISHING_ROLE_ARN);
96 this.imageAssetPublishingRoleArn = spec.specialize(this.props.imageAssetPublishingRoleArn ?? DefaultStackSynthesizer.DEFAULT_IMAGE_ASSET_PUBLISHING_ROLE_ARN);
97 this.lookupRoleArn = spec.specialize(this.props.lookupRoleArn ?? DefaultStackSynthesizer.DEFAULT_LOOKUP_ROLE_ARN);
98 this.bucketPrefix = spec.specialize(this.props.bucketPrefix ?? DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX);
99 this.dockerTagPrefix = spec.specialize(this.props.dockerTagPrefix ?? DefaultStackSynthesizer.DEFAULT_DOCKER_ASSET_PREFIX);
100 this.bootstrapStackVersionSsmParameter = spec.qualifierOnly(this.props.bootstrapStackVersionSsmParameter ?? DefaultStackSynthesizer.DEFAULT_BOOTSTRAP_STACK_VERSION_SSM_PARAMETER);
101 }
102 addFileAsset(asset) {
103 try {
104 jsiiDeprecationWarnings._aws_cdk_core_FileAssetSource(asset);
105 }
106 catch (error) {
107 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
108 Error.captureStackTrace(error, this.addFileAsset);
109 }
110 throw error;
111 }
112 _shared_1.assertBound(this.stack);
113 _shared_1.assertBound(this.bucketName);
114 _shared_1.assertBound(this.bucketPrefix);
115 return this.assetManifest.addFileAssetDefault(asset, this.stack, this.bucketName, this.bucketPrefix, {
116 assumeRoleArn: this.fileAssetPublishingRoleArn,
117 assumeRoleExternalId: this.props.fileAssetPublishingExternalId,
118 });
119 }
120 addDockerImageAsset(asset) {
121 try {
122 jsiiDeprecationWarnings._aws_cdk_core_DockerImageAssetSource(asset);
123 }
124 catch (error) {
125 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
126 Error.captureStackTrace(error, this.addDockerImageAsset);
127 }
128 throw error;
129 }
130 _shared_1.assertBound(this.stack);
131 _shared_1.assertBound(this.repositoryName);
132 _shared_1.assertBound(this.dockerTagPrefix);
133 return this.assetManifest.addDockerImageAssetDefault(asset, this.stack, this.repositoryName, this.dockerTagPrefix, {
134 assumeRoleArn: this.imageAssetPublishingRoleArn,
135 assumeRoleExternalId: this.props.imageAssetPublishingExternalId,
136 });
137 }
138 synthesizeStackTemplate(stack, session) {
139 try {
140 jsiiDeprecationWarnings._aws_cdk_core_Stack(stack);
141 jsiiDeprecationWarnings._aws_cdk_core_ISynthesisSession(session);
142 }
143 catch (error) {
144 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
145 Error.captureStackTrace(error, this.synthesizeStackTemplate);
146 }
147 throw error;
148 }
149 stack._synthesizeTemplate(session, this.lookupRoleArn);
150 }
151 /**
152 * Synthesize the associated stack to the session
153 */
154 synthesize(session) {
155 try {
156 jsiiDeprecationWarnings._aws_cdk_core_ISynthesisSession(session);
157 }
158 catch (error) {
159 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
160 Error.captureStackTrace(error, this.synthesize);
161 }
162 throw error;
163 }
164 _shared_1.assertBound(this.stack);
165 _shared_1.assertBound(this.qualifier);
166 // Must be done here -- if it's done in bind() (called in the Stack's constructor)
167 // then it will become impossible to set context after that.
168 //
169 // If it's done AFTER _synthesizeTemplate(), then the template won't contain the
170 // right constructs.
171 if (this.props.generateBootstrapVersionRule ?? true) {
172 addBootstrapVersionRule(this.stack, MIN_BOOTSTRAP_STACK_VERSION, this.bootstrapStackVersionSsmParameter);
173 }
174 this.synthesizeStackTemplate(this.stack, session);
175 const templateAsset = this.addFileAsset(_shared_1.stackTemplateFileAsset(this.stack, session));
176 const assetManifestId = this.assetManifest.writeManifest(this.stack, session, {
177 requiresBootstrapStackVersion: MIN_BOOTSTRAP_STACK_VERSION,
178 bootstrapStackVersionSsmParameter: this.bootstrapStackVersionSsmParameter,
179 });
180 this.emitStackArtifact(this.stack, session, {
181 assumeRoleExternalId: this.props.deployRoleExternalId,
182 assumeRoleArn: this._deployRoleArn,
183 cloudFormationExecutionRoleArn: this._cloudFormationExecutionRoleArn,
184 stackTemplateAssetObjectUrl: templateAsset.s3ObjectUrlWithPlaceholders,
185 requiresBootstrapStackVersion: MIN_BOOTSTRAP_STACK_VERSION,
186 bootstrapStackVersionSsmParameter: this.bootstrapStackVersionSsmParameter,
187 additionalDependencies: [assetManifestId],
188 lookupRole: this.useLookupRoleForStackOperations && this.lookupRoleArn ? {
189 arn: this.lookupRoleArn,
190 assumeRoleExternalId: this.props.lookupRoleExternalId,
191 requiresBootstrapStackVersion: MIN_LOOKUP_ROLE_BOOTSTRAP_STACK_VERSION,
192 bootstrapStackVersionSsmParameter: this.bootstrapStackVersionSsmParameter,
193 } : undefined,
194 });
195 }
196 /**
197 * Returns the ARN of the deploy Role.
198 */
199 get deployRoleArn() {
200 if (!this._deployRoleArn) {
201 throw new Error('deployRoleArn getter can only be called after the synthesizer has been bound to a Stack');
202 }
203 return this._deployRoleArn;
204 }
205 /**
206 * Returns the ARN of the CFN execution Role.
207 */
208 get cloudFormationExecutionRoleArn() {
209 if (!this._cloudFormationExecutionRoleArn) {
210 throw new Error('cloudFormationExecutionRoleArn getter can only be called after the synthesizer has been bound to a Stack');
211 }
212 return this._cloudFormationExecutionRoleArn;
213 }
214 get stack() {
215 return this._stack;
216 }
217}
218exports.DefaultStackSynthesizer = DefaultStackSynthesizer;
219_a = JSII_RTTI_SYMBOL_1;
220DefaultStackSynthesizer[_a] = { fqn: "@aws-cdk/core.DefaultStackSynthesizer", version: "1.204.0" };
221/**
222 * Default ARN qualifier
223 */
224DefaultStackSynthesizer.DEFAULT_QUALIFIER = 'hnb659fds';
225/**
226 * Default CloudFormation role ARN.
227 */
228DefaultStackSynthesizer.DEFAULT_CLOUDFORMATION_ROLE_ARN = 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-cfn-exec-role-${AWS::AccountId}-${AWS::Region}';
229/**
230 * Default deploy role ARN.
231 */
232DefaultStackSynthesizer.DEFAULT_DEPLOY_ROLE_ARN = 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-deploy-role-${AWS::AccountId}-${AWS::Region}';
233/**
234 * Default asset publishing role ARN for file (S3) assets.
235 */
236DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PUBLISHING_ROLE_ARN = 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-file-publishing-role-${AWS::AccountId}-${AWS::Region}';
237/**
238 * Default asset publishing role ARN for image (ECR) assets.
239 */
240DefaultStackSynthesizer.DEFAULT_IMAGE_ASSET_PUBLISHING_ROLE_ARN = 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-image-publishing-role-${AWS::AccountId}-${AWS::Region}';
241/**
242 * Default lookup role ARN for missing values.
243 */
244DefaultStackSynthesizer.DEFAULT_LOOKUP_ROLE_ARN = 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-${Qualifier}-lookup-role-${AWS::AccountId}-${AWS::Region}';
245/**
246 * Default image assets repository name
247 */
248DefaultStackSynthesizer.DEFAULT_IMAGE_ASSETS_REPOSITORY_NAME = 'cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}';
249/**
250 * Default file assets bucket name
251 */
252DefaultStackSynthesizer.DEFAULT_FILE_ASSETS_BUCKET_NAME = 'cdk-${Qualifier}-assets-${AWS::AccountId}-${AWS::Region}';
253/**
254 * Name of the CloudFormation Export with the asset key name
255 */
256DefaultStackSynthesizer.DEFAULT_FILE_ASSET_KEY_ARN_EXPORT_NAME = 'CdkBootstrap-${Qualifier}-FileAssetKeyArn';
257/**
258 * Default file asset prefix
259 */
260DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX = '';
261/**
262 * Default Docker asset prefix
263 */
264DefaultStackSynthesizer.DEFAULT_DOCKER_ASSET_PREFIX = '';
265/**
266 * Default bootstrap stack version SSM parameter.
267 */
268DefaultStackSynthesizer.DEFAULT_BOOTSTRAP_STACK_VERSION_SSM_PARAMETER = '/cdk-bootstrap/${Qualifier}/version';
269/**
270 * Add a CfnRule to the Stack which checks the current version of the bootstrap stack this template is targeting
271 *
272 * The CLI normally checks this, but in a pipeline the CLI is not involved
273 * so we encode this rule into the template in a way that CloudFormation will check it.
274 */
275function addBootstrapVersionRule(stack, requiredVersion, bootstrapStackVersionSsmParameter) {
276 // Because of https://github.com/aws/aws-cdk/blob/master/packages/assert-internal/lib/synth-utils.ts#L74
277 // synthesize() may be called more than once on a stack in unit tests, and the below would break
278 // if we execute it a second time. Guard against the constructs already existing.
279 if (stack.node.tryFindChild('BootstrapVersion')) {
280 return;
281 }
282 const param = new cfn_parameter_1.CfnParameter(stack, 'BootstrapVersion', {
283 type: 'AWS::SSM::Parameter::Value<String>',
284 description: `Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. ${cxapi.SSMPARAM_NO_INVALIDATE}`,
285 default: bootstrapStackVersionSsmParameter,
286 });
287 // There is no >= check in CloudFormation, so we have to check the number
288 // is NOT in [1, 2, 3, ... <required> - 1]
289 const oldVersions = range(1, requiredVersion).map(n => `${n}`);
290 new cfn_rule_1.CfnRule(stack, 'CheckBootstrapVersion', {
291 assertions: [
292 {
293 assert: cfn_fn_1.Fn.conditionNot(cfn_fn_1.Fn.conditionContains(oldVersions, param.valueAsString)),
294 assertDescription: `CDK bootstrap stack version ${requiredVersion} required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.`,
295 },
296 ],
297 });
298}
299function range(startIncl, endExcl) {
300 const ret = new Array();
301 for (let i = startIncl; i < endExcl; i++) {
302 ret.push(i);
303 }
304 return ret;
305}
306//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVmYXVsdC1zeW50aGVzaXplci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImRlZmF1bHQtc3ludGhlc2l6ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEseUNBQXlDO0FBRXpDLHNDQUErQjtBQUMvQixvREFBZ0Q7QUFDaEQsMENBQXNDO0FBR3RDLG9DQUFpQztBQUNqQyx1RUFBaUU7QUFDakUsdUNBQW1GO0FBQ25GLDJEQUF1RDtBQUUxQyxRQUFBLDJCQUEyQixHQUFHLGtDQUFrQyxDQUFDO0FBRTlFLDRCQUE0QjtBQUU1Qjs7R0FFRztBQUNILE1BQU0sMkJBQTJCLEdBQUcsQ0FBQyxDQUFDO0FBRXRDOzs7R0FHRztBQUNILE1BQU0sdUNBQXVDLEdBQUcsQ0FBQyxDQUFDO0FBZ01sRDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQWEsdUJBQXdCLFNBQVEsb0NBQWdCO0lBNEUzRCxZQUE2QixRQUFzQyxFQUFFO1FBQ25FLEtBQUssRUFBRSxDQUFDO1FBRG1CLFVBQUssR0FBTCxLQUFLLENBQW1DO1FBRjdELGtCQUFhLEdBQUcsSUFBSSw4Q0FBb0IsRUFBRSxDQUFDOzs7Ozs7K0NBMUV4Qyx1QkFBdUI7Ozs7UUE4RWhDLElBQUksQ0FBQywrQkFBK0IsR0FBRyxLQUFLLENBQUMsK0JBQStCLElBQUksSUFBSSxDQUFDO1FBRXJGLEtBQUssTUFBTSxHQUFHLElBQUksS0FBSyxFQUFFO1lBQ3ZCLElBQUksS0FBSyxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsRUFBRTtnQkFDN0IsZUFBZSxDQUFDLEdBQXlDLENBQUMsQ0FBQzthQUM1RDtTQUNGO1FBRUQsU0FBUyxlQUFlLENBQStDLEdBQU07WUFDM0UsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hCLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLGFBQUssQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ3hELE1BQU0sSUFB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QUUsQ0FBQyxHQUFHLE9BQU8sRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUN4QyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQ2I7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdAYXdzLWNkay9jeC1hcGknO1xuaW1wb3J0IHsgRG9ja2VySW1hZ2VBc3NldExvY2F0aW9uLCBEb2NrZXJJbWFnZUFzc2V0U291cmNlLCBGaWxlQXNzZXRMb2NhdGlvbiwgRmlsZUFzc2V0U291cmNlIH0gZnJvbSAnLi4vYXNzZXRzJztcbmltcG9ydCB7IEZuIH0gZnJvbSAnLi4vY2ZuLWZuJztcbmltcG9ydCB7IENmblBhcmFtZXRlciB9IGZyb20gJy4uL2Nmbi1wYXJhbWV0ZXInO1xuaW1wb3J0IHsgQ2ZuUnVsZSB9IGZyb20gJy4uL2Nmbi1ydWxlJztcbmltcG9ydCB7IElTeW50aGVzaXNTZXNzaW9uIH0gZnJvbSAnLi4vY29uc3RydWN0LWNvbXBhdCc7XG5pbXBvcnQgeyBTdGFjayB9IGZyb20gJy4uL3N0YWNrJztcbmltcG9ydCB7IFRva2VuIH0gZnJvbSAnLi4vdG9rZW4nO1xuaW1wb3J0IHsgQXNzZXRNYW5pZmVzdEJ1aWxkZXIgfSBmcm9tICcuL19hc3NldC1tYW5pZmVzdC1idWlsZGVyJztcbmltcG9ydCB7IGFzc2VydEJvdW5kLCBTdHJpbmdTcGVjaWFsaXplciwgc3RhY2tUZW1wbGF0ZUZpbGVBc3NldCB9IGZyb20gJy4vX3NoYXJlZCc7XG5pbXBvcnQgeyBTdGFja1N5bnRoZXNpemVyIH0gZnJvbSAnLi9zdGFjay1zeW50aGVzaXplcic7XG5cbmV4cG9ydCBjb25zdCBCT09UU1RSQVBfUVVBTElGSUVSX0NPTlRFWFQgPSAnQGF3cy1jZGsvY29yZTpib290c3RyYXBRdWFsaWZpZXInO1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBtYXgtbGVuICovXG5cbi8qKlxuICogVGhlIG1pbmltdW0gYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gcmVxdWlyZWQgYnkgdGhpcyBhcHAuXG4gKi9cbmNvbnN0IE1JTl9CT09UU1RSQVBfU1RBQ0tfVkVSU0lPTiA9IDY7XG5cbi8qKlxuICogVGhlIG1pbmltdW0gYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gcmVxdWlyZWRcbiAqIHRvIHVzZSB0aGUgbG9va3VwIHJvbGUuXG4gKi9cbmNvbnN0IE1JTl9MT09LVVBfUk9MRV9CT09UU1RSQVBfU1RBQ0tfVkVSU0lPTiA9IDg7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBwcm9wZXJ0aWVzIGZvciBEZWZhdWx0U3RhY2tTeW50aGVzaXplclxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlZmF1bHRTdGFja1N5bnRoZXNpemVyUHJvcHMge1xuICAvKipcbiAgICogTmFtZSBvZiB0aGUgUzMgYnVja2V0IHRvIGhvbGQgZmlsZSBhc3NldHNcbiAgICpcbiAgICogWW91IG11c3Qgc3VwcGx5IHRoaXMgaWYgeW91IGhhdmUgZ2l2ZW4gYSBub24tc3RhbmRhcmQgbmFtZSB0byB0aGUgc3RhZ2luZyBidWNrZXQuXG4gICAqXG4gICAqIFRoZSBwbGFjZWhvbGRlcnMgYCR7UXVhbGlmaWVyfWAsIGAke0FXUzo6QWNjb3VudElkfWAgYW5kIGAke0FXUzo6UmVnaW9ufWAgd2lsbFxuICAgKiBiZSByZXBsYWNlZCB3aXRoIHRoZSB2YWx1ZXMgb2YgcXVhbGlmaWVyIGFuZCB0aGUgc3RhY2sncyBhY2NvdW50IGFuZCByZWdpb24sXG4gICAqIHJlc3BlY3RpdmVseS5cbiAgICpcbiAgICogQGRlZmF1bHQgRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIuREVGQVVMVF9GSUxFX0FTU0VUU19CVUNLRVRfTkFNRVxuICAgKi9cbiAgcmVhZG9ubHkgZmlsZUFzc2V0c0J1Y2tldE5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIEVDUiByZXBvc2l0b3J5IHRvIGhvbGQgRG9ja2VyIEltYWdlIGFzc2V0c1xuICAgKlxuICAgKiBZb3UgbXVzdCBzdXBwbHkgdGhpcyBpZiB5b3UgaGF2ZSBnaXZlbiBhIG5vbi1zdGFuZGFyZCBuYW1lIHRvIHRoZSBFQ1IgcmVwb3NpdG9yeS5cbiAgICpcbiAgICogVGhlIHBsYWNlaG9sZGVycyBgJHtRdWFsaWZpZXJ9YCwgYCR7QVdTOjpBY2NvdW50SWR9YCBhbmQgYCR7QVdTOjpSZWdpb259YCB3aWxsXG4gICAqIGJlIHJlcGxhY2VkIHdpdGggdGhlIHZhbHVlcyBvZiBxdWFsaWZpZXIgYW5kIHRoZSBzdGFjaydzIGFjY291bnQgYW5kIHJlZ2lvbixcbiAgICogcmVzcGVjdGl2ZWx5LlxuICAgKlxuICAgKiBAZGVmYXVsdCBEZWZhdWx0U3RhY2tTeW50aGVzaXplci5ERUZBVUxUX0lNQUdFX0FTU0VUU19SRVBPU0lUT1JZX05BTUVcbiAgICovXG4gIHJlYWRvbmx5IGltYWdlQXNzZXRzUmVwb3NpdG9yeU5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSByb2xlIHRvIHVzZSB0byBwdWJsaXNoIGZpbGUgYXNzZXRzIHRvIHRoZSBTMyBidWNrZXQgaW4gdGhpcyBlbnZpcm9ubWVudFxuICAgKlxuICAgKiBZb3UgbXVzdCBzdXBwbHkgdGhpcyBpZiB5b3UgaGF2ZSBnaXZlbiBhIG5vbi1zdGFuZGFyZCBuYW1lIHRvIHRoZSBwdWJsaXNoaW5nIHJvbGUuXG4gICAqXG4gICAqIFRoZSBwbGFjZWhvbGRlcnMgYCR7UXVhbGlmaWVyfWAsIGAke0FXUzo6QWNjb3VudElkfWAgYW5kIGAke0FXUzo6UmVnaW9ufWAgd2lsbFxuICAgKiBiZSByZXBsYWNlZCB3aXRoIHRoZSB2YWx1ZXMgb2YgcXVhbGlmaWVyIGFuZCB0aGUgc3RhY2sncyBhY2NvdW50IGFuZCByZWdpb24sXG4gICAqIHJlc3BlY3RpdmVseS5cbiAgICpcbiAgICogQGRlZmF1bHQgRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIuREVGQVVMVF9GSUxFX0FTU0VUX1BVQkxJU0hJTkdfUk9MRV9BUk5cbiAgICovXG4gIHJlYWRvbmx5IGZpbGVBc3NldFB1Ymxpc2hpbmdSb2xlQXJuPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBFeHRlcm5hbCBJRCB0byB1c2Ugd2hlbiBhc3N1bWluZyByb2xlIGZvciBmaWxlIGFzc2V0IHB1Ymxpc2hpbmdcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBleHRlcm5hbCBJRFxuICAgKi9cbiAgcmVhZG9ubHkgZmlsZUFzc2V0UHVibGlzaGluZ0V4dGVybmFsSWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSByb2xlIHRvIHVzZSB0byBwdWJsaXNoIGltYWdlIGFzc2V0cyB0byB0aGUgRUNSIHJlcG9zaXRvcnkgaW4gdGhpcyBlbnZpcm9ubWVudFxuICAgKlxuICAgKiBZb3UgbXVzdCBzdXBwbHkgdGhpcyBpZiB5b3UgaGF2ZSBnaXZlbiBhIG5vbi1zdGFuZGFyZCBuYW1lIHRvIHRoZSBwdWJsaXNoaW5nIHJvbGUuXG4gICAqXG4gICAqIFRoZSBwbGFjZWhvbGRlcnMgYCR7UXVhbGlmaWVyfWAsIGAke0FXUzo6QWNjb3VudElkfWAgYW5kIGAke0FXUzo6UmVnaW9ufWAgd2lsbFxuICAgKiBiZSByZXBsYWNlZCB3aXRoIHRoZSB2YWx1ZXMgb2YgcXVhbGlmaWVyIGFuZCB0aGUgc3RhY2sncyBhY2NvdW50IGFuZCByZWdpb24sXG4gICAqIHJlc3BlY3RpdmVseS5cbiAgICpcbiAgICogQGRlZmF1bHQgRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIuREVGQVVMVF9JTUFHRV9BU1NFVF9QVUJMSVNISU5HX1JPTEVfQVJOXG4gICAqL1xuICByZWFkb25seSBpbWFnZUFzc2V0UHVibGlzaGluZ1JvbGVBcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSByb2xlIHRvIHVzZSB0byBsb29rIHVwIHZhbHVlcyBmcm9tIHRoZSB0YXJnZXQgQVdTIGFjY291bnQgZHVyaW5nIHN5bnRoZXNpc1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vbmVcbiAgICovXG4gIHJlYWRvbmx5IGxvb2t1cFJvbGVBcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEV4dGVybmFsIElEIHRvIHVzZSB3aGVuIGFzc3VtaW5nIGxvb2t1cCByb2xlXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZXh0ZXJuYWwgSURcbiAgICovXG4gIHJlYWRvbmx5IGxvb2t1cFJvbGVFeHRlcm5hbElkPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBVc2UgdGhlIGJvb3RzdHJhcHBlZCBsb29rdXAgcm9sZSBmb3IgKHJlYWQtb25seSkgc3RhY2sgb3BlcmF0aW9uc1xuICAgKlxuICAgKiBVc2UgdGhlIGxvb2t1cCByb2xlIHdoZW4gcGVyZm9ybWluZyBhIGBjZGsgZGlmZmAuIElmIHNldCB0byBgZmFsc2VgLCB0aGVcbiAgICogYGRlcGxveSByb2xlYCBjcmVkZW50aWFscyB3aWxsIGJlIHVzZWQgdG8gcGVyZm9ybSBhIGBjZGsgZGlmZmAuXG4gICAqXG4gICAqIFJlcXVpcmVzIGJvb3RzdHJhcCBzdGFjayB2ZXJzaW9uIDguXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHVzZUxvb2t1cFJvbGVGb3JTdGFja09wZXJhdGlvbnM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBFeHRlcm5hbCBJRCB0byB1c2Ugd2hlbiBhc3N1bWluZyByb2xlIGZvciBpbWFnZSBhc3NldCBwdWJsaXNoaW5nXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZXh0ZXJuYWwgSURcbiAgICovXG4gIHJlYWRvbmx5IGltYWdlQXNzZXRQdWJsaXNoaW5nRXh0ZXJuYWxJZD86IHN0cmluZztcblxuICAvKipcbiAgICogRXh0ZXJuYWwgSUQgdG8gdXNlIHdoZW4gYXNzdW1pbmcgcm9sZSBmb3IgY2xvdWRmb3JtYXRpb24gZGVwbG95bWVudHNcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBleHRlcm5hbCBJRFxuICAgKi9cbiAgcmVhZG9ubHkgZGVwbG95Um9sZUV4dGVybmFsSWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSByb2xlIHRvIGFzc3VtZSB0byBpbml0aWF0ZSBhIGRlcGxveW1lbnQgaW4gdGhpcyBlbnZpcm9ubWVudFxuICAgKlxuICAgKiBZb3UgbXVzdCBzdXBwbHkgdGhpcyBpZiB5b3UgaGF2ZSBnaXZlbiBhIG5vbi1zdGFuZGFyZCBuYW1lIHRvIHRoZSBwdWJsaXNoaW5nIHJvbGUuXG4gICAqXG4gICAqIFRoZSBwbGFjZWhvbGRlcnMgYCR7UXVhbGlmaWVyfWAsIGAke0FXUzo6QWNjb3VudElkfWAgYW5kIGAke0FXUzo6UmVnaW9ufWAgd2lsbFxuICAgKiBiZSByZXBsYWNlZCB3aXRoIHRoZSB2YWx1ZXMgb2YgcXVhbGlmaWVyIGFuZCB0aGUgc3RhY2sncyBhY2NvdW50IGFuZCByZWdpb24sXG4gICAqIHJlc3BlY3RpdmVseS5cbiAgICpcbiAgICogQGRlZmF1bHQgRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIuREVGQVVMVF9ERVBMT1lfUk9MRV9BUk5cbiAgICovXG4gIHJlYWRvbmx5IGRlcGxveVJvbGVBcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSByb2xlIENsb3VkRm9ybWF0aW9uIHdpbGwgYXNzdW1lIHdoZW4gZGVwbG95aW5nIHRoZSBTdGFja1xuICAgKlxuICAgKiBZb3UgbXVzdCBzdXBwbHkgdGhpcyBpZiB5b3UgaGF2ZSBnaXZlbiBhIG5vbi1zdGFuZGFyZCBuYW1lIHRvIHRoZSBleGVjdXRpb24gcm9sZS5cbiAgICpcbiAgICogVGhlIHBsYWNlaG9sZGVycyBgJHtRdWFsaWZpZXJ9YCwgYCR7QVdTOjpBY2NvdW50SWR9YCBhbmQgYCR7QVdTOjpSZWdpb259YCB3aWxsXG4gICAqIGJlIHJlcGxhY2VkIHdpdGggdGhlIHZhbHVlcyBvZiBxdWFsaWZpZXIgYW5kIHRoZSBzdGFjaydzIGFjY291bnQgYW5kIHJlZ2lvbixcbiAgICogcmVzcGVjdGl2ZWx5LlxuICAgKlxuICAgKiBAZGVmYXVsdCBEZWZhdWx0U3RhY2tTeW50aGVzaXplci5ERUZBVUxUX0NMT1VERk9STUFUSU9OX1JPTEVfQVJOXG4gICAqL1xuICByZWFkb25seSBjbG91ZEZvcm1hdGlvbkV4ZWN1dGlvblJvbGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE5hbWUgb2YgdGhlIENsb3VkRm9ybWF0aW9uIEV4cG9ydCB3aXRoIHRoZSBhc3NldCBrZXkgbmFtZVxuICAgKlxuICAgKiBZb3UgbXVzdCBzdXBwbHkgdGhpcyBpZiB5b3UgaGF2ZSBnaXZlbiBhIG5vbi1zdGFuZGFyZCBuYW1lIHRvIHRoZSBLTVMga2V5IGV4cG9ydFxuICAgKlxuICAgKiBUaGUgcGxhY2Vob2xkZXJzIGAke1F1YWxpZmllcn1gLCBgJHtBV1M6OkFjY291bnRJZH1gIGFuZCBgJHtBV1M6OlJlZ2lvbn1gIHdpbGxcbiAgICogYmUgcmVwbGFjZWQgd2l0aCB0aGUgdmFsdWVzIG9mIHF1YWxpZmllciBhbmQgdGhlIHN0YWNrJ3MgYWNjb3VudCBhbmQgcmVnaW9uLFxuICAgKiByZXNwZWN0aXZlbHkuXG4gICAqXG4gICAqIEBkZWZhdWx0IERlZmF1bHRTdGFja1N5bnRoZXNpemVyLkRFRkFVTFRfRklMRV9BU1NFVF9LRVlfQVJOX0VYUE9SVF9OQU1FXG4gICAqIEBkZXByZWNhdGVkIFRoaXMgcHJvcGVydHkgaXMgbm90IHVzZWQgYW55bW9yZVxuICAgKi9cbiAgcmVhZG9ubHkgZmlsZUFzc2V0S2V5QXJuRXhwb3J0TmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogUXVhbGlmaWVyIHRvIGRpc2FtYmlndWF0ZSBtdWx0aXBsZSBlbnZpcm9ubWVudHMgaW4gdGhlIHNhbWUgYWNjb3VudFxuICAgKlxuICAgKiBZb3UgY2FuIHVzZSB0aGlzIGFuZCBsZWF2ZSB0aGUgb3RoZXIgbmFtaW5nIHByb3BlcnRpZXMgZW1wdHkgaWYgeW91IGhhdmUgZGVwbG95ZWRcbiAgICogdGhlIGJvb3RzdHJhcCBlbnZpcm9ubWVudCB3aXRoIHN0YW5kYXJkIG5hbWVzIGJ1dCBvbmx5IGRpZmZlcm5ldCBxdWFsaWZpZXJzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFZhbHVlIG9mIGNvbnRleHQga2V5ICdAYXdzLWNkay9jb3JlOmJvb3RzdHJhcFF1YWxpZmllcicgaWYgc2V0LCBvdGhlcndpc2UgYERlZmF1bHRTdGFja1N5bnRoZXNpemVyLkRFRkFVTFRfUVVBTElGSUVSYFxuICAgKi9cbiAgcmVhZG9ubHkgcXVhbGlmaWVyPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGFkZCBhIFJ1bGUgdG8gdGhlIHN0YWNrIHRlbXBsYXRlIHZlcmlmeWluZyB0aGUgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb25cbiAgICpcbiAgICogVGhpcyBnZW5lcmFsbHkgc2hvdWxkIGJlIGxlZnQgc2V0IHRvIGB0cnVlYCwgdW5sZXNzIHlvdSBleHBsaWNpdGx5XG4gICAqIHdhbnQgdG8gYmUgYWJsZSB0byBkZXBsb3kgdG8gYW4gdW5ib290c3RyYXBwZWQgZW52aXJvbm1lbnQuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGdlbmVyYXRlQm9vdHN0cmFwVmVyc2lvblJ1bGU/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBidWNrZXRQcmVmaXggdG8gdXNlIHdoaWxlIHN0b3JpbmcgUzMgQXNzZXRzXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIuREVGQVVMVF9GSUxFX0FTU0VUX1BSRUZJWFxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0UHJlZml4Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIHByZWZpeCB0byB1c2Ugd2hpbGUgdGFnZ2luZyBhbmQgdXBsb2FkaW5nIERvY2tlciBpbWFnZXMgdG8gRUNSLlxuICAgKlxuICAgKiBUaGlzIGRvZXMgbm90IGFkZCBhbnkgc2VwYXJhdG9ycyAtIHRoZSBzb3VyY2UgaGFzaCB3aWxsIGJlIGFwcGVuZGVkIHRvXG4gICAqIHRoaXMgc3RyaW5nIGRpcmVjdGx5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIERlZmF1bHRTdGFja1N5bnRoZXNpemVyLkRFRkFVTFRfRE9DS0VSX0FTU0VUX1BSRUZJWFxuICAgKi9cbiAgcmVhZG9ubHkgZG9ja2VyVGFnUHJlZml4Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBCb290c3RyYXAgc3RhY2sgdmVyc2lvbiBTU00gcGFyYW1ldGVyLlxuICAgKlxuICAgKiBUaGUgcGxhY2Vob2xkZXIgYCR7UXVhbGlmaWVyfWAgd2lsbCBiZSByZXBsYWNlZCB3aXRoIHRoZSB2YWx1ZSBvZiBxdWFsaWZpZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IERlZmF1bHRTdGFja1N5bnRoZXNpemVyLkRFRkFVTFRfQk9PVFNUUkFQX1NUQUNLX1ZFUlNJT05fU1NNX1BBUkFNRVRFUlxuICAgKi9cbiAgcmVhZG9ubHkgYm9vdHN0cmFwU3RhY2tWZXJzaW9uU3NtUGFyYW1ldGVyPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFVzZXMgY29udmVudGlvbmFsbHkgbmFtZWQgcm9sZXMgYW5kIGFzc2V0IHN0b3JhZ2UgbG9jYXRpb25zXG4gKlxuICogVGhpcyBzeW50aGVzaXplcjpcbiAqXG4gKiAtIFN1cHBvcnRzIGNyb3NzLWFjY291bnQgZGVwbG95bWVudHMgKHRoZSBDTEkgY2FuIGhhdmUgY3JlZGVudGlhbHMgdG8gb25lXG4gKiAgIGFjY291bnQsIGFuZCB5b3UgY2FuIHN0aWxsIGRlcGxveSB0byBhbm90aGVyIGFjY291bnQgYnkgYXNzdW1pbmcgcm9sZXMgd2l0aFxuICogICB3ZWxsLWtub3duIG5hbWVzIGluIHRoZSBvdGhlciBhY2NvdW50KS5cbiAqIC0gU3VwcG9ydHMgdGhlICoqQ0RLIFBpcGVsaW5lcyoqIGxpYnJhcnkuXG4gKlxuICogUmVxdWlyZXMgdGhlIGVudmlyb25tZW50IHRvIGhhdmUgYmVlbiBib290c3RyYXBwZWQgd2l0aCBCb290c3RyYXAgU3RhY2sgVjJcbiAqIChhbHNvIGtub3duIGFzIFwibW9kZXJuIGJvb3RzdHJhcCBzdGFja1wiKS4gVGhlIHN5bnRoZXNpemVyIGFkZHMgYSB2ZXJzaW9uXG4gKiBjaGVjayB0byB0aGUgdGVtcGxhdGUsIHRvIG1ha2Ugc3VyZSB0aGUgYm9vdHN0cmFwIHN0YWNrIGlzIHJlY2VudCBlbm91Z2hcbiAqIHRvIHN1cHBvcnQgYWxsIGZlYXR1cmVzIGV4cGVjdGVkIGJ5IHRoaXMgc3ludGhlc2l6ZXIuXG4gKi9cbmV4cG9ydCBjbGFzcyBEZWZhdWx0U3RhY2tTeW50aGVzaXplciBleHRlbmRzIFN0YWNrU3ludGhlc2l6ZXIge1xuICAvKipcbiAgICogRGVmYXVsdCBBUk4gcXVhbGlmaWVyXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfUVVBTElGSUVSID0gJ2huYjY1OWZkcyc7XG5cbiAgLyoqXG4gICAqIERlZmF1bHQgQ2xvdWRGb3JtYXRpb24gcm9sZSBBUk4uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfQ0xPVURGT1JNQVRJT05fUk9MRV9BUk4gPSAnYXJuOiR7QVdTOjpQYXJ0aXRpb259OmlhbTo6JHtBV1M6OkFjY291bnRJZH06cm9sZS9jZGstJHtRdWFsaWZpZXJ9LWNmbi1leGVjLXJvbGUtJHtBV1M6OkFjY291bnRJZH0tJHtBV1M6OlJlZ2lvbn0nO1xuXG4gIC8qKlxuICAgKiBEZWZhdWx0IGRlcGxveSByb2xlIEFSTi5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9ERVBMT1lfUk9MRV9BUk4gPSAnYXJuOiR7QVdTOjpQYXJ0aXRpb259OmlhbTo6JHtBV1M6OkFjY291bnRJZH06cm9sZS9jZGstJHtRdWFsaWZpZXJ9LWRlcGxveS1yb2xlLSR7QVdTOjpBY2NvdW50SWR9LSR7QVdTOjpSZWdpb259JztcblxuICAvKipcbiAgICogRGVmYXVsdCBhc3NldCBwdWJsaXNoaW5nIHJvbGUgQVJOIGZvciBmaWxlIChTMykgYXNzZXRzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0ZJTEVfQVNTRVRfUFVCTElTSElOR19ST0xFX0FSTiA9ICdhcm46JHtBV1M6OlBhcnRpdGlvbn06aWFtOjoke0FXUzo6QWNjb3VudElkfTpyb2xlL2Nkay0ke1F1YWxpZmllcn0tZmlsZS1wdWJsaXNoaW5nLXJvbGUtJHtBV1M6OkFjY291bnRJZH0tJHtBV1M6OlJlZ2lvbn0nO1xuXG4gIC8qKlxuICAgKiBEZWZhdWx0IGFzc2V0IHB1Ymxpc2hpbmcgcm9sZSBBUk4gZm9yIGltYWdlIChFQ1IpIGFzc2V0cy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9JTUFHRV9BU1NFVF9QVUJMSVNISU5HX1JPTEVfQVJOID0gJ2Fybjoke0FXUzo6UGFydGl0aW9ufTppYW06OiR7QVdTOjpBY2NvdW50SWR9OnJvbGUvY2RrLSR7UXVhbGlmaWVyfS1pbWFnZS1wdWJsaXNoaW5nLXJvbGUtJHtBV1M6OkFjY291bnRJZH0tJHtBV1M6OlJlZ2lvbn0nO1xuXG4gIC8qKlxuICAgKiBEZWZhdWx0IGxvb2t1cCByb2xlIEFSTiBmb3IgbWlzc2luZyB2YWx1ZXMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfTE9PS1VQX1JPTEVfQVJOID0gJ2Fybjoke0FXUzo6UGFydGl0aW9ufTppYW06OiR7QVdTOjpBY2NvdW50SWR9OnJvbGUvY2RrLSR7UXVhbGlmaWVyfS1sb29rdXAtcm9sZS0ke0FXUzo6QWNjb3VudElkfS0ke0FXUzo6UmVnaW9ufSc7XG5cbiAgLyoqXG4gICAqIERlZmF1bHQgaW1hZ2UgYXNzZXRzIHJlcG9zaXRvcnkgbmFtZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0lNQUdFX0FTU0VUU19SRVBPU0lUT1JZX05BTUUgPSAnY2RrLSR7UXVhbGlmaWVyfS1jb250YWluZXItYXNzZXRzLSR7QVdTOjpBY2NvdW50SWR9LSR7QVdTOjpSZWdpb259JztcblxuICAvKipcbiAgICogRGVmYXVsdCBmaWxlIGFzc2V0cyBidWNrZXQgbmFtZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0ZJTEVfQVNTRVRTX0JVQ0tFVF9OQU1FID0gJ2Nkay0ke1F1YWxpZmllcn0tYXNzZXRzLSR7QVdTOjpBY2NvdW50SWR9LSR7QVdTOjpSZWdpb259JztcblxuICAvKipcbiAgICogTmFtZSBvZiB0aGUgQ2xvdWRGb3JtYXRpb24gRXhwb3J0IHdpdGggdGhlIGFzc2V0IGtleSBuYW1lXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfRklMRV9BU1NFVF9LRVlfQVJOX0VYUE9SVF9OQU1FID0gJ0Nka0Jvb3RzdHJhcC0ke1F1YWxpZmllcn0tRmlsZUFzc2V0S2V5QXJuJztcblxuICAvKipcbiAgICogRGVmYXVsdCBmaWxlIGFzc2V0IHByZWZpeFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0ZJTEVfQVNTRVRfUFJFRklYID0gJyc7XG4gIC8qKlxuICAgKiBEZWZhdWx0IERvY2tlciBhc3NldCBwcmVmaXhcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9ET0NLRVJfQVNTRVRfUFJFRklYID0gJyc7XG5cbiAgLyoqXG4gICAqIERlZmF1bHQgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gU1NNIHBhcmFtZXRlci5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgREVGQVVMVF9CT09UU1RSQVBfU1RBQ0tfVkVSU0lPTl9TU01fUEFSQU1FVEVSID0gJy9jZGstYm9vdHN0cmFwLyR7UXVhbGlmaWVyfS92ZXJzaW9uJztcblxuICBwcml2YXRlIF9zdGFjaz86IFN0YWNrO1xuICBwcml2YXRlIGJ1Y2tldE5hbWU/OiBzdHJpbmc7XG4gIHByaXZhdGUgcmVwb3NpdG9yeU5hbWU/OiBzdHJpbmc7XG4gIHByaXZhdGUgX2RlcGxveVJvbGVBcm4/OiBzdHJpbmc7XG4gIHByaXZhdGUgX2Nsb3VkRm9ybWF0aW9uRXhlY3V0aW9uUm9sZUFybj86IHN0cmluZztcbiAgcHJpdmF0ZSBmaWxlQXNzZXRQdWJsaXNoaW5nUm9sZUFybj86IHN0cmluZztcbiAgcHJpdmF0ZSBpbWFnZUFzc2V0UHVibGlzaGluZ1JvbGVBcm4/OiBzdHJpbmc7XG4gIHByaXZhdGUgbG9va3VwUm9sZUFybj86IHN0cmluZztcbiAgcHJpdmF0ZSB1c2VMb29rdXBSb2xlRm9yU3RhY2tPcGVyYXRpb25zOiBib29sZWFuO1xuICBwcml2YXRlIHF1YWxpZmllcj86IHN0cmluZztcbiAgcHJpdmF0ZSBidWNrZXRQcmVmaXg/OiBzdHJpbmc7XG4gIHByaXZhdGUgZG9ja2VyVGFnUHJlZml4Pzogc3RyaW5nO1xuICBwcml2YXRlIGJvb3RzdHJhcFN0YWNrVmVyc2lvblNzbVBhcmFtZXRlcj86IHN0cmluZztcblxuICBwcml2YXRlIGFzc2V0TWFuaWZlc3QgPSBuZXcgQXNzZXRNYW5pZmVzdEJ1aWxkZXIoKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHByb3BzOiBEZWZhdWx0U3RhY2tTeW50aGVzaXplclByb3BzID0ge30pIHtcbiAgICBzdXBlcigpO1xuICAgIHRoaXMudXNlTG9va3VwUm9sZUZvclN0YWNrT3BlcmF0aW9ucyA9IHByb3BzLnVzZUxvb2t1cFJvbGVGb3JTdGFja09wZXJhdGlvbnMgPz8gdHJ1ZTtcblxuICAgIGZvciAoY29uc3Qga2V5IGluIHByb3BzKSB7XG4gICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICB2YWxpZGF0ZU5vVG9rZW4oa2V5IGFzIGtleW9mIERlZmF1bHRTdGFja1N5bnRoZXNpemVyUHJvcHMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHZhbGlkYXRlTm9Ub2tlbjxBIGV4dGVuZHMga2V5b2YgRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXJQcm9wcz4oa2V5OiBBKSB7XG4gICAgICBjb25zdCBwcm9wID0gcHJvcHNba2V5XTtcbiAgICAgIGlmICh0eXBlb2YgcHJvcCA9PT0gJ3N0cmluZycgJiYgVG9rZW4uaXNVbnJlc29sdmVkKHByb3ApKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRGVmYXVsdFN5bnRoZXNpemVyIHByb3BlcnR5ICcke2tleX0nIGNhbm5vdCBjb250YWluIHRva2Vuczsgb25seSB0aGUgZm9sbG93aW5nIHBsYWNlaG9sZGVyIHN0cmluZ3MgYXJlIGFsbG93ZWQ6IGAgKyBbXG4gICAgICAgICAgJyR7UXVhbGlmaWVyfScsXG4gICAgICAgICAgY3hhcGkuRW52aXJvbm1lbnRQbGFjZWhvbGRlcnMuQ1VSUkVOVF9SRUdJT04sXG4gICAgICAgICAgY3hhcGkuRW52aXJvbm1lbnRQbGFjZWhvbGRlcnMuQ1VSUkVOVF9BQ0NPVU5ULFxuICAgICAgICAgIGN4YXBpLkVudmlyb25tZW50UGxhY2Vob2xkZXJzLkNVUlJFTlRfUEFSVElUSU9OLFxuICAgICAgICBdLmpvaW4oJywgJykpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBiaW5kKHN0YWNrOiBTdGFjayk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9zdGFjayAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgU3RhY2tTeW50aGVzaXplciBjYW4gb25seSBiZSB1c2VkIGZvciBvbmUgU3RhY2s6IGNyZWF0ZSBhIG5ldyBpbnN0YW5jZSB0byB1c2Ugd2l0aCBhIGRpZmZlcmVudCBTdGFjaycpO1xuICAgIH1cblxuICAgIHRoaXMuX3N0YWNrID0gc3RhY2s7XG5cbiAgICBjb25zdCBxdWFsaWZpZXIgPSB0aGlzLnByb3BzLnF1YWxpZmllciA/PyBzdGFjay5ub2RlLnRyeUdldENvbnRleHQoQk9PVFNUUkFQX1FVQUxJRklFUl9DT05URVhUKSA/PyBEZWZhdWx0U3RhY2tTeW50aGVzaXplci5ERUZBVUxUX1FVQUxJRklFUjtcbiAgICB0aGlzLnF1YWxpZmllciA9IHF1YWxpZmllcjtcblxuICAgIGNvbnN0IHNwZWMgPSBuZXcgU3RyaW5nU3BlY2lhbGl6ZXIoc3RhY2ssIHF1YWxpZmllcik7XG5cbiAgICAvKiBlc2xpbnQtZGlzYWJsZSBtYXgtbGVuICovXG4gICAgdGhpcy5idWNrZXROYW1lID0gc3BlYy5zcGVjaWFsaXplKHRoaXMucHJvcHMuZmlsZUFzc2V0c0J1Y2tldE5hbWUgPz8gRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIuREVGQVVMVF9GSUxFX0FTU0VUU19CVUNLRVRfTkFNRSk7XG4gICAgdGhpcy5yZXBvc2l0b3J5TmFtZSA9IHNwZWMuc3BlY2lhbGl6ZSh0aGlzLnByb3BzLmltYWdlQXNzZXRzUmVwb3NpdG9yeU5hbWUgPz8gRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIuREVGQVVMVF9JTUFHRV9BU1NFVFNfUkVQT1NJVE9SWV9OQU1FKTtcbiAgICB0aGlzLl9kZXBsb3lSb2xlQXJuID0gc3BlYy5zcGVjaWFsaXplKHRoaXMucHJvcHMuZGVwbG95Um9sZUFybiA/PyBEZWZhdWx0U3RhY2tTeW50aGVzaXplci5ERUZBVUxUX0RFUExPWV9ST0xFX0FSTik7XG4gICAgdGhpcy5fY2xvdWRGb3JtYXRpb25FeGVjdXRpb25Sb2xlQXJuID0gc3BlYy5zcGVjaWFsaXplKHRoaXMucHJvcHMuY2xvdWRGb3JtYXRpb25FeGVjdXRpb25Sb2xlID8/IERlZmF1bHRTdGFja1N5bnRoZXNpemVyLkRFRkFVTFRfQ0xPVURGT1JNQVRJT05fUk9MRV9BUk4pO1xuICAgIHRoaXMuZmlsZUFzc2V0UHVibGlzaGluZ1JvbGVBcm4gPSBzcGVjLnNwZWNpYWxpemUodGhpcy5wcm9wcy5maWxlQXNzZXRQdWJsaXNoaW5nUm9sZUFybiA/PyBEZWZhdWx0U3RhY2tTeW50aGVzaXplci5ERUZBVUxUX0ZJTEVfQVNTRVRfUFVCTElTSElOR19ST0xFX0FSTik7XG4gICAgdGhpcy5pbWFnZUFzc2V0UHVibGlzaGluZ1JvbGVBcm4gPSBzcGVjLnNwZWNpYWxpemUodGhpcy5wcm9wcy5pbWFnZUFzc2V0UHVibGlzaGluZ1JvbGVBcm4gPz8gRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIuREVGQVVMVF9JTUFHRV9BU1NFVF9QVUJMSVNISU5HX1JPTEVfQVJOKTtcbiAgICB0aGlzLmxvb2t1cFJvbGVBcm4gPSBzcGVjLnNwZWNpYWxpemUodGhpcy5wcm9wcy5sb29rdXBSb2xlQXJuID8/IERlZmF1bHRTdGFja1N5bnRoZXNpemVyLkRFRkFVTFRfTE9PS1VQX1JPTEVfQVJOKTtcbiAgICB0aGlzLmJ1Y2tldFByZWZpeCA9IHNwZWMuc3BlY2lhbGl6ZSh0aGlzLnByb3BzLmJ1Y2tldFByZWZpeCA/PyBEZWZhdWx0U3RhY2tTeW50aGVzaXplci5ERUZBVUxUX0ZJTEVfQVNTRVRfUFJFRklYKTtcbiAgICB0aGlzLmRvY2tlclRhZ1ByZWZpeCA9IHNwZWMuc3BlY2lhbGl6ZSh0aGlzLnByb3BzLmRvY2tlclRhZ1ByZWZpeCA/PyBEZWZhdWx0U3RhY2tTeW50aGVzaXplci5ERUZBVUxUX0RPQ0tFUl9BU1NFVF9QUkVGSVgpO1xuICAgIHRoaXMuYm9vdHN0cmFwU3RhY2tWZXJzaW9uU3NtUGFyYW1ldGVyID0gc3BlYy5xdWFsaWZpZXJPbmx5KHRoaXMucHJvcHMuYm9vdHN0cmFwU3RhY2tWZXJzaW9uU3NtUGFyYW1ldGVyID8/IERlZmF1bHRTdGFja1N5bnRoZXNpemVyLkRFRkFVTFRfQk9PVFNUUkFQX1NUQUNLX1ZFUlNJT05fU1NNX1BBUkFNRVRFUik7XG4gICAgLyogZXNsaW50LWVuYWJsZSBtYXgtbGVuICovXG4gIH1cblxuICBwdWJsaWMgYWRkRmlsZUFzc2V0KGFzc2V0OiBGaWxlQXNzZXRTb3VyY2UpOiBGaWxlQXNzZXRMb2NhdGlvbiB7XG4gICAgYXNzZXJ0Qm91bmQodGhpcy5zdGFjayk7XG4gICAgYXNzZXJ0Qm91bmQodGhpcy5idWNrZXROYW1lKTtcbiAgICBhc3NlcnRCb3VuZCh0aGlzLmJ1Y2tldFByZWZpeCk7XG5cbiAgICByZXR1cm4gdGhpcy5hc3NldE1hbmlmZXN0LmFkZEZpbGVBc3NldERlZmF1bHQoYXNzZXQsIHRoaXMuc3RhY2ssIHRoaXMuYnVja2V0TmFtZSwgdGhpcy5idWNrZXRQcmVmaXgsIHtcbiAgICAgIGFzc3VtZVJvbGVBcm46IHRoaXMuZmlsZUFzc2V0UHVibGlzaGluZ1JvbGVBcm4sXG4gICAgICBhc3N1bWVSb2xlRXh0ZXJuYWxJZDogdGhpcy5wcm9wcy5maWxlQXNzZXRQdWJsaXNoaW5nRXh0ZXJuYWxJZCxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhZGREb2NrZXJJbWFnZUFzc2V0KGFzc2V0OiBEb2NrZXJJbWFnZUFzc2V0U291cmNlKTogRG9ja2VySW1hZ2VBc3NldExvY2F0aW9uIHtcbiAgICBhc3NlcnRCb3VuZCh0aGlzLnN0YWNrKTtcbiAgICBhc3NlcnRCb3VuZCh0aGlzLnJlcG9zaXRvcnlOYW1lKTtcbiAgICBhc3NlcnRCb3VuZCh0aGlzLmRvY2tlclRhZ1ByZWZpeCk7XG5cbiAgICByZXR1cm4gdGhpcy5hc3NldE1hbmlmZXN0LmFkZERvY2tlckltYWdlQXNzZXREZWZhdWx0KGFzc2V0LCB0aGlzLnN0YWNrLCB0aGlzLnJlcG9zaXRvcnlOYW1lLCB0aGlzLmRvY2tlclRhZ1ByZWZpeCwge1xuICAgICAgYXNzdW1lUm9sZUFybjogdGhpcy5pbWFnZUFzc2V0UHVibGlzaGluZ1JvbGVBcm4sXG4gICAgICBhc3N1bWVSb2xlRXh0ZXJuYWxJZDogdGhpcy5wcm9wcy5pbWFnZUFzc2V0UHVibGlzaGluZ0V4dGVybmFsSWQsXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgc3ludGhlc2l6ZVN0YWNrVGVtcGxhdGUoc3RhY2s6IFN0YWNrLCBzZXNzaW9uOiBJU3ludGhlc2lzU2Vzc2lvbikge1xuICAgIHN0YWNrLl9zeW50aGVzaXplVGVtcGxhdGUoc2Vzc2lvbiwgdGhpcy5sb29rdXBSb2xlQXJuKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTeW50aGVzaXplIHRoZSBhc3NvY2lhdGVkIHN0YWNrIHRvIHRoZSBzZXNzaW9uXG4gICAqL1xuICBwdWJsaWMgc3ludGhlc2l6ZShzZXNzaW9uOiBJU3ludGhlc2lzU2Vzc2lvbik6IHZvaWQge1xuICAgIGFzc2VydEJvdW5kKHRoaXMuc3RhY2spO1xuICAgIGFzc2VydEJvdW5kKHRoaXMucXVhbGlmaWVyKTtcblxuICAgIC8vIE11c3QgYmUgZG9uZSBoZXJlIC0tIGlmIGl0J3MgZG9uZSBpbiBiaW5kKCkgKGNhbGxlZCBpbiB0aGUgU3RhY2sncyBjb25zdHJ1Y3RvcilcbiAgICAvLyB0aGVuIGl0IHdpbGwgYmVjb21lIGltcG9zc2libGUgdG8gc2V0IGNvbnRleHQgYWZ0ZXIgdGhhdC5cbiAgICAvL1xuICAgIC8vIElmIGl0J3MgZG9uZSBBRlRFUiBfc3ludGhlc2l6ZVRlbXBsYXRlKCksIHRoZW4gdGhlIHRlbXBsYXRlIHdvbid0IGNvbnRhaW4gdGhlXG4gICAgLy8gcmlnaHQgY29uc3RydWN0cy5cbiAgICBpZiAodGhpcy5wcm9wcy5nZW5lcmF0ZUJvb3RzdHJhcFZlcnNpb25SdWxlID8/IHRydWUpIHtcbiAgICAgIGFkZEJvb3RzdHJhcFZlcnNpb25SdWxlKHRoaXMuc3RhY2ssIE1JTl9CT09UU1RSQVBfU1RBQ0tfVkVSU0lPTiwgPHN0cmluZz4gdGhpcy5ib290c3RyYXBTdGFja1ZlcnNpb25Tc21QYXJhbWV0ZXIpO1xuICAgIH1cblxuICAgIHRoaXMuc3ludGhlc2l6ZVN0YWNrVGVtcGxhdGUodGhpcy5zdGFjaywgc2Vzc2lvbik7XG5cbiAgICBjb25zdCB0ZW1wbGF0ZUFzc2V0ID0gdGhpcy5hZGRGaWxlQXNzZXQoc3RhY2tUZW1wbGF0ZUZpbGVBc3NldCh0aGlzLnN0YWNrLCBzZXNzaW9uKSk7XG5cbiAgICBjb25zdCBhc3NldE1hbmlmZXN0SWQgPSB0aGlzLmFzc2V0TWFuaWZlc3Qud3JpdGVNYW5pZmVzdCh0aGlzLnN0YWNrLCBzZXNzaW9uLCB7XG4gICAgICByZXF1aXJlc0Jvb3RzdHJhcFN0YWNrVmVyc2lvbjogTUlOX0JPT1RTVFJBUF9TVEFDS19WRVJTSU9OLFxuICAgICAgYm9vdHN0cmFwU3RhY2tWZXJzaW9uU3NtUGFyYW1ldGVyOiB0aGlzLmJvb3RzdHJhcFN0YWNrVmVyc2lvblNzbVBhcmFtZXRlcixcbiAgICB9KTtcblxuICAgIHRoaXMuZW1pdFN0YWNrQXJ0aWZhY3QodGhpcy5zdGFjaywgc2Vzc2lvbiwge1xuICAgICAgYXNzdW1lUm9sZUV4dGVybmFsSWQ6IHRoaXMucHJvcHMuZGVwbG95Um9sZUV4dGVybmFsSWQsXG4gICAgICBhc3N1bWVSb2xlQXJuOiB0aGlzLl9kZXBsb3lSb2xlQXJuLFxuICAgICAgY2xvdWRGb3JtYXRpb25FeGVjdXRpb25Sb2xlQXJuOiB0aGlzLl9jbG91ZEZvcm1hdGlvbkV4ZWN1dGlvblJvbGVBcm4sXG4gICAgICBzdGFja1RlbXBsYXRlQXNzZXRPYmplY3RVcmw6IHRlbXBsYXRlQXNzZXQuczNPYmplY3RVcmxXaXRoUGxhY2Vob2xkZXJzLFxuICAgICAgcmVxdWlyZXNCb290c3RyYXBTdGFja1ZlcnNpb246IE1JTl9CT09UU1RSQVBfU1RBQ0tfVkVSU0lPTixcbiAgICAgIGJvb3RzdHJhcFN0YWNrVmVyc2lvblNzbVBhcmFtZXRlcjogdGhpcy5ib290c3RyYXBTdGFja1ZlcnNpb25Tc21QYXJhbWV0ZXIsXG4gICAgICBhZGRpdGlvbmFsRGVwZW5kZW5jaWVzOiBbYXNzZXRNYW5pZmVzdElkXSxcbiAgICAgIGxvb2t1cFJvbGU6IHRoaXMudXNlTG9va3VwUm9sZUZvclN0YWNrT3BlcmF0aW9ucyAmJiB0aGlzLmxvb2t1cFJvbGVBcm4gPyB7XG4gICAgICAgIGFybjogdGhpcy5sb29rdXBSb2xlQXJuLFxuICAgICAgICBhc3N1bWVSb2xlRXh0ZXJuYWxJZDogdGhpcy5wcm9wcy5sb29rdXBSb2xlRXh0ZXJuYWxJZCxcbiAgICAgICAgcmVxdWlyZXNCb290c3RyYXBTdGFja1ZlcnNpb246IE1JTl9MT09LVVBfUk9MRV9CT09UU1RSQVBfU1RBQ0tfVkVSU0lPTixcbiAgICAgICAgYm9vdHN0cmFwU3RhY2tWZXJzaW9uU3NtUGFyYW1ldGVyOiB0aGlzLmJvb3RzdHJhcFN0YWNrVmVyc2lvblNzbVBhcmFtZXRlcixcbiAgICAgIH0gOiB1bmRlZmluZWQsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgQVJOIG9mIHRoZSBkZXBsb3kgUm9sZS5cbiAgICovXG4gIHB1YmxpYyBnZXQgZGVwbG95Um9sZUFybigpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5fZGVwbG95Um9sZUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdkZXBsb3lSb2xlQXJuIGdldHRlciBjYW4gb25seSBiZSBjYWxsZWQgYWZ0ZXIgdGhlIHN5bnRoZXNpemVyIGhhcyBiZWVuIGJvdW5kIHRvIGEgU3RhY2snKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2RlcGxveVJvbGVBcm47XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgQVJOIG9mIHRoZSBDRk4gZXhlY3V0aW9uIFJvbGUuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGNsb3VkRm9ybWF0aW9uRXhlY3V0aW9uUm9sZUFybigpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5fY2xvdWRGb3JtYXRpb25FeGVjdXRpb25Sb2xlQXJuKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nsb3VkRm9ybWF0aW9uRXhlY3V0aW9uUm9sZUFybiBnZXR0ZXIgY2FuIG9ubHkgYmUgY2FsbGVkIGFmdGVyIHRoZSBzeW50aGVzaXplciBoYXMgYmVlbiBib3VuZCB0byBhIFN0YWNrJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jbG91ZEZvcm1hdGlvbkV4ZWN1dGlvblJvbGVBcm47XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IHN0YWNrKCk6IFN0YWNrIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhY2s7XG4gIH1cbn1cblxuLyoqXG4gKiBBZGQgYSBDZm5SdWxlIHRvIHRoZSBTdGFjayB3aGljaCBjaGVja3MgdGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgYm9vdHN0cmFwIHN0YWNrIHRoaXMgdGVtcGxhdGUgaXMgdGFyZ2V0aW5nXG4gKlxuICogVGhlIENMSSBub3JtYWxseSBjaGVja3MgdGhpcywgYnV0IGluIGEgcGlwZWxpbmUgdGhlIENMSSBpcyBub3QgaW52b2x2ZWRcbiAqIHNvIHdlIGVuY29kZSB0aGlzIHJ1bGUgaW50byB0aGUgdGVtcGxhdGUgaW4gYSB3YXkgdGhhdCBDbG91ZEZvcm1hdGlvbiB3aWxsIGNoZWNrIGl0LlxuICovXG5mdW5jdGlvbiBhZGRCb290c3RyYXBWZXJzaW9uUnVsZShzdGFjazogU3RhY2ssIHJlcXVpcmVkVmVyc2lvbjogbnVtYmVyLCBib290c3RyYXBTdGFja1ZlcnNpb25Tc21QYXJhbWV0ZXI6IHN0cmluZykge1xuICAvLyBCZWNhdXNlIG9mIGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9ibG9iL21hc3Rlci9wYWNrYWdlcy9hc3NlcnQtaW50ZXJuYWwvbGliL3N5bnRoLXV0aWxzLnRzI0w3NFxuICAvLyBzeW50aGVzaXplKCkgbWF5IGJlIGNhbGxlZCBtb3JlIHRoYW4gb25jZSBvbiBhIHN0YWNrIGluIHVuaXQgdGVzdHMsIGFuZCB0aGUgYmVsb3cgd291bGQgYnJlYWtcbiAgLy8gaWYgd2UgZXhlY3V0ZSBpdCBhIHNlY29uZCB0aW1lLiBHdWFyZCBhZ2FpbnN0IHRoZSBjb25zdHJ1Y3RzIGFscmVhZHkgZXhpc3RpbmcuXG4gIGlmIChzdGFjay5ub2RlLnRyeUZpbmRDaGlsZCgnQm9vdHN0cmFwVmVyc2lvbicpKSB7IHJldHVybjsgfVxuXG4gIGNvbnN0IHBhcmFtID0gbmV3IENmblBhcmFtZXRlcihzdGFjaywgJ0Jvb3RzdHJhcFZlcnNpb24nLCB7XG4gICAgdHlwZTogJ0FXUzo6U1NNOjpQYXJhbWV0ZXI6OlZhbHVlPFN0cmluZz4nLFxuICAgIGRlc2NyaXB0aW9uOiBgVmVyc2lvbiBvZiB0aGUgQ0RLIEJvb3RzdHJhcCByZXNvdXJjZXMgaW4gdGhpcyBlbnZpcm9ubWVudCwgYXV0b21hdGljYWxseSByZXRyaWV2ZWQgZnJvbSBTU00gUGFyYW1ldGVyIFN0b3JlLiAke2N4YXBpLlNTTVBBUkFNX05PX0lOVkFMSURBVEV9YCxcbiAgICBkZWZhdWx0OiBib290c3RyYXBTdGFja1ZlcnNpb25Tc21QYXJhbWV0ZXIsXG4gIH0pO1xuXG4gIC8vIFRoZXJlIGlzIG5vID49IGNoZWNrIGluIENsb3VkRm9ybWF0aW9uLCBzbyB3ZSBoYXZlIHRvIGNoZWNrIHRoZSBudW1iZXJcbiAgLy8gaXMgTk9UIGluIFsxLCAyLCAzLCAuLi4gPHJlcXVpcmVkPiAtIDFdXG4gIGNvbnN0IG9sZFZlcnNpb25zID0gcmFuZ2UoMSwgcmVxdWlyZWRWZXJzaW9uKS5tYXAobiA9PiBgJHtufWApO1xuXG4gIG5ldyBDZm5SdWxlKHN0YWNrLCAnQ2hlY2tCb290c3RyYXBWZXJzaW9uJywge1xuICAgIGFzc2VydGlvbnM6IFtcbiAgICAgIHtcbiAgICAgICAgYXNzZXJ0OiBGbi5jb25kaXRpb25Ob3QoRm4uY29uZGl0aW9uQ29udGFpbnMob2xkVmVyc2lvbnMsIHBhcmFtLnZhbHVlQXNTdHJpbmcpKSxcbiAgICAgICAgYXNzZXJ0RGVzY3JpcHRpb246IGBDREsgYm9vdHN0cmFwIHN0YWNrIHZlcnNpb24gJHtyZXF1aXJlZFZlcnNpb259IHJlcXVpcmVkLiBQbGVhc2UgcnVuICdjZGsgYm9vdHN0cmFwJyB3aXRoIGEgcmVjZW50IHZlcnNpb24gb2YgdGhlIENESyBDTEkuYCxcbiAgICAgIH0sXG4gICAgXSxcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJhbmdlKHN0YXJ0SW5jbDogbnVtYmVyLCBlbmRFeGNsOiBudW1iZXIpIHtcbiAgY29uc3QgcmV0ID0gbmV3IEFycmF5PG51bWJlcj4oKTtcbiAgZm9yIChsZXQgaSA9IHN0YXJ0SW5jbDsgaSA8IGVuZEV4Y2w7IGkrKykge1xuICAgIHJldC5wdXNoKGkpO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbiJdfQ==
\No newline at end of file