UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

293 lines 39.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const yaml_1 = require("yaml"); const bootstrap_1 = require("../../lib/api/bootstrap"); const serialize_1 = require("../../lib/serialize"); const mock_sdk_1 = require("../util/mock-sdk"); const env = { account: '123456789012', region: 'us-east-1', name: 'mock', }; let sdk; let executed; let protectedTermination; let cfnMocks; let changeSetTemplate; let bootstrapper; beforeEach(() => { sdk = new mock_sdk_1.MockSdkProvider(); executed = false; protectedTermination = false; bootstrapper = new bootstrap_1.Bootstrapper({ source: 'legacy' }); cfnMocks = { describeStackEvents: jest.fn().mockReturnValue({}), describeStacks: jest.fn() // First two calls, no stacks exist (first is for version checking, second is in deploy-stack.ts) .mockImplementationOnce(() => ({ Stacks: [] })) .mockImplementationOnce(() => ({ Stacks: [] })) // Second call, stack has been created .mockImplementationOnce(() => ({ Stacks: [ { StackStatus: 'CREATE_COMPLETE', StackStatusReason: 'It is magic', EnableTerminationProtection: false, }, ], })), createChangeSet: jest.fn((info) => { changeSetTemplate = (0, serialize_1.deserializeStructure)(info.TemplateBody); return {}; }), describeChangeSet: jest.fn(() => ({ Status: 'CREATE_COMPLETE', Changes: [], })), executeChangeSet: jest.fn(() => { executed = true; return {}; }), deleteChangeSet: jest.fn(), getTemplate: jest.fn(() => { executed = true; return {}; }), deleteStack: jest.fn(), updateTerminationProtection: jest.fn(() => { protectedTermination = true; return {}; }), }; sdk.stubCloudFormation(cfnMocks); }); test('do bootstrap', async () => { // WHEN const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack' }); // THEN const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; expect(bucketProperties.BucketName).toBeUndefined(); expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) .toBeUndefined(); expect(changeSetTemplate.Conditions.UsePublicAccessBlockConfiguration['Fn::Equals'][0]).toBe('true'); expect(ret.noOp).toBeFalsy(); expect(executed).toBeTruthy(); }); test('do bootstrap using custom bucket name', async () => { // WHEN const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack', parameters: { bucketName: 'foobar', }, }); // THEN const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; expect(bucketProperties.BucketName).toBe('foobar'); expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) .toBeUndefined(); expect(changeSetTemplate.Conditions.UsePublicAccessBlockConfiguration['Fn::Equals'][0]).toBe('true'); expect(ret.noOp).toBeFalsy(); expect(executed).toBeTruthy(); }); test('do bootstrap using KMS CMK', async () => { // WHEN const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack', parameters: { kmsKeyId: 'myKmsKey', }, }); // THEN const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; expect(bucketProperties.BucketName).toBeUndefined(); expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) .toBe('myKmsKey'); expect(changeSetTemplate.Conditions.UsePublicAccessBlockConfiguration['Fn::Equals'][0]).toBe('true'); expect(ret.noOp).toBeFalsy(); expect(executed).toBeTruthy(); }); test('bootstrap disable bucket Public Access Block Configuration', async () => { // WHEN const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack', parameters: { publicAccessBlockConfiguration: false, }, }); // THEN const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; expect(bucketProperties.BucketName).toBeUndefined(); expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) .toBeUndefined(); expect(changeSetTemplate.Conditions.UsePublicAccessBlockConfiguration['Fn::Equals'][0]).toBe('false'); expect(ret.noOp).toBeFalsy(); expect(executed).toBeTruthy(); }); test('do bootstrap with custom tags for toolkit stack', async () => { // WHEN const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack', tags: [{ Key: 'Foo', Value: 'Bar' }], }); // THEN const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; expect(bucketProperties.BucketName).toBeUndefined(); expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) .toBeUndefined(); expect(changeSetTemplate.Conditions.UsePublicAccessBlockConfiguration['Fn::Equals'][0]).toBe('true'); expect(ret.noOp).toBeFalsy(); expect(executed).toBeTruthy(); }); test('passing trusted accounts to the old bootstrapping results in an error', async () => { await expect(bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack', parameters: { trustedAccounts: ['0123456789012'], }, })) .rejects .toThrow('--trust can only be passed for the modern bootstrap experience.'); }); test('passing CFN execution policies to the old bootstrapping results in an error', async () => { await expect(bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack', parameters: { cloudFormationExecutionPolicies: ['arn:aws:iam::aws:policy/AdministratorAccess'], }, })) .rejects .toThrow('--cloudformation-execution-policies can only be passed for the modern bootstrap experience.'); }); test('even if the bootstrap stack is in a rollback state, can still retry bootstrapping it', async () => { cfnMocks.describeStacks .mockReset() // First two calls, the stack exists with a 'rollback complete' status // (first is for version checking, second is in deploy-stack.ts) .mockImplementationOnce(() => ({ Stacks: [ { StackStatus: 'UPDATE_ROLLBACK_COMPLETE', StackStatusReason: 'It is magic', Outputs: [ { OutputKey: 'BucketName', OutputValue: 'bucket' }, { OutputKey: 'BucketDomainName', OutputValue: 'aws.com' }, ], }, ], })) .mockImplementationOnce(() => ({ Stacks: [ { StackStatus: 'UPDATE_ROLLBACK_COMPLETE', StackStatusReason: 'It is magic', Outputs: [ { OutputKey: 'BucketName', OutputValue: 'bucket' }, { OutputKey: 'BucketDomainName', OutputValue: 'aws.com' }, ], }, ], })) // Third call, stack has been created .mockImplementationOnce(() => ({ Stacks: [ { StackStatus: 'CREATE_COMPLETE', StackStatusReason: 'It is magic', EnableTerminationProtection: false, }, ], })); // WHEN const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack' }); // THEN const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; expect(bucketProperties.BucketName).toBeUndefined(); expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) .toBeUndefined(); expect(ret.noOp).toBeFalsy(); expect(executed).toBeTruthy(); }); test('even if the bootstrap stack failed to create, can still retry bootstrapping it', async () => { cfnMocks.describeStacks .mockReset() // First two calls, the stack exists with a 'rollback complete' status // (first is for version checking, second is in deploy-stack.ts) .mockImplementationOnce(() => ({ Stacks: [ { StackStatus: 'ROLLBACK_COMPLETE', StackStatusReason: 'It is magic', Outputs: [ { OutputKey: 'BucketName', OutputValue: 'bucket' }, ], }, ], })) .mockImplementationOnce(() => ({ Stacks: [ { StackStatus: 'ROLLBACK_COMPLETE', StackStatusReason: 'It is magic', Outputs: [ { OutputKey: 'BucketName', OutputValue: 'bucket' }, ], }, ], })) // Third call, we just did a delete and want to see it gone .mockImplementationOnce(() => ({ Stacks: [] })) // Fourth call, stack has been created .mockImplementationOnce(() => ({ Stacks: [ { StackStatus: 'CREATE_COMPLETE', StackStatusReason: 'It is magic', EnableTerminationProtection: false, }, ], })); // WHEN const ret = await bootstrapper.bootstrapEnvironment(env, sdk, { toolkitStackName: 'mockStack' }); // THEN const bucketProperties = changeSetTemplate.Resources.StagingBucket.Properties; expect(bucketProperties.BucketName).toBeUndefined(); expect(bucketProperties.BucketEncryption.ServerSideEncryptionConfiguration[0].ServerSideEncryptionByDefault.KMSMasterKeyID) .toBeUndefined(); expect(ret.noOp).toBeFalsy(); expect(executed).toBeTruthy(); expect(cfnMocks.deleteStack).toHaveBeenCalled(); }); test('stack is not termination protected by default', async () => { // WHEN await bootstrapper.bootstrapEnvironment(env, sdk); // THEN expect(executed).toBeTruthy(); expect(protectedTermination).toBeFalsy(); }); test('stack is termination protected when set', async () => { // WHEN await bootstrapper.bootstrapEnvironment(env, sdk, { terminationProtection: true, }); // THEN expect(executed).toBeTruthy(); expect(protectedTermination).toBeTruthy(); }); test('do showTemplate YAML', async () => { process.stdout.write = jest.fn().mockImplementationOnce((template) => { // THEN expect((0, yaml_1.parse)(template)).toHaveProperty('Description', 'The CDK Toolkit Stack. It was created by `cdk bootstrap` and manages resources necessary for managing your Cloud Applications with AWS CDK.'); }); // WHEN await bootstrapper.showTemplate(false); }); test('do showTemplate JSON', async () => { process.stdout.write = jest.fn().mockImplementationOnce((template) => { // THEN expect(JSON.parse(template)).toHaveProperty('Description', 'The CDK Toolkit Stack. It was created by `cdk bootstrap` and manages resources necessary for managing your Cloud Applications with AWS CDK.'); }); // WHEN await bootstrapper.showTemplate(true); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9vdHN0cmFwLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJib290c3RyYXAudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLCtCQUE2QjtBQUM3Qix1REFBdUQ7QUFDdkQsbURBQTJEO0FBQzNELCtDQUF3RTtBQUV4RSxNQUFNLEdBQUcsR0FBRztJQUNWLE9BQU8sRUFBRSxjQUFjO0lBQ3ZCLE1BQU0sRUFBRSxXQUFXO0lBQ25CLElBQUksRUFBRSxNQUFNO0NBQ2IsQ0FBQztBQUVGLElBQUksR0FBb0IsQ0FBQztBQUN6QixJQUFJLFFBQWlCLENBQUM7QUFDdEIsSUFBSSxvQkFBNkIsQ0FBQztBQUNsQyxJQUFJLFFBQThELENBQUM7QUFDbkUsSUFBSSxpQkFBa0MsQ0FBQztBQUN2QyxJQUFJLFlBQTBCLENBQUM7QUFDL0IsVUFBVSxDQUFDLEdBQUcsRUFBRTtJQUNkLEdBQUcsR0FBRyxJQUFJLDBCQUFlLEVBQUUsQ0FBQztJQUM1QixRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ2pCLG9CQUFvQixHQUFHLEtBQUssQ0FBQztJQUM3QixZQUFZLEdBQUcsSUFBSSx3QkFBWSxDQUFDLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7SUFFdEQsUUFBUSxHQUFHO1FBQ1QsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7UUFDbEQsY0FBYyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUU7WUFDdkIsaUdBQWlHO2FBQ2hHLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQzthQUM5QyxzQkFBc0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDL0Msc0NBQXNDO2FBQ3JDLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDN0IsTUFBTSxFQUFFO2dCQUNOO29CQUNFLFdBQVcsRUFBRSxpQkFBaUI7b0JBQzlCLGlCQUFpQixFQUFFLGFBQWE7b0JBQ2hDLDJCQUEyQixFQUFFLEtBQUs7aUJBQ25DO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDTCxlQUFlLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQTBCLEVBQUUsRUFBRTtZQUN0RCxpQkFBaUIsR0FBRyxJQUFBLGdDQUFvQixFQUFDLElBQUksQ0FBQyxZQUFzQixDQUFDLENBQUM7WUFDdEUsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDLENBQUM7UUFDRixpQkFBaUIsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDaEMsTUFBTSxFQUFFLGlCQUFpQjtZQUN6QixPQUFPLEVBQUUsRUFBRTtTQUNaLENBQUMsQ0FBQztRQUNILGdCQUFnQixFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFO1lBQzdCLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDaEIsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDLENBQUM7UUFDRixlQUFlLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBRTtRQUMxQixXQUFXLEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUU7WUFDeEIsUUFBUSxHQUFHLElBQUksQ0FBQztZQUNoQixPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUMsQ0FBQztRQUNGLFdBQVcsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFO1FBQ3RCLDJCQUEyQixFQUFFLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFO1lBQ3hDLG9CQUFvQixHQUFHLElBQUksQ0FBQztZQUM1QixPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUMsQ0FBQztLQUNILENBQUM7SUFDRixHQUFHLENBQUMsa0JBQWtCLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDbkMsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsY0FBYyxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQzlCLE9BQU87SUFDUCxNQUFNLEdBQUcsR0FBRyxNQUFNLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUVqRyxPQUFPO0lBQ1AsTUFBTSxnQkFBZ0IsR0FBRyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQztJQUM5RSxNQUFNLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDcEQsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGdCQUFnQixDQUFDLGlDQUFpQyxDQUFDLENBQUMsQ0FBQyxDQUFDLDZCQUE2QixDQUFDLGNBQWMsQ0FBQztTQUN4SCxhQUFhLEVBQUUsQ0FBQztJQUNuQixNQUFNLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLGlDQUFpQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3JHLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDN0IsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO0FBQ2hDLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLHVDQUF1QyxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3ZELE9BQU87SUFDUCxNQUFNLEdBQUcsR0FBRyxNQUFNLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFO1FBQzVELGdCQUFnQixFQUFFLFdBQVc7UUFDN0IsVUFBVSxFQUFFO1lBQ1YsVUFBVSxFQUFFLFFBQVE7U0FDckI7S0FDRixDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxnQkFBZ0IsR0FBRyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQztJQUM5RSxNQUFNLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ25ELE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyw2QkFBNkIsQ0FBQyxjQUFjLENBQUM7U0FDeEgsYUFBYSxFQUFFLENBQUM7SUFDbkIsTUFBTSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxpQ0FBaUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNyRyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzdCLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztBQUNoQyxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyw0QkFBNEIsRUFBRSxLQUFLLElBQUksRUFBRTtJQUM1QyxPQUFPO0lBQ1AsTUFBTSxHQUFHLEdBQUcsTUFBTSxZQUFZLENBQUMsb0JBQW9CLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRTtRQUM1RCxnQkFBZ0IsRUFBRSxXQUFXO1FBQzdCLFVBQVUsRUFBRTtZQUNWLFFBQVEsRUFBRSxVQUFVO1NBQ3JCO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sZ0JBQWdCLEdBQUcsaUJBQWlCLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUM7SUFDOUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3BELE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyw2QkFBNkIsQ0FBQyxjQUFjLENBQUM7U0FDeEgsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3BCLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsaUNBQWlDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDckcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQztJQUM3QixNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsVUFBVSxFQUFFLENBQUM7QUFDaEMsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsNERBQTRELEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDNUUsT0FBTztJQUNQLE1BQU0sR0FBRyxHQUFHLE1BQU0sWUFBWSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUU7UUFDNUQsZ0JBQWdCLEVBQUUsV0FBVztRQUM3QixVQUFVLEVBQUU7WUFDViw4QkFBOEIsRUFBRSxLQUFLO1NBQ3RDO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sZ0JBQWdCLEdBQUcsaUJBQWlCLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUM7SUFDOUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3BELE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyw2QkFBNkIsQ0FBQyxjQUFjLENBQUM7U0FDeEgsYUFBYSxFQUFFLENBQUM7SUFDbkIsTUFBTSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxpQ0FBaUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN0RyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzdCLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztBQUNoQyxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxpREFBaUQsRUFBRSxLQUFLLElBQUksRUFBRTtJQUNqRSxPQUFPO0lBQ1AsTUFBTSxHQUFHLEdBQUcsTUFBTSxZQUFZLENBQUMsb0JBQW9CLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRTtRQUM1RCxnQkFBZ0IsRUFBRSxXQUFXO1FBQzdCLElBQUksRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUM7S0FDckMsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sZ0JBQWdCLEdBQUcsaUJBQWlCLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUM7SUFDOUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3BELE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyw2QkFBNkIsQ0FBQyxjQUFjLENBQUM7U0FDeEgsYUFBYSxFQUFFLENBQUM7SUFDbkIsTUFBTSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxpQ0FBaUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNyRyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzdCLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztBQUNoQyxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyx1RUFBdUUsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN2RixNQUFNLE1BQU0sQ0FBQyxZQUFZLENBQUMsb0JBQW9CLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRTtRQUN2RCxnQkFBZ0IsRUFBRSxXQUFXO1FBQzdCLFVBQVUsRUFBRTtZQUNWLGVBQWUsRUFBRSxDQUFDLGVBQWUsQ0FBQztTQUNuQztLQUNGLENBQUMsQ0FBQztTQUNBLE9BQU87U0FDUCxPQUFPLENBQUMsaUVBQWlFLENBQUMsQ0FBQztBQUNoRixDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyw2RUFBNkUsRUFBRSxLQUFLLElBQUksRUFBRTtJQUM3RixNQUFNLE1BQU0sQ0FBQyxZQUFZLENBQUMsb0JBQW9CLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRTtRQUN2RCxnQkFBZ0IsRUFBRSxXQUFXO1FBQzdCLFVBQVUsRUFBRTtZQUNWLCtCQUErQixFQUFFLENBQUMsNkNBQTZDLENBQUM7U0FDakY7S0FDRixDQUFDLENBQUM7U0FDQSxPQUFPO1NBQ1AsT0FBTyxDQUFDLDZGQUE2RixDQUFDLENBQUM7QUFDNUcsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsc0ZBQXNGLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDckcsUUFBUSxDQUFDLGNBQTZCO1NBQ3BDLFNBQVMsRUFBRTtRQUNaLHNFQUFzRTtRQUN0RSxnRUFBZ0U7U0FDL0Qsc0JBQXNCLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUM3QixNQUFNLEVBQUU7WUFDTjtnQkFDRSxXQUFXLEVBQUUsMEJBQTBCO2dCQUN2QyxpQkFBaUIsRUFBRSxhQUFhO2dCQUNoQyxPQUFPLEVBQUU7b0JBQ1AsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUU7b0JBQ2xELEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUU7aUJBQzFEO2FBQ0Y7U0FDRjtLQUNGLENBQUMsQ0FBQztTQUNGLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDN0IsTUFBTSxFQUFFO1lBQ047Z0JBQ0UsV0FBVyxFQUFFLDBCQUEwQjtnQkFDdkMsaUJBQWlCLEVBQUUsYUFBYTtnQkFDaEMsT0FBTyxFQUFFO29CQUNQLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFO29CQUNsRCxFQUFFLFNBQVMsRUFBRSxrQkFBa0IsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFO2lCQUMxRDthQUNGO1NBQ0Y7S0FDRixDQUFDLENBQUM7UUFDSCxxQ0FBcUM7U0FDcEMsc0JBQXNCLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUM3QixNQUFNLEVBQUU7WUFDTjtnQkFDRSxXQUFXLEVBQUUsaUJBQWlCO2dCQUM5QixpQkFBaUIsRUFBRSxhQUFhO2dCQUNoQywyQkFBMkIsRUFBRSxLQUFLO2FBQ25DO1NBQ0Y7S0FDRixDQUFDLENBQUMsQ0FBQztJQUVOLE9BQU87SUFDUCxNQUFNLEdBQUcsR0FBRyxNQUFNLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUVqRyxPQUFPO0lBQ1AsTUFBTSxnQkFBZ0IsR0FBRyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQztJQUM5RSxNQUFNLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDcEQsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGdCQUFnQixDQUFDLGlDQUFpQyxDQUFDLENBQUMsQ0FBQyxDQUFDLDZCQUE2QixDQUFDLGNBQWMsQ0FBQztTQUN4SCxhQUFhLEVBQUUsQ0FBQztJQUNuQixNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzdCLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztBQUNoQyxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxnRkFBZ0YsRUFBRSxLQUFLLElBQUksRUFBRTtJQUMvRixRQUFRLENBQUMsY0FBNkI7U0FDcEMsU0FBUyxFQUFFO1FBQ1osc0VBQXNFO1FBQ3RFLGdFQUFnRTtTQUMvRCxzQkFBc0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQzdCLE1BQU0sRUFBRTtZQUNOO2dCQUNFLFdBQVcsRUFBRSxtQkFBbUI7Z0JBQ2hDLGlCQUFpQixFQUFFLGFBQWE7Z0JBQ2hDLE9BQU8sRUFBRTtvQkFDUCxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRTtpQkFDbkQ7YUFDMEI7U0FDOUI7S0FDRixDQUFDLENBQUM7U0FDRixzQkFBc0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQzdCLE1BQU0sRUFBRTtZQUNOO2dCQUNFLFdBQVcsRUFBRSxtQkFBbUI7Z0JBQ2hDLGlCQUFpQixFQUFFLGFBQWE7Z0JBQ2hDLE9BQU8sRUFBRTtvQkFDUCxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRTtpQkFDbkQ7YUFDRjtTQUNGO0tBQ0YsQ0FBQyxDQUFDO1FBQ0gsMkRBQTJEO1NBQzFELHNCQUFzQixDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUMvQyxzQ0FBc0M7U0FDckMsc0JBQXNCLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUM3QixNQUFNLEVBQUU7WUFDTjtnQkFDRSxXQUFXLEVBQUUsaUJBQWlCO2dCQUM5QixpQkFBaUIsRUFBRSxhQUFhO2dCQUNoQywyQkFBMkIsRUFBRSxLQUFLO2FBQ25DO1NBQ0Y7S0FDRixDQUFDLENBQUMsQ0FBQztJQUVOLE9BQU87SUFDUCxNQUFNLEdBQUcsR0FBRyxNQUFNLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUVqRyxPQUFPO0lBQ1AsTUFBTSxnQkFBZ0IsR0FBRyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQztJQUM5RSxNQUFNLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxDQUFDLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDcEQsTUFBTSxDQUFDLGdCQUFnQixDQUFDLGdCQUFnQixDQUFDLGlDQUFpQyxDQUFDLENBQUMsQ0FBQyxDQUFDLDZCQUE2QixDQUFDLGNBQWMsQ0FBQztTQUN4SCxhQUFhLEVBQUUsQ0FBQztJQUNuQixNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO0lBQzdCLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUM5QixNQUFNLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLGdCQUFnQixFQUFFLENBQUM7QUFDbEQsQ0FBQyxDQUFDLENBQUM7QUFFSCxJQUFJLENBQUMsK0NBQStDLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDL0QsT0FBTztJQUNQLE1BQU0sWUFBWSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUVsRCxPQUFPO0lBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQzlCLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO0FBQzNDLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLHlDQUF5QyxFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3pELE9BQU87SUFDUCxNQUFNLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFO1FBQ2hELHFCQUFxQixFQUFFLElBQUk7S0FDNUIsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUM5QixNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztBQUM1QyxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxzQkFBc0IsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN0QyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRTtRQUNuRSxPQUFPO1FBQ1AsTUFBTSxDQUFDLElBQUEsWUFBSyxFQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLGFBQWEsRUFBRSw2SUFBNkksQ0FBQyxDQUFDO0lBQ3ZNLENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTztJQUNQLE1BQU0sWUFBWSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN6QyxDQUFDLENBQUMsQ0FBQztBQUVILElBQUksQ0FBQyxzQkFBc0IsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN0QyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRTtRQUNuRSxPQUFPO1FBQ1AsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUMsYUFBYSxFQUFFLDZJQUE2SSxDQUFDLENBQUM7SUFDNU0sQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPO0lBQ1AsTUFBTSxZQUFZLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3hDLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L29yZGVyICovXG5pbXBvcnQgeyBDcmVhdGVDaGFuZ2VTZXRJbnB1dCB9IGZyb20gJ2F3cy1zZGsvY2xpZW50cy9jbG91ZGZvcm1hdGlvbic7XG5pbXBvcnQgeyBwYXJzZSB9IGZyb20gJ3lhbWwnO1xuaW1wb3J0IHsgQm9vdHN0cmFwcGVyIH0gZnJvbSAnLi4vLi4vbGliL2FwaS9ib290c3RyYXAnO1xuaW1wb3J0IHsgZGVzZXJpYWxpemVTdHJ1Y3R1cmUgfSBmcm9tICcuLi8uLi9saWIvc2VyaWFsaXplJztcbmltcG9ydCB7IE1vY2tTZGtQcm92aWRlciwgU3luY0hhbmRsZXJTdWJzZXRPZiB9IGZyb20gJy4uL3V0aWwvbW9jay1zZGsnO1xuXG5jb25zdCBlbnYgPSB7XG4gIGFjY291bnQ6ICcxMjM0NTY3ODkwMTInLFxuICByZWdpb246ICd1cy1lYXN0LTEnLFxuICBuYW1lOiAnbW9jaycsXG59O1xuXG5sZXQgc2RrOiBNb2NrU2RrUHJvdmlkZXI7XG5sZXQgZXhlY3V0ZWQ6IGJvb2xlYW47XG5sZXQgcHJvdGVjdGVkVGVybWluYXRpb246IGJvb2xlYW47XG5sZXQgY2ZuTW9ja3M6IGplc3QuTW9ja2VkPFN5bmNIYW5kbGVyU3Vic2V0T2Y8QVdTLkNsb3VkRm9ybWF0aW9uPj47XG5sZXQgY2hhbmdlU2V0VGVtcGxhdGU6IGFueSB8IHVuZGVmaW5lZDtcbmxldCBib290c3RyYXBwZXI6IEJvb3RzdHJhcHBlcjtcbmJlZm9yZUVhY2goKCkgPT4ge1xuICBzZGsgPSBuZXcgTW9ja1Nka1Byb3ZpZGVyKCk7XG4gIGV4ZWN1dGVkID0gZmFsc2U7XG4gIHByb3RlY3RlZFRlcm1pbmF0aW9uID0gZmFsc2U7XG4gIGJvb3RzdHJhcHBlciA9IG5ldyBCb290c3RyYXBwZXIoeyBzb3VyY2U6ICdsZWdhY3knIH0pO1xuXG4gIGNmbk1vY2tzID0ge1xuICAgIGRlc2NyaWJlU3RhY2tFdmVudHM6IGplc3QuZm4oKS5tb2NrUmV0dXJuVmFsdWUoe30pLFxuICAgIGRlc2NyaWJlU3RhY2tzOiBqZXN0LmZuKClcbiAgICAgIC8vIEZpcnN0IHR3byBjYWxscywgbm8gc3RhY2tzIGV4aXN0IChmaXJzdCBpcyBmb3IgdmVyc2lvbiBjaGVja2luZywgc2Vjb25kIGlzIGluIGRlcGxveS1zdGFjay50cylcbiAgICAgIC5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCgpID0+ICh7IFN0YWNrczogW10gfSkpXG4gICAgICAubW9ja0ltcGxlbWVudGF0aW9uT25jZSgoKSA9PiAoeyBTdGFja3M6IFtdIH0pKVxuICAgICAgLy8gU2Vjb25kIGNhbGwsIHN0YWNrIGhhcyBiZWVuIGNyZWF0ZWRcbiAgICAgIC5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCgpID0+ICh7XG4gICAgICAgIFN0YWNrczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIFN0YWNrU3RhdHVzOiAnQ1JFQVRFX0NPTVBMRVRFJyxcbiAgICAgICAgICAgIFN0YWNrU3RhdHVzUmVhc29uOiAnSXQgaXMgbWFnaWMnLFxuICAgICAgICAgICAgRW5hYmxlVGVybWluYXRpb25Qcm90ZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSkpLFxuICAgIGNyZWF0ZUNoYW5nZVNldDogamVzdC5mbigoaW5mbzogQ3JlYXRlQ2hhbmdlU2V0SW5wdXQpID0+IHtcbiAgICAgIGNoYW5nZVNldFRlbXBsYXRlID0gZGVzZXJpYWxpemVTdHJ1Y3R1cmUoaW5mby5UZW1wbGF0ZUJvZHkgYXMgc3RyaW5nKTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9KSxcbiAgICBkZXNjcmliZUNoYW5nZVNldDogamVzdC5mbigoKSA9PiAoe1xuICAgICAgU3RhdHVzOiAnQ1JFQVRFX0NPTVBMRVRFJyxcbiAgICAgIENoYW5nZXM6IFtdLFxuICAgIH0pKSxcbiAgICBleGVjdXRlQ2hhbmdlU2V0OiBqZXN0LmZuKCgpID0+IHtcbiAgICAgIGV4ZWN1dGVkID0gdHJ1ZTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9KSxcbiAgICBkZWxldGVDaGFuZ2VTZXQ6IGplc3QuZm4oKSxcbiAgICBnZXRUZW1wbGF0ZTogamVzdC5mbigoKSA9PiB7XG4gICAgICBleGVjdXRlZCA9IHRydWU7XG4gICAgICByZXR1cm4ge307XG4gICAgfSksXG4gICAgZGVsZXRlU3RhY2s6IGplc3QuZm4oKSxcbiAgICB1cGRhdGVUZXJtaW5hdGlvblByb3RlY3Rpb246IGplc3QuZm4oKCkgPT4ge1xuICAgICAgcHJvdGVjdGVkVGVybWluYXRpb24gPSB0cnVlO1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH0pLFxuICB9O1xuICBzZGsuc3R1YkNsb3VkRm9ybWF0aW9uKGNmbk1vY2tzKTtcbn0pO1xuXG50ZXN0KCdkbyBib290c3RyYXAnLCBhc3luYyAoKSA9PiB7XG4gIC8vIFdIRU5cbiAgY29uc3QgcmV0ID0gYXdhaXQgYm9vdHN0cmFwcGVyLmJvb3RzdHJhcEVudmlyb25tZW50KGVudiwgc2RrLCB7IHRvb2xraXRTdGFja05hbWU6ICdtb2NrU3RhY2snIH0pO1xuXG4gIC8vIFRIRU5cbiAgY29uc3QgYnVja2V0UHJvcGVydGllcyA9IGNoYW5nZVNldFRlbXBsYXRlLlJlc291cmNlcy5TdGFnaW5nQnVja2V0LlByb3BlcnRpZXM7XG4gIGV4cGVjdChidWNrZXRQcm9wZXJ0aWVzLkJ1Y2tldE5hbWUpLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KGJ1Y2tldFByb3BlcnRpZXMuQnVja2V0RW5jcnlwdGlvbi5TZXJ2ZXJTaWRlRW5jcnlwdGlvbkNvbmZpZ3VyYXRpb25bMF0uU2VydmVyU2lkZUVuY3J5cHRpb25CeURlZmF1bHQuS01TTWFzdGVyS2V5SUQpXG4gICAgLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KGNoYW5nZVNldFRlbXBsYXRlLkNvbmRpdGlvbnMuVXNlUHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uWydGbjo6RXF1YWxzJ11bMF0pLnRvQmUoJ3RydWUnKTtcbiAgZXhwZWN0KHJldC5ub09wKS50b0JlRmFsc3koKTtcbiAgZXhwZWN0KGV4ZWN1dGVkKS50b0JlVHJ1dGh5KCk7XG59KTtcblxudGVzdCgnZG8gYm9vdHN0cmFwIHVzaW5nIGN1c3RvbSBidWNrZXQgbmFtZScsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBjb25zdCByZXQgPSBhd2FpdCBib290c3RyYXBwZXIuYm9vdHN0cmFwRW52aXJvbm1lbnQoZW52LCBzZGssIHtcbiAgICB0b29sa2l0U3RhY2tOYW1lOiAnbW9ja1N0YWNrJyxcbiAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICBidWNrZXROYW1lOiAnZm9vYmFyJyxcbiAgICB9LFxuICB9KTtcblxuICAvLyBUSEVOXG4gIGNvbnN0IGJ1Y2tldFByb3BlcnRpZXMgPSBjaGFuZ2VTZXRUZW1wbGF0ZS5SZXNvdXJjZXMuU3RhZ2luZ0J1Y2tldC5Qcm9wZXJ0aWVzO1xuICBleHBlY3QoYnVja2V0UHJvcGVydGllcy5CdWNrZXROYW1lKS50b0JlKCdmb29iYXInKTtcbiAgZXhwZWN0KGJ1Y2tldFByb3BlcnRpZXMuQnVja2V0RW5jcnlwdGlvbi5TZXJ2ZXJTaWRlRW5jcnlwdGlvbkNvbmZpZ3VyYXRpb25bMF0uU2VydmVyU2lkZUVuY3J5cHRpb25CeURlZmF1bHQuS01TTWFzdGVyS2V5SUQpXG4gICAgLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KGNoYW5nZVNldFRlbXBsYXRlLkNvbmRpdGlvbnMuVXNlUHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uWydGbjo6RXF1YWxzJ11bMF0pLnRvQmUoJ3RydWUnKTtcbiAgZXhwZWN0KHJldC5ub09wKS50b0JlRmFsc3koKTtcbiAgZXhwZWN0KGV4ZWN1dGVkKS50b0JlVHJ1dGh5KCk7XG59KTtcblxudGVzdCgnZG8gYm9vdHN0cmFwIHVzaW5nIEtNUyBDTUsnLCBhc3luYyAoKSA9PiB7XG4gIC8vIFdIRU5cbiAgY29uc3QgcmV0ID0gYXdhaXQgYm9vdHN0cmFwcGVyLmJvb3RzdHJhcEVudmlyb25tZW50KGVudiwgc2RrLCB7XG4gICAgdG9vbGtpdFN0YWNrTmFtZTogJ21vY2tTdGFjaycsXG4gICAgcGFyYW1ldGVyczoge1xuICAgICAga21zS2V5SWQ6ICdteUttc0tleScsXG4gICAgfSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBjb25zdCBidWNrZXRQcm9wZXJ0aWVzID0gY2hhbmdlU2V0VGVtcGxhdGUuUmVzb3VyY2VzLlN0YWdpbmdCdWNrZXQuUHJvcGVydGllcztcbiAgZXhwZWN0KGJ1Y2tldFByb3BlcnRpZXMuQnVja2V0TmFtZSkudG9CZVVuZGVmaW5lZCgpO1xuICBleHBlY3QoYnVja2V0UHJvcGVydGllcy5CdWNrZXRFbmNyeXB0aW9uLlNlcnZlclNpZGVFbmNyeXB0aW9uQ29uZmlndXJhdGlvblswXS5TZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdC5LTVNNYXN0ZXJLZXlJRClcbiAgICAudG9CZSgnbXlLbXNLZXknKTtcbiAgZXhwZWN0KGNoYW5nZVNldFRlbXBsYXRlLkNvbmRpdGlvbnMuVXNlUHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uWydGbjo6RXF1YWxzJ11bMF0pLnRvQmUoJ3RydWUnKTtcbiAgZXhwZWN0KHJldC5ub09wKS50b0JlRmFsc3koKTtcbiAgZXhwZWN0KGV4ZWN1dGVkKS50b0JlVHJ1dGh5KCk7XG59KTtcblxudGVzdCgnYm9vdHN0cmFwIGRpc2FibGUgYnVja2V0IFB1YmxpYyBBY2Nlc3MgQmxvY2sgQ29uZmlndXJhdGlvbicsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBjb25zdCByZXQgPSBhd2FpdCBib290c3RyYXBwZXIuYm9vdHN0cmFwRW52aXJvbm1lbnQoZW52LCBzZGssIHtcbiAgICB0b29sa2l0U3RhY2tOYW1lOiAnbW9ja1N0YWNrJyxcbiAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICBwdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb246IGZhbHNlLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgY29uc3QgYnVja2V0UHJvcGVydGllcyA9IGNoYW5nZVNldFRlbXBsYXRlLlJlc291cmNlcy5TdGFnaW5nQnVja2V0LlByb3BlcnRpZXM7XG4gIGV4cGVjdChidWNrZXRQcm9wZXJ0aWVzLkJ1Y2tldE5hbWUpLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KGJ1Y2tldFByb3BlcnRpZXMuQnVja2V0RW5jcnlwdGlvbi5TZXJ2ZXJTaWRlRW5jcnlwdGlvbkNvbmZpZ3VyYXRpb25bMF0uU2VydmVyU2lkZUVuY3J5cHRpb25CeURlZmF1bHQuS01TTWFzdGVyS2V5SUQpXG4gICAgLnRvQmVVbmRlZmluZWQoKTtcbiAgZXhwZWN0KGNoYW5nZVNldFRlbXBsYXRlLkNvbmRpdGlvbnMuVXNlUHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uWydGbjo6RXF1YWxzJ11bMF0pLnRvQmUoJ2ZhbHNlJyk7XG4gIGV4cGVjdChyZXQubm9PcCkudG9CZUZhbHN5KCk7XG4gIGV4cGVjdChleGVjdXRlZCkudG9CZVRydXRoeSgpO1xufSk7XG5cbnRlc3QoJ2RvIGJvb3RzdHJhcCB3aXRoIGN1c3RvbSB0YWdzIGZvciB0b29sa2l0IHN0YWNrJywgYXN5bmMgKCkgPT4ge1xuICAvLyBXSEVOXG4gIGNvbnN0IHJldCA9IGF3YWl0IGJvb3RzdHJhcHBlci5ib290c3RyYXBFbnZpcm9ubWVudChlbnYsIHNkaywge1xuICAgIHRvb2xraXRTdGFja05hbWU6ICdtb2NrU3RhY2snLFxuICAgIHRhZ3M6IFt7IEtleTogJ0ZvbycsIFZhbHVlOiAnQmFyJyB9XSxcbiAgfSk7XG5cbiAgLy8gVEhFTlxuICBjb25zdCBidWNrZXRQcm9wZXJ0aWVzID0gY2hhbmdlU2V0VGVtcGxhdGUuUmVzb3VyY2VzLlN0YWdpbmdCdWNrZXQuUHJvcGVydGllcztcbiAgZXhwZWN0KGJ1Y2tldFByb3BlcnRpZXMuQnVja2V0TmFtZSkudG9CZVVuZGVmaW5lZCgpO1xuICBleHBlY3QoYnVja2V0UHJvcGVydGllcy5CdWNrZXRFbmNyeXB0aW9uLlNlcnZlclNpZGVFbmNyeXB0aW9uQ29uZmlndXJhdGlvblswXS5TZXJ2ZXJTaWRlRW5jcnlwdGlvbkJ5RGVmYXVsdC5LTVNNYXN0ZXJLZXlJRClcbiAgICAudG9CZVVuZGVmaW5lZCgpO1xuICBleHBlY3QoY2hhbmdlU2V0VGVtcGxhdGUuQ29uZGl0aW9ucy5Vc2VQdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb25bJ0ZuOjpFcXVhbHMnXVswXSkudG9CZSgndHJ1ZScpO1xuICBleHBlY3QocmV0Lm5vT3ApLnRvQmVGYWxzeSgpO1xuICBleHBlY3QoZXhlY3V0ZWQpLnRvQmVUcnV0aHkoKTtcbn0pO1xuXG50ZXN0KCdwYXNzaW5nIHRydXN0ZWQgYWNjb3VudHMgdG8gdGhlIG9sZCBib290c3RyYXBwaW5nIHJlc3VsdHMgaW4gYW4gZXJyb3InLCBhc3luYyAoKSA9PiB7XG4gIGF3YWl0IGV4cGVjdChib290c3RyYXBwZXIuYm9vdHN0cmFwRW52aXJvbm1lbnQoZW52LCBzZGssIHtcbiAgICB0b29sa2l0U3RhY2tOYW1lOiAnbW9ja1N0YWNrJyxcbiAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICB0cnVzdGVkQWNjb3VudHM6IFsnMDEyMzQ1Njc4OTAxMiddLFxuICAgIH0sXG4gIH0pKVxuICAgIC5yZWplY3RzXG4gICAgLnRvVGhyb3coJy0tdHJ1c3QgY2FuIG9ubHkgYmUgcGFzc2VkIGZvciB0aGUgbW9kZXJuIGJvb3RzdHJhcCBleHBlcmllbmNlLicpO1xufSk7XG5cbnRlc3QoJ3Bhc3NpbmcgQ0ZOIGV4ZWN1dGlvbiBwb2xpY2llcyB0byB0aGUgb2xkIGJvb3RzdHJhcHBpbmcgcmVzdWx0cyBpbiBhbiBlcnJvcicsIGFzeW5jICgpID0+IHtcbiAgYXdhaXQgZXhwZWN0KGJvb3RzdHJhcHBlci5ib290c3RyYXBFbnZpcm9ubWVudChlbnYsIHNkaywge1xuICAgIHRvb2xraXRTdGFja05hbWU6ICdtb2NrU3RhY2snLFxuICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgIGNsb3VkRm9ybWF0aW9uRXhlY3V0aW9uUG9saWNpZXM6IFsnYXJuOmF3czppYW06OmF3czpwb2xpY3kvQWRtaW5pc3RyYXRvckFjY2VzcyddLFxuICAgIH0sXG4gIH0pKVxuICAgIC5yZWplY3RzXG4gICAgLnRvVGhyb3coJy0tY2xvdWRmb3JtYXRpb24tZXhlY3V0aW9uLXBvbGljaWVzIGNhbiBvbmx5IGJlIHBhc3NlZCBmb3IgdGhlIG1vZGVybiBib290c3RyYXAgZXhwZXJpZW5jZS4nKTtcbn0pO1xuXG50ZXN0KCdldmVuIGlmIHRoZSBib290c3RyYXAgc3RhY2sgaXMgaW4gYSByb2xsYmFjayBzdGF0ZSwgY2FuIHN0aWxsIHJldHJ5IGJvb3RzdHJhcHBpbmcgaXQnLCBhc3luYyAoKSA9PiB7XG4gIChjZm5Nb2Nrcy5kZXNjcmliZVN0YWNrcyEgYXMgamVzdC5Nb2NrKVxuICAgIC5tb2NrUmVzZXQoKVxuICAgIC8vIEZpcnN0IHR3byBjYWxscywgdGhlIHN0YWNrIGV4aXN0cyB3aXRoIGEgJ3JvbGxiYWNrIGNvbXBsZXRlJyBzdGF0dXNcbiAgICAvLyAoZmlyc3QgaXMgZm9yIHZlcnNpb24gY2hlY2tpbmcsIHNlY29uZCBpcyBpbiBkZXBsb3ktc3RhY2sudHMpXG4gICAgLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoKCkgPT4gKHtcbiAgICAgIFN0YWNrczogW1xuICAgICAgICB7XG4gICAgICAgICAgU3RhY2tTdGF0dXM6ICdVUERBVEVfUk9MTEJBQ0tfQ09NUExFVEUnLFxuICAgICAgICAgIFN0YWNrU3RhdHVzUmVhc29uOiAnSXQgaXMgbWFnaWMnLFxuICAgICAgICAgIE91dHB1dHM6IFtcbiAgICAgICAgICAgIHsgT3V0cHV0S2V5OiAnQnVja2V0TmFtZScsIE91dHB1dFZhbHVlOiAnYnVja2V0JyB9LFxuICAgICAgICAgICAgeyBPdXRwdXRLZXk6ICdCdWNrZXREb21haW5OYW1lJywgT3V0cHV0VmFsdWU6ICdhd3MuY29tJyB9LFxuICAgICAgICAgIF0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pKVxuICAgIC5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCgpID0+ICh7XG4gICAgICBTdGFja3M6IFtcbiAgICAgICAge1xuICAgICAgICAgIFN0YWNrU3RhdHVzOiAnVVBEQVRFX1JPTExCQUNLX0NPTVBMRVRFJyxcbiAgICAgICAgICBTdGFja1N0YXR1c1JlYXNvbjogJ0l0IGlzIG1hZ2ljJyxcbiAgICAgICAgICBPdXRwdXRzOiBbXG4gICAgICAgICAgICB7IE91dHB1dEtleTogJ0J1Y2tldE5hbWUnLCBPdXRwdXRWYWx1ZTogJ2J1Y2tldCcgfSxcbiAgICAgICAgICAgIHsgT3V0cHV0S2V5OiAnQnVja2V0RG9tYWluTmFtZScsIE91dHB1dFZhbHVlOiAnYXdzLmNvbScgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KSlcbiAgICAvLyBUaGlyZCBjYWxsLCBzdGFjayBoYXMgYmVlbiBjcmVhdGVkXG4gICAgLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoKCkgPT4gKHtcbiAgICAgIFN0YWNrczogW1xuICAgICAgICB7XG4gICAgICAgICAgU3RhY2tTdGF0dXM6ICdDUkVBVEVfQ09NUExFVEUnLFxuICAgICAgICAgIFN0YWNrU3RhdHVzUmVhc29uOiAnSXQgaXMgbWFnaWMnLFxuICAgICAgICAgIEVuYWJsZVRlcm1pbmF0aW9uUHJvdGVjdGlvbjogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pKTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IHJldCA9IGF3YWl0IGJvb3RzdHJhcHBlci5ib290c3RyYXBFbnZpcm9ubWVudChlbnYsIHNkaywgeyB0b29sa2l0U3RhY2tOYW1lOiAnbW9ja1N0YWNrJyB9KTtcblxuICAvLyBUSEVOXG4gIGNvbnN0IGJ1Y2tldFByb3BlcnRpZXMgPSBjaGFuZ2VTZXRUZW1wbGF0ZS5SZXNvdXJjZXMuU3RhZ2luZ0J1Y2tldC5Qcm9wZXJ0aWVzO1xuICBleHBlY3QoYnVja2V0UHJvcGVydGllcy5CdWNrZXROYW1lKS50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChidWNrZXRQcm9wZXJ0aWVzLkJ1Y2tldEVuY3J5cHRpb24uU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uWzBdLlNlcnZlclNpZGVFbmNyeXB0aW9uQnlEZWZhdWx0LktNU01hc3RlcktleUlEKVxuICAgIC50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChyZXQubm9PcCkudG9CZUZhbHN5KCk7XG4gIGV4cGVjdChleGVjdXRlZCkudG9CZVRydXRoeSgpO1xufSk7XG5cbnRlc3QoJ2V2ZW4gaWYgdGhlIGJvb3RzdHJhcCBzdGFjayBmYWlsZWQgdG8gY3JlYXRlLCBjYW4gc3RpbGwgcmV0cnkgYm9vdHN0cmFwcGluZyBpdCcsIGFzeW5jICgpID0+IHtcbiAgKGNmbk1vY2tzLmRlc2NyaWJlU3RhY2tzISBhcyBqZXN0Lk1vY2spXG4gICAgLm1vY2tSZXNldCgpXG4gICAgLy8gRmlyc3QgdHdvIGNhbGxzLCB0aGUgc3RhY2sgZXhpc3RzIHdpdGggYSAncm9sbGJhY2sgY29tcGxldGUnIHN0YXR1c1xuICAgIC8vIChmaXJzdCBpcyBmb3IgdmVyc2lvbiBjaGVja2luZywgc2Vjb25kIGlzIGluIGRlcGxveS1zdGFjay50cylcbiAgICAubW9ja0ltcGxlbWVudGF0aW9uT25jZSgoKSA9PiAoe1xuICAgICAgU3RhY2tzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBTdGFja1N0YXR1czogJ1JPTExCQUNLX0NPTVBMRVRFJyxcbiAgICAgICAgICBTdGFja1N0YXR1c1JlYXNvbjogJ0l0IGlzIG1hZ2ljJyxcbiAgICAgICAgICBPdXRwdXRzOiBbXG4gICAgICAgICAgICB7IE91dHB1dEtleTogJ0J1Y2tldE5hbWUnLCBPdXRwdXRWYWx1ZTogJ2J1Y2tldCcgfSxcbiAgICAgICAgICBdLFxuICAgICAgICB9IGFzIEFXUy5DbG91ZEZvcm1hdGlvbi5TdGFjayxcbiAgICAgIF0sXG4gICAgfSkpXG4gICAgLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoKCkgPT4gKHtcbiAgICAgIFN0YWNrczogW1xuICAgICAgICB7XG4gICAgICAgICAgU3RhY2tTdGF0dXM6ICdST0xMQkFDS19DT01QTEVURScsXG4gICAgICAgICAgU3RhY2tTdGF0dXNSZWFzb246ICdJdCBpcyBtYWdpYycsXG4gICAgICAgICAgT3V0cHV0czogW1xuICAgICAgICAgICAgeyBPdXRwdXRLZXk6ICdCdWNrZXROYW1lJywgT3V0cHV0VmFsdWU6ICdidWNrZXQnIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSkpXG4gICAgLy8gVGhpcmQgY2FsbCwgd2UganVzdCBkaWQgYSBkZWxldGUgYW5kIHdhbnQgdG8gc2VlIGl0IGdvbmVcbiAgICAubW9ja0ltcGxlbWVudGF0aW9uT25jZSgoKSA9PiAoeyBTdGFja3M6IFtdIH0pKVxuICAgIC8vIEZvdXJ0aCBjYWxsLCBzdGFjayBoYXMgYmVlbiBjcmVhdGVkXG4gICAgLm1vY2tJbXBsZW1lbnRhdGlvbk9uY2UoKCkgPT4gKHtcbiAgICAgIFN0YWNrczogW1xuICAgICAgICB7XG4gICAgICAgICAgU3RhY2tTdGF0dXM6ICdDUkVBVEVfQ09NUExFVEUnLFxuICAgICAgICAgIFN0YWNrU3RhdHVzUmVhc29uOiAnSXQgaXMgbWFnaWMnLFxuICAgICAgICAgIEVuYWJsZVRlcm1pbmF0aW9uUHJvdGVjdGlvbjogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pKTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IHJldCA9IGF3YWl0IGJvb3RzdHJhcHBlci5ib290c3RyYXBFbnZpcm9ubWVudChlbnYsIHNkaywgeyB0b29sa2l0U3RhY2tOYW1lOiAnbW9ja1N0YWNrJyB9KTtcblxuICAvLyBUSEVOXG4gIGNvbnN0IGJ1Y2tldFByb3BlcnRpZXMgPSBjaGFuZ2VTZXRUZW1wbGF0ZS5SZXNvdXJjZXMuU3RhZ2luZ0J1Y2tldC5Qcm9wZXJ0aWVzO1xuICBleHBlY3QoYnVja2V0UHJvcGVydGllcy5CdWNrZXROYW1lKS50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChidWNrZXRQcm9wZXJ0aWVzLkJ1Y2tldEVuY3J5cHRpb24uU2VydmVyU2lkZUVuY3J5cHRpb25Db25maWd1cmF0aW9uWzBdLlNlcnZlclNpZGVFbmNyeXB0aW9uQnlEZWZhdWx0LktNU01hc3RlcktleUlEKVxuICAgIC50b0JlVW5kZWZpbmVkKCk7XG4gIGV4cGVjdChyZXQubm9PcCkudG9CZUZhbHN5KCk7XG4gIGV4cGVjdChleGVjdXRlZCkudG9CZVRydXRoeSgpO1xuICBleHBlY3QoY2ZuTW9ja3MuZGVsZXRlU3RhY2spLnRvSGF2ZUJlZW5DYWxsZWQoKTtcbn0pO1xuXG50ZXN0KCdzdGFjayBpcyBub3QgdGVybWluYXRpb24gcHJvdGVjdGVkIGJ5IGRlZmF1bHQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIFdIRU5cbiAgYXdhaXQgYm9vdHN0cmFwcGVyLmJvb3RzdHJhcEVudmlyb25tZW50KGVudiwgc2RrKTtcblxuICAvLyBUSEVOXG4gIGV4cGVjdChleGVjdXRlZCkudG9CZVRydXRoeSgpO1xuICBleHBlY3QocHJvdGVjdGVkVGVybWluYXRpb24pLnRvQmVGYWxzeSgpO1xufSk7XG5cbnRlc3QoJ3N0YWNrIGlzIHRlcm1pbmF0aW9uIHByb3RlY3RlZCB3aGVuIHNldCcsIGFzeW5jICgpID0+IHtcbiAgLy8gV0hFTlxuICBhd2FpdCBib290c3RyYXBwZXIuYm9vdHN0cmFwRW52aXJvbm1lbnQoZW52LCBzZGssIHtcbiAgICB0ZXJtaW5hdGlvblByb3RlY3Rpb246IHRydWUsXG4gIH0pO1xuXG4gIC8vIFRIRU5cbiAgZXhwZWN0KGV4ZWN1dGVkKS50b0JlVHJ1dGh5KCk7XG4gIGV4cGVjdChwcm90ZWN0ZWRUZXJtaW5hdGlvbikudG9CZVRydXRoeSgpO1xufSk7XG5cbnRlc3QoJ2RvIHNob3dUZW1wbGF0ZSBZQU1MJywgYXN5bmMgKCkgPT4ge1xuICBwcm9jZXNzLnN0ZG91dC53cml0ZSA9IGplc3QuZm4oKS5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCh0ZW1wbGF0ZSkgPT4ge1xuICAgIC8vIFRIRU5cbiAgICBleHBlY3QocGFyc2UodGVtcGxhdGUpKS50b0hhdmVQcm9wZXJ0eSgnRGVzY3JpcHRpb24nLCAnVGhlIENESyBUb29sa2l0IFN0YWNrLiBJdCB3YXMgY3JlYXRlZCBieSBgY2RrIGJvb3RzdHJhcGAgYW5kIG1hbmFnZXMgcmVzb3VyY2VzIG5lY2Vzc2FyeSBmb3IgbWFuYWdpbmcgeW91ciBDbG91ZCBBcHBsaWNhdGlvbnMgd2l0aCBBV1MgQ0RLLicpO1xuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGJvb3RzdHJhcHBlci5zaG93VGVtcGxhdGUoZmFsc2UpO1xufSk7XG5cbnRlc3QoJ2RvIHNob3dUZW1wbGF0ZSBKU09OJywgYXN5bmMgKCkgPT4ge1xuICBwcm9jZXNzLnN0ZG91dC53cml0ZSA9IGplc3QuZm4oKS5tb2NrSW1wbGVtZW50YXRpb25PbmNlKCh0ZW1wbGF0ZSkgPT4ge1xuICAgIC8vIFRIRU5cbiAgICBleHBlY3QoSlNPTi5wYXJzZSh0ZW1wbGF0ZSkpLnRvSGF2ZVByb3BlcnR5KCdEZXNjcmlwdGlvbicsICdUaGUgQ0RLIFRvb2xraXQgU3RhY2suIEl0IHdhcyBjcmVhdGVkIGJ5IGBjZGsgYm9vdHN0cmFwYCBhbmQgbWFuYWdlcyByZXNvdXJjZXMgbmVjZXNzYXJ5IGZvciBtYW5hZ2luZyB5b3VyIENsb3VkIEFwcGxpY2F0aW9ucyB3aXRoIEFXUyBDREsuJyk7XG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgYXdhaXQgYm9vdHN0cmFwcGVyLnNob3dUZW1wbGF0ZSh0cnVlKTtcbn0pO1xuIl19