UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

237 lines 33.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-disable import/order */ jest.mock('child_process'); const cdk_build_tools_1 = require("@aws-cdk/cdk-build-tools"); const cxschema = require("@aws-cdk/cloud-assembly-schema"); const cdk = require("aws-cdk-lib"); const semver = require("semver"); const sinon = require("sinon"); const ts_mock_imports_1 = require("ts-mock-imports"); const exec_1 = require("../../lib/api/cxapp/exec"); const user_configuration_1 = require("../../lib/cli/user-configuration"); const util_1 = require("../util"); const mock_child_process_1 = require("../util/mock-child_process"); const mock_sdk_1 = require("../util/mock-sdk"); const rwlock_1 = require("../../lib/api/util/rwlock"); const assembly_versions_1 = require("./assembly-versions"); const cli_io_host_1 = require("../../lib/toolkit/cli-io-host"); let sdkProvider; let config; beforeEach(() => { cli_io_host_1.CliIoHost.instance().logLevel = 'debug'; sdkProvider = new mock_sdk_1.MockSdkProvider(); config = new user_configuration_1.Configuration(); config.settings.set(['output'], 'cdk.out'); // insert contents in fake filesystem (0, cdk_build_tools_1.bockfs)({ '/home/project/cloud-executable': 'ARBITRARY', '/home/project/windows.js': 'ARBITRARY', 'home/project/executable-app.js': 'ARBITRARY', }); cdk_build_tools_1.bockfs.workingDirectory('/home/project'); cdk_build_tools_1.bockfs.executable('/home/project/cloud-executable'); cdk_build_tools_1.bockfs.executable('/home/project/executable-app.js'); }); afterEach(() => { cli_io_host_1.CliIoHost.instance().logLevel = 'info'; sinon.restore(); cdk_build_tools_1.bockfs.restore(); }); // We need to increase the default 5s jest // timeout for async tests because the 'execProgram' invocation // might take a while :\ const TEN_SECOND_TIMEOUT = 10000; function createApp() { const app = new cdk.App({ outdir: 'cdk.out' }); const stack = new cdk.Stack(app, 'Stack'); new cdk.CfnResource(stack, 'Role', { type: 'AWS::IAM::Role', properties: { RoleName: 'Role', }, }); return app; } test('cli throws when manifest version > schema version', async () => { const app = createApp(); const currentSchemaVersion = cxschema.Manifest.version(); const mockManifestVersion = semver.inc(currentSchemaVersion, 'major'); // this mock will cause the framework to use a greater schema version than the real one, // and should cause the CLI to fail. const mockVersionNumber = ts_mock_imports_1.ImportMock.mockFunction(cxschema.Manifest, 'version', mockManifestVersion); try { app.synth(); } finally { mockVersionNumber.restore(); } (0, assembly_versions_1.rewriteManifestVersion)('cdk.out', `${mockManifestVersion}`); const expectedError = 'This CDK CLI is not compatible with the CDK library used by your application. Please upgrade the CLI to the latest version.' + `\n(Cloud assembly schema version mismatch: Maximum schema version supported is ${semver.major(currentSchemaVersion)}.x.x, but found ${mockManifestVersion})`; config.settings.set(['app'], 'cdk.out'); await expect((0, exec_1.execProgram)(sdkProvider, config)).rejects.toEqual(new Error(expectedError)); }, TEN_SECOND_TIMEOUT); test('cli does not throw when manifest version = schema version', async () => { const app = createApp(); app.synth(); rewriteManifestVersionToOurs(); config.settings.set(['app'], 'cdk.out'); const { lock } = await (0, exec_1.execProgram)(sdkProvider, config); await lock.release(); }, TEN_SECOND_TIMEOUT); // Why do we have to do something here at all? Because `aws-cdk-lib` has its own version of `cloud-assembly-schema`, // which will have real version `38.0.0`, different from the `0.0.0` version of `cloud-assembly-schema` that the CLI // uses. // // Since our Cloud Assembly Schema version will be `0.0.0` and there is no such thing as `-1.0.0`, this test doesn't // make any sense anymore. // eslint-disable-next-line jest/no-disabled-tests test.skip('cli does not throw when manifest version < schema version', async () => { const app = createApp(); const currentSchemaVersion = cxschema.Manifest.version(); app.synth(); rewriteManifestVersionToOurs(); config.settings.set(['app'], 'cdk.out'); // this mock will cause the cli to think its exepcted schema version is // greater that the version created in the manifest, which is what we are testing for. const mockVersionNumber = ts_mock_imports_1.ImportMock.mockFunction(cxschema.Manifest, 'version', semver.inc(currentSchemaVersion, 'major')); try { const { lock } = await (0, exec_1.execProgram)(sdkProvider, config); await lock.release(); } finally { mockVersionNumber.restore(); } }, TEN_SECOND_TIMEOUT); test('validates --app key is present', async () => { // GIVEN no config key for `app` await expect((0, exec_1.execProgram)(sdkProvider, config)).rejects.toThrow('--app is required either in command-line, in cdk.json or in ~/.cdk.json'); }); test('bypasses synth when app points to a cloud assembly', async () => { // GIVEN config.settings.set(['app'], 'cdk.out'); writeOutputAssembly(); rewriteManifestVersionToOurs(); // WHEN const { assembly: cloudAssembly, lock } = await (0, exec_1.execProgram)(sdkProvider, config); expect(cloudAssembly.artifacts).toEqual([]); expect(cloudAssembly.directory).toEqual('cdk.out'); await lock.release(); }); test('the application set in --app is executed', async () => { // GIVEN config.settings.set(['app'], 'cloud-executable'); (0, mock_child_process_1.mockSpawn)({ commandLine: 'cloud-executable', sideEffect: () => writeOutputAssembly(), }); // WHEN const { lock } = await (0, exec_1.execProgram)(sdkProvider, config); await lock.release(); }); test('the application set in --app is executed as-is if it contains a filename that does not exist', async () => { // GIVEN config.settings.set(['app'], 'does-not-exist'); (0, mock_child_process_1.mockSpawn)({ commandLine: 'does-not-exist', sideEffect: () => writeOutputAssembly(), }); // WHEN const { lock } = await (0, exec_1.execProgram)(sdkProvider, config); await lock.release(); }); test('the application set in --app is executed with arguments', async () => { // GIVEN config.settings.set(['app'], 'cloud-executable an-arg'); (0, mock_child_process_1.mockSpawn)({ commandLine: 'cloud-executable an-arg', sideEffect: () => writeOutputAssembly(), }); // WHEN const { lock } = await (0, exec_1.execProgram)(sdkProvider, config); await lock.release(); }); test('application set in --app as `*.js` always uses handler on windows', async () => { // GIVEN sinon.stub(process, 'platform').value('win32'); config.settings.set(['app'], 'windows.js'); (0, mock_child_process_1.mockSpawn)({ commandLine: process.execPath + ' windows.js', sideEffect: () => writeOutputAssembly(), }); // WHEN const { lock } = await (0, exec_1.execProgram)(sdkProvider, config); await lock.release(); }); test('application set in --app is `*.js` and executable', async () => { // GIVEN config.settings.set(['app'], 'executable-app.js'); (0, mock_child_process_1.mockSpawn)({ commandLine: 'executable-app.js', sideEffect: () => writeOutputAssembly(), }); // WHEN const { lock } = await (0, exec_1.execProgram)(sdkProvider, config); await lock.release(); }); test('cli throws when the `build` script fails', async () => { // GIVEN config.settings.set(['build'], 'fake-command'); (0, mock_child_process_1.mockSpawn)({ commandLine: 'fake-command', exitCode: 127, }); // WHEN await expect((0, exec_1.execProgram)(sdkProvider, config)).rejects.toEqual(new Error('Subprocess exited with error 127')); }, TEN_SECOND_TIMEOUT); test('cli does not throw when the `build` script succeeds', async () => { // GIVEN config.settings.set(['build'], 'real command'); config.settings.set(['app'], 'executable-app.js'); (0, mock_child_process_1.mockSpawn)({ commandLine: 'real command', // `build` key is not split on whitespace exitCode: 0, }, { commandLine: 'executable-app.js', sideEffect: () => writeOutputAssembly(), }); // WHEN const { lock } = await (0, exec_1.execProgram)(sdkProvider, config); await lock.release(); }, TEN_SECOND_TIMEOUT); test('cli releases the outdir lock when execProgram throws', async () => { // GIVEN config.settings.set(['app'], 'cloud-executable'); (0, mock_child_process_1.mockSpawn)({ commandLine: 'fake-command', exitCode: 127, }); // WHEN await expect((0, exec_1.execProgram)(sdkProvider, config)).rejects.toThrow(); const output = config.settings.get(['output']); expect(output).toBeDefined(); // check that the lock is released const lock = await new rwlock_1.RWLock(output).acquireWrite(); await lock.release(); }); function writeOutputAssembly() { const asm = (0, util_1.testAssembly)({ stacks: [], }); cdk_build_tools_1.bockfs.write('/home/project/cdk.out/manifest.json', JSON.stringify(asm.manifest)); rewriteManifestVersionToOurs(cdk_build_tools_1.bockfs.path('/home/project/cdk.out')); } /** * Rewrite the manifest schema version in the given directory to match the version number we expect (probably `0.0.0`). * * Why do we have to do this? Because `aws-cdk-lib` has its own version of `cloud-assembly-schema`, * which will have real version `38.0.0`, different from the `0.0.0` version of `cloud-assembly-schema` that the CLI * uses. * * If we don't do this, every time we load a Cloud Assembly the code will say "Maximum schema version supported is 0.x.x, but found 30.0.0".0 */ function rewriteManifestVersionToOurs(dir = 'cdk.out') { (0, assembly_versions_1.rewriteManifestVersion)(dir, cxschema.Manifest.version()); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhlYy50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZXhlYy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsaUNBQWlDO0FBQ2pDLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7QUFDM0IsOERBQWtEO0FBQ2xELDJEQUEyRDtBQUMzRCxtQ0FBbUM7QUFDbkMsaUNBQWlDO0FBQ2pDLCtCQUErQjtBQUMvQixxREFBNkM7QUFDN0MsbURBQXVEO0FBQ3ZELHlFQUFpRTtBQUNqRSxrQ0FBdUM7QUFDdkMsbUVBQXVEO0FBQ3ZELCtDQUFtRDtBQUNuRCxzREFBbUQ7QUFDbkQsMkRBQTZEO0FBQzdELCtEQUEwRDtBQUUxRCxJQUFJLFdBQTRCLENBQUM7QUFDakMsSUFBSSxNQUFxQixDQUFDO0FBQzFCLFVBQVUsQ0FBQyxHQUFHLEVBQUU7SUFDZCx1QkFBUyxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7SUFFeEMsV0FBVyxHQUFHLElBQUksMEJBQWUsRUFBRSxDQUFDO0lBQ3BDLE1BQU0sR0FBRyxJQUFJLGtDQUFhLEVBQUUsQ0FBQztJQUU3QixNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBRTNDLHFDQUFxQztJQUNyQyxJQUFBLHdCQUFNLEVBQUM7UUFDTCxnQ0FBZ0MsRUFBRSxXQUFXO1FBQzdDLDBCQUEwQixFQUFFLFdBQVc7UUFDdkMsZ0NBQWdDLEVBQUUsV0FBVztLQUM5QyxDQUFDLENBQUM7SUFDSCx3QkFBTSxDQUFDLGdCQUFnQixDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ3pDLHdCQUFNLENBQUMsVUFBVSxDQUFDLGdDQUFnQyxDQUFDLENBQUM7SUFDcEQsd0JBQU0sQ0FBQyxVQUFVLENBQUMsaUNBQWlDLENBQUMsQ0FBQztBQUN2RCxDQUFDLENBQUMsQ0FBQztBQUVILFNBQVMsQ0FBQyxHQUFHLEVBQUU7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LENBQUMsTUFBTSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFN0Isa0NBQWtDO0lBQ2xDLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxlQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDckQsTUFBTSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7QUFDdkIsQ0FBQyxDQUFDLENBQUM7QUFFSCxTQUFTLG1CQUFtQjtJQUMxQixNQUFNLEdBQUcsR0FBRyxJQUFBLG1CQUFZLEVBQUM7UUFDdkIsTUFBTSxFQUFFLEVBQUU7S0FDWCxDQUFDLENBQUM7SUFDSCx3QkFBTSxDQUFDLEtBQUssQ0FBQyxxQ0FBcUMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQ2xGLDRCQUE0QixDQUFDLHdCQUFNLENBQUMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLENBQUMsQ0FBQztBQUNyRSxDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxTQUFTLDRCQUE0QixDQUFDLE1BQWMsU0FBUztJQUMzRCxJQUFBLDBDQUFzQixFQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7QUFDM0QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9vcmRlciAqL1xuamVzdC5tb2NrKCdjaGlsZF9wcm9jZXNzJyk7XG5pbXBvcnQgeyBib2NrZnMgfSBmcm9tICdAYXdzLWNkay9jZGstYnVpbGQtdG9vbHMnO1xuaW1wb3J0ICogYXMgY3hzY2hlbWEgZnJvbSAnQGF3cy1jZGsvY2xvdWQtYXNzZW1ibHktc2NoZW1hJztcbmltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBzZW12ZXIgZnJvbSAnc2VtdmVyJztcbmltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCB7IEltcG9ydE1vY2sgfSBmcm9tICd0cy1tb2NrLWltcG9ydHMnO1xuaW1wb3J0IHsgZXhlY1Byb2dyYW0gfSBmcm9tICcuLi8uLi9saWIvYXBpL2N4YXBwL2V4ZWMnO1xuaW1wb3J0IHsgQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uLy4uL2xpYi9jbGkvdXNlci1jb25maWd1cmF0aW9uJztcbmltcG9ydCB7IHRlc3RBc3NlbWJseSB9IGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHsgbW9ja1NwYXduIH0gZnJvbSAnLi4vdXRpbC9tb2NrLWNoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgTW9ja1Nka1Byb3ZpZGVyIH0gZnJvbSAnLi4vdXRpbC9tb2NrLXNkayc7XG5pbXBvcnQgeyBSV0xvY2sgfSBmcm9tICcuLi8uLi9saWIvYXBpL3V0aWwvcndsb2NrJztcbmltcG9ydCB7IHJld3JpdGVNYW5pZmVzdFZlcnNpb24gfSBmcm9tICcuL2Fzc2VtYmx5LXZlcnNpb25zJztcbmltcG9ydCB7IENsaUlvSG9zdCB9IGZyb20gJy4uLy4uL2xpYi90b29sa2l0L2NsaS1pby1ob3N0JztcblxubGV0IHNka1Byb3ZpZGVyOiBNb2NrU2RrUHJvdmlkZXI7XG5sZXQgY29uZmlnOiBDb25maWd1cmF0aW9uO1xuYmVmb3JlRWFjaCgoKSA9PiB7XG4gIENsaUlvSG9zdC5pbnN0YW5jZSgpLmxvZ0xldmVsID0gJ2RlYnVnJztcblxuICBzZGtQcm92aWRlciA9IG5ldyBNb2NrU2RrUHJvdmlkZXIoKTtcbiAgY29uZmlnID0gbmV3IENvbmZpZ3VyYXRpb24oKTtcblxuICBjb25maWcuc2V0dGluZ3Muc2V0KFsnb3V0cHV0J10sICdjZGsub3V0Jyk7XG5cbiAgLy8gaW5zZXJ0IGNvbnRlbnRzIGluIGZha2UgZmlsZXN5c3RlbVxuICBib2NrZnMoe1xuICAgICcvaG9tZS9wcm9qZWN0L2Nsb3VkLWV4ZWN1dGFibGUnOiAnQVJCSVRSQVJZJyxcbiAgICAnL2hvbWUvcHJvamVjdC93aW5kb3dzLmpzJzogJ0FSQklUUkFSWScsXG4gICAgJ2hvbWUvcHJvamVjdC9leGVjdXRhYmxlLWFwcC5qcyc6ICdBUkJJVFJBUlknLFxuICB9KTtcbiAgYm9ja2ZzLndvcmtpbmdEaXJlY3RvcnkoJy9ob21lL3Byb2plY3QnKTtcbiAgYm9ja2ZzLmV4ZWN1dGFibGUoJy9ob21lL3Byb2plY3QvY2xvdWQtZXhlY3V0YWJsZScpO1xuICBib2NrZnMuZXhlY3V0YWJsZSgnL2hvbWUvcHJvamVjdC9leGVjdXRhYmxlLWFwcC5qcycpO1xufSk7XG5cbmFmdGVyRWFjaCgoKSA9PiB7XG4gIENsaUlvSG9zdC5pbnN0YW5jZSgpLmxvZ0xldmVsID0gJ2luZm8nO1xuXG4gIHNpbm9uLnJlc3RvcmUoKTtcbiAgYm9ja2ZzLnJlc3RvcmUoKTtcbn0pO1xuXG4vLyBXZSBuZWVkIHRvIGluY3JlYXNlIHRoZSBkZWZhdWx0IDVzIGplc3Rcbi8vIHRpbWVvdXQgZm9yIGFzeW5jIHRlc3RzIGJlY2F1c2UgdGhlICdleGVjUHJvZ3JhbScgaW52b2NhdGlvblxuLy8gbWlnaHQgdGFrZSBhIHdoaWxlIDpcXFxuY29uc3QgVEVOX1NFQ09ORF9USU1FT1VUID0gMTAwMDA7XG5cbmZ1bmN0aW9uIGNyZWF0ZUFwcCgpOiBjZGsuQXBwIHtcbiAgY29uc3QgYXBwID0gbmV3IGNkay5BcHAoeyBvdXRkaXI6ICdjZGsub3V0JyB9KTtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgY2RrLlN0YWNrKGFwcCwgJ1N0YWNrJyk7XG5cbiAgbmV3IGNkay5DZm5SZXNvdXJjZShzdGFjaywgJ1JvbGUnLCB7XG4gICAgdHlwZTogJ0FXUzo6SUFNOjpSb2xlJyxcbiAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICBSb2xlTmFtZTogJ1JvbGUnLFxuICAgIH0sXG4gIH0pO1xuXG4gIHJldHVybiBhcHA7XG59XG5cbnRlc3QoJ2NsaSB0aHJvd3Mgd2hlbiBtYW5pZmVzdCB2ZXJzaW9uID4gc2NoZW1hIHZlcnNpb24nLCBhc3luYyAoKSA9PiB7XG5cbiAgY29uc3QgYXBwID0gY3JlYXRlQXBwKCk7XG4gIGNvbnN0IGN1cnJlbnRTY2hlbWFWZXJzaW9uID0gY3hzY2hlbWEuTWFuaWZlc3QudmVyc2lvbigpO1xuICBjb25zdCBtb2NrTWFuaWZlc3RWZXJzaW9uID0gc2VtdmVyLmluYyhjdXJyZW50U2NoZW1hVmVyc2lvbiwgJ21ham9yJyk7XG5cbiAgLy8gdGhpcyBtb2NrIHdpbGwgY2F1c2UgdGhlIGZyYW1ld29yayB0byB1c2UgYSBncmVhdGVyIHNjaGVtYSB2ZXJzaW9uIHRoYW4gdGhlIHJlYWwgb25lLFxuICAvLyBhbmQgc2hvdWxkIGNhdXNlIHRoZSBDTEkgdG8gZmFpbC5cbiAgY29uc3QgbW9ja1ZlcnNpb25OdW1iZXIgPSBJbXBvcnRNb2NrLm1vY2tGdW5jdGlvbihjeHNjaGVtYS5NYW5pZmVzdCwgJ3ZlcnNpb24nLCBtb2NrTWFuaWZlc3RWZXJzaW9uKTtcbiAgdHJ5IHtcbiAgICBhcHAuc3ludGgoKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBtb2NrVmVyc2lvbk51bWJlci5yZXN0b3JlKCk7XG4gIH1cblxuICByZXdyaXRlTWFuaWZlc3RWZXJzaW9uKCdjZGsub3V0JywgYCR7bW9ja01hbmlmZXN0VmVyc2lvbn1gKTtcblxuICBjb25zdCBleHBlY3RlZEVycm9yID0gJ1RoaXMgQ0RLIENMSSBpcyBub3QgY29tcGF0aWJsZSB3aXRoIHRoZSBDREsgbGlicmFyeSB1c2VkIGJ5IHlvdXIgYXBwbGljYXRpb24uIFBsZWFzZSB1cGdyYWRlIHRoZSBDTEkgdG8gdGhlIGxhdGVzdCB2ZXJzaW9uLidcbiAgICArIGBcXG4oQ2xvdWQgYXNzZW1ibHkgc2NoZW1hIHZlcnNpb24gbWlzbWF0Y2g6IE1heGltdW0gc2NoZW1hIHZlcnNpb24gc3VwcG9ydGVkIGlzICR7c2VtdmVyLm1ham9yKGN1cnJlbnRTY2hlbWFWZXJzaW9uKX0ueC54LCBidXQgZm91bmQgJHttb2NrTWFuaWZlc3RWZXJzaW9ufSlgO1xuXG4gIGNvbmZpZy5zZXR0aW5ncy5zZXQoWydhcHAnXSwgJ2Nkay5vdXQnKTtcblxuICBhd2FpdCBleHBlY3QoZXhlY1Byb2dyYW0oc2RrUHJvdmlkZXIsIGNvbmZpZykpLnJlamVjdHMudG9FcXVhbChuZXcgRXJyb3IoZXhwZWN0ZWRFcnJvcikpO1xuXG59LCBURU5fU0VDT05EX1RJTUVPVVQpO1xuXG50ZXN0KCdjbGkgZG9lcyBub3QgdGhyb3cgd2hlbiBtYW5pZmVzdCB2ZXJzaW9uID0gc2NoZW1hIHZlcnNpb24nLCBhc3luYyAoKSA9PiB7XG5cbiAgY29uc3QgYXBwID0gY3JlYXRlQXBwKCk7XG4gIGFwcC5zeW50aCgpO1xuXG4gIHJld3JpdGVNYW5pZmVzdFZlcnNpb25Ub091cnMoKTtcblxuICBjb25maWcuc2V0dGluZ3Muc2V0KFsnYXBwJ10sICdjZGsub3V0Jyk7XG5cbiAgY29uc3QgeyBsb2NrIH0gPSBhd2FpdCBleGVjUHJvZ3JhbShzZGtQcm92aWRlciwgY29uZmlnKTtcbiAgYXdhaXQgbG9jay5yZWxlYXNlKCk7XG5cbn0sIFRFTl9TRUNPTkRfVElNRU9VVCk7XG5cbi8vIFdoeSBkbyB3ZSBoYXZlIHRvIGRvIHNvbWV0aGluZyBoZXJlIGF0IGFsbD8gQmVjYXVzZSBgYXdzLWNkay1saWJgIGhhcyBpdHMgb3duIHZlcnNpb24gb2YgYGNsb3VkLWFzc2VtYmx5LXNjaGVtYWAsXG4vLyB3aGljaCB3aWxsIGhhdmUgcmVhbCB2ZXJzaW9uIGAzOC4wLjBgLCBkaWZmZXJlbnQgZnJvbSB0aGUgYDAuMC4wYCB2ZXJzaW9uIG9mIGBjbG91ZC1hc3NlbWJseS1zY2hlbWFgIHRoYXQgdGhlIENMSVxuLy8gdXNlcy5cbi8vXG4vLyBTaW5jZSBvdXIgQ2xvdWQgQXNzZW1ibHkgU2NoZW1hIHZlcnNpb24gd2lsbCBiZSBgMC4wLjBgIGFuZCB0aGVyZSBpcyBubyBzdWNoIHRoaW5nIGFzIGAtMS4wLjBgLCB0aGlzIHRlc3QgZG9lc24ndFxuLy8gbWFrZSBhbnkgc2Vuc2UgYW55bW9yZS5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBqZXN0L25vLWRpc2FibGVkLXRlc3RzXG50ZXN0LnNraXAoJ2NsaSBkb2VzIG5vdCB0aHJvdyB3aGVuIG1hbmlmZXN0IHZlcnNpb24gPCBzY2hlbWEgdmVyc2lvbicsIGFzeW5jICgpID0+IHtcblxuICBjb25zdCBhcHAgPSBjcmVhdGVBcHAoKTtcbiAgY29uc3QgY3VycmVudFNjaGVtYVZlcnNpb24gPSBjeHNjaGVtYS5NYW5pZmVzdC52ZXJzaW9uKCk7XG5cbiAgYXBwLnN5bnRoKCk7XG5cbiAgcmV3cml0ZU1hbmlmZXN0VmVyc2lvblRvT3VycygpO1xuXG4gIGNvbmZpZy5zZXR0aW5ncy5zZXQoWydhcHAnXSwgJ2Nkay5vdXQnKTtcblxuICAvLyB0aGlzIG1vY2sgd2lsbCBjYXVzZSB0aGUgY2xpIHRvIHRoaW5rIGl0cyBleGVwY3RlZCBzY2hlbWEgdmVyc2lvbiBpc1xuICAvLyBncmVhdGVyIHRoYXQgdGhlIHZlcnNpb24gY3JlYXRlZCBpbiB0aGUgbWFuaWZlc3QsIHdoaWNoIGlzIHdoYXQgd2UgYXJlIHRlc3RpbmcgZm9yLlxuICBjb25zdCBtb2NrVmVyc2lvbk51bWJlciA9IEltcG9ydE1vY2subW9ja0Z1bmN0aW9uKGN4c2NoZW1hLk1hbmlmZXN0LCAndmVyc2lvbicsIHNlbXZlci5pbmMoY3VycmVudFNjaGVtYVZlcnNpb24sICdtYWpvcicpKTtcbiAgdHJ5IHtcbiAgICBjb25zdCB7IGxvY2sgfSA9IGF3YWl0IGV4ZWNQcm9ncmFtKHNka1Byb3ZpZGVyLCBjb25maWcpO1xuICAgIGF3YWl0IGxvY2sucmVsZWFzZSgpO1xuICB9IGZpbmFsbHkge1xuICAgIG1vY2tWZXJzaW9uTnVtYmVyLnJlc3RvcmUoKTtcbiAgfVxuXG59LCBURU5fU0VDT05EX1RJTUVPVVQpO1xuXG50ZXN0KCd2YWxpZGF0ZXMgLS1hcHAga2V5IGlzIHByZXNlbnQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOIG5vIGNvbmZpZyBrZXkgZm9yIGBhcHBgXG4gIGF3YWl0IGV4cGVjdChleGVjUHJvZ3JhbShzZGtQcm92aWRlciwgY29uZmlnKSkucmVqZWN0cy50b1Rocm93KFxuICAgICctLWFwcCBpcyByZXF1aXJlZCBlaXRoZXIgaW4gY29tbWFuZC1saW5lLCBpbiBjZGsuanNvbiBvciBpbiB+Ly5jZGsuanNvbicsXG4gICk7XG5cbn0pO1xuXG50ZXN0KCdieXBhc3NlcyBzeW50aCB3aGVuIGFwcCBwb2ludHMgdG8gYSBjbG91ZCBhc3NlbWJseScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uZmlnLnNldHRpbmdzLnNldChbJ2FwcCddLCAnY2RrLm91dCcpO1xuICB3cml0ZU91dHB1dEFzc2VtYmx5KCk7XG4gIHJld3JpdGVNYW5pZmVzdFZlcnNpb25Ub091cnMoKTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IHsgYXNzZW1ibHk6IGNsb3VkQXNzZW1ibHksIGxvY2sgfSA9IGF3YWl0IGV4ZWNQcm9ncmFtKHNka1Byb3ZpZGVyLCBjb25maWcpO1xuICBleHBlY3QoY2xvdWRBc3NlbWJseS5hcnRpZmFjdHMpLnRvRXF1YWwoW10pO1xuICBleHBlY3QoY2xvdWRBc3NlbWJseS5kaXJlY3RvcnkpLnRvRXF1YWwoJ2Nkay5vdXQnKTtcblxuICBhd2FpdCBsb2NrLnJlbGVhc2UoKTtcbn0pO1xuXG50ZXN0KCd0aGUgYXBwbGljYXRpb24gc2V0IGluIC0tYXBwIGlzIGV4ZWN1dGVkJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBjb25maWcuc2V0dGluZ3Muc2V0KFsnYXBwJ10sICdjbG91ZC1leGVjdXRhYmxlJyk7XG4gIG1vY2tTcGF3bih7XG4gICAgY29tbWFuZExpbmU6ICdjbG91ZC1leGVjdXRhYmxlJyxcbiAgICBzaWRlRWZmZWN0OiAoKSA9PiB3cml0ZU91dHB1dEFzc2VtYmx5KCksXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgeyBsb2NrIH0gPSBhd2FpdCBleGVjUHJvZ3JhbShzZGtQcm92aWRlciwgY29uZmlnKTtcbiAgYXdhaXQgbG9jay5yZWxlYXNlKCk7XG59KTtcblxudGVzdCgndGhlIGFwcGxpY2F0aW9uIHNldCBpbiAtLWFwcCBpcyBleGVjdXRlZCBhcy1pcyBpZiBpdCBjb250YWlucyBhIGZpbGVuYW1lIHRoYXQgZG9lcyBub3QgZXhpc3QnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGNvbmZpZy5zZXR0aW5ncy5zZXQoWydhcHAnXSwgJ2RvZXMtbm90LWV4aXN0Jyk7XG4gIG1vY2tTcGF3bih7XG4gICAgY29tbWFuZExpbmU6ICdkb2VzLW5vdC1leGlzdCcsXG4gICAgc2lkZUVmZmVjdDogKCkgPT4gd3JpdGVPdXRwdXRBc3NlbWJseSgpLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IHsgbG9jayB9ID0gYXdhaXQgZXhlY1Byb2dyYW0oc2RrUHJvdmlkZXIsIGNvbmZpZyk7XG4gIGF3YWl0IGxvY2sucmVsZWFzZSgpO1xufSk7XG5cbnRlc3QoJ3RoZSBhcHBsaWNhdGlvbiBzZXQgaW4gLS1hcHAgaXMgZXhlY3V0ZWQgd2l0aCBhcmd1bWVudHMnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGNvbmZpZy5zZXR0aW5ncy5zZXQoWydhcHAnXSwgJ2Nsb3VkLWV4ZWN1dGFibGUgYW4tYXJnJyk7XG4gIG1vY2tTcGF3bih7XG4gICAgY29tbWFuZExpbmU6ICdjbG91ZC1leGVjdXRhYmxlIGFuLWFyZycsXG4gICAgc2lkZUVmZmVjdDogKCkgPT4gd3JpdGVPdXRwdXRBc3NlbWJseSgpLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IHsgbG9jayB9ID0gYXdhaXQgZXhlY1Byb2dyYW0oc2RrUHJvdmlkZXIsIGNvbmZpZyk7XG4gIGF3YWl0IGxvY2sucmVsZWFzZSgpO1xufSk7XG5cbnRlc3QoJ2FwcGxpY2F0aW9uIHNldCBpbiAtLWFwcCBhcyBgKi5qc2AgYWx3YXlzIHVzZXMgaGFuZGxlciBvbiB3aW5kb3dzJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBzaW5vbi5zdHViKHByb2Nlc3MsICdwbGF0Zm9ybScpLnZhbHVlKCd3aW4zMicpO1xuICBjb25maWcuc2V0dGluZ3Muc2V0KFsnYXBwJ10sICd3aW5kb3dzLmpzJyk7XG4gIG1vY2tTcGF3bih7XG4gICAgY29tbWFuZExpbmU6IHByb2Nlc3MuZXhlY1BhdGggKyAnIHdpbmRvd3MuanMnLFxuICAgIHNpZGVFZmZlY3Q6ICgpID0+IHdyaXRlT3V0cHV0QXNzZW1ibHkoKSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCB7IGxvY2sgfSA9IGF3YWl0IGV4ZWNQcm9ncmFtKHNka1Byb3ZpZGVyLCBjb25maWcpO1xuICBhd2FpdCBsb2NrLnJlbGVhc2UoKTtcbn0pO1xuXG50ZXN0KCdhcHBsaWNhdGlvbiBzZXQgaW4gLS1hcHAgaXMgYCouanNgIGFuZCBleGVjdXRhYmxlJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBjb25maWcuc2V0dGluZ3Muc2V0KFsnYXBwJ10sICdleGVjdXRhYmxlLWFwcC5qcycpO1xuICBtb2NrU3Bhd24oe1xuICAgIGNvbW1hbmRMaW5lOiAnZXhlY3V0YWJsZS1hcHAuanMnLFxuICAgIHNpZGVFZmZlY3Q6ICgpID0+IHdyaXRlT3V0cHV0QXNzZW1ibHkoKSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCB7IGxvY2sgfSA9IGF3YWl0IGV4ZWNQcm9ncmFtKHNka1Byb3ZpZGVyLCBjb25maWcpO1xuICBhd2FpdCBsb2NrLnJlbGVhc2UoKTtcbn0pO1xuXG50ZXN0KCdjbGkgdGhyb3dzIHdoZW4gdGhlIGBidWlsZGAgc2NyaXB0IGZhaWxzJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBjb25maWcuc2V0dGluZ3Muc2V0KFsnYnVpbGQnXSwgJ2Zha2UtY29tbWFuZCcpO1xuICBtb2NrU3Bhd24oe1xuICAgIGNvbW1hbmRMaW5lOiAnZmFrZS1jb21tYW5kJyxcbiAgICBleGl0Q29kZTogMTI3LFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGV4cGVjdChleGVjUHJvZ3JhbShzZGtQcm92aWRlciwgY29uZmlnKSkucmVqZWN0cy50b0VxdWFsKG5ldyBFcnJvcignU3VicHJvY2VzcyBleGl0ZWQgd2l0aCBlcnJvciAxMjcnKSk7XG59LCBURU5fU0VDT05EX1RJTUVPVVQpO1xuXG50ZXN0KCdjbGkgZG9lcyBub3QgdGhyb3cgd2hlbiB0aGUgYGJ1aWxkYCBzY3JpcHQgc3VjY2VlZHMnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOXG4gIGNvbmZpZy5zZXR0aW5ncy5zZXQoWydidWlsZCddLCAncmVhbCBjb21tYW5kJyk7XG4gIGNvbmZpZy5zZXR0aW5ncy5zZXQoWydhcHAnXSwgJ2V4ZWN1dGFibGUtYXBwLmpzJyk7XG4gIG1vY2tTcGF3bih7XG4gICAgY29tbWFuZExpbmU6ICdyZWFsIGNvbW1hbmQnLCAvLyBgYnVpbGRgIGtleSBpcyBub3Qgc3BsaXQgb24gd2hpdGVzcGFjZVxuICAgIGV4aXRDb2RlOiAwLFxuICB9LFxuICB7XG4gICAgY29tbWFuZExpbmU6ICdleGVjdXRhYmxlLWFwcC5qcycsXG4gICAgc2lkZUVmZmVjdDogKCkgPT4gd3JpdGVPdXRwdXRBc3NlbWJseSgpLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IHsgbG9jayB9ID0gYXdhaXQgZXhlY1Byb2dyYW0oc2RrUHJvdmlkZXIsIGNvbmZpZyk7XG4gIGF3YWl0IGxvY2sucmVsZWFzZSgpO1xufSwgVEVOX1NFQ09ORF9USU1FT1VUKTtcblxudGVzdCgnY2xpIHJlbGVhc2VzIHRoZSBvdXRkaXIgbG9jayB3aGVuIGV4ZWNQcm9ncmFtIHRocm93cycsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uZmlnLnNldHRpbmdzLnNldChbJ2FwcCddLCAnY2xvdWQtZXhlY3V0YWJsZScpO1xuICBtb2NrU3Bhd24oe1xuICAgIGNvbW1hbmRMaW5lOiAnZmFrZS1jb21tYW5kJyxcbiAgICBleGl0Q29kZTogMTI3LFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGF3YWl0IGV4cGVjdChleGVjUHJvZ3JhbShzZGtQcm92aWRlciwgY29uZmlnKSkucmVqZWN0cy50b1Rocm93KCk7XG5cbiAgY29uc3Qgb3V0cHV0ID0gY29uZmlnLnNldHRpbmdzLmdldChbJ291dHB1dCddKTtcbiAgZXhwZWN0KG91dHB1dCkudG9CZURlZmluZWQoKTtcblxuICAvLyBjaGVjayB0aGF0IHRoZSBsb2NrIGlzIHJlbGVhc2VkXG4gIGNvbnN0IGxvY2sgPSBhd2FpdCBuZXcgUldMb2NrKG91dHB1dCkuYWNxdWlyZVdyaXRlKCk7XG4gIGF3YWl0IGxvY2sucmVsZWFzZSgpO1xufSk7XG5cbmZ1bmN0aW9uIHdyaXRlT3V0cHV0QXNzZW1ibHkoKSB7XG4gIGNvbnN0IGFzbSA9IHRlc3RBc3NlbWJseSh7XG4gICAgc3RhY2tzOiBbXSxcbiAgfSk7XG4gIGJvY2tmcy53cml0ZSgnL2hvbWUvcHJvamVjdC9jZGsub3V0L21hbmlmZXN0Lmpzb24nLCBKU09OLnN0cmluZ2lmeShhc20ubWFuaWZlc3QpKTtcbiAgcmV3cml0ZU1hbmlmZXN0VmVyc2lvblRvT3Vycyhib2NrZnMucGF0aCgnL2hvbWUvcHJvamVjdC9jZGsub3V0JykpO1xufVxuXG4vKipcbiAqIFJld3JpdGUgdGhlIG1hbmlmZXN0IHNjaGVtYSB2ZXJzaW9uIGluIHRoZSBnaXZlbiBkaXJlY3RvcnkgdG8gbWF0Y2ggdGhlIHZlcnNpb24gbnVtYmVyIHdlIGV4cGVjdCAocHJvYmFibHkgYDAuMC4wYCkuXG4gKlxuICogV2h5IGRvIHdlIGhhdmUgdG8gZG8gdGhpcz8gQmVjYXVzZSBgYXdzLWNkay1saWJgIGhhcyBpdHMgb3duIHZlcnNpb24gb2YgYGNsb3VkLWFzc2VtYmx5LXNjaGVtYWAsXG4gKiB3aGljaCB3aWxsIGhhdmUgcmVhbCB2ZXJzaW9uIGAzOC4wLjBgLCBkaWZmZXJlbnQgZnJvbSB0aGUgYDAuMC4wYCB2ZXJzaW9uIG9mIGBjbG91ZC1hc3NlbWJseS1zY2hlbWFgIHRoYXQgdGhlIENMSVxuICogdXNlcy5cbiAqXG4gKiBJZiB3ZSBkb24ndCBkbyB0aGlzLCBldmVyeSB0aW1lIHdlIGxvYWQgYSBDbG91ZCBBc3NlbWJseSB0aGUgY29kZSB3aWxsIHNheSBcIk1heGltdW0gc2NoZW1hIHZlcnNpb24gc3VwcG9ydGVkIGlzIDAueC54LCBidXQgZm91bmQgMzAuMC4wXCIuMFxuICovXG5mdW5jdGlvbiByZXdyaXRlTWFuaWZlc3RWZXJzaW9uVG9PdXJzKGRpcjogc3RyaW5nID0gJ2Nkay5vdXQnKSB7XG4gIHJld3JpdGVNYW5pZmVzdFZlcnNpb24oZGlyLCBjeHNjaGVtYS5NYW5pZmVzdC52ZXJzaW9uKCkpO1xufVxuIl19