UNPKG

@aws-cdk/integ-tests-alpha

Version:

CDK Integration Testing Constructs

301 lines 32.3 kB
"use strict"; var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AssertionsProvider = void 0; const jsiiDeprecationWarnings = require("../../../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const path = require("path"); const core_1 = require("aws-cdk-lib/core"); const helpers_internal_1 = require("aws-cdk-lib/core/lib/helpers-internal"); const helpers_internal_2 = require("aws-cdk-lib/custom-resources/lib/helpers-internal"); const constructs_1 = require("constructs"); /** * integ-tests can only depend on '@aws-cdk/core' so * this construct creates a lambda function provider using * only CfnResource */ let LambdaFunctionProvider = (() => { let _classSuper = constructs_1.Construct; let _instanceExtraInitializers = []; let _get_serviceToken_decorators; return class LambdaFunctionProvider extends _classSuper { static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; _get_serviceToken_decorators = [helpers_internal_1.memoizedGetter]; __esDecorate(this, null, _get_serviceToken_decorators, { kind: "getter", name: "serviceToken", static: false, private: false, access: { has: obj => "serviceToken" in obj, get: obj => obj.serviceToken }, metadata: _metadata }, null, _instanceExtraInitializers); if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } /** * A Reference to the provider lambda exeuction role ARN */ roleArn = __runInitializers(this, _instanceExtraInitializers); policies = []; handler; constructor(scope, id, props) { super(scope, id); const staging = new core_1.AssetStaging(this, 'Staging', { sourcePath: path.join(__dirname, 'lambda-handler.bundle'), }); const stack = core_1.Stack.of(this); const asset = stack.synthesizer.addFileAsset({ fileName: staging.relativeStagedPath(stack), sourceHash: staging.assetHash, packaging: core_1.FileAssetPackaging.ZIP_DIRECTORY, }); const role = new core_1.CfnResource(this, 'Role', { type: 'AWS::IAM::Role', properties: { AssumeRolePolicyDocument: { Version: '2012-10-17', Statement: [{ Action: 'sts:AssumeRole', Effect: 'Allow', Principal: { Service: 'lambda.amazonaws.com' } }], }, ManagedPolicyArns: [ { 'Fn::Sub': 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole' }, ], Policies: core_1.Lazy.any({ produce: () => { const policies = this.policies.length > 0 ? [ { PolicyName: 'Inline', PolicyDocument: { Version: '2012-10-17', Statement: this.policies, }, }, ] : undefined; return policies; }, }), }, }); const functionProperties = { Runtime: (0, core_1.determineLatestNodeRuntimeName)(this), Code: { S3Bucket: asset.bucketName, S3Key: asset.objectKey, }, Timeout: core_1.Duration.minutes(2).toSeconds(), Handler: props?.handler ?? 'index.handler', Role: role.getAtt('Arn'), }; if (props?.logRetention) { const logGroup = new core_1.CfnResource(this, 'LogGroup', { type: 'AWS::Logs::LogGroup', properties: { LogGroupName: `/aws/lambda/${id}`, RetentionInDays: props.logRetention, }, }); functionProperties.LoggingConfig = { LogGroup: logGroup.ref, }; } this.handler = new core_1.CfnResource(this, 'Handler', { type: 'AWS::Lambda::Function', properties: functionProperties, }); this.roleArn = role.getAtt('Arn'); } /** * The ARN of the lambda function which can be used * as a serviceToken to a CustomResource */ get serviceToken() { return core_1.Token.asString(this.handler.getAtt('Arn')); } addPolicies(policies) { this.policies.push(...policies); } }; })(); /** * Mimic the singletonfunction construct in '@aws-cdk/aws-lambda' */ class SingletonFunction extends constructs_1.Construct { serviceToken; lambdaFunction; constructor(scope, id, props) { super(scope, id); this.lambdaFunction = this.ensureFunction(props); this.serviceToken = this.lambdaFunction.serviceToken; } ensureFunction(props) { const constructName = 'SingletonFunction' + slugify(props.uuid); const existing = core_1.Stack.of(this).node.tryFindChild(constructName); if (existing) { return existing; } return new LambdaFunctionProvider(core_1.Stack.of(this), constructName, { handler: props.handler, logRetention: props.logRetention, }); } /** * Add an IAM policy statement to the inline policy of the * lambdas function's role * * **Please note**: this is a direct IAM JSON policy blob, *not* a `iam.PolicyStatement` * object like you will see in the rest of the CDK. * * * singleton.addToRolePolicy({ * Effect: 'Allow', * Action: 's3:GetObject', * Resources: '*', * }); */ addToRolePolicy(statement) { this.lambdaFunction.addPolicies([statement]); } /** * Create a policy statement from a specific api call */ addPolicyStatementFromSdkCall(service, api, resources) { this.lambdaFunction.addPolicies([{ Action: [(0, helpers_internal_2.awsSdkToIamAction)(service, api)], Effect: 'Allow', Resource: resources || ['*'], }]); } } /** * Represents an assertions provider. The creates a singletone * Lambda Function that will create a single function per stack * that serves as the custom resource provider for the various * assertion providers */ class AssertionsProvider extends constructs_1.Construct { static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/integ-tests-alpha.AssertionsProvider", version: "2.257.0-alpha.0" }; /** * The ARN of the lambda function which can be used * as a serviceToken to a CustomResource */ serviceToken; /** * A reference to the provider Lambda Function * execution Role ARN */ handlerRoleArn; handler; constructor(scope, id, props) { super(scope, id); try { jsiiDeprecationWarnings._aws_cdk_integ_tests_alpha_AssertionsProviderProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, AssertionsProvider); } throw error; } this.handler = new SingletonFunction(this, 'AssertionsProvider', { handler: props?.handler, uuid: props?.uuid ?? '1488541a-7b23-4664-81b6-9b4408076b81', logRetention: props?.logRetention, }); this.handlerRoleArn = this.handler.lambdaFunction.roleArn; this.serviceToken = this.handler.serviceToken; } /** * Encode an object so it can be passed * as custom resource parameters. Custom resources will convert * all input parameters to strings so we encode non-strings here * so we can then decode them correctly in the provider function */ encode(obj) { if (!obj) { return obj; } return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, encodeValue(value)])); function encodeValue(value) { if (ArrayBuffer.isView(value)) { return { $type: 'ArrayBufferView', string: new TextDecoder().decode(value), }; } return JSON.stringify(value); } } /** * Create a policy statement from a specific api call */ addPolicyStatementFromSdkCall(service, api, resources) { this.handler.addPolicyStatementFromSdkCall(service, api, resources); } /** * Add an IAM policy statement to the inline policy of the * lambdas function's role * * **Please note**: this is a direct IAM JSON policy blob, *not* a `iam.PolicyStatement` * object like you will see in the rest of the CDK. * * * @example * declare const provider: AssertionsProvider; * provider.addToRolePolicy({ * Effect: 'Allow', * Action: ['s3:GetObject'], * Resource: ['*'], * }); */ addToRolePolicy(statement) { this.handler.addToRolePolicy(statement); } /** * Grant a principal access to invoke the assertion provider * lambda function * [disable-awslint:no-grants] * * @param principalArn the ARN of the principal that should be given * permission to invoke the assertion provider */ grantInvoke(principalArn) { new core_1.CfnResource(this, 'Invoke', { type: 'AWS::Lambda::Permission', properties: { Action: 'lambda:InvokeFunction', FunctionName: this.serviceToken, Principal: principalArn, }, }); } } exports.AssertionsProvider = AssertionsProvider; function slugify(x) { return x.replace(/[^a-zA-Z0-9]/g, ''); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwcm92aWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSw2QkFBNkI7QUFHN0IsMkNBUzBCO0FBQzFCLDRFQUF1RTtBQUN2RSx3RkFBc0Y7QUFDdEYsMkNBQXVDO0FBcUJ2Qzs7OztHQUlHO0lBQ0csc0JBQXNCO3NCQUFTLHNCQUFTOzs7aUJBQXhDLHNCQUF1QixTQUFRLFdBQVM7Ozs0Q0F3RjNDLGlDQUFjO1lBQ2YsMkxBQVcsWUFBWSw2REFFdEI7OztRQTFGRDs7V0FFRztRQUNhLE9BQU8sR0FKbkIsbURBQXNCLENBSVM7UUFFbEIsUUFBUSxHQUFVLEVBQUUsQ0FBQztRQUVyQixPQUFPLENBQWM7UUFFdEMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFtQztZQUMzRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBRWpCLE1BQU0sT0FBTyxHQUFHLElBQUksbUJBQVksQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFO2dCQUNoRCxVQUFVLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsdUJBQXVCLENBQUM7YUFDMUQsQ0FBQyxDQUFDO1lBRUgsTUFBTSxLQUFLLEdBQUcsWUFBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUM3QixNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQztnQkFDM0MsUUFBUSxFQUFFLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUM7Z0JBQzNDLFVBQVUsRUFBRSxPQUFPLENBQUMsU0FBUztnQkFDN0IsU0FBUyxFQUFFLHlCQUFrQixDQUFDLGFBQWE7YUFDNUMsQ0FBQyxDQUFDO1lBRUgsTUFBTSxJQUFJLEdBQUcsSUFBSSxrQkFBVyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUU7Z0JBQ3pD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QUFDO2lCQUN0RCxDQUFDO1lBQ0osQ0FBQztZQUVELE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMvQixDQUFDO0tBQ0Y7SUFFRDs7T0FFRztJQUNJLDZCQUE2QixDQUFDLE9BQWUsRUFBRSxHQUFXLEVBQUUsU0FBb0I7UUFDckYsSUFBSSxDQUFDLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0tBQ3JFO0lBRUQ7Ozs7Ozs7Ozs7Ozs7OztPQWVHO0lBQ0ksZUFBZSxDQUFDLFNBQWM7UUFDbkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsU0FBUyxDQUFDLENBQUM7S0FDekM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ksV0FBVyxDQUFDLFlBQW9CO1FBQ3JDLElBQUksa0JBQVcsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFO1lBQzlCLElBQUksRUFBRSx5QkFBeUI7WUFDL0IsVUFBVSxFQUFFO2dCQUNWLE1BQU0sRUFBRSx1QkFBdUI7Z0JBQy9CLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtnQkFDL0IsU0FBUyxFQUFFLFlBQVk7YUFDeEI7U0FDRixDQUFDLENBQUM7S0FDSjs7QUFqR0gsZ0RBa0dDO0FBRUQsU0FBUyxPQUFPLENBQUMsQ0FBUztJQUN4QixPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ3hDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHR5cGUgeyBSZXRlbnRpb25EYXlzIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxvZ3MnO1xuaW1wb3J0IHR5cGUgeyBSZWZlcmVuY2UgfSBmcm9tICdhd3MtY2RrLWxpYi9jb3JlJztcbmltcG9ydCB7XG4gIER1cmF0aW9uLFxuICBDZm5SZXNvdXJjZSxcbiAgQXNzZXRTdGFnaW5nLFxuICBTdGFjayxcbiAgRmlsZUFzc2V0UGFja2FnaW5nLFxuICBUb2tlbixcbiAgTGF6eSxcbiAgZGV0ZXJtaW5lTGF0ZXN0Tm9kZVJ1bnRpbWVOYW1lLFxufSBmcm9tICdhd3MtY2RrLWxpYi9jb3JlJztcbmltcG9ydCB7IG1lbW9pemVkR2V0dGVyIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZS9saWIvaGVscGVycy1pbnRlcm5hbCc7XG5pbXBvcnQgeyBhd3NTZGtUb0lhbUFjdGlvbiB9IGZyb20gJ2F3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXMvbGliL2hlbHBlcnMtaW50ZXJuYWwnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYSBsYW1iZGEgZnVuY3Rpb24gcHJvdmlkZXJcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYW1iZGFGdW5jdGlvblByb3ZpZGVyUHJvcHMge1xuICAvKipcbiAgICogVGhlIGhhbmRsZXIgdG8gdXNlIGZvciB0aGUgbGFtYmRhIGZ1bmN0aW9uXG4gICAqXG4gICAqIEBkZWZhdWx0IGluZGV4LmhhbmRsZXJcbiAgICovXG4gIHJlYWRvbmx5IGhhbmRsZXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEhvdyBsb25nLCBpbiBkYXlzLCB0aGUgbG9nIGNvbnRlbnRzIHdpbGwgYmUgcmV0YWluZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gcmV0ZW50aW9uIGRheXMgc3BlY2lmaWVkXG4gICAqL1xuICByZWFkb25seSBsb2dSZXRlbnRpb24/OiBSZXRlbnRpb25EYXlzO1xufVxuXG4vKipcbiAqIGludGVnLXRlc3RzIGNhbiBvbmx5IGRlcGVuZCBvbiAnQGF3cy1jZGsvY29yZScgc29cbiAqIHRoaXMgY29uc3RydWN0IGNyZWF0ZXMgYSBsYW1iZGEgZnVuY3Rpb24gcHJvdmlkZXIgdXNpbmdcbiAqIG9ubHkgQ2ZuUmVzb3VyY2VcbiAqL1xuY2xhc3MgTGFtYmRhRnVuY3Rpb25Qcm92aWRlciBleHRlbmRzIENvbnN0cnVjdCB7XG4gIC8qKlxuICAgKiBBIFJlZmVyZW5jZSB0byB0aGUgcHJvdmlkZXIgbGFtYmRhIGV4ZXVjdGlvbiByb2xlIEFSTlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHJvbGVBcm46IFJlZmVyZW5jZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IHBvbGljaWVzOiBhbnlbXSA9IFtdO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgaGFuZGxlcjogQ2ZuUmVzb3VyY2U7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM/OiBMYW1iZGFGdW5jdGlvblByb3ZpZGVyUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3Qgc3RhZ2luZyA9IG5ldyBBc3NldFN0YWdpbmcodGhpcywgJ1N0YWdpbmcnLCB7XG4gICAgICBzb3VyY2VQYXRoOiBwYXRoLmpvaW4oX19kaXJuYW1lLCAnbGFtYmRhLWhhbmRsZXIuYnVuZGxlJyksXG4gICAgfSk7XG5cbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIGNvbnN0IGFzc2V0ID0gc3RhY2suc3ludGhlc2l6ZXIuYWRkRmlsZUFzc2V0KHtcbiAgICAgIGZpbGVOYW1lOiBzdGFnaW5nLnJlbGF0aXZlU3RhZ2VkUGF0aChzdGFjayksXG4gICAgICBzb3VyY2VIYXNoOiBzdGFnaW5nLmFzc2V0SGFzaCxcbiAgICAgIHBhY2thZ2luZzogRmlsZUFzc2V0UGFja2FnaW5nLlpJUF9ESVJFQ1RPUlksXG4gICAgfSk7XG5cbiAgICBjb25zdCByb2xlID0gbmV3IENmblJlc291cmNlKHRoaXMsICdSb2xlJywge1xuICAgICAgdHlwZTogJ0FXUzo6SUFNOjpSb2xlJyxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgQXNzdW1lUm9sZVBvbGljeURvY3VtZW50OiB7XG4gICAgICAgICAgVmVyc2lvbjogJzIwMTItMTAtMTcnLFxuICAgICAgICAgIFN0YXRlbWVudDogW3sgQWN0aW9uOiAnc3RzOkFzc3VtZVJvbGUnLCBFZmZlY3Q6ICdBbGxvdycsIFByaW5jaXBhbDogeyBTZXJ2aWNlOiAnbGFtYmRhLmFtYXpvbmF3cy5jb20nIH0gfV0sXG4gICAgICAgIH0sXG4gICAgICAgIE1hbmFnZWRQb2xpY3lBcm5zOiBbXG4gICAgICAgICAgeyAnRm46OlN1Yic6ICdhcm46JHtBV1M6OlBhcnRpdGlvbn06aWFtOjphd3M6cG9saWN5L3NlcnZpY2Utcm9sZS9BV1NMYW1iZGFCYXNpY0V4ZWN1dGlvblJvbGUnIH0sXG4gICAgICAgIF0sXG4gICAgICAgIFBvbGljaWVzOiBMYXp5LmFueSh7XG4gICAgICAgICAgcHJvZHVjZTogKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcG9saWNpZXMgPSB0aGlzLnBvbGljaWVzLmxlbmd0aCA+IDAgPyBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBQb2xpY3lOYW1lOiAnSW5saW5lJyxcbiAgICAgICAgICAgICAgICBQb2xpY3lEb2N1bWVudDoge1xuICAgICAgICAgICAgICAgICAgVmVyc2lvbjogJzIwMTItMTAtMTcnLFxuICAgICAgICAgICAgICAgICAgU3RhdGVtZW50OiB0aGlzLnBvbGljaWVzLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgcmV0dXJuIHBvbGljaWVzO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGZ1bmN0aW9uUHJvcGVydGllczogYW55ID0ge1xuICAgICAgUnVudGltZTogZGV0ZXJtaW5lTGF0ZXN0Tm9kZVJ1bnRpbWVOYW1lKHRoaXMpLFxuICAgICAgQ29kZToge1xuICAgICAgICBTM0J1Y2tldDogYXNzZXQuYnVja2V0TmFtZSxcbiAgICAgICAgUzNLZXk6IGFzc2V0Lm9iamVjdEtleSxcbiAgICAgIH0sXG4gICAgICBUaW1lb3V0OiBEdXJhdGlvbi5taW51dGVzKDIpLnRvU2Vjb25kcygpLFxuICAgICAgSGFuZGxlcjogcHJvcHM/LmhhbmRsZXIgPz8gJ2luZGV4LmhhbmRsZXInLFxuICAgICAgUm9sZTogcm9sZS5nZXRBdHQoJ0FybicpLFxuICAgIH07XG5cbiAgICBpZiAocHJvcHM/LmxvZ1JldGVudGlvbikge1xuICAgICAgY29uc3QgbG9nR3JvdXAgPSBuZXcgQ2ZuUmVzb3VyY2UodGhpcywgJ0xvZ0dyb3VwJywge1xuICAgICAgICB0eXBlOiAnQVdTOjpMb2dzOjpMb2dHcm91cCcsXG4gICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICBMb2dHcm91cE5hbWU6IGAvYXdzL2xhbWJkYS8ke2lkfWAsXG4gICAgICAgICAgUmV0ZW50aW9uSW5EYXlzOiBwcm9wcy5sb2dSZXRlbnRpb24sXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgZnVuY3Rpb25Qcm9wZXJ0aWVzLkxvZ2dpbmdDb25maWcgPSB7XG4gICAgICAgIExvZ0dyb3VwOiBsb2dHcm91cC5yZWYsXG4gICAgICB9O1xuICAgIH1cblxuICAgIHRoaXMuaGFuZGxlciA9IG5ldyBDZm5SZXNvdXJjZSh0aGlzLCAnSGFuZGxlcicsIHtcbiAgICAgIHR5cGU6ICdBV1M6OkxhbWJkYTo6RnVuY3Rpb24nLFxuICAgICAgcHJvcGVydGllczogZnVuY3Rpb25Qcm9wZXJ0aWVzLFxuICAgIH0pO1xuXG4gICAgdGhpcy5yb2xlQXJuID0gcm9sZS5nZXRBdHQoJ0FybicpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGxhbWJkYSBmdW5jdGlvbiB3aGljaCBjYW4gYmUgdXNlZFxuICAgKiBhcyBhIHNlcnZpY2VUb2tlbiB0byBhIEN1c3RvbVJlc291cmNlXG4gICAqL1xuICBAbWVtb2l6ZWRHZXR0ZXJcbiAgcHVibGljIGdldCBzZXJ2aWNlVG9rZW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gVG9rZW4uYXNTdHJpbmcodGhpcy5oYW5kbGVyLmdldEF0dCgnQXJuJykpO1xuICB9XG5cbiAgcHVibGljIGFkZFBvbGljaWVzKHBvbGljaWVzOiBhbnlbXSk6IHZvaWQge1xuICAgIHRoaXMucG9saWNpZXMucHVzaCguLi5wb2xpY2llcyk7XG4gIH1cbn1cblxuaW50ZXJmYWNlIFNpbmdsZXRvbkZ1bmN0aW9uUHJvcHMgZXh0ZW5kcyBMYW1iZGFGdW5jdGlvblByb3ZpZGVyUHJvcHMge1xuICAvKipcbiAgICogQSB1bmlxdWUgaWRlbnRpZmllciB0byBpZGVudGlmeSB0aGlzIGxhbWJkYVxuICAgKlxuICAgKiBUaGUgaWRlbnRpZmllciBzaG91bGQgYmUgdW5pcXVlIGFjcm9zcyBhbGwgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVycy5cbiAgICogV2UgcmVjb21tZW5kIGdlbmVyYXRpbmcgYSBVVUlEIHBlciBwcm92aWRlci5cbiAgICovXG4gIHJlYWRvbmx5IHV1aWQ6IHN0cmluZztcbn1cblxuLyoqXG4gKiBNaW1pYyB0aGUgc2luZ2xldG9uZnVuY3Rpb24gY29uc3RydWN0IGluICdAYXdzLWNkay9hd3MtbGFtYmRhJ1xuICovXG5jbGFzcyBTaW5nbGV0b25GdW5jdGlvbiBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHB1YmxpYyByZWFkb25seSBzZXJ2aWNlVG9rZW46IHN0cmluZztcblxuICBwdWJsaWMgcmVhZG9ubHkgbGFtYmRhRnVuY3Rpb246IExhbWJkYUZ1bmN0aW9uUHJvdmlkZXI7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBTaW5nbGV0b25GdW5jdGlvblByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICB0aGlzLmxhbWJkYUZ1bmN0aW9uID0gdGhpcy5lbnN1cmVGdW5jdGlvbihwcm9wcyk7XG4gICAgdGhpcy5zZXJ2aWNlVG9rZW4gPSB0aGlzLmxhbWJkYUZ1bmN0aW9uLnNlcnZpY2VUb2tlbjtcbiAgfVxuXG4gIHByaXZhdGUgZW5zdXJlRnVuY3Rpb24ocHJvcHM6IFNpbmdsZXRvbkZ1bmN0aW9uUHJvcHMpOiBMYW1iZGFGdW5jdGlvblByb3ZpZGVyIHtcbiAgICBjb25zdCBjb25zdHJ1Y3ROYW1lID0gJ1NpbmdsZXRvbkZ1bmN0aW9uJyArIHNsdWdpZnkocHJvcHMudXVpZCk7XG4gICAgY29uc3QgZXhpc3RpbmcgPSBTdGFjay5vZih0aGlzKS5ub2RlLnRyeUZpbmRDaGlsZChjb25zdHJ1Y3ROYW1lKTtcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHJldHVybiBleGlzdGluZyBhcyBMYW1iZGFGdW5jdGlvblByb3ZpZGVyO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgTGFtYmRhRnVuY3Rpb25Qcm92aWRlcihTdGFjay5vZih0aGlzKSwgY29uc3RydWN0TmFtZSwge1xuICAgICAgaGFuZGxlcjogcHJvcHMuaGFuZGxlcixcbiAgICAgIGxvZ1JldGVudGlvbjogcHJvcHMubG9nUmV0ZW50aW9uLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhbiBJQU0gcG9saWN5IHN0YXRlbWVudCB0byB0aGUgaW5saW5lIHBvbGljeSBvZiB0aGVcbiAgICogbGFtYmRhcyBmdW5jdGlvbidzIHJvbGVcbiAgICpcbiAgICogKipQbGVhc2Ugbm90ZSoqOiB0aGlzIGlzIGEgZGlyZWN0IElBTSBKU09OIHBvbGljeSBibG9iLCAqbm90KiBhIGBpYW0uUG9saWN5U3RhdGVtZW50YFxuICAgKiBvYmplY3QgbGlrZSB5b3Ugd2lsbCBzZWUgaW4gdGhlIHJlc3Qgb2YgdGhlIENESy5cbiAgICpcbiAgICpcbiAgICogc2luZ2xldG9uLmFkZFRvUm9sZVBvbGljeSh7XG4gICAqICAgRWZmZWN0OiAnQWxsb3cnLFxuICAgKiAgIEFjdGlvbjogJ3MzOkdldE9iamVjdCcsXG4gICAqICAgUmVzb3VyY2VzOiAnKicsXG4gICAqIH0pO1xuICAgKi9cbiAgcHVibGljIGFkZFRvUm9sZVBvbGljeShzdGF0ZW1lbnQ6IGFueSk6IHZvaWQge1xuICAgIHRoaXMubGFtYmRhRnVuY3Rpb24uYWRkUG9saWNpZXMoW3N0YXRlbWVudF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIHBvbGljeSBzdGF0ZW1lbnQgZnJvbSBhIHNwZWNpZmljIGFwaSBjYWxsXG4gICAqL1xuICBwdWJsaWMgYWRkUG9saWN5U3RhdGVtZW50RnJvbVNka0NhbGwoc2VydmljZTogc3RyaW5nLCBhcGk6IHN0cmluZywgcmVzb3VyY2VzPzogc3RyaW5nW10pOiB2b2lkIHtcbiAgICB0aGlzLmxhbWJkYUZ1bmN0aW9uLmFkZFBvbGljaWVzKFt7XG4gICAgICBBY3Rpb246IFthd3NTZGtUb0lhbUFjdGlvbihzZXJ2aWNlLCBhcGkpXSxcbiAgICAgIEVmZmVjdDogJ0FsbG93JyxcbiAgICAgIFJlc291cmNlOiByZXNvdXJjZXMgfHwgWycqJ10sXG4gICAgfV0pO1xuICB9XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgZGVmaW5pbmcgYW4gQXNzZXJ0aW9uc1Byb3ZpZGVyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXNzZXJ0aW9uc1Byb3ZpZGVyUHJvcHMgZXh0ZW5kcyBMYW1iZGFGdW5jdGlvblByb3ZpZGVyUHJvcHMge1xuICAvKipcbiAgICogVGhpcyBkZXRlcm1pbmVzIHRoZSB1bmlxdWVuZXNzIG9mIGVhY2ggQXNzZXJ0aW9uc1Byb3ZpZGVyLlxuICAgKiBZb3Ugc2hvdWxkIG9ubHkgbmVlZCB0byBwcm92aWRlIHNvbWV0aGluZyBkaWZmZXJlbnQgaGVyZSBpZiB5b3VcbiAgICogX2tub3dfIHRoYXQgeW91IG5lZWQgYSBzZXBhcmF0ZSBwcm92aWRlclxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHRoZSBkZWZhdWx0IHV1aWQgaXMgdXNlZFxuICAgKi9cbiAgcmVhZG9ubHkgdXVpZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIGFuIGFzc2VydGlvbnMgcHJvdmlkZXIuIFRoZSBjcmVhdGVzIGEgc2luZ2xldG9uZVxuICogTGFtYmRhIEZ1bmN0aW9uIHRoYXQgd2lsbCBjcmVhdGUgYSBzaW5nbGUgZnVuY3Rpb24gcGVyIHN0YWNrXG4gKiB0aGF0IHNlcnZlcyBhcyB0aGUgY3VzdG9tIHJlc291cmNlIHByb3ZpZGVyIGZvciB0aGUgdmFyaW91c1xuICogYXNzZXJ0aW9uIHByb3ZpZGVyc1xuICovXG5leHBvcnQgY2xhc3MgQXNzZXJ0aW9uc1Byb3ZpZGVyIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGxhbWJkYSBmdW5jdGlvbiB3aGljaCBjYW4gYmUgdXNlZFxuICAgKiBhcyBhIHNlcnZpY2VUb2tlbiB0byBhIEN1c3RvbVJlc291cmNlXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgc2VydmljZVRva2VuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgcmVmZXJlbmNlIHRvIHRoZSBwcm92aWRlciBMYW1iZGEgRnVuY3Rpb25cbiAgICogZXhlY3V0aW9uIFJvbGUgQVJOXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaGFuZGxlclJvbGVBcm46IFJlZmVyZW5jZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZXI6IFNpbmdsZXRvbkZ1bmN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzPzogQXNzZXJ0aW9uc1Byb3ZpZGVyUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgdGhpcy5oYW5kbGVyID0gbmV3IFNpbmdsZXRvbkZ1bmN0aW9uKHRoaXMsICdBc3NlcnRpb25zUHJvdmlkZXInLCB7XG4gICAgICBoYW5kbGVyOiBwcm9wcz8uaGFuZGxlcixcbiAgICAgIHV1aWQ6IHByb3BzPy51dWlkID8/ICcxNDg4NTQxYS03YjIzLTQ2NjQtODFiNi05YjQ0MDgwNzZiODEnLFxuICAgICAgbG9nUmV0ZW50aW9uOiBwcm9wcz8ubG9nUmV0ZW50aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5oYW5kbGVyUm9sZUFybiA9IHRoaXMuaGFuZGxlci5sYW1iZGFGdW5jdGlvbi5yb2xlQXJuO1xuXG4gICAgdGhpcy5zZXJ2aWNlVG9rZW4gPSB0aGlzLmhhbmRsZXIuc2VydmljZVRva2VuO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuY29kZSBhbiBvYmplY3Qgc28gaXQgY2FuIGJlIHBhc3NlZFxuICAgKiBhcyBjdXN0b20gcmVzb3VyY2UgcGFyYW1ldGVycy4gQ3VzdG9tIHJlc291cmNlcyB3aWxsIGNvbnZlcnRcbiAgICogYWxsIGlucHV0IHBhcmFtZXRlcnMgdG8gc3RyaW5ncyBzbyB3ZSBlbmNvZGUgbm9uLXN0cmluZ3MgaGVyZVxuICAgKiBzbyB3ZSBjYW4gdGhlbiBkZWNvZGUgdGhlbSBjb3JyZWN0bHkgaW4gdGhlIHByb3ZpZGVyIGZ1bmN0aW9uXG4gICAqL1xuICBwdWJsaWMgZW5jb2RlKG9iajogYW55KTogYW55IHtcbiAgICBpZiAoIW9iaikge1xuICAgICAgcmV0dXJuIG9iajtcbiAgICB9XG4gICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhPYmplY3QuZW50cmllcyhvYmopLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBba2V5LCBlbmNvZGVWYWx1ZSh2YWx1ZSldKSk7XG5cbiAgICBmdW5jdGlvbiBlbmNvZGVWYWx1ZSh2YWx1ZTogYW55KTogYW55IHtcbiAgICAgIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgJHR5cGU6ICdBcnJheUJ1ZmZlclZpZXcnLFxuICAgICAgICAgIHN0cmluZzogbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKHZhbHVlIGFzIFVpbnQ4QXJyYXkpLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBwb2xpY3kgc3RhdGVtZW50IGZyb20gYSBzcGVjaWZpYyBhcGkgY2FsbFxuICAgKi9cbiAgcHVibGljIGFkZFBvbGljeVN0YXRlbWVudEZyb21TZGtDYWxsKHNlcnZpY2U6IHN0cmluZywgYXBpOiBzdHJpbmcsIHJlc291cmNlcz86IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgdGhpcy5oYW5kbGVyLmFkZFBvbGljeVN0YXRlbWVudEZyb21TZGtDYWxsKHNlcnZpY2UsIGFwaSwgcmVzb3VyY2VzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYW4gSUFNIHBvbGljeSBzdGF0ZW1lbnQgdG8gdGhlIGlubGluZSBwb2xpY3kgb2YgdGhlXG4gICAqIGxhbWJkYXMgZnVuY3Rpb24ncyByb2xlXG4gICAqXG4gICAqICoqUGxlYXNlIG5vdGUqKjogdGhpcyBpcyBhIGRpcmVjdCBJQU0gSlNPTiBwb2xpY3kgYmxvYiwgKm5vdCogYSBgaWFtLlBvbGljeVN0YXRlbWVudGBcbiAgICogb2JqZWN0IGxpa2UgeW91IHdpbGwgc2VlIGluIHRoZSByZXN0IG9mIHRoZSBDREsuXG4gICAqXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGRlY2xhcmUgY29uc3QgcHJvdmlkZXI6IEFzc2VydGlvbnNQcm92aWRlcjtcbiAgICogcHJvdmlkZXIuYWRkVG9Sb2xlUG9saWN5KHtcbiAgICogICBFZmZlY3Q6ICdBbGxvdycsXG4gICAqICAgQWN0aW9uOiBbJ3MzOkdldE9iamVjdCddLFxuICAgKiAgIFJlc291cmNlOiBbJyonXSxcbiAgICogfSk7XG4gICAqL1xuICBwdWJsaWMgYWRkVG9Sb2xlUG9saWN5KHN0YXRlbWVudDogYW55KTogdm9pZCB7XG4gICAgdGhpcy5oYW5kbGVyLmFkZFRvUm9sZVBvbGljeShzdGF0ZW1lbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50IGEgcHJpbmNpcGFsIGFjY2VzcyB0byBpbnZva2UgdGhlIGFzc2VydGlvbiBwcm92aWRlclxuICAgKiBsYW1iZGEgZnVuY3Rpb25cbiAgICogW2Rpc2FibGUtYXdzbGludDpuby1ncmFudHNdXG4gICAqXG4gICAqIEBwYXJhbSBwcmluY2lwYWxBcm4gdGhlIEFSTiBvZiB0aGUgcHJpbmNpcGFsIHRoYXQgc2hvdWxkIGJlIGdpdmVuXG4gICAqICBwZXJtaXNzaW9uIHRvIGludm9rZSB0aGUgYXNzZXJ0aW9uIHByb3ZpZGVyXG4gICAqL1xuICBwdWJsaWMgZ3JhbnRJbnZva2UocHJpbmNpcGFsQXJuOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBuZXcgQ2ZuUmVzb3VyY2UodGhpcywgJ0ludm9rZScsIHtcbiAgICAgIHR5cGU6ICdBV1M6OkxhbWJkYTo6UGVybWlzc2lvbicsXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIEFjdGlvbjogJ2xhbWJkYTpJbnZva2VGdW5jdGlvbicsXG4gICAgICAgIEZ1bmN0aW9uTmFtZTogdGhpcy5zZXJ2aWNlVG9rZW4sXG4gICAgICAgIFByaW5jaXBhbDogcHJpbmNpcGFsQXJuLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzbHVnaWZ5KHg6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB4LnJlcGxhY2UoL1teYS16QS1aMC05XS9nLCAnJyk7XG59XG4iXX0=