lambda-version.js
1 "use strict"; 2 var _a; 3 Object.defineProperty(exports, "__esModule", { value: true }); 4 exports.extractQualifierFromArn = exports.Version = void 0; 5 const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); 6 const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); 7 const core_1 = require("@aws-cdk/core"); 8 const function_1 = require("./function"); 9 const function_base_1 = require("./function-base"); 10 const lambda_generated_1 = require("./lambda.generated"); 11 const util_1 = require("./util"); 12 /** 13 * A single newly-deployed version of a Lambda function. 14 * 15 * This object exists to--at deploy time--query the "then-current" version of 16 * the Lambda function that it refers to. This Version object can then be 17 * used in `Alias` to refer to a particular deployment of a Lambda. 18 * 19 * This means that for every new update you deploy to your Lambda (using the 20 * CDK and Aliases), you must always create a new Version object. In 21 * particular, it must have a different name, so that a new resource is 22 * created. 23 * 24 * If you want to ensure that you're associating the right version with 25 * the right deployment, specify the `codeSha256` property while 26 * creating the `Version. 27 * 28 * @stability stable 29 */ 30 class Version extends function_base_1.QualifiedFunctionBase { 31 /** 32 * @stability stable 33 */ 34 constructor(scope, id, props) { 35 super(scope, id); 36 /** 37 * Whether the addPermission() call adds any permissions. 38 * 39 * True for new Lambdas, false for version $LATEST and imported Lambdas 40 * from different accounts. 41 * 42 * @stability stable 43 */ 44 this.canCreatePermissions = true; 45 jsiiDeprecationWarnings._aws_cdk_aws_lambda_VersionProps(props); 46 this.lambda = props.lambda; 47 const version = new lambda_generated_1.CfnVersion(this, 'Resource', { 48 codeSha256: props.codeSha256, 49 description: props.description, 50 functionName: props.lambda.functionName, 51 provisionedConcurrencyConfig: this.determineProvisionedConcurrency(props), 52 }); 53 if (props.removalPolicy) { 54 version.applyRemovalPolicy(props.removalPolicy, { 55 default: core_1.RemovalPolicy.DESTROY, 56 }); 57 } 58 this.version = version.attrVersion; 59 this.functionArn = version.ref; 60 this.functionName = `${this.lambda.functionName}:${this.version}`; 61 this.qualifier = version.attrVersion; 62 if (props.onFailure || props.onSuccess || props.maxEventAge || props.retryAttempts !== undefined) { 63 this.configureAsyncInvoke({ 64 onFailure: props.onFailure, 65 onSuccess: props.onSuccess, 66 maxEventAge: props.maxEventAge, 67 retryAttempts: props.retryAttempts, 68 }); 69 } 70 } 71 /** 72 * Construct a Version object from a Version ARN. 73 * 74 * @param scope The cdk scope creating this resource. 75 * @param id The cdk id of this resource. 76 * @param versionArn The version ARN to create this version from. 77 * @stability stable 78 */ 79 static fromVersionArn(scope, id, versionArn) { 80 const version = extractQualifierFromArn(versionArn); 81 const lambda = function_1.Function.fromFunctionArn(scope, `${id}Function`, versionArn); 82 class Import extends function_base_1.QualifiedFunctionBase { 83 constructor() { 84 super(...arguments); 85 this.version = version; 86 this.lambda = lambda; 87 this.functionName = `${lambda.functionName}:${version}`; 88 this.functionArn = versionArn; 89 this.grantPrincipal = lambda.grantPrincipal; 90 this.role = lambda.role; 91 this.qualifier = version; 92 this.canCreatePermissions = this._isStackAccount(); 93 } 94 addAlias(name, opts = {}) { 95 return util_1.addAlias(this, this, name, opts); 96 } 97 get edgeArn() { 98 if (version === '$LATEST') { 99 throw new Error('$LATEST function version cannot be used for Lambda@Edge'); 100 } 101 return this.functionArn; 102 } 103 } 104 return new Import(scope, id); 105 } 106 /** 107 * @stability stable 108 */ 109 static fromVersionAttributes(scope, id, attrs) { 110 jsiiDeprecationWarnings._aws_cdk_aws_lambda_VersionAttributes(attrs); 111 class Import extends function_base_1.QualifiedFunctionBase { 112 constructor() { 113 super(...arguments); 114 this.version = attrs.version; 115 this.lambda = attrs.lambda; 116 this.functionName = `${attrs.lambda.functionName}:${attrs.version}`; 117 this.functionArn = `${attrs.lambda.functionArn}:${attrs.version}`; 118 this.grantPrincipal = attrs.lambda.grantPrincipal; 119 this.role = attrs.lambda.role; 120 this.qualifier = attrs.version; 121 this.canCreatePermissions = this._isStackAccount(); 122 } 123 addAlias(name, opts = {}) { 124 return util_1.addAlias(this, this, name, opts); 125 } 126 get edgeArn() { 127 if (attrs.version === '$LATEST') { 128 throw new Error('$LATEST function version cannot be used for Lambda@Edge'); 129 } 130 return this.functionArn; 131 } 132 } 133 return new Import(scope, id); 134 } 135 /** 136 * The principal this Lambda Function is running as. 137 * 138 * @stability stable 139 */ 140 get grantPrincipal() { 141 return this.lambda.grantPrincipal; 142 } 143 /** 144 * The IAM role associated with this function. 145 * 146 * Undefined if the function was imported without a role. 147 * 148 * @stability stable 149 */ 150 get role() { 151 return this.lambda.role; 152 } 153 /** 154 * Return the given named metric for this Function. 155 * 156 * @stability stable 157 */ 158 metric(metricName, props = {}) { 159 // Metrics on Aliases need the "bare" function name, and the alias' ARN, this differs from the base behavior. 160 return super.metric(metricName, { 161 dimensions: { 162 FunctionName: this.lambda.functionName, 163 // construct the ARN from the underlying lambda so that alarms on an alias 164 // don't cause a circular dependency with CodeDeploy 165 // see: https://github.com/aws/aws-cdk/issues/2231 166 Resource: `${this.lambda.functionArn}:${this.version}`, 167 }, 168 ...props, 169 }); 170 } 171 /** 172 * Defines an alias for this version. 173 * 174 * @param aliasName The name of the alias (e.g. "live"). 175 * @param options Alias options. 176 * @stability stable 177 */ 178 addAlias(aliasName, options = {}) { 179 jsiiDeprecationWarnings._aws_cdk_aws_lambda_AliasOptions(options); 180 return util_1.addAlias(this, this, aliasName, options); 181 } 182 /** 183 * The ARN of the version for Lambda@Edge. 184 * 185 * @stability stable 186 */ 187 get edgeArn() { 188 // Validate first that this version can be used for Lambda@Edge 189 if (this.version === '$LATEST') { 190 throw new Error('$LATEST function version cannot be used for Lambda@Edge'); 191 } 192 // Check compatibility at synthesis. It could be that the version was associated 193 // with a CloudFront distribution first and made incompatible afterwards. 194 return core_1.Lazy.string({ 195 produce: () => { 196 // Validate that the underlying function can be used for Lambda@Edge 197 if (this.lambda instanceof function_1.Function) { 198 this.lambda._checkEdgeCompatibility(); 199 } 200 return this.functionArn; 201 }, 202 }); 203 } 204 /** 205 * Validate that the provisionedConcurrentExecutions makes sense 206 * 207 * Member must have value greater than or equal to 1 208 */ 209 determineProvisionedConcurrency(props) { 210 if (!props.provisionedConcurrentExecutions) { 211 return undefined; 212 } 213 if (props.provisionedConcurrentExecutions <= 0) { 214 throw new Error('provisionedConcurrentExecutions must have value greater than or equal to 1'); 215 } 216 return { provisionedConcurrentExecutions: props.provisionedConcurrentExecutions }; 217 } 218 } 219 exports.Version = Version; 220 _a = JSII_RTTI_SYMBOL_1; 221 Version[_a] = { fqn: "@aws-cdk/aws-lambda.Version", version: "1.134.0" }; 222 /** 223 * Given an opaque (token) ARN, returns a CloudFormation expression that extracts the 224 * qualifier (= version or alias) from the ARN. 225 * 226 * Version ARNs look like this: 227 * 228 * arn:aws:lambda:region:account-id:function:function-name:qualifier 229 * 230 * ..which means that in order to extract the `qualifier` component from the ARN, we can 231 * split the ARN using ":" and select the component in index 7. 232 * 233 * @returns `FnSelect(7, FnSplit(':', arn))` 234 */ 235 function extractQualifierFromArn(arn) { 236 return core_1.Fn.select(7, core_1.Fn.split(':', arn)); 237 } 238 exports.extractQualifierFromArn = extractQualifierFromArn; 239 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLXZlcnNpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJsYW1iZGEtdmVyc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFDQSx3Q0FBd0Q7QUFJeEQseUNBQXNDO0FBQ3RDLG1EQUFtRTtBQUNuRSx5REFBZ0Q7QUFDaEQsaUNBQWtDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBOENsQyxNQUFhLE9BQVEsU0FBUSxxQ0FBcUI7Ozs7SUFrRWhELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBbUI7UUFDM0QsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQzs7Ozs7Ozs7O1FBSEEseUJBQW9CLEdBQUcsSUFBSSxDQUFDOztRQUs3QyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFFM0IsTUFBTSxPQUFPLEdBQUcsSUFBSSw2QkFBVSxDQUFDLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDL0MsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVO1lBQzVCLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVztZQUM5QixZQUFZLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxZQUFZO1lBQ3ZDLDRCQUE0QixFQUFFLElBQUksQ0FBQywrQkFBK0IsQ0FBQyxLQUFLLENBQUM7U0FDMUUsQ0FBQyxDQUFDO1FBRUgsSUFBSSxLQUFLLENBQUMsYUFBYSxFQUFFO1lBQ3ZCLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsYUFBYSxFQUFFO2dCQUM5QyxPQUFPLEVBQUUsb0JBQWEsQ0FBQyxPQUFPO2FBQy9CLENBQUMsQ0FBQztTQUNKO1FBRUQsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDO1FBQ25DLElBQUksQ0FBQyxXQUFXLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQztRQUMvQixJQUFJLENBQUMsWUFBWSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLElB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eUQsQ0FBQyxDQUFDO1NBQzVFO1FBRUQsZ0ZBQWdGO1FBQ2hGLHlFQUF5RTtRQUN6RSxPQUFPLFdBQUksQ0FBQyxNQUFNLENBQUM7WUFDakIsT0FBTyxFQUFFLEdBQUcsRUFBRTtnQkFDWixvRUFBb0U7Z0JBQ3BFLElBQUksSUFBSSxDQUFDLE1BQU0sWUFBWSxtQkFBUSxFQUFFO29CQUNuQyxJQUFJLENBQUMsTUFBTSxDQUFDLHVCQUF1QixFQUFFLENBQUM7aUJBQ3ZDO2dCQUVELE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQztZQUMxQixDQUFDO1NBQ0YsQ0FBQyxDQUFDO0tBQ0o7SUFFRDs7OztPQUlHO0lBQ0ssK0JBQStCLENBQUMsS0FBbUI7UUFDekQsSUFBSSxDQUFDLEtBQUssQ0FBQywrQkFBK0IsRUFBRTtZQUMxQyxPQUFPLFNBQVMsQ0FBQztTQUNsQjtRQUVELElBQUksS0FBSyxDQUFDLCtCQUErQixJQUFJLENBQUMsRUFBRTtZQUM5QyxNQUFNLElBQUksS0FBSyxDQUFDLDRFQUE0RSxDQUFDLENBQUM7U0FDL0Y7UUFFRCxPQUFPLEVBQUUsK0JBQStCLEVBQUUsS0FBSyxDQUFDLCtCQUErQixFQUFFLENBQUM7S0FDbkY7O0FBaktILDBCQWtLQzs7O0FBRUQ7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsU0FBZ0IsdUJBQXVCLENBQUMsR0FBVztJQUNqRCxPQUFPLFNBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLFNBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDMUMsQ0FBQztBQUZELDBEQUVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tICdAYXdzLWNkay9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQgeyBGbiwgTGF6eSwgUmVtb3ZhbFBvbGljeSB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBbGlhcywgQWxpYXNPcHRpb25zIH0gZnJvbSAnLi9hbGlhcyc7XG5pbXBvcnQgeyBFdmVudEludm9rZUNvbmZpZ09wdGlvbnMgfSBmcm9tICcuL2V2ZW50LWludm9rZS1jb25maWcnO1xuaW1wb3J0IHsgRnVuY3Rpb24gfSBmcm9tICcuL2Z1bmN0aW9uJztcbmltcG9ydCB7IElGdW5jdGlvbiwgUXVhbGlmaWVkRnVuY3Rpb25CYXNlIH0gZnJvbSAnLi9mdW5jdGlvbi1iYXNlJztcbmltcG9ydCB7IENmblZlcnNpb24gfSBmcm9tICcuL2xhbWJkYS5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgYWRkQWxpYXMgfSBmcm9tICcuL3V0aWwnO1xuXG5leHBvcnQgaW50ZXJmYWNlIElWZXJzaW9uIGV4dGVuZHMgSUZ1bmN0aW9uIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgdmVyc2lvbjogc3RyaW5nO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IGxhbWJkYTogSUZ1bmN0aW9uO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBlZGdlQXJuOiBzdHJpbmc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBhZGRBbGlhcyhhbGlhc05hbWU6IHN0cmluZywgb3B0aW9ucz86IEFsaWFzT3B0aW9ucyk6IEFsaWFzO1xufVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgVmVyc2lvbk9wdGlvbnMgZXh0ZW5kcyBFdmVudEludm9rZUNvbmZpZ09wdGlvbnMge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBjb2RlU2hhMjU2Pzogc3RyaW5nO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgcHJvdmlzaW9uZWRDb25jdXJyZW50RXhlY3V0aW9ucz86IG51bWJlcjtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IHJlbW92YWxQb2xpY3k/OiBSZW1vdmFsUG9saWN5O1xufVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5leHBvcnQgaW50ZXJmYWNlIFZlcnNpb25Qcm9wcyBleHRlbmRzIFZlcnNpb25PcHRpb25zIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBsYW1iZGE6IElGdW5jdGlvbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBWZXJzaW9uQXR0cmlidXRlcyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSB2ZXJzaW9uOiBzdHJpbmc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgbGFtYmRhOiBJRnVuY3Rpb247XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5leHBvcnQgY2xhc3MgVmVyc2lvbiBleHRlbmRzIFF1YWxpZmllZEZ1bmN0aW9uQmFzZSBpbXBsZW1lbnRzIElWZXJzaW9uIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyBmcm9tVmVyc2lvbkFybihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCB2ZXJzaW9uQXJuOiBzdHJpbmcpOiBJVmVyc2lvbiB7XG4gICAgY29uc3QgdmVyc2lvbiA9IGV4dHJhY3RRdWFsaWZpZXJGcm9tQXJuKHZlcnNpb25Bcm4pO1xuICAgIGNvbnN0IGxhbWJkYSA9IEZ1bmN0aW9uLmZyb21GdW5jdGlvbkFybihzY29wZSwgYCR7aWR9RnVuY3Rpb25gLCB2ZXJzaW9uQXJuKTtcblxuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIFF1YWxpZmllZEZ1bmN0aW9uQmFzZSBpbXBsZW1lbnRzIElWZXJzaW9uIHtcbiAgICAgIHB1YmxpYyByZWFkb25seSB2ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgIHB1YmxpYyByZWFkb25seSBsYW1iZGEgPSBsYW1iZGE7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZnVuY3Rpb25OYW1lID0gYCR7bGFtYmRhLmZ1bmN0aW9uTmFtZX06JHt2ZXJzaW9ufWA7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZnVuY3Rpb25Bcm4gPSB2ZXJzaW9uQXJuO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGdyYW50UHJpbmNpcGFsID0gbGFtYmRhLmdyYW50UHJpbmNpcGFsO1xuICAgICAgcHVibGljIHJlYWRvbmx5IHJvbGUgPSBsYW1iZGEucm9sZTtcblxuICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IHF1YWxpZmllciA9IHZlcnNpb247XG4gICAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgY2FuQ3JlYXRlUGVybWlzc2lvbnMgPSB0aGlzLl9pc1N0YWNrQWNjb3VudCgpO1xuXG4gICAgICBwdWJsaWMgYWRkQWxpYXMobmFtZTogc3RyaW5nLCBvcHRzOiBBbGlhc09wdGlvbnMgPSB7IH0pOiBBbGlhcyB7XG4gICAgICAgIHJldHVybiBhZGRBbGlhcyh0aGlzLCB0aGlzLCBuYW1lLCBvcHRzKTtcbiAgICAgIH1cblxuICAgICAgcHVibGljIGdldCBlZGdlQXJuKCk6IHN0cmluZyB7XG4gICAgICAgIGlmICh2ZXJzaW9uID09PSAnJExBVEVTVCcpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJyRMQVRFU1QgZnVuY3Rpb24gdmVyc2lvbiBjYW5ub3QgYmUgdXNlZCBmb3IgTGFtYmRhQEVkZ2UnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5mdW5jdGlvbkFybjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoc2NvcGUsIGlkKTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVZlcnNpb25BdHRyaWJ1dGVzKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIGF0dHJzOiBWZXJzaW9uQXR0cmlidXRlcyk6IElWZXJzaW9uIHtcbiAgICBjbGFzcyBJbXBvcnQgZXh0ZW5kcyBRdWFsaWZpZWRGdW5jdGlvbkJhc2UgaW1wbGVtZW50cyBJVmVyc2lvbiB7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgdmVyc2lvbiA9IGF0dHJzLnZlcnNpb247XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgbGFtYmRhID0gYXR0cnMubGFtYmRhO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGZ1bmN0aW9uTmFtZSA9IGAke2F0dHJzLmxhbWJkYS5mdW5jdGlvbk5hbWV9OiR7YXR0cnMudmVyc2lvbn1gO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGZ1bmN0aW9uQXJuID0gYCR7YXR0cnMubGFtYmRhLmZ1bmN0aW9uQXJufToke2F0dHJzLnZlcnNpb259YDtcbiAgICAgIHB1YmxpYyByZWFkb25seSBncmFudFByaW5jaXBhbCA9IGF0dHJzLmxhbWJkYS5ncmFudFByaW5jaXBhbDtcbiAgICAgIHB1YmxpYyByZWFkb25seSByb2xlID0gYXR0cnMubGFtYmRhLnJvbGU7XG5cbiAgICAgIHByb3RlY3RlZCByZWFkb25seSBxdWFsaWZpZXIgPSBhdHRycy52ZXJzaW9uO1xuICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IGNhbkNyZWF0ZVBlcm1pc3Npb25zID0gdGhpcy5faXNTdGFja0FjY291bnQoKTtcblxuICAgICAgcHVibGljIGFkZEFsaWFzKG5hbWU6IHN0cmluZywgb3B0czogQWxpYXNPcHRpb25zID0geyB9KTogQWxpYXMge1xuICAgICAgICByZXR1cm4gYWRkQWxpYXModGhpcywgdGhpcywgbmFtZSwgb3B0cyk7XG4gICAgICB9XG5cbiAgICAgIHB1YmxpYyBnZXQgZWRnZUFybigpOiBzdHJpbmcge1xuICAgICAgICBpZiAoYXR0cnMudmVyc2lvbiA9PT0gJyRMQVRFU1QnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCckTEFURVNUIGZ1bmN0aW9uIHZlcnNpb24gY2Fubm90IGJlIHVzZWQgZm9yIExhbWJkYUBFZGdlJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuZnVuY3Rpb25Bcm47XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXcgSW1wb3J0KHNjb3BlLCBpZCk7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgdmVyc2lvbjogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgbGFtYmRhOiBJRnVuY3Rpb247XG4gIHB1YmxpYyByZWFkb25seSBmdW5jdGlvbkFybjogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgZnVuY3Rpb25OYW1lOiBzdHJpbmc7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHF1YWxpZmllcjogc3RyaW5nO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgY2FuQ3JlYXRlUGVybWlzc2lvbnMgPSB0cnVlO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBWZXJzaW9uUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgdGhpcy5sYW1iZGEgPSBwcm9wcy5sYW1iZGE7XG5cbiAgICBjb25zdCB2ZXJzaW9uID0gbmV3IENmblZlcnNpb24odGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgY29kZVNoYTI1NjogcHJvcHMuY29kZVNoYTI1NixcbiAgICAgIGRlc2NyaXB0aW9uOiBwcm9wcy5kZXNjcmlwdGlvbixcbiAgICAgIGZ1bmN0aW9uTmFtZTogcHJvcHMubGFtYmRhLmZ1bmN0aW9uTmFtZSxcbiAgICAgIHByb3Zpc2lvbmVkQ29uY3VycmVuY3lDb25maWc6IHRoaXMuZGV0ZXJtaW5lUHJvdmlzaW9uZWRDb25jdXJyZW5jeShwcm9wcyksXG4gICAgfSk7XG5cbiAgICBpZiAocHJvcHMucmVtb3ZhbFBvbGljeSkge1xuICAgICAgdmVyc2lvbi5hcHBseVJlbW92YWxQb2xpY3kocHJvcHMucmVtb3ZhbFBvbGljeSwge1xuICAgICAgICBkZWZhdWx0OiBSZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnZlcnNpb24gPSB2ZXJzaW9uLmF0dHJWZXJzaW9uO1xuICAgIHRoaXMuZnVuY3Rpb25Bcm4gPSB2ZXJzaW9uLnJlZjtcbiAgICB0aGlzLmZ1bmN0aW9uTmFtZSA9IGAke3RoaXMubGFtYmRhLmZ1bmN0aW9uTmFtZX06JHt0aGlzLnZlcnNpb259YDtcbiAgICB0aGlzLnF1YWxpZmllciA9IHZlcnNpb24uYXR0clZlcnNpb247XG5cbiAgICBpZiAocHJvcHMub25GYWlsdXJlIHx8IHByb3BzLm9uU3VjY2VzcyB8fCBwcm9wcy5tYXhFdmVudEFnZSB8fCBwcm9wcy5yZXRyeUF0dGVtcHRzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuY29uZmlndXJlQXN5bmNJbnZva2Uoe1xuICAgICAgICBvbkZhaWx1cmU6IHByb3BzLm9uRmFpbHVyZSxcbiAgICAgICAgb25TdWNjZXNzOiBwcm9wcy5vblN1Y2Nlc3MsXG4gICAgICAgIG1heEV2ZW50QWdlOiBwcm9wcy5tYXhFdmVudEFnZSxcbiAgICAgICAgcmV0cnlBdHRlbXB0czogcHJvcHMucmV0cnlBdHRlbXB0cyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXQgZ3JhbnRQcmluY2lwYWwoKSB7XG4gICAgcmV0dXJuIHRoaXMubGFtYmRhLmdyYW50UHJpbmNpcGFsO1xuICB9XG5cbiAgcHVibGljIGdldCByb2xlKCkge1xuICAgIHJldHVybiB0aGlzLmxhbWJkYS5yb2xlO1xuICB9XG5cbiAgcHVibGljIG1ldHJpYyhtZXRyaWNOYW1lOiBzdHJpbmcsIHByb3BzOiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMgPSB7fSk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICAvLyBNZXRyaWNzIG9uIEFsaWFzZXMgbmVlZCB0aGUgXCJiYXJlXCIgZnVuY3Rpb24gbmFtZSwgYW5kIHRoZSBhbGlhcycgQVJOLCB0aGlzIGRpZmZlcnMgZnJvbSB0aGUgYmFzZSBiZWhhdmlvci5cbiAgICByZXR1cm4gc3VwZXIubWV0cmljKG1ldHJpY05hbWUsIHtcbiAgICAgIGRpbWVuc2lvbnM6IHtcbiAgICAgICAgRnVuY3Rpb25OYW1lOiB0aGlzLmxhbWJkYS5mdW5jdGlvbk5hbWUsXG4gICAgICAgIC8vIGNvbnN0cnVjdCB0aGUgQVJOIGZyb20gdGhlIHVuZGVybHlpbmcgbGFtYmRhIHNvIHRoYXQgYWxhcm1zIG9uIGFuIGFsaWFzXG4gICAgICAgIC8vIGRvbid0IGNhdXNlIGEgY2lyY3VsYXIgZGVwZW5kZW5jeSB3aXRoIENvZGVEZXBsb3lcbiAgICAgICAgLy8gc2VlOiBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvaXNzdWVzLzIyMzFcbiAgICAgICAgUmVzb3VyY2U6IGAke3RoaXMubGFtYmRhLmZ1bmN0aW9uQXJufToke3RoaXMudmVyc2lvbn1gLFxuICAgICAgfSxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBhZGRBbGlhcyhhbGlhc05hbWU6IHN0cmluZywgb3B0aW9uczogQWxpYXNPcHRpb25zID0geyB9KTogQWxpYXMge1xuICAgIHJldHVybiBhZGRBbGlhcyh0aGlzLCB0aGlzLCBhbGlhc05hbWUsIG9wdGlvbnMpO1xuICB9XG5cbiAgcHVibGljIGdldCBlZGdlQXJuKCk6IHN0cmluZyB7XG4gICAgLy8gVmFsaWRhdGUgZmlyc3QgdGhhdCB0aGlzIHZlcnNpb24gY2FuIGJlIHVzZWQgZm9yIExhbWJkYUBFZGdlXG4gICAgaWYgKHRoaXMudmVyc2lvbiA9PT0gJyRMQVRFU1QnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJyRMQVRFU1QgZnVuY3Rpb24gdmVyc2lvbiBjYW5ub3QgYmUgdXNlZCBmb3IgTGFtYmRhQEVkZ2UnKTtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBjb21wYXRpYmlsaXR5IGF0IHN5bnRoZXNpcy4gSXQgY291bGQgYmUgdGhhdCB0aGUgdmVyc2lvbiB3YXMgYXNzb2NpYXRlZFxuICAgIC8vIHdpdGggYSBDbG91ZEZyb250IGRpc3RyaWJ1dGlvbiBmaXJzdCBhbmQgbWFkZSBpbmNvbXBhdGlibGUgYWZ0ZXJ3YXJkcy5cbiAgICByZXR1cm4gTGF6eS5zdHJpbmcoe1xuICAgICAgcHJvZHVjZTogKCkgPT4ge1xuICAgICAgICAvLyBWYWxpZGF0ZSB0aGF0IHRoZSB1bmRlcmx5aW5nIGZ1bmN0aW9uIGNhbiBiZSB1c2VkIGZvciBMYW1iZGFARWRnZVxuICAgICAgICBpZiAodGhpcy5sYW1iZGEgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgIHRoaXMubGFtYmRhLl9jaGVja0VkZ2VDb21wYXRpYmlsaXR5KCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5mdW5jdGlvbkFybjtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCB0aGUgcHJvdmlzaW9uZWRDb25jdXJyZW50RXhlY3V0aW9ucyBtYWtlcyBzZW5zZVxuICAgKlxuICAgKiBNZW1iZXIgbXVzdCBoYXZlIHZhbHVlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxXG4gICAqL1xuICBwcml2YXRlIGRldGVybWluZVByb3Zpc2lvbmVkQ29uY3VycmVuY3kocHJvcHM6IFZlcnNpb25Qcm9wcyk6IENmblZlcnNpb24uUHJvdmlzaW9uZWRDb25jdXJyZW5jeUNvbmZpZ3VyYXRpb25Qcm9wZXJ0eSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFwcm9wcy5wcm92aXNpb25lZENvbmN1cnJlbnRFeGVjdXRpb25zKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5wcm92aXNpb25lZENvbmN1cnJlbnRFeGVjdXRpb25zIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncHJvdmlzaW9uZWRDb25jdXJyZW50RXhlY3V0aW9ucyBtdXN0IGhhdmUgdmFsdWUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBwcm92aXNpb25lZENvbmN1cnJlbnRFeGVjdXRpb25zOiBwcm9wcy5wcm92aXNpb25lZENvbmN1cnJlbnRFeGVjdXRpb25zIH07XG4gIH1cbn1cblxuLyoqXG4gKiBHaXZlbiBhbiBvcGFxdWUgKHRva2VuKSBBUk4sIHJldHVybnMgYSBDbG91ZEZvcm1hdGlvbiBleHByZXNzaW9uIHRoYXQgZXh0cmFjdHMgdGhlXG4gKiBxdWFsaWZpZXIgKD0gdmVyc2lvbiBvciBhbGlhcykgZnJvbSB0aGUgQVJOLlxuICpcbiAqIFZlcnNpb24gQVJOcyBsb29rIGxpa2UgdGhpczpcbiAqXG4gKiAgIGFybjphd3M6bGFtYmRhOnJlZ2lvbjphY2NvdW50LWlkOmZ1bmN0aW9uOmZ1bmN0aW9uLW5hbWU6cXVhbGlmaWVyXG4gKlxuICogLi53aGljaCBtZWFucyB0aGF0IGluIG9yZGVyIHRvIGV4dHJhY3QgdGhlIGBxdWFsaWZpZXJgIGNvbXBvbmVudCBmcm9tIHRoZSBBUk4sIHdlIGNhblxuICogc3BsaXQgdGhlIEFSTiB1c2luZyBcIjpcIiBhbmQgc2VsZWN0IHRoZSBjb21wb25lbnQgaW4gaW5kZXggNy5cbiAqXG4gKiBAcmV0dXJucyBgRm5TZWxlY3QoNywgRm5TcGxpdCgnOicsIGFybikpYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdFF1YWxpZmllckZyb21Bcm4oYXJuOiBzdHJpbmcpIHtcbiAgcmV0dXJuIEZuLnNlbGVjdCg3LCBGbi5zcGxpdCgnOicsIGFybikpO1xufVxuIl19