UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

196 lines 26.9 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-lib/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 logging_1 = require("../../lib/logging"); const settings_1 = require("../../lib/settings"); const util_1 = require("../util"); const mock_child_process_1 = require("../util/mock-child_process"); const mock_sdk_1 = require("../util/mock-sdk"); let sdkProvider; let config; beforeEach(() => { (0, logging_1.setLogLevel)(logging_1.LogLevel.DEBUG); sdkProvider = new mock_sdk_1.MockSdkProvider(); config = new settings_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(() => { (0, logging_1.setLogLevel)(logging_1.LogLevel.DEFAULT); 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(); } 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 ${currentSchemaVersion}, 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(); config.settings.set(['app'], 'cdk.out'); const { lock } = await (0, exec_1.execProgram)(sdkProvider, config); await lock.release(); }, TEN_SECOND_TIMEOUT); test('cli does not throw when manifest version < schema version', async () => { const app = createApp(); const currentSchemaVersion = cxschema.Manifest.version(); app.synth(); 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(); // 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', exitCode: 0, }, { commandLine: 'executable-app.js', sideEffect: () => writeOutputAssembly(), }); // WHEN const { lock } = await (0, exec_1.execProgram)(sdkProvider, config); await lock.release(); }, TEN_SECOND_TIMEOUT); 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)); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhlYy50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZXhlYy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsaUNBQWlDO0FBQ2pDLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7QUFDM0IsOERBQWtEO0FBQ2xELDhEQUE4RDtBQUM5RCxtQ0FBbUM7QUFDbkMsaUNBQWlDO0FBQ2pDLCtCQUErQjtBQUMvQixxREFBNkM7QUFDN0MsbURBQXVEO0FBQ3ZELCtDQUEwRDtBQUMxRCxpREFBbUQ7QUFDbkQsa0NBQXVDO0FBQ3ZDLG1FQUF1RDtBQUN2RCwrQ0FBbUQ7QUFFbkQsSUFBSSxXQUE0QixDQUFDO0FBQ2pDLElBQUksTUFBcUIsQ0FBQztBQUMxQixVQUFVLENBQUMsR0FBRyxFQUFFO0lBQ2QsSUFBQSxxQkFBVyxFQUFDLGtCQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFNUIsV0FBVyxHQUFHLElBQUksMEJBQWUsRUFBRSxDQUFDO0lBQ3BDLE1BQU0sR0FBRyxJQUFJLHdCQUFhLEVBQUUsQ0FBQztJQUU3QixNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBRTNDLHFDQUFxQztJQUNyQyxJQUFBLHdCQUFNLEVBQUM7UUFDTCxnQ0FBZ0MsRUFBRSxXQUFXO1FBQzdDLDBCQUEwQixFQUFFLFdBQVc7UUFDdkMsZ0NBQWdDLEVBQUUsV0FBVztLQUM5QyxDQUFDLENBQUM7SUFDSCx3QkFBTSxDQUFDLGdCQUFnQixDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ3pDLHdCQUFNLENBQUMsVUFBVSxDQUFDLGdDQUFnQyxDQUFDLENBQUM7SUFDcEQsd0JBQU0sQ0FBQyxVQUFVLENBQUMsaUNBQWlDLENBQUMsQ0FBQztBQUN2RCxDQUFDLENBQUMsQ0FBQztBQUVILFNBQVMsQ0FBQyxHQUFHLEVBQUU7SUFDYixJQUFBLHFCQUFXLEVBQUMsa0JBQVEsQ0FB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O0tBQ3hDLENBQUMsQ0FBQztJQUVILE9BQU87SUFDUCxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsTUFBTSxJQUFBLGtCQUFXLEVBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3hELE1BQU0sSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO0FBQ3ZCLENBQUMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO0FBRXZCLFNBQVMsbUJBQW1CO0lBQzFCLE1BQU0sR0FBRyxHQUFHLElBQUEsbUJBQVksRUFBQztRQUN2QixNQUFNLEVBQUUsRUFBRTtLQUNYLENBQUMsQ0FBQztJQUNILHdCQUFNLENBQUMsS0FBSyxDQUFDLHFDQUFxQyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7QUFDcEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9vcmRlciAqL1xuamVzdC5tb2NrKCdjaGlsZF9wcm9jZXNzJyk7XG5pbXBvcnQgeyBib2NrZnMgfSBmcm9tICdAYXdzLWNkay9jZGstYnVpbGQtdG9vbHMnO1xuaW1wb3J0ICogYXMgY3hzY2hlbWEgZnJvbSAnYXdzLWNkay1saWIvY2xvdWQtYXNzZW1ibHktc2NoZW1hJztcbmltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBzZW12ZXIgZnJvbSAnc2VtdmVyJztcbmltcG9ydCAqIGFzIHNpbm9uIGZyb20gJ3Npbm9uJztcbmltcG9ydCB7IEltcG9ydE1vY2sgfSBmcm9tICd0cy1tb2NrLWltcG9ydHMnO1xuaW1wb3J0IHsgZXhlY1Byb2dyYW0gfSBmcm9tICcuLi8uLi9saWIvYXBpL2N4YXBwL2V4ZWMnO1xuaW1wb3J0IHsgTG9nTGV2ZWwsIHNldExvZ0xldmVsIH0gZnJvbSAnLi4vLi4vbGliL2xvZ2dpbmcnO1xuaW1wb3J0IHsgQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uLy4uL2xpYi9zZXR0aW5ncyc7XG5pbXBvcnQgeyB0ZXN0QXNzZW1ibHkgfSBmcm9tICcuLi91dGlsJztcbmltcG9ydCB7IG1vY2tTcGF3biB9IGZyb20gJy4uL3V0aWwvbW9jay1jaGlsZF9wcm9jZXNzJztcbmltcG9ydCB7IE1vY2tTZGtQcm92aWRlciB9IGZyb20gJy4uL3V0aWwvbW9jay1zZGsnO1xuXG5sZXQgc2RrUHJvdmlkZXI6IE1vY2tTZGtQcm92aWRlcjtcbmxldCBjb25maWc6IENvbmZpZ3VyYXRpb247XG5iZWZvcmVFYWNoKCgpID0+IHtcbiAgc2V0TG9nTGV2ZWwoTG9nTGV2ZWwuREVCVUcpO1xuXG4gIHNka1Byb3ZpZGVyID0gbmV3IE1vY2tTZGtQcm92aWRlcigpO1xuICBjb25maWcgPSBuZXcgQ29uZmlndXJhdGlvbigpO1xuXG4gIGNvbmZpZy5zZXR0aW5ncy5zZXQoWydvdXRwdXQnXSwgJ2Nkay5vdXQnKTtcblxuICAvLyBpbnNlcnQgY29udGVudHMgaW4gZmFrZSBmaWxlc3lzdGVtXG4gIGJvY2tmcyh7XG4gICAgJy9ob21lL3Byb2plY3QvY2xvdWQtZXhlY3V0YWJsZSc6ICdBUkJJVFJBUlknLFxuICAgICcvaG9tZS9wcm9qZWN0L3dpbmRvd3MuanMnOiAnQVJCSVRSQVJZJyxcbiAgICAnaG9tZS9wcm9qZWN0L2V4ZWN1dGFibGUtYXBwLmpzJzogJ0FSQklUUkFSWScsXG4gIH0pO1xuICBib2NrZnMud29ya2luZ0RpcmVjdG9yeSgnL2hvbWUvcHJvamVjdCcpO1xuICBib2NrZnMuZXhlY3V0YWJsZSgnL2hvbWUvcHJvamVjdC9jbG91ZC1leGVjdXRhYmxlJyk7XG4gIGJvY2tmcy5leGVjdXRhYmxlKCcvaG9tZS9wcm9qZWN0L2V4ZWN1dGFibGUtYXBwLmpzJyk7XG59KTtcblxuYWZ0ZXJFYWNoKCgpID0+IHtcbiAgc2V0TG9nTGV2ZWwoTG9nTGV2ZWwuREVGQVVMVCk7XG5cbiAgc2lub24ucmVzdG9yZSgpO1xuICBib2NrZnMucmVzdG9yZSgpO1xufSk7XG5cbi8vIFdlIG5lZWQgdG8gaW5jcmVhc2UgdGhlIGRlZmF1bHQgNXMgamVzdFxuLy8gdGltZW91dCBmb3IgYXN5bmMgdGVzdHMgYmVjYXVzZSB0aGUgJ2V4ZWNQcm9ncmFtJyBpbnZvY2F0aW9uXG4vLyBtaWdodCB0YWtlIGEgd2hpbGUgOlxcXG5jb25zdCBURU5fU0VDT05EX1RJTUVPVVQgPSAxMDAwMDtcblxuZnVuY3Rpb24gY3JlYXRlQXBwKCk6IGNkay5BcHAge1xuICBjb25zdCBhcHAgPSBuZXcgY2RrLkFwcCh7IG91dGRpcjogJ2Nkay5vdXQnIH0pO1xuICBjb25zdCBzdGFjayA9IG5ldyBjZGsuU3RhY2soYXBwLCAnU3RhY2snKTtcblxuICBuZXcgY2RrLkNmblJlc291cmNlKHN0YWNrLCAnUm9sZScsIHtcbiAgICB0eXBlOiAnQVdTOjpJQU06OlJvbGUnLFxuICAgIHByb3BlcnRpZXM6IHtcbiAgICAgIFJvbGVOYW1lOiAnUm9sZScsXG4gICAgfSxcbiAgfSk7XG5cbiAgcmV0dXJuIGFwcDtcbn1cblxudGVzdCgnY2xpIHRocm93cyB3aGVuIG1hbmlmZXN0IHZlcnNpb24gPiBzY2hlbWEgdmVyc2lvbicsIGFzeW5jICgpID0+IHtcblxuICBjb25zdCBhcHAgPSBjcmVhdGVBcHAoKTtcbiAgY29uc3QgY3VycmVudFNjaGVtYVZlcnNpb24gPSBjeHNjaGVtYS5NYW5pZmVzdC52ZXJzaW9uKCk7XG4gIGNvbnN0IG1vY2tNYW5pZmVzdFZlcnNpb24gPSBzZW12ZXIuaW5jKGN1cnJlbnRTY2hlbWFWZXJzaW9uLCAnbWFqb3InKTtcblxuICAvLyB0aGlzIG1vY2sgd2lsbCBjYXVzZSB0aGUgZnJhbWV3b3JrIHRvIHVzZSBhIGdyZWF0ZXIgc2NoZW1hIHZlcnNpb24gdGhhbiB0aGUgcmVhbCBvbmUsXG4gIC8vIGFuZCBzaG91bGQgY2F1c2UgdGhlIENMSSB0byBmYWlsLlxuICBjb25zdCBtb2NrVmVyc2lvbk51bWJlciA9IEltcG9ydE1vY2subW9ja0Z1bmN0aW9uKGN4c2NoZW1hLk1hbmlmZXN0LCAndmVyc2lvbicsIG1vY2tNYW5pZmVzdFZlcnNpb24pO1xuICB0cnkge1xuICAgIGFwcC5zeW50aCgpO1xuICB9IGZpbmFsbHkge1xuICAgIG1vY2tWZXJzaW9uTnVtYmVyLnJlc3RvcmUoKTtcbiAgfVxuXG4gIGNvbnN0IGV4cGVjdGVkRXJyb3IgPSAnVGhpcyBDREsgQ0xJIGlzIG5vdCBjb21wYXRpYmxlIHdpdGggdGhlIENESyBsaWJyYXJ5IHVzZWQgYnkgeW91ciBhcHBsaWNhdGlvbi4gUGxlYXNlIHVwZ3JhZGUgdGhlIENMSSB0byB0aGUgbGF0ZXN0IHZlcnNpb24uJ1xuICAgICsgYFxcbihDbG91ZCBhc3NlbWJseSBzY2hlbWEgdmVyc2lvbiBtaXNtYXRjaDogTWF4aW11bSBzY2hlbWEgdmVyc2lvbiBzdXBwb3J0ZWQgaXMgJHtjdXJyZW50U2NoZW1hVmVyc2lvbn0sIGJ1dCBmb3VuZCAke21vY2tNYW5pZmVzdFZlcnNpb259KWA7XG5cbiAgY29uZmlnLnNldHRpbmdzLnNldChbJ2FwcCddLCAnY2RrLm91dCcpO1xuXG4gIGF3YWl0IGV4cGVjdChleGVjUHJvZ3JhbShzZGtQcm92aWRlciwgY29uZmlnKSkucmVqZWN0cy50b0VxdWFsKG5ldyBFcnJvcihleHBlY3RlZEVycm9yKSk7XG5cbn0sIFRFTl9TRUNPTkRfVElNRU9VVCk7XG5cbnRlc3QoJ2NsaSBkb2VzIG5vdCB0aHJvdyB3aGVuIG1hbmlmZXN0IHZlcnNpb24gPSBzY2hlbWEgdmVyc2lvbicsIGFzeW5jICgpID0+IHtcblxuICBjb25zdCBhcHAgPSBjcmVhdGVBcHAoKTtcbiAgYXBwLnN5bnRoKCk7XG5cbiAgY29uZmlnLnNldHRpbmdzLnNldChbJ2FwcCddLCAnY2RrLm91dCcpO1xuXG4gIGNvbnN0IHsgbG9jayB9ID0gYXdhaXQgZXhlY1Byb2dyYW0oc2RrUHJvdmlkZXIsIGNvbmZpZyk7XG4gIGF3YWl0IGxvY2sucmVsZWFzZSgpO1xuXG59LCBURU5fU0VDT05EX1RJTUVPVVQpO1xuXG50ZXN0KCdjbGkgZG9lcyBub3QgdGhyb3cgd2hlbiBtYW5pZmVzdCB2ZXJzaW9uIDwgc2NoZW1hIHZlcnNpb24nLCBhc3luYyAoKSA9PiB7XG5cbiAgY29uc3QgYXBwID0gY3JlYXRlQXBwKCk7XG4gIGNvbnN0IGN1cnJlbnRTY2hlbWFWZXJzaW9uID0gY3hzY2hlbWEuTWFuaWZlc3QudmVyc2lvbigpO1xuXG4gIGFwcC5zeW50aCgpO1xuXG4gIGNvbmZpZy5zZXR0aW5ncy5zZXQoWydhcHAnXSwgJ2Nkay5vdXQnKTtcblxuICAvLyB0aGlzIG1vY2sgd2lsbCBjYXVzZSB0aGUgY2xpIHRvIHRoaW5rIGl0cyBleGVwY3RlZCBzY2hlbWEgdmVyc2lvbiBpc1xuICAvLyBncmVhdGVyIHRoYXQgdGhlIHZlcnNpb24gY3JlYXRlZCBpbiB0aGUgbWFuaWZlc3QsIHdoaWNoIGlzIHdoYXQgd2UgYXJlIHRlc3RpbmcgZm9yLlxuICBjb25zdCBtb2NrVmVyc2lvbk51bWJlciA9IEltcG9ydE1vY2subW9ja0Z1bmN0aW9uKGN4c2NoZW1hLk1hbmlmZXN0LCAndmVyc2lvbicsIHNlbXZlci5pbmMoY3VycmVudFNjaGVtYVZlcnNpb24sICdtYWpvcicpKTtcbiAgdHJ5IHtcbiAgICBjb25zdCB7IGxvY2sgfSA9IGF3YWl0IGV4ZWNQcm9ncmFtKHNka1Byb3ZpZGVyLCBjb25maWcpO1xuICAgIGF3YWl0IGxvY2sucmVsZWFzZSgpO1xuICB9IGZpbmFsbHkge1xuICAgIG1vY2tWZXJzaW9uTnVtYmVyLnJlc3RvcmUoKTtcbiAgfVxuXG59LCBURU5fU0VDT05EX1RJTUVPVVQpO1xuXG50ZXN0KCd2YWxpZGF0ZXMgLS1hcHAga2V5IGlzIHByZXNlbnQnLCBhc3luYyAoKSA9PiB7XG4gIC8vIEdJVkVOIG5vIGNvbmZpZyBrZXkgZm9yIGBhcHBgXG4gIGF3YWl0IGV4cGVjdChleGVjUHJvZ3JhbShzZGtQcm92aWRlciwgY29uZmlnKSkucmVqZWN0cy50b1Rocm93KFxuICAgICctLWFwcCBpcyByZXF1aXJlZCBlaXRoZXIgaW4gY29tbWFuZC1saW5lLCBpbiBjZGsuanNvbiBvciBpbiB+Ly5jZGsuanNvbicsXG4gICk7XG5cbn0pO1xuXG50ZXN0KCdieXBhc3NlcyBzeW50aCB3aGVuIGFwcCBwb2ludHMgdG8gYSBjbG91ZCBhc3NlbWJseScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uZmlnLnNldHRpbmdzLnNldChbJ2FwcCddLCAnY2RrLm91dCcpO1xuICB3cml0ZU91dHB1dEFzc2VtYmx5KCk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCB7IGFzc2VtYmx5OiBjbG91ZEFzc2VtYmx5LCBsb2NrIH0gPSBhd2FpdCBleGVjUHJvZ3JhbShzZGtQcm92aWRlciwgY29uZmlnKTtcbiAgZXhwZWN0KGNsb3VkQXNzZW1ibHkuYXJ0aWZhY3RzKS50b0VxdWFsKFtdKTtcbiAgZXhwZWN0KGNsb3VkQXNzZW1ibHkuZGlyZWN0b3J5KS50b0VxdWFsKCdjZGsub3V0Jyk7XG5cbiAgYXdhaXQgbG9jay5yZWxlYXNlKCk7XG59KTtcblxudGVzdCgndGhlIGFwcGxpY2F0aW9uIHNldCBpbiAtLWFwcCBpcyBleGVjdXRlZCcsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uZmlnLnNldHRpbmdzLnNldChbJ2FwcCddLCAnY2xvdWQtZXhlY3V0YWJsZScpO1xuICBtb2NrU3Bhd24oe1xuICAgIGNvbW1hbmRMaW5lOiAnY2xvdWQtZXhlY3V0YWJsZScsXG4gICAgc2lkZUVmZmVjdDogKCkgPT4gd3JpdGVPdXRwdXRBc3NlbWJseSgpLFxuICB9KTtcblxuICAvLyBXSEVOXG4gIGNvbnN0IHsgbG9jayB9ID0gYXdhaXQgZXhlY1Byb2dyYW0oc2RrUHJvdmlkZXIsIGNvbmZpZyk7XG4gIGF3YWl0IGxvY2sucmVsZWFzZSgpO1xufSk7XG5cbnRlc3QoJ3RoZSBhcHBsaWNhdGlvbiBzZXQgaW4gLS1hcHAgaXMgZXhlY3V0ZWQgYXMtaXMgaWYgaXQgY29udGFpbnMgYSBmaWxlbmFtZSB0aGF0IGRvZXMgbm90IGV4aXN0JywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBjb25maWcuc2V0dGluZ3Muc2V0KFsnYXBwJ10sICdkb2VzLW5vdC1leGlzdCcpO1xuICBtb2NrU3Bhd24oe1xuICAgIGNvbW1hbmRMaW5lOiAnZG9lcy1ub3QtZXhpc3QnLFxuICAgIHNpZGVFZmZlY3Q6ICgpID0+IHdyaXRlT3V0cHV0QXNzZW1ibHkoKSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCB7IGxvY2sgfSA9IGF3YWl0IGV4ZWNQcm9ncmFtKHNka1Byb3ZpZGVyLCBjb25maWcpO1xuICBhd2FpdCBsb2NrLnJlbGVhc2UoKTtcbn0pO1xuXG50ZXN0KCd0aGUgYXBwbGljYXRpb24gc2V0IGluIC0tYXBwIGlzIGV4ZWN1dGVkIHdpdGggYXJndW1lbnRzJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBjb25maWcuc2V0dGluZ3Muc2V0KFsnYXBwJ10sICdjbG91ZC1leGVjdXRhYmxlIGFuLWFyZycpO1xuICBtb2NrU3Bhd24oe1xuICAgIGNvbW1hbmRMaW5lOiAnY2xvdWQtZXhlY3V0YWJsZSBhbi1hcmcnLFxuICAgIHNpZGVFZmZlY3Q6ICgpID0+IHdyaXRlT3V0cHV0QXNzZW1ibHkoKSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCB7IGxvY2sgfSA9IGF3YWl0IGV4ZWNQcm9ncmFtKHNka1Byb3ZpZGVyLCBjb25maWcpO1xuICBhd2FpdCBsb2NrLnJlbGVhc2UoKTtcbn0pO1xuXG50ZXN0KCdhcHBsaWNhdGlvbiBzZXQgaW4gLS1hcHAgYXMgYCouanNgIGFsd2F5cyB1c2VzIGhhbmRsZXIgb24gd2luZG93cycsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgc2lub24uc3R1Yihwcm9jZXNzLCAncGxhdGZvcm0nKS52YWx1ZSgnd2luMzInKTtcbiAgY29uZmlnLnNldHRpbmdzLnNldChbJ2FwcCddLCAnd2luZG93cy5qcycpO1xuICBtb2NrU3Bhd24oe1xuICAgIGNvbW1hbmRMaW5lOiBwcm9jZXNzLmV4ZWNQYXRoICsgJyB3aW5kb3dzLmpzJyxcbiAgICBzaWRlRWZmZWN0OiAoKSA9PiB3cml0ZU91dHB1dEFzc2VtYmx5KCksXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgeyBsb2NrIH0gPSBhd2FpdCBleGVjUHJvZ3JhbShzZGtQcm92aWRlciwgY29uZmlnKTtcbiAgYXdhaXQgbG9jay5yZWxlYXNlKCk7XG59KTtcblxudGVzdCgnYXBwbGljYXRpb24gc2V0IGluIC0tYXBwIGlzIGAqLmpzYCBhbmQgZXhlY3V0YWJsZScsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uZmlnLnNldHRpbmdzLnNldChbJ2FwcCddLCAnZXhlY3V0YWJsZS1hcHAuanMnKTtcbiAgbW9ja1NwYXduKHtcbiAgICBjb21tYW5kTGluZTogJ2V4ZWN1dGFibGUtYXBwLmpzJyxcbiAgICBzaWRlRWZmZWN0OiAoKSA9PiB3cml0ZU91dHB1dEFzc2VtYmx5KCksXG4gIH0pO1xuXG4gIC8vIFdIRU5cbiAgY29uc3QgeyBsb2NrIH0gPSBhd2FpdCBleGVjUHJvZ3JhbShzZGtQcm92aWRlciwgY29uZmlnKTtcbiAgYXdhaXQgbG9jay5yZWxlYXNlKCk7XG59KTtcblxudGVzdCgnY2xpIHRocm93cyB3aGVuIHRoZSBgYnVpbGRgIHNjcmlwdCBmYWlscycsIGFzeW5jICgpID0+IHtcbiAgLy8gR0lWRU5cbiAgY29uZmlnLnNldHRpbmdzLnNldChbJ2J1aWxkJ10sICdmYWtlLWNvbW1hbmQnKTtcbiAgbW9ja1NwYXduKHtcbiAgICBjb21tYW5kTGluZTogJ2Zha2UtY29tbWFuZCcsXG4gICAgZXhpdENvZGU6IDEyNyxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBhd2FpdCBleHBlY3QoZXhlY1Byb2dyYW0oc2RrUHJvdmlkZXIsIGNvbmZpZykpLnJlamVjdHMudG9FcXVhbChuZXcgRXJyb3IoJ1N1YnByb2Nlc3MgZXhpdGVkIHdpdGggZXJyb3IgMTI3JykpO1xufSwgVEVOX1NFQ09ORF9USU1FT1VUKTtcblxudGVzdCgnY2xpIGRvZXMgbm90IHRocm93IHdoZW4gdGhlIGBidWlsZGAgc2NyaXB0IHN1Y2NlZWRzJywgYXN5bmMgKCkgPT4ge1xuICAvLyBHSVZFTlxuICBjb25maWcuc2V0dGluZ3Muc2V0KFsnYnVpbGQnXSwgJ3JlYWwgY29tbWFuZCcpO1xuICBjb25maWcuc2V0dGluZ3Muc2V0KFsnYXBwJ10sICdleGVjdXRhYmxlLWFwcC5qcycpO1xuICBtb2NrU3Bhd24oe1xuICAgIGNvbW1hbmRMaW5lOiAncmVhbCBjb21tYW5kJywgLy8gYGJ1aWxkYCBrZXkgaXMgbm90IHNwbGl0IG9uIHdoaXRlc3BhY2VcbiAgICBleGl0Q29kZTogMCxcbiAgfSxcbiAge1xuICAgIGNvbW1hbmRMaW5lOiAnZXhlY3V0YWJsZS1hcHAuanMnLFxuICAgIHNpZGVFZmZlY3Q6ICgpID0+IHdyaXRlT3V0cHV0QXNzZW1ibHkoKSxcbiAgfSk7XG5cbiAgLy8gV0hFTlxuICBjb25zdCB7IGxvY2sgfSA9IGF3YWl0IGV4ZWNQcm9ncmFtKHNka1Byb3ZpZGVyLCBjb25maWcpO1xuICBhd2FpdCBsb2NrLnJlbGVhc2UoKTtcbn0sIFRFTl9TRUNPTkRfVElNRU9VVCk7XG5cbmZ1bmN0aW9uIHdyaXRlT3V0cHV0QXNzZW1ibHkoKSB7XG4gIGNvbnN0IGFzbSA9IHRlc3RBc3NlbWJseSh7XG4gICAgc3RhY2tzOiBbXSxcbiAgfSk7XG4gIGJvY2tmcy53cml0ZSgnL2hvbWUvcHJvamVjdC9jZGsub3V0L21hbmlmZXN0Lmpzb24nLCBKU09OLnN0cmluZ2lmeShhc20ubWFuaWZlc3QpKTtcbn1cbiJdfQ==