1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.DefaultStackSynthesizer = exports.BOOTSTRAP_QUALIFIER_CONTEXT = void 0;
|
5 | const jsiiDeprecationWarnings = require("../../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const cxapi = require("@aws-cdk/cx-api");
|
8 | const cfn_fn_1 = require("../cfn-fn");
|
9 | const cfn_parameter_1 = require("../cfn-parameter");
|
10 | const cfn_rule_1 = require("../cfn-rule");
|
11 | const token_1 = require("../token");
|
12 | const _asset_manifest_builder_1 = require("./_asset-manifest-builder");
|
13 | const _shared_1 = require("./_shared");
|
14 | const stack_synthesizer_1 = require("./stack-synthesizer");
|
15 | exports.BOOTSTRAP_QUALIFIER_CONTEXT = '@aws-cdk/core:bootstrapQualifier';
|
16 | /* eslint-disable max-len */
|
17 | /**
|
18 | * The minimum bootstrap stack version required by this app.
|
19 | */
|
20 | const MIN_BOOTSTRAP_STACK_VERSION = 6;
|
21 | /**
|
22 | * The minimum bootstrap stack version required
|
23 | * to use the lookup role.
|
24 | */
|
25 | const 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 | */
|
41 | class 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 | }
|
218 | exports.DefaultStackSynthesizer = DefaultStackSynthesizer;
|
219 | _a = JSII_RTTI_SYMBOL_1;
|
220 | DefaultStackSynthesizer[_a] = { fqn: "@aws-cdk/core.DefaultStackSynthesizer", version: "1.204.0" };
|
221 | /**
|
222 | * Default ARN qualifier
|
223 | */
|
224 | DefaultStackSynthesizer.DEFAULT_QUALIFIER = 'hnb659fds';
|
225 | /**
|
226 | * Default CloudFormation role ARN.
|
227 | */
|
228 | DefaultStackSynthesizer.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 | */
|
232 | DefaultStackSynthesizer.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 | */
|
236 | DefaultStackSynthesizer.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 | */
|
240 | DefaultStackSynthesizer.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 | */
|
244 | DefaultStackSynthesizer.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 | */
|
248 | DefaultStackSynthesizer.DEFAULT_IMAGE_ASSETS_REPOSITORY_NAME = 'cdk-${Qualifier}-container-assets-${AWS::AccountId}-${AWS::Region}';
|
249 | /**
|
250 | * Default file assets bucket name
|
251 | */
|
252 | DefaultStackSynthesizer.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 | */
|
256 | DefaultStackSynthesizer.DEFAULT_FILE_ASSET_KEY_ARN_EXPORT_NAME = 'CdkBootstrap-${Qualifier}-FileAssetKeyArn';
|
257 | /**
|
258 | * Default file asset prefix
|
259 | */
|
260 | DefaultStackSynthesizer.DEFAULT_FILE_ASSET_PREFIX = '';
|
261 | /**
|
262 | * Default Docker asset prefix
|
263 | */
|
264 | DefaultStackSynthesizer.DEFAULT_DOCKER_ASSET_PREFIX = '';
|
265 | /**
|
266 | * Default bootstrap stack version SSM parameter.
|
267 | */
|
268 | DefaultStackSynthesizer.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 | */
|
275 | function 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 | }
|
299 | function 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 |