UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

327 lines 46.5 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var SDK_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.isUnrecoverableAwsError = exports.SDK = void 0; const AWS = require("aws-sdk"); const _env_1 = require("./_env"); const account_cache_1 = require("./account-cache"); const cached_1 = require("./cached"); const tracing_1 = require("../../util/tracing"); // We need to map regions to domain suffixes, and the SDK already has a function to do this. // It's not part of the public API, but it's also unlikely to go away. // // Reuse that function, and add a safety check, so we don't accidentally break if they ever // refactor that away. /* eslint-disable @typescript-eslint/no-require-imports */ const regionUtil = require('aws-sdk/lib/region_config'); require('aws-sdk/lib/maintenance_mode_message').suppress = true; /* eslint-enable @typescript-eslint/no-require-imports */ if (!regionUtil.getEndpointSuffix) { throw new Error('This version of AWS SDK for JS does not have the \'getEndpointSuffix\' function!'); } /** * Base functionality of SDK without credential fetching */ let SDK = exports.SDK = SDK_1 = class SDK { constructor(_credentials, region, httpOptions = {}, sdkOptions = {}) { this._credentials = _credentials; this.sdkOptions = sdkOptions; /** * Default retry options for SDK clients. */ this.retryOptions = { maxRetries: 6, retryDelayOptions: { base: 300 } }; /** * The more generous retry policy for CloudFormation, which has a 1 TPM limit on certain APIs, * which are abundantly used for deployment tracking, ... * * So we're allowing way more retries, but waiting a bit more. */ this.cloudFormationRetryOptions = { maxRetries: 10, retryDelayOptions: { base: 1000 } }; /** * STS is used to check credential validity, don't do too many retries. */ this.stsRetryOptions = { maxRetries: 3, retryDelayOptions: { base: 100 } }; /** * Whether we have proof that the credentials have not expired * * We need to do some manual plumbing around this because the JS SDKv2 treats `ExpiredToken` * as retriable and we have hefty retries on CFN calls making the CLI hang for a good 15 minutes * if the credentials have expired. */ this._credentialsValidated = false; this.config = { ...httpOptions, ...this.retryOptions, credentials: _credentials, region, logger: { log: (...messages) => messages.forEach(m => (0, _env_1.trace)('%s', m)) }, }; this.currentRegion = region; } appendCustomUserAgent(userAgentData) { if (!userAgentData) { return; } const currentCustomUserAgent = this.config.customUserAgent; this.config.customUserAgent = currentCustomUserAgent ? `${currentCustomUserAgent} ${userAgentData}` : userAgentData; } removeCustomUserAgent(userAgentData) { this.config.customUserAgent = this.config.customUserAgent?.replace(userAgentData, ''); } lambda() { return this.wrapServiceErrorHandling(new AWS.Lambda(this.config)); } cloudFormation() { return this.wrapServiceErrorHandling(new AWS.CloudFormation({ ...this.config, ...this.cloudFormationRetryOptions, })); } ec2() { return this.wrapServiceErrorHandling(new AWS.EC2(this.config)); } iam() { return this.wrapServiceErrorHandling(new AWS.IAM(this.config)); } ssm() { return this.wrapServiceErrorHandling(new AWS.SSM(this.config)); } s3() { return this.wrapServiceErrorHandling(new AWS.S3(this.config)); } route53() { return this.wrapServiceErrorHandling(new AWS.Route53(this.config)); } ecr() { return this.wrapServiceErrorHandling(new AWS.ECR(this.config)); } ecs() { return this.wrapServiceErrorHandling(new AWS.ECS(this.config)); } elbv2() { return this.wrapServiceErrorHandling(new AWS.ELBv2(this.config)); } secretsManager() { return this.wrapServiceErrorHandling(new AWS.SecretsManager(this.config)); } kms() { return this.wrapServiceErrorHandling(new AWS.KMS(this.config)); } stepFunctions() { return this.wrapServiceErrorHandling(new AWS.StepFunctions(this.config)); } codeBuild() { return this.wrapServiceErrorHandling(new AWS.CodeBuild(this.config)); } cloudWatchLogs() { return this.wrapServiceErrorHandling(new AWS.CloudWatchLogs(this.config)); } appsync() { return this.wrapServiceErrorHandling(new AWS.AppSync(this.config)); } async currentAccount() { // Get/refresh if necessary before we can access `accessKeyId` await this.forceCredentialRetrieval(); return (0, cached_1.cached)(this, CURRENT_ACCOUNT_KEY, () => SDK_1.accountCache.fetch(this._credentials.accessKeyId, async () => { // if we don't have one, resolve from STS and store in cache. (0, _env_1.debug)('Looking up default account ID from STS'); const result = await new AWS.STS({ ...this.config, ...this.stsRetryOptions }).getCallerIdentity().promise(); const accountId = result.Account; const partition = result.Arn.split(':')[1]; if (!accountId) { throw new Error('STS didn\'t return an account ID'); } (0, _env_1.debug)('Default account ID:', accountId); // Save another STS call later if this one already succeeded this._credentialsValidated = true; return { accountId, partition }; })); } /** * Return the current credentials * * Don't use -- only used to write tests around assuming roles. */ async currentCredentials() { await this.forceCredentialRetrieval(); return this._credentials; } /** * Force retrieval of the current credentials * * Relevant if the current credentials are AssumeRole credentials -- do the actual * lookup, and translate any error into a useful error message (taking into * account credential provenance). */ async forceCredentialRetrieval() { try { await this._credentials.getPromise(); } catch (e) { if (isUnrecoverableAwsError(e)) { throw e; } // Only reason this would fail is if it was an AssumRole. Otherwise, // reading from an INI file or reading env variables is unlikely to fail. (0, _env_1.debug)(`Assuming role failed: ${e.message}`); throw new Error([ 'Could not assume role in target account', ...this.sdkOptions.assumeRoleCredentialsSourceDescription ? [`using ${this.sdkOptions.assumeRoleCredentialsSourceDescription}`] : [], e.message, '. Please make sure that this role exists in the account. If it doesn\'t exist, (re)-bootstrap the environment ' + 'with the right \'--trust\', using the latest version of the CDK CLI.', ].join(' ')); } } /** * Make sure the the current credentials are not expired */ async validateCredentials() { if (this._credentialsValidated) { return; } await new AWS.STS({ ...this.config, ...this.stsRetryOptions }).getCallerIdentity().promise(); this._credentialsValidated = true; } getEndpointSuffix(region) { return regionUtil.getEndpointSuffix(region); } /** * Return a wrapping object for the underlying service object * * Responds to failures in the underlying service calls, in two different * ways: * * - When errors are encountered, log the failing call and the error that * it triggered (at debug level). This is necessary because the lack of * stack traces in NodeJS otherwise makes it very hard to suss out where * a certain AWS error occurred. * - The JS SDK has a funny business of wrapping any credential-based error * in a super-generic (and in our case wrong) exception. If we then use a * 'ChainableTemporaryCredentials' and the target role doesn't exist, * the error message that shows up by default is super misleading * (https://github.com/aws/aws-sdk-js/issues/3272). We can fix this because * the exception contains the "inner exception", so we unwrap and throw * the correct error ("cannot assume role"). * * The wrapping business below is slightly more complicated than you'd think * because we must hook into the `promise()` method of the object that's being * returned from the methods of the object that we wrap, so there's two * levels of wrapping going on, and also some exceptions to the wrapping magic. */ wrapServiceErrorHandling(serviceObject) { const classObject = serviceObject.constructor.prototype; const self = this; return new Proxy(serviceObject, { get(obj, prop) { const real = obj[prop]; // Things we don't want to intercept: // - Anything that's not a function. // - 'constructor', s3.upload() will use this to do some magic and we need the underlying constructor. // - Any method that's not on the service class (do not intercept 'makeRequest' and other helpers). if (prop === 'constructor' || !classObject.hasOwnProperty(prop) || !isFunction(real)) { return real; } // NOTE: This must be a function() and not an () => { // because I need 'this' to be dynamically bound and not statically bound. // If your linter complains don't listen to it! return function () { // Call the underlying function. If it returns an object with a promise() // method on it, wrap that 'promise' method. const args = [].slice.call(arguments, 0); const response = real.apply(this, args); // Don't intercept unless the return value is an object with a '.promise()' method. if (typeof response !== 'object' || !response) { return response; } if (!('promise' in response)) { return response; } // Return an object with the promise method replaced with a wrapper which will // do additional things to errors. return Object.assign(Object.create(response), { promise() { return response.promise().catch((e) => { e = self.makeDetailedException(e); (0, _env_1.debug)(`Call failed: ${prop}(${JSON.stringify(args[0])}) => ${e.message} (code=${e.code})`); return Promise.reject(e); // Re-'throw' the new error }); }, }); }; }, }); } /** * Extract a more detailed error out of a generic error if we can * * If this is an error about Assuming Roles, add in the context showing the * chain of credentials we used to try to assume the role. */ makeDetailedException(e) { // This is the super-generic "something's wrong" error that the JS SDK wraps other errors in. // https://github.com/aws/aws-sdk-js/blob/f0ac2e53457c7512883d0677013eacaad6cd8a19/lib/event_listeners.js#L84 if (typeof e.message === 'string' && e.message.startsWith('Missing credentials in config')) { const original = e.originalError; if (original) { // When the SDK does a 'util.copy', they lose the Error-ness of the inner error // (they copy the Error's properties into a plain object) so make it an Error object again. e = Object.assign(new Error(), original); } } // At this point, the error might still be a generic "ChainableTemporaryCredentials failed" // error which wraps the REAL error (AssumeRole failed). We're going to replace the error // message with one that's more likely to help users, and tell them the most probable // fix (bootstrapping). The underlying service call failure will be appended below. if (e.message === 'Could not load credentials from ChainableTemporaryCredentials') { e.message = [ 'Could not assume role in target account', ...this.sdkOptions.assumeRoleCredentialsSourceDescription ? [`using ${this.sdkOptions.assumeRoleCredentialsSourceDescription}`] : [], '(did you bootstrap the environment with the right \'--trust\'s?)', ].join(' '); } // Replace the message on this error with a concatenation of all inner error messages. // Must more clear what's going on that way. e.message = allChainedExceptionMessages(e); return e; } }; SDK.accountCache = new account_cache_1.AccountAccessKeyCache(); exports.SDK = SDK = SDK_1 = __decorate([ tracing_1.traceMethods ], SDK); const CURRENT_ACCOUNT_KEY = Symbol('current_account_key'); function isFunction(x) { return x && {}.toString.call(x) === '[object Function]'; } /** * Return the concatenated message of all exceptions in the AWS exception chain */ function allChainedExceptionMessages(e) { const ret = new Array(); while (e) { ret.push(e.message); e = e.originalError; } return ret.join(': '); } /** * Return whether an error should not be recovered from */ function isUnrecoverableAwsError(e) { return e.code === 'ExpiredToken'; } exports.isUnrecoverableAwsError = isUnrecoverableAwsError; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2RrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic2RrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSwrQkFBK0I7QUFFL0IsaUNBQXNDO0FBQ3RDLG1EQUF3RDtBQUN4RCxxQ0FBa0M7QUFFbEMsZ0RBQWtEO0FBRWxELDRGQUE0RjtBQUM1RixzRUFBc0U7QUFDdEUsRUFBRTtBQUNGLDJGQUEyRjtBQUMzRixzQkFBc0I7QUFFdEIsMERBQTBEO0FBQzFELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO0FBQ3hELE9BQU8sQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7QUFDaEUseURBQXlEO0FBRXpELElBQUksQ0FBQyxVQUFVLENBQUMsaUJBQWlCLEVBQUU7SUFDakMsTUFBTSxJQUFJLEtBQUssQ0FBQyxrRkFBa0YsQ0FBQyxDQUFDO0NBQ3JHO0FBOEREOztHQUVHO0FBRUksSUFBTSxHQUFHLHlCQUFULE1BQU0sR0FBRztJQWtDZCxZQUNtQixZQUE2QixFQUM5QyxNQUFjLEVBQ2QsY0FBb0MsRUFBRSxFQUNyQixhQUF5QixFQUFFO1FBSDNCLGlCQUFZLEdBQVosWUFBWSxDQUFpQjtRQUc3QixlQUFVLEdBQVYsVUFBVSxDQUFpQjtRQS9COUM7O1dBRUc7UUFDYyxpQkFBWSxHQUFHLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO1FBRXBGOzs7OztXQUtHO1FBQ2MsK0JBQTBCLEdBQUcsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLGlCQUFpQixFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUssRUFBRSxFQUFFLENBQUM7UUFFckc7O1dBRUc7UUFDYyxvQkFBZSxHQUFHLEVBQUUsVUFBVSxFQUFFLENBQUMsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsRUFBRSxD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Q0FBQyxPQUFPLEdBQUcsMkJBQTJCLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0MsT0FBTyxDQUFDLENBQUM7SUFDWCxDQUFDOztBQXJUdUIsZ0JBQVksR0FBRyxJQUFJLHFDQUFxQixFQUFFLEFBQTlCLENBQStCO2NBRHhELEdBQUc7SUFEZixzQkFBWTtHQUNBLEdBQUcsQ0F1VGY7QUFFRCxNQUFNLG1CQUFtQixHQUFHLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0FBRTFELFNBQVMsVUFBVSxDQUFDLENBQU07SUFDeEIsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssbUJBQW1CLENBQUM7QUFDMUQsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUywyQkFBMkIsQ0FBQyxDQUFvQjtJQUN2RCxNQUFNLEdBQUcsR0FBRyxJQUFJLEtBQUssRUFBVSxDQUFDO0lBQ2hDLE9BQU8sQ0FBQyxFQUFFO1FBQ1IsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDcEIsQ0FBQyxHQUFJLENBQVMsQ0FBQyxhQUFhLENBQUM7S0FDOUI7SUFDRCxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDeEIsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0IsdUJBQXVCLENBQUMsQ0FBUTtJQUM5QyxPQUFRLENBQVMsQ0FBQyxJQUFJLEtBQUssY0FBYyxDQUFDO0FBQzVDLENBQUM7QUFGRCwwREFFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIEFXUyBmcm9tICdhd3Mtc2RrJztcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJhdGlvbk9wdGlvbnMgfSBmcm9tICdhd3Mtc2RrL2xpYi9jb25maWctYmFzZSc7XG5pbXBvcnQgeyBkZWJ1ZywgdHJhY2UgfSBmcm9tICcuL19lbnYnO1xuaW1wb3J0IHsgQWNjb3VudEFjY2Vzc0tleUNhY2hlIH0gZnJvbSAnLi9hY2NvdW50LWNhY2hlJztcbmltcG9ydCB7IGNhY2hlZCB9IGZyb20gJy4vY2FjaGVkJztcbmltcG9ydCB7IEFjY291bnQgfSBmcm9tICcuL3Nkay1wcm92aWRlcic7XG5pbXBvcnQgeyB0cmFjZU1ldGhvZHMgfSBmcm9tICcuLi8uLi91dGlsL3RyYWNpbmcnO1xuXG4vLyBXZSBuZWVkIHRvIG1hcCByZWdpb25zIHRvIGRvbWFpbiBzdWZmaXhlcywgYW5kIHRoZSBTREsgYWxyZWFkeSBoYXMgYSBmdW5jdGlvbiB0byBkbyB0aGlzLlxuLy8gSXQncyBub3QgcGFydCBvZiB0aGUgcHVibGljIEFQSSwgYnV0IGl0J3MgYWxzbyB1bmxpa2VseSB0byBnbyBhd2F5LlxuLy9cbi8vIFJldXNlIHRoYXQgZnVuY3Rpb24sIGFuZCBhZGQgYSBzYWZldHkgY2hlY2ssIHNvIHdlIGRvbid0IGFjY2lkZW50YWxseSBicmVhayBpZiB0aGV5IGV2ZXJcbi8vIHJlZmFjdG9yIHRoYXQgYXdheS5cblxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAqL1xuY29uc3QgcmVnaW9uVXRpbCA9IHJlcXVpcmUoJ2F3cy1zZGsvbGliL3JlZ2lvbl9jb25maWcnKTtcbnJlcXVpcmUoJ2F3cy1zZGsvbGliL21haW50ZW5hbmNlX21vZGVfbWVzc2FnZScpLnN1cHByZXNzID0gdHJ1ZTtcbi8qIGVzbGludC1lbmFibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAqL1xuXG5pZiAoIXJlZ2lvblV0aWwuZ2V0RW5kcG9pbnRTdWZmaXgpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdUaGlzIHZlcnNpb24gb2YgQVdTIFNESyBmb3IgSlMgZG9lcyBub3QgaGF2ZSB0aGUgXFwnZ2V0RW5kcG9pbnRTdWZmaXhcXCcgZnVuY3Rpb24hJyk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVNESyB7XG4gIC8qKlxuICAgKiBUaGUgcmVnaW9uIHRoaXMgU0RLIGhhcyBiZWVuIGluc3RhbnRpYXRlZCBmb3JcbiAgICpcbiAgICogKEFzIGRpc3RpbmN0IGZyb20gdGhlIGBkZWZhdWx0UmVnaW9uKClgIG9uIFNka1Byb3ZpZGVyIHdoaWNoXG4gICAqIHJlcHJlc2VudHMgdGhlIHJlZ2lvbiBjb25maWd1cmVkIGluIHRoZSBkZWZhdWx0IGNvbmZpZykuXG4gICAqL1xuICByZWFkb25seSBjdXJyZW50UmVnaW9uOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBBY2NvdW50IHRoaXMgU0RLIGhhcyBiZWVuIGluc3RhbnRpYXRlZCBmb3JcbiAgICpcbiAgICogKEFzIGRpc3RpbmN0IGZyb20gdGhlIGBkZWZhdWx0QWNjb3VudCgpYCBvbiBTZGtQcm92aWRlciB3aGljaFxuICAgKiByZXByZXNlbnRzIHRoZSBhY2NvdW50IGF2YWlsYWJsZSBieSB1c2luZyBkZWZhdWx0IGNyZWRlbnRpYWxzKS5cbiAgICovXG4gIGN1cnJlbnRBY2NvdW50KCk6IFByb21pc2U8QWNjb3VudD47XG5cbiAgZ2V0RW5kcG9pbnRTdWZmaXgocmVnaW9uOiBzdHJpbmcpOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFwcGVuZHMgdGhlIGdpdmVuIHN0cmluZyBhcyB0aGUgZXh0cmEgaW5mb3JtYXRpb24gdG8gcHV0IGludG8gdGhlIFVzZXItQWdlbnQgaGVhZGVyIGZvciBhbnkgcmVxdWVzdHMgaW52b2tlZCBieSB0aGlzIFNESy5cbiAgICogSWYgdGhlIHN0cmluZyBpcyAndW5kZWZpbmVkJywgdGhpcyBtZXRob2QgaGFzIG5vIGVmZmVjdC5cbiAgICovXG4gIGFwcGVuZEN1c3RvbVVzZXJBZ2VudCh1c2VyQWdlbnREYXRhPzogc3RyaW5nKTogdm9pZDtcblxuICAvKipcbiAgICogUmVtb3ZlcyB0aGUgZ2l2ZW4gc3RyaW5nIGZyb20gdGhlIGV4dHJhIFVzZXItQWdlbnQgaGVhZGVyIGRhdGEgdXNlZCBmb3IgcmVxdWVzdHMgaW52b2tlZCBieSB0aGlzIFNESy5cbiAgICovXG4gIHJlbW92ZUN1c3RvbVVzZXJBZ2VudCh1c2VyQWdlbnREYXRhOiBzdHJpbmcpOiB2b2lkO1xuXG4gIGxhbWJkYSgpOiBBV1MuTGFtYmRhO1xuICBjbG91ZEZvcm1hdGlvbigpOiBBV1MuQ2xvdWRGb3JtYXRpb247XG4gIGVjMigpOiBBV1MuRUMyO1xuICBpYW0oKTogQVdTLklBTTtcbiAgc3NtKCk6IEFXUy5TU007XG4gIHMzKCk6IEFXUy5TMztcbiAgcm91dGU1MygpOiBBV1MuUm91dGU1MztcbiAgZWNyKCk6IEFXUy5FQ1I7XG4gIGVjcygpOiBBV1MuRUNTO1xuICBlbGJ2MigpOiBBV1MuRUxCdjI7XG4gIHNlY3JldHNNYW5hZ2VyKCk6IEFXUy5TZWNyZXRzTWFuYWdlcjtcbiAga21zKCk6IEFXUy5LTVM7XG4gIHN0ZXBGdW5jdGlvbnMoKTogQVdTLlN0ZXBGdW5jdGlvbnM7XG4gIGNvZGVCdWlsZCgpOiBBV1MuQ29kZUJ1aWxkXG4gIGNsb3VkV2F0Y2hMb2dzKCk6IEFXUy5DbG91ZFdhdGNoTG9ncztcbiAgYXBwc3luYygpOiBBV1MuQXBwU3luYztcbn1cblxuLyoqXG4gKiBBZGRpdGlvbmFsIFNESyBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTZGtPcHRpb25zIHtcbiAgLyoqXG4gICAqIEFkZGl0aW9uYWwgZGVzY3JpcHRpdmUgc3RyaW5ncyB0aGF0IGluZGljYXRlIHdoZXJlIHRoZSBcIkFzc3VtZVJvbGVcIiBjcmVkZW50aWFscyBhcmUgY29taW5nIGZyb21cbiAgICpcbiAgICogV2lsbCBiZSBwcmludGVkIGluIGFuIGVycm9yIG1lc3NhZ2UgdG8gaGVscCB1c2VycyBkaWFnbm9zZSBhdXRoIHByb2JsZW1zLlxuICAgKi9cbiAgcmVhZG9ubHkgYXNzdW1lUm9sZUNyZWRlbnRpYWxzU291cmNlRGVzY3JpcHRpb24/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQmFzZSBmdW5jdGlvbmFsaXR5IG9mIFNESyB3aXRob3V0IGNyZWRlbnRpYWwgZmV0Y2hpbmdcbiAqL1xuQHRyYWNlTWV0aG9kc1xuZXhwb3J0IGNsYXNzIFNESyBpbXBsZW1lbnRzIElTREsge1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBhY2NvdW50Q2FjaGUgPSBuZXcgQWNjb3VudEFjY2Vzc0tleUNhY2hlKCk7XG5cbiAgcHVibGljIHJlYWRvbmx5IGN1cnJlbnRSZWdpb246IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IGNvbmZpZzogQ29uZmlndXJhdGlvbk9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIERlZmF1bHQgcmV0cnkgb3B0aW9ucyBmb3IgU0RLIGNsaWVudHMuXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHJldHJ5T3B0aW9ucyA9IHsgbWF4UmV0cmllczogNiwgcmV0cnlEZWxheU9wdGlvbnM6IHsgYmFzZTogMzAwIH0gfTtcblxuICAvKipcbiAgICogVGhlIG1vcmUgZ2VuZXJvdXMgcmV0cnkgcG9saWN5IGZvciBDbG91ZEZvcm1hdGlvbiwgd2hpY2ggaGFzIGEgMSBUUE0gbGltaXQgb24gY2VydGFpbiBBUElzLFxuICAgKiB3aGljaCBhcmUgYWJ1bmRhbnRseSB1c2VkIGZvciBkZXBsb3ltZW50IHRyYWNraW5nLCAuLi5cbiAgICpcbiAgICogU28gd2UncmUgYWxsb3dpbmcgd2F5IG1vcmUgcmV0cmllcywgYnV0IHdhaXRpbmcgYSBiaXQgbW9yZS5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgY2xvdWRGb3JtYXRpb25SZXRyeU9wdGlvbnMgPSB7IG1heFJldHJpZXM6IDEwLCByZXRyeURlbGF5T3B0aW9uczogeyBiYXNlOiAxXzAwMCB9IH07XG5cbiAgLyoqXG4gICAqIFNUUyBpcyB1c2VkIHRvIGNoZWNrIGNyZWRlbnRpYWwgdmFsaWRpdHksIGRvbid0IGRvIHRvbyBtYW55IHJldHJpZXMuXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHN0c1JldHJ5T3B0aW9ucyA9IHsgbWF4UmV0cmllczogMywgcmV0cnlEZWxheU9wdGlvbnM6IHsgYmFzZTogMTAwIH0gfTtcblxuICAvKipcbiAgICogV2hldGhlciB3ZSBoYXZlIHByb29mIHRoYXQgdGhlIGNyZWRlbnRpYWxzIGhhdmUgbm90IGV4cGlyZWRcbiAgICpcbiAgICogV2UgbmVlZCB0byBkbyBzb21lIG1hbnVhbCBwbHVtYmluZyBhcm91bmQgdGhpcyBiZWNhdXNlIHRoZSBKUyBTREt2MiB0cmVhdHMgYEV4cGlyZWRUb2tlbmBcbiAgICogYXMgcmV0cmlhYmxlIGFuZCB3ZSBoYXZlIGhlZnR5IHJldHJpZXMgb24gQ0ZOIGNhbGxzIG1ha2luZyB0aGUgQ0xJIGhhbmcgZm9yIGEgZ29vZCAxNSBtaW51dGVzXG4gICAqIGlmIHRoZSBjcmVkZW50aWFscyBoYXZlIGV4cGlyZWQuXG4gICAqL1xuICBwcml2YXRlIF9jcmVkZW50aWFsc1ZhbGlkYXRlZCA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2NyZWRlbnRpYWxzOiBBV1MuQ3JlZGVudGlhbHMsXG4gICAgcmVnaW9uOiBzdHJpbmcsXG4gICAgaHR0cE9wdGlvbnM6IENvbmZpZ3VyYXRpb25PcHRpb25zID0ge30sXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZGtPcHRpb25zOiBTZGtPcHRpb25zID0ge30pIHtcblxuICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgLi4uaHR0cE9wdGlvbnMsXG4gICAgICAuLi50aGlzLnJldHJ5T3B0aW9ucyxcbiAgICAgIGNyZWRlbnRpYWxzOiBfY3JlZGVudGlhbHMsXG4gICAgICByZWdpb24sXG4gICAgICBsb2dnZXI6IHsgbG9nOiAoLi4ubWVzc2FnZXMpID0+IG1lc3NhZ2VzLmZvckVhY2gobSA9PiB0cmFjZSgnJXMnLCBtKSkgfSxcbiAgICB9O1xuICAgIHRoaXMuY3VycmVudFJlZ2lvbiA9IHJlZ2lvbjtcbiAgfVxuXG4gIHB1YmxpYyBhcHBlbmRDdXN0b21Vc2VyQWdlbnQodXNlckFnZW50RGF0YT86IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghdXNlckFnZW50RGF0YSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRDdXN0b21Vc2VyQWdlbnQgPSB0aGlzLmNvbmZpZy5jdXN0b21Vc2VyQWdlbnQ7XG4gICAgdGhpcy5jb25maWcuY3VzdG9tVXNlckFnZW50ID0gY3VycmVudEN1c3RvbVVzZXJBZ2VudFxuICAgICAgPyBgJHtjdXJyZW50Q3VzdG9tVXNlckFnZW50fSAke3VzZXJBZ2VudERhdGF9YFxuICAgICAgOiB1c2VyQWdlbnREYXRhO1xuICB9XG5cbiAgcHVibGljIHJlbW92ZUN1c3RvbVVzZXJBZ2VudCh1c2VyQWdlbnREYXRhOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmNvbmZpZy5jdXN0b21Vc2VyQWdlbnQgPSB0aGlzLmNvbmZpZy5jdXN0b21Vc2VyQWdlbnQ/LnJlcGxhY2UodXNlckFnZW50RGF0YSwgJycpO1xuICB9XG5cbiAgcHVibGljIGxhbWJkYSgpOiBBV1MuTGFtYmRhIHtcbiAgICByZXR1cm4gdGhpcy53cmFwU2VydmljZUVycm9ySGFuZGxpbmcobmV3IEFXUy5MYW1iZGEodGhpcy5jb25maWcpKTtcbiAgfVxuXG4gIHB1YmxpYyBjbG91ZEZvcm1hdGlvbigpOiBBV1MuQ2xvdWRGb3JtYXRpb24ge1xuICAgIHJldHVybiB0aGlzLndyYXBTZXJ2aWNlRXJyb3JIYW5kbGluZyhuZXcgQVdTLkNsb3VkRm9ybWF0aW9uKHtcbiAgICAgIC4uLnRoaXMuY29uZmlnLFxuICAgICAgLi4udGhpcy5jbG91ZEZvcm1hdGlvblJldHJ5T3B0aW9ucyxcbiAgICB9KSk7XG4gIH1cblxuICBwdWJsaWMgZWMyKCk6IEFXUy5FQzIge1xuICAgIHJldHVybiB0aGlzLndyYXBTZXJ2aWNlRXJyb3JIYW5kbGluZyhuZXcgQVdTLkVDMih0aGlzLmNvbmZpZykpO1xuICB9XG5cbiAgcHVibGljIGlhbSgpOiBBV1MuSUFNIHtcbiAgICByZXR1cm4gdGhpcy53cmFwU2VydmljZUVycm9ySGFuZGxpbmcobmV3IEFXUy5JQU0odGhpcy5jb25maWcpKTtcbiAgfVxuXG4gIHB1YmxpYyBzc20oKTogQVdTLlNTTSB7XG4gICAgcmV0dXJuIHRoaXMud3JhcFNlcnZpY2VFcnJvckhhbmRsaW5nKG5ldyBBV1MuU1NNKHRoaXMuY29uZmlnKSk7XG4gIH1cblxuICBwdWJsaWMgczMoKTogQVdTLlMzIHtcbiAgICByZXR1cm4gdGhpcy53cmFwU2VydmljZUVycm9ySGFuZGxpbmcobmV3IEFXUy5TMyh0aGlzLmNvbmZpZykpO1xuICB9XG5cbiAgcHVibGljIHJvdXRlNTMoKTogQVdTLlJvdXRlNTMge1xuICAgIHJldHVybiB0aGlzLndyYXBTZXJ2aWNlRXJyb3JIYW5kbGluZyhuZXcgQVdTLlJvdXRlNTModGhpcy5jb25maWcpKTtcbiAgfVxuXG4gIHB1YmxpYyBlY3IoKTogQVdTLkVDUiB7XG4gICAgcmV0dXJuIHRoaXMud3JhcFNlcnZpY2VFcnJvckhhbmRsaW5nKG5ldyBBV1MuRUNSKHRoaXMuY29uZmlnKSk7XG4gIH1cblxuICBwdWJsaWMgZWNzKCk6IEFXUy5FQ1Mge1xuICAgIHJldHVybiB0aGlzLndyYXBTZXJ2aWNlRXJyb3JIYW5kbGluZyhuZXcgQVdTLkVDUyh0aGlzLmNvbmZpZykpO1xuICB9XG5cbiAgcHVibGljIGVsYnYyKCk6IEFXUy5FTEJ2MiB7XG4gICAgcmV0dXJuIHRoaXMud3JhcFNlcnZpY2VFcnJvckhhbmRsaW5nKG5ldyBBV1MuRUxCdjIodGhpcy5jb25maWcpKTtcbiAgfVxuXG4gIHB1YmxpYyBzZWNyZXRzTWFuYWdlcigpOiBBV1MuU2VjcmV0c01hbmFnZXIge1xuICAgIHJldHVybiB0aGlzLndyYXBTZXJ2aWNlRXJyb3JIYW5kbGluZyhuZXcgQVdTLlNlY3JldHNNYW5hZ2VyKHRoaXMuY29uZmlnKSk7XG4gIH1cblxuICBwdWJsaWMga21zKCk6IEFXUy5LTVMge1xuICAgIHJldHVybiB0aGlzLndyYXBTZXJ2aWNlRXJyb3JIYW5kbGluZyhuZXcgQVdTLktNUyh0aGlzLmNvbmZpZykpO1xuICB9XG5cbiAgcHVibGljIHN0ZXBGdW5jdGlvbnMoKTogQVdTLlN0ZXBGdW5jdGlvbnMge1xuICAgIHJldHVybiB0aGlzLndyYXBTZXJ2aWNlRXJyb3JIYW5kbGluZyhuZXcgQVdTLlN0ZXBGdW5jdGlvbnModGhpcy5jb25maWcpKTtcbiAgfVxuXG4gIHB1YmxpYyBjb2RlQnVpbGQoKTogQVdTLkNvZGVCdWlsZCB7XG4gICAgcmV0dXJuIHRoaXMud3JhcFNlcnZpY2VFcnJvckhhbmRsaW5nKG5ldyBBV1MuQ29kZUJ1aWxkKHRoaXMuY29uZmlnKSk7XG4gIH1cblxuICBwdWJsaWMgY2xvdWRXYXRjaExvZ3MoKTogQVdTLkNsb3VkV2F0Y2hMb2dzIHtcbiAgICByZXR1cm4gdGhpcy53cmFwU2VydmljZUVycm9ySGFuZGxpbmcobmV3IEFXUy5DbG91ZFdhdGNoTG9ncyh0aGlzLmNvbmZpZykpO1xuICB9XG5cbiAgcHVibGljIGFwcHN5bmMoKTogQVdTLkFwcFN5bmMge1xuICAgIHJldHVybiB0aGlzLndyYXBTZXJ2aWNlRXJyb3JIYW5kbGluZyhuZXcgQVdTLkFwcFN5bmModGhpcy5jb25maWcpKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBjdXJyZW50QWNjb3VudCgpOiBQcm9taXNlPEFjY291bnQ+IHtcbiAgICAvLyBHZXQvcmVmcmVzaCBpZiBuZWNlc3NhcnkgYmVmb3JlIHdlIGNhbiBhY2Nlc3MgYGFjY2Vzc0tleUlkYFxuICAgIGF3YWl0IHRoaXMuZm9yY2VDcmVkZW50aWFsUmV0cmlldmFsKCk7XG5cbiAgICByZXR1cm4gY2FjaGVkKHRoaXMsIENVUlJFTlRfQUNDT1VOVF9LRVksICgpID0+IFNESy5hY2NvdW50Q2FjaGUuZmV0Y2godGhpcy5fY3JlZGVudGlhbHMuYWNjZXNzS2V5SWQsIGFzeW5jICgpID0+IHtcbiAgICAgIC8vIGlmIHdlIGRvbid0IGhhdmUgb25lLCByZXNvbHZlIGZyb20gU1RTIGFuZCBzdG9yZSBpbiBjYWNoZS5cbiAgICAgIGRlYnVnKCdMb29raW5nIHVwIGRlZmF1bHQgYWNjb3VudCBJRCBmcm9tIFNUUycpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbmV3IEFXUy5TVFMoeyAuLi50aGlzLmNvbmZpZywgLi4udGhpcy5zdHNSZXRyeU9wdGlvbnMgfSkuZ2V0Q2FsbGVySWRlbnRpdHkoKS5wcm9taXNlKCk7XG4gICAgICBjb25zdCBhY2NvdW50SWQgPSByZXN1bHQuQWNjb3VudDtcbiAgICAgIGNvbnN0IHBhcnRpdGlvbiA9IHJlc3VsdC5Bcm4hLnNwbGl0KCc6JylbMV07XG4gICAgICBpZiAoIWFjY291bnRJZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1NUUyBkaWRuXFwndCByZXR1cm4gYW4gYWNjb3VudCBJRCcpO1xuICAgICAgfVxuICAgICAgZGVidWcoJ0RlZmF1bHQgYWNjb3VudCBJRDonLCBhY2NvdW50SWQpO1xuXG4gICAgICAvLyBTYXZlIGFub3RoZXIgU1RTIGNhbGwgbGF0ZXIgaWYgdGhpcyBvbmUgYWxyZWFkeSBzdWNjZWVkZWRcbiAgICAgIHRoaXMuX2NyZWRlbnRpYWxzVmFsaWRhdGVkID0gdHJ1ZTtcbiAgICAgIHJldHVybiB7IGFjY291bnRJZCwgcGFydGl0aW9uIH07XG4gICAgfSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgY3VycmVudCBjcmVkZW50aWFsc1xuICAgKlxuICAgKiBEb24ndCB1c2UgLS0gb25seSB1c2VkIHRvIHdyaXRlIHRlc3RzIGFyb3VuZCBhc3N1bWluZyByb2xlcy5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBjdXJyZW50Q3JlZGVudGlhbHMoKTogUHJvbWlzZTxBV1MuQ3JlZGVudGlhbHM+IHtcbiAgICBhd2FpdCB0aGlzLmZvcmNlQ3JlZGVudGlhbFJldHJpZXZhbCgpO1xuICAgIHJldHVybiB0aGlzLl9jcmVkZW50aWFscztcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JjZSByZXRyaWV2YWwgb2YgdGhlIGN1cnJlbnQgY3JlZGVudGlhbHNcbiAgICpcbiAgICogUmVsZXZhbnQgaWYgdGhlIGN1cnJlbnQgY3JlZGVudGlhbHMgYXJlIEFzc3VtZVJvbGUgY3JlZGVudGlhbHMgLS0gZG8gdGhlIGFjdHVhbFxuICAgKiBsb29rdXAsIGFuZCB0cmFuc2xhdGUgYW55IGVycm9yIGludG8gYSB1c2VmdWwgZXJyb3IgbWVzc2FnZSAodGFraW5nIGludG9cbiAgICogYWNjb3VudCBjcmVkZW50aWFsIHByb3ZlbmFuY2UpLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIGZvcmNlQ3JlZGVudGlhbFJldHJpZXZhbCgpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5fY3JlZGVudGlhbHMuZ2V0UHJvbWlzZSgpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKGlzVW5yZWNvdmVyYWJsZUF3c0Vycm9yKGUpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG5cbiAgICAgIC8vIE9ubHkgcmVhc29uIHRoaXMgd291bGQgZmFpbCBpcyBpZiBpdCB3YXMgYW4gQXNzdW1Sb2xlLiBPdGhlcndpc2UsXG4gICAgICAvLyByZWFkaW5nIGZyb20gYW4gSU5JIGZpbGUgb3IgcmVhZGluZyBlbnYgdmFyaWFibGVzIGlzIHVubGlrZWx5IHRvIGZhaWwuXG4gICAgICBkZWJ1ZyhgQXNzdW1pbmcgcm9sZSBmYWlsZWQ6ICR7ZS5tZXNzYWdlfWApO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFtcbiAgICAgICAgJ0NvdWxkIG5vdCBhc3N1bWUgcm9sZSBpbiB0YXJnZXQgYWNjb3VudCcsXG4gICAgICAgIC4uLnRoaXMuc2RrT3B0aW9ucy5hc3N1bWVSb2xlQ3JlZGVudGlhbHNTb3VyY2VEZXNjcmlwdGlvblxuICAgICAgICAgID8gW2B1c2luZyAke3RoaXMuc2RrT3B0aW9ucy5hc3N1bWVSb2xlQ3JlZGVudGlhbHNTb3VyY2VEZXNjcmlwdGlvbn1gXVxuICAgICAgICAgIDogW10sXG4gICAgICAgIGUubWVzc2FnZSxcbiAgICAgICAgJy4gUGxlYXNlIG1ha2Ugc3VyZSB0aGF0IHRoaXMgcm9sZSBleGlzdHMgaW4gdGhlIGFjY291bnQuIElmIGl0IGRvZXNuXFwndCBleGlzdCwgKHJlKS1ib290c3RyYXAgdGhlIGVudmlyb25tZW50ICcgK1xuICAgICAgICAnd2l0aCB0aGUgcmlnaHQgXFwnLS10cnVzdFxcJywgdXNpbmcgdGhlIGxhdGVzdCB2ZXJzaW9uIG9mIHRoZSBDREsgQ0xJLicsXG4gICAgICBdLmpvaW4oJyAnKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ha2Ugc3VyZSB0aGUgdGhlIGN1cnJlbnQgY3JlZGVudGlhbHMgYXJlIG5vdCBleHBpcmVkXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdmFsaWRhdGVDcmVkZW50aWFscygpIHtcbiAgICBpZiAodGhpcy5fY3JlZGVudGlhbHNWYWxpZGF0ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCBuZXcgQVdTLlNUUyh7IC4uLnRoaXMuY29uZmlnLCAuLi50aGlzLnN0c1JldHJ5T3B0aW9ucyB9KS5nZXRDYWxsZXJJZGVudGl0eSgpLnByb21pc2UoKTtcbiAgICB0aGlzLl9jcmVkZW50aWFsc1ZhbGlkYXRlZCA9IHRydWU7XG4gIH1cblxuICBwdWJsaWMgZ2V0RW5kcG9pbnRTdWZmaXgocmVnaW9uOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiByZWdpb25VdGlsLmdldEVuZHBvaW50U3VmZml4KHJlZ2lvbik7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGEgd3JhcHBpbmcgb2JqZWN0IGZvciB0aGUgdW5kZXJseWluZyBzZXJ2aWNlIG9iamVjdFxuICAgKlxuICAgKiBSZXNwb25kcyB0byBmYWlsdXJlcyBpbiB0aGUgdW5kZXJseWluZyBzZXJ2aWNlIGNhbGxzLCBpbiB0d28gZGlmZmVyZW50XG4gICAqIHdheXM6XG4gICAqXG4gICAqIC0gV2hlbiBlcnJvcnMgYXJlIGVuY291bnRlcmVkLCBsb2cgdGhlIGZhaWxpbmcgY2FsbCBhbmQgdGhlIGVycm9yIHRoYXRcbiAgICogICBpdCB0cmlnZ2VyZWQgKGF0IGRlYnVnIGxldmVsKS4gVGhpcyBpcyBuZWNlc3NhcnkgYmVjYXVzZSB0aGUgbGFjayBvZlxuICAgKiAgIHN0YWNrIHRyYWNlcyBpbiBOb2RlSlMgb3RoZXJ3aXNlIG1ha2VzIGl0IHZlcnkgaGFyZCB0byBzdXNzIG91dCB3aGVyZVxuICAgKiAgIGEgY2VydGFpbiBBV1MgZXJyb3Igb2NjdXJyZWQuXG4gICAqIC0gVGhlIEpTIFNESyBoYXMgYSBmdW5ueSBidXNpbmVzcyBvZiB3cmFwcGluZyBhbnkgY3JlZGVudGlhbC1iYXNlZCBlcnJvclxuICAgKiAgIGluIGEgc3VwZXItZ2VuZXJpYyAoYW5kIGluIG91ciBjYXNlIHdyb25nKSBleGNlcHRpb24uIElmIHdlIHRoZW4gdXNlIGFcbiAgICogICAnQ2hhaW5hYmxlVGVtcG9yYXJ5Q3JlZGVudGlhbHMnIGFuZCB0aGUgdGFyZ2V0IHJvbGUgZG9lc24ndCBleGlzdCxcbiAgICogICB0aGUgZXJyb3IgbWVzc2FnZSB0aGF0IHNob3dzIHVwIGJ5IGRlZmF1bHQgaXMgc3VwZXIgbWlzbGVhZGluZ1xuICAgKiAgIChodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1zZGstanMvaXNzdWVzLzMyNzIpLiBXZSBjYW4gZml4IHRoaXMgYmVjYXVzZVxuICAgKiAgIHRoZSBleGNlcHRpb24gY29udGFpbnMgdGhlIFwiaW5uZXIgZXhjZXB0aW9uXCIsIHNvIHdlIHVud3JhcCBhbmQgdGhyb3dcbiAgICogICB0aGUgY29ycmVjdCBlcnJvciAoXCJjYW5ub3QgYXNzdW1lIHJvbGVcIikuXG4gICAqXG4gICAqIFRoZSB3cmFwcGluZyBidXNpbmVzcyBiZWxvdyBpcyBzbGlnaHRseSBtb3JlIGNvbXBsaWNhdGVkIHRoYW4geW91J2QgdGhpbmtcbiAgICogYmVjYXVzZSB3ZSBtdXN0IGhvb2sgaW50byB0aGUgYHByb21pc2UoKWAgbWV0aG9kIG9mIHRoZSBvYmplY3QgdGhhdCdzIGJlaW5nXG4gICAqIHJldHVybmVkIGZyb20gdGhlIG1ldGhvZHMgb2YgdGhlIG9iamVjdCB0aGF0IHdlIHdyYXAsIHNvIHRoZXJlJ3MgdHdvXG4gICAqIGxldmVscyBvZiB3cmFwcGluZyBnb2luZyBvbiwgYW5kIGFsc28gc29tZSBleGNlcHRpb25zIHRvIHRoZSB3cmFwcGluZyBtYWdpYy5cbiAgICovXG4gIHByaXZhdGUgd3JhcFNlcnZpY2VFcnJvckhhbmRsaW5nPEEgZXh0ZW5kcyBvYmplY3Q+KHNlcnZpY2VPYmplY3Q6IEEpOiBBIHtcbiAgICBjb25zdCBjbGFzc09iamVjdCA9IHNlcnZpY2VPYmplY3QuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gICAgcmV0dXJuIG5ldyBQcm94eShzZXJ2aWNlT2JqZWN0LCB7XG4gICAgICBnZXQob2JqOiBBLCBwcm9wOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgcmVhbCA9IChvYmogYXMgYW55KVtwcm9wXTtcbiAgICAgICAgLy8gVGhpbmdzIHdlIGRvbid0IHdhbnQgdG8gaW50ZXJjZXB0OlxuICAgICAgICAvLyAtIEFueXRoaW5nIHRoYXQncyBub3QgYSBmdW5jdGlvbi5cbiAgICAgICAgLy8gLSAnY29uc3RydWN0b3InLCBzMy51cGxvYWQoKSB3aWxsIHVzZSB0aGlzIHRvIGRvIHNvbWUgbWFnaWMgYW5kIHdlIG5lZWQgdGhlIHVuZGVybHlpbmcgY29uc3RydWN0b3IuXG4gICAgICAgIC8vIC0gQW55IG1ldGhvZCB0aGF0J3Mgbm90IG9uIHRoZSBzZXJ2aWNlIGNsYXNzIChkbyBub3QgaW50ZXJjZXB0ICdtYWtlUmVxdWVzdCcgYW5kIG90aGVyIGhlbHBlcnMpLlxuICAgICAgICBpZiAocHJvcCA9PT0gJ2NvbnN0cnVjdG9yJyB8fCAhY2xhc3NPYmplY3QuaGFzT3duUHJvcGVydHkocHJvcCkgfHwgIWlzRnVuY3Rpb24ocmVhbCkpIHsgcmV0dXJuIHJlYWw7IH1cblxuICAgICAgICAvLyBOT1RFOiBUaGlzIG11c3QgYmUgYSBmdW5jdGlvbigpIGFuZCBub3QgYW4gKCkgPT4ge1xuICAgICAgICAvLyBiZWNhdXNlIEkgbmVlZCAndGhpcycgdG8gYmUgZHluYW1pY2FsbHkgYm91bmQgYW5kIG5vdCBzdGF0aWNhbGx5IGJvdW5kLlxuICAgICAgICAvLyBJZiB5b3VyIGxpbnRlciBjb21wbGFpbnMgZG9uJ3QgbGlzdGVuIHRvIGl0IVxuICAgICAgICByZXR1cm4gZnVuY3Rpb24odGhpczogYW55KSB7XG4gICAgICAgICAgLy8gQ2FsbCB0aGUgdW5kZXJseWluZyBmdW5jdGlvbi4gSWYgaXQgcmV0dXJucyBhbiBvYmplY3Qgd2l0aCBhIHByb21pc2UoKVxuICAgICAgICAgIC8vIG1ldGhvZCBvbiBpdCwgd3JhcCB0aGF0ICdwcm9taXNlJyBtZXRob2QuXG4gICAgICAgICAgY29uc3QgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKTtcbiAgICAgICAgICBjb25zdCByZXNwb25zZSA9IHJlYWwuYXBwbHkodGhpcywgYXJncyk7XG5cbiAgICAgICAgICAvLyBEb24ndCBpbnRlcmNlcHQgdW5sZXNzIHRoZSByZXR1cm4gdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYSAnLnByb21pc2UoKScgbWV0aG9kLlxuICAgICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2UgIT09ICdvYmplY3QnIHx8ICFyZXNwb25zZSkgeyByZXR1cm4gcmVzcG9uc2U7IH1cbiAgICAgICAgICBpZiAoISgncHJvbWlzZScgaW4gcmVzcG9uc2UpKSB7IHJldHVybiByZXNwb25zZTsgfVxuXG4gICAgICAgICAgLy8gUmV0dXJuIGFuIG9iamVjdCB3aXRoIHRoZSBwcm9taXNlIG1ldGhvZCByZXBsYWNlZCB3aXRoIGEgd3JhcHBlciB3aGljaCB3aWxsXG4gICAgICAgICAgLy8gZG8gYWRkaXRpb25hbCB0aGluZ3MgdG8gZXJyb3JzLlxuICAgICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUocmVzcG9uc2UpLCB7XG4gICAgICAgICAgICBwcm9taXNlKCkge1xuICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UucHJvbWlzZSgpLmNhdGNoKChlOiBFcnJvciAmIHsgY29kZT86IHN0cmluZyB9KSA9PiB7XG4gICAgICAgICAgICAgICAgZSA9IHNlbGYubWFrZURldGFpbGVkRXhjZXB0aW9uKGUpO1xuICAgICAgICAgICAgICAgIGRlYnVnKGBDYWxsIGZhaWxlZDogJHtwcm9wfSgke0pTT04uc3RyaW5naWZ5KGFyZ3NbMF0pfSkgPT4gJHtlLm1lc3NhZ2V9IChjb2RlPSR7ZS5jb2RlfSlgKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7IC8vIFJlLSd0aHJvdycgdGhlIG5ldyBlcnJvclxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4dHJhY3QgYSBtb3JlIGRldGFpbGVkIGVycm9yIG91dCBvZiBhIGdlbmVyaWMgZXJyb3IgaWYgd2UgY2FuXG4gICAqXG4gICAqIElmIHRoaXMgaXMgYW4gZXJyb3IgYWJvdXQgQXNzdW1pbmcgUm9sZXMsIGFkZCBpbiB0aGUgY29udGV4dCBzaG93aW5nIHRoZVxuICAgKiBjaGFpbiBvZiBjcmVkZW50aWFscyB3ZSB1c2VkIHRvIHRyeSB0byBhc3N1bWUgdGhlIHJvbGUuXG4gICAqL1xuICBwcml2YXRlIG1ha2VEZXRhaWxlZEV4Y2VwdGlvbihlOiBFcnJvcik6IEVycm9yIHtcbiAgICAvLyBUaGlzIGlzIHRoZSBzdXBlci1nZW5lcmljIFwic29tZXRoaW5nJ3Mgd3JvbmdcIiBlcnJvciB0aGF0IHRoZSBKUyBTREsgd3JhcHMgb3RoZXIgZXJyb3JzIGluLlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLXNkay1qcy9ibG9iL2YwYWMyZTUzNDU3Yzc1MTI4ODNkMDY3NzAxM2VhY2FhZDZjZDhhMTkvbGliL2V2ZW50X2xpc3RlbmVycy5qcyNMODRcbiAgICBpZiAodHlwZW9mIGUubWVzc2FnZSA9PT0gJ3N0cmluZycgJiYgZS5tZXNzYWdlLnN0YXJ0c1dpdGgoJ01pc3NpbmcgY3JlZGVudGlhbHMgaW4gY29uZmlnJykpIHtcbiAgICAgIGNvbnN0IG9yaWdpbmFsID0gKGUgYXMgYW55KS5vcmlnaW5hbEVycm9yO1xuICAgICAgaWYgKG9yaWdpbmFsKSB7XG4gICAgICAgIC8vIFdoZW4gdGhlIFNESyBkb2VzIGEgJ3V0aWwuY29weScsIHRoZXkgbG9zZSB0aGUgRXJyb3ItbmVzcyBvZiB0aGUgaW5uZXIgZXJyb3JcbiAgICAgICAgLy8gKHRoZXkgY29weSB0aGUgRXJyb3IncyBwcm9wZXJ0aWVzIGludG8gYSBwbGFpbiBvYmplY3QpIHNvIG1ha2UgaXQgYW4gRXJyb3Igb2JqZWN0IGFnYWluLlxuICAgICAgICBlID0gT2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoKSwgb3JpZ2luYWwpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEF0IHRoaXMgcG9pbnQsIHRoZSBlcnJvciBtaWdodCBzdGlsbCBiZSBhIGdlbmVyaWMgXCJDaGFpbmFibGVUZW1wb3JhcnlDcmVkZW50aWFscyBmYWlsZWRcIlxuICAgIC8vIGVycm9yIHdoaWNoIHdyYXBzIHRoZSBSRUFMIGVycm9yIChBc3N1bWVSb2xlIGZhaWxlZCkuIFdlJ3JlIGdvaW5nIHRvIHJlcGxhY2UgdGhlIGVycm9yXG4gICAgLy8gbWVzc2FnZSB3aXRoIG9uZSB0aGF0J3MgbW9yZSBsaWtlbHkgdG8gaGVscCB1c2VycywgYW5kIHRlbGwgdGhlbSB0aGUgbW9zdCBwcm9iYWJsZVxuICAgIC8vIGZpeCAoYm9vdHN0cmFwcGluZykuIFRoZSB1bmRlcmx5aW5nIHNlcnZpY2UgY2FsbCBmYWlsdXJlIHdpbGwgYmUgYXBwZW5kZWQgYmVsb3cuXG4gICAgaWYgKGUubWVzc2FnZSA9PT0gJ0NvdWxkIG5vdCBsb2FkIGNyZWRlbnRpYWxzIGZyb20gQ2hhaW5hYmxlVGVtcG9yYXJ5Q3JlZGVudGlhbHMnKSB7XG4gICAgICBlLm1lc3NhZ2UgPSBbXG4gICAgICAgICdDb3VsZCBub3QgYXNzdW1lIHJvbGUgaW4gdGFyZ2V0IGFjY291bnQnLFxuICAgICAgICAuLi50aGlzLnNka09wdGlvbnMuYXNzdW1lUm9sZUNyZWRlbnRpYWxzU291cmNlRGVzY3JpcHRpb25cbiAgICAgICAgICA/IFtgdXNpbmcgJHt0aGlzLnNka09wdGlvbnMuYXNzdW1lUm9sZUNyZWRlbnRpYWxzU291cmNlRGVzY3JpcHRpb259YF1cbiAgICAgICAgICA6IFtdLFxuICAgICAgICAnKGRpZCB5b3UgYm9vdHN0cmFwIHRoZSBlbnZpcm9ubWVudCB3aXRoIHRoZSByaWdodCBcXCctLXRydXN0XFwncz8pJyxcbiAgICAgIF0uam9pbignICcpO1xuICAgIH1cblxuICAgIC8vIFJlcGxhY2UgdGhlIG1lc3NhZ2Ugb24gdGhpcyBlcnJvciB3aXRoIGEgY29uY2F0ZW5hdGlvbiBvZiBhbGwgaW5uZXIgZXJyb3IgbWVzc2FnZXMuXG4gICAgLy8gTXVzdCBtb3JlIGNsZWFyIHdoYXQncyBnb2luZyBvbiB0aGF0IHdheS5cbiAgICBlLm1lc3NhZ2UgPSBhbGxDaGFpbmVkRXhjZXB0aW9uTWVzc2FnZXMoZSk7XG4gICAgcmV0dXJuIGU7XG4gIH1cbn1cblxuY29uc3QgQ1VSUkVOVF9BQ0NPVU5UX0tFWSA9IFN5bWJvbCgnY3VycmVudF9hY2NvdW50X2tleScpO1xuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKHg6IGFueSk6IHggaXMgKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnkge1xuICByZXR1cm4geCAmJiB7fS50b1N0cmluZy5jYWxsKHgpID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG4vKipcbiAqIFJldHVybiB0aGUgY29uY2F0ZW5hdGVkIG1lc3NhZ2Ugb2YgYWxsIGV4Y2VwdGlvbnMgaW4gdGhlIEFXUyBleGNlcHRpb24gY2hhaW5cbiAqL1xuZnVuY3Rpb24gYWxsQ2hhaW5lZEV4Y2VwdGlvbk1lc3NhZ2VzKGU6IEVycm9yIHwgdW5kZWZpbmVkKSB7XG4gIGNvbnN0IHJldCA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG4gIHdoaWxlIChlKSB7XG4gICAgcmV0LnB1c2goZS5tZXNzYWdlKTtcbiAgICBlID0gKGUgYXMgYW55KS5vcmlnaW5hbEVycm9yO1xuICB9XG4gIHJldHVybiByZXQuam9pbignOiAnKTtcbn1cblxuLyoqXG4gKiBSZXR1cm4gd2hldGhlciBhbiBlcnJvciBzaG91bGQgbm90IGJlIHJlY292ZXJlZCBmcm9tXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1VucmVjb3ZlcmFibGVBd3NFcnJvcihlOiBFcnJvcikge1xuICByZXR1cm4gKGUgYXMgYW55KS5jb2RlID09PSAnRXhwaXJlZFRva2VuJztcbn1cbiJdfQ==