UNPKG

cdk8s-cli

Version:

This is the command line tool for Cloud Development Kit (CDK) for Kubernetes (cdk8s).

304 lines • 36.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.crdsArePresent = exports.isHelmImport = exports.isK8sImport = exports.deriveFileName = exports.hashAndEncode = exports.parseImports = exports.findConstructMetadata = exports.findManifests = exports.download = exports.safeParseYaml = exports.safeParseJson = exports.validateApp = exports.synthApp = exports.mkdtemp = exports.shell = exports.PREFIX_DELIM = void 0; const child_process_1 = require("child_process"); const crypto_1 = require("crypto"); const fs_1 = require("fs"); const http = __importStar(require("http")); const https = __importStar(require("https")); const os = __importStar(require("os")); const path = __importStar(require("path")); const url_1 = require("url"); const fs = __importStar(require("fs-extra")); const yaml = __importStar(require("yaml")); const crds_dev_1 = require("./import/crds-dev"); const validation_1 = require("./plugins/validation"); exports.PREFIX_DELIM = ':='; async function shell(program, args = [], options = {}) { var _a, _b; const command = `"${program} ${args.join(' ')}" at ${path.resolve((_b = (_a = options.cwd) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '.')}`; return new Promise((ok, ko) => { var _a; const child = (0, child_process_1.spawn)(program, args, { stdio: ['inherit', 'pipe', 'inherit'], ...options }); const data = new Array(); (_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on('data', chunk => data.push(chunk)); child.once('error', err => ko(new Error(`command ${command} failed: ${err}`))); child.once('exit', code => { if (code === 0) { return ok(Buffer.concat(data).toString('utf-8')); } else { return ko(new Error(`command ${command} returned a non-zero exit code ${code}`)); } }); }); } exports.shell = shell; async function mkdtemp(closure) { const workdir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk8s-')); try { await closure(workdir); } finally { await fs.remove(workdir); } } exports.mkdtemp = mkdtemp; async function synthApp(command, outdir, stdout, metadata) { var _a; if (!stdout) { console.log('Synthesizing application'); } await shell(command, [], { shell: true, env: { ...process.env, CDK8S_OUTDIR: outdir, // record metadata so that the validation report // has contruct aware context. CDK8S_RECORD_CONSTRUCT_METADATA: (_a = process.env.CDK8S_RECORD_CONSTRUCT_METADATA) !== null && _a !== void 0 ? _a : (metadata ? 'true' : 'false'), }, }); if (!await fs.pathExists(outdir)) { console.error(`ERROR: synthesis failed, app expected to create "${outdir}"`); process.exit(1); } let found = false; const yamlFiles = await findManifests(outdir); if (yamlFiles === null || yamlFiles === void 0 ? void 0 : yamlFiles.length) { if (!stdout) { for (const yamlFile of yamlFiles) { console.log(` - ${yamlFile}`); } } found = true; } if (!found) { console.error('No manifests synthesized'); } const constructMetadata = findConstructMetadata(outdir); return { manifests: yamlFiles, constructMetadata }; } exports.synthApp = synthApp; async function validateApp(app, stdout, validations, pluginManager, reportsFile) { const validators = []; for (const validation of validations) { const { plugin, context } = validation_1.ValidationPlugin.load(validation, app, stdout, pluginManager); validators.push({ plugin, context }); } const reports = []; let success = true; console.log('Performing validations'); for (const validator of validators) { await validator.plugin.validate(validator.context); const report = validator.context.report; success = success && report.success; reports.push(report); } console.log('Validations finished'); // now we can print them. we don't incrementally print // so to not clutter the terminal in case of errors. for (const report of reports) { console.log(''); console.log(report.toString()); console.log(''); } if (reportsFile) { if (fs.existsSync(reportsFile)) { throw new Error(`Unable to write validation reports file. Already exists: ${reportsFile}`); } // write the reports in JSON to a file fs.writeFileSync(reportsFile, JSON.stringify({ reports: reports.map(r => r.toJson()), }, null, 2)); } // exit with failure if any report resulted in a failure if (!success) { console.error('Validation failed. See above reports for details'); process.exit(2); } console.log('Validations ended succesfully'); } exports.validateApp = validateApp; function safeParseJson(text, reviver) { const json = JSON.parse(text); reviver.sanitize(json); return json; } exports.safeParseJson = safeParseJson; function safeParseYaml(text, reviver) { // parseAllDocuments doesnt accept a reviver // so we first parse normally and than transform // to JS using the reviver. const parsed = yaml.parseAllDocuments(text); const docs = []; for (const doc of parsed) { const json = doc.toJS(); reviver.sanitize(json); docs.push(json); } return docs; } exports.safeParseYaml = safeParseYaml; async function download(url) { let client; const proto = (0, url_1.parse)(url).protocol; if (!proto || proto === 'file:') { return fs.readFile(url, 'utf-8'); } switch (proto) { case 'https:': client = https; break; case 'http:': client = http; break; default: throw new Error(`unsupported protocol ${proto}`); } return new Promise((ok, ko) => { const req = client.get(url, res => { switch (res.statusCode) { case 200: { const data = new Array(); res.on('data', chunk => data.push(chunk)); res.once('end', () => ok(Buffer.concat(data).toString('utf-8'))); res.once('error', ko); break; } case 301: case 302: { if (res.headers.location) { ok(download(res.headers.location)); } break; } default: { ko(new Error(`${res.statusMessage}: ${url}`)); } } }); req.once('error', ko); req.end(); }); } exports.download = download; async function findManifests(directory) { // Ensure path is valid try { await fs_1.promises.access(directory); } catch { return []; } // Read Path contents const entries = await fs_1.promises.readdir(directory, { withFileTypes: true }); // Get files within the current directory const files = entries .filter(file => (!file.isDirectory() && file.name.endsWith('.yaml'))) .map(file => (directory + '/' + file.name)); // Get sub-folders within the current folder const folders = entries.filter(folder => folder.isDirectory()); for (const folder of folders) { files.push(...await findManifests(`${directory}/${folder.name}`)); } return files; } exports.findManifests = findManifests; function findConstructMetadata(directory) { // this file is optionally created during synthesis const p = path.join(directory, 'construct-metadata.json'); return fs.existsSync(p) ? p : undefined; } exports.findConstructMetadata = findConstructMetadata; function parseImports(spec) { const splitImport = spec.split(exports.PREFIX_DELIM); // k8s@x.y.z // crd.yaml // url.com/crd.yaml if (splitImport.length === 1) { return { source: spec, }; } // crd:=crd.yaml // crd:=url.com/crd.yaml if (splitImport.length === 2) { return { moduleNamePrefix: splitImport[0], source: splitImport[1], }; } throw new Error('Unable to parse import specification. Syntax is [NAME:=]SPEC'); } exports.parseImports = parseImports; function hashAndEncode(input, algorithm = 'sha256', encoding = 'hex') { const hash = (0, crypto_1.createHash)(algorithm); hash.update(input); return hash.digest(encoding); } exports.hashAndEncode = hashAndEncode; function deriveFileName(url) { const devUrl = (0, crds_dev_1.matchCrdsDevUrl)(url); let filename = undefined; if (devUrl) { const lastIndexOfSlash = devUrl.lastIndexOf('/'); const lastIndexOfAt = devUrl.lastIndexOf('@'); filename = (lastIndexOfSlash > 0 && lastIndexOfAt > 0) ? devUrl.slice(lastIndexOfSlash + 1, lastIndexOfAt) : undefined; } else { const lastIndexOfSlash = url.lastIndexOf('/'); const lastIndexOfYaml = url.lastIndexOf('.yaml') > 0 ? url.lastIndexOf('.yaml') : url.lastIndexOf('.yml'); filename = (lastIndexOfSlash > 0 && lastIndexOfYaml > 0) ? url.slice(lastIndexOfSlash + 1, lastIndexOfYaml) : undefined; } if (!filename) { // If the url if for a local file, then just encode the filename and not the entire path // Since path can depend on platform let file = (0, fs_1.existsSync)(url) ? path.basename(url) : url; filename = hashAndEncode(file); } return filename; } exports.deriveFileName = deriveFileName; function isK8sImport(value) { if (value !== 'k8s' && !value.startsWith('k8s@')) { return false; } return true; } exports.isK8sImport = isK8sImport; function isHelmImport(value) { if (!value.startsWith('helm:') && !value.includes(':=helm:')) { return false; } return true; } exports.isHelmImport = isHelmImport; function crdsArePresent(imprts) { return (imprts !== null && imprts !== void 0 ? imprts : []).some(imprt => (!isK8sImport(imprt) && !isHelmImport(imprt))); } exports.crdsArePresent = crdsArePresent; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaURBQW9EO0FBQ3BELG1DQUEwRDtBQUMxRCwyQkFBMEM7QUFDMUMsMkNBQTZCO0FBQzdCLDZDQUErQjtBQUMvQix1Q0FBeUI7QUFDekIsMkNBQTZCO0FBQzdCLDZCQUE0QjtBQUM1Qiw2Q0FBK0I7QUFDL0IsMkNBQTZCO0FBRTdCLGdEQUFvRDtBQUVwRCxxREFBeUc7QUFHNUYsUUFBQSxZQUFZLEdBQUcsSUFBSSxDQUFDO0FBRTFCLEtBQUssVUFBVSxLQUFLLENBQUMsT0FBZSxFQUFFLE9BQWlCLEVBQUUsRUFBRSxVQUF3QixFQUFHOztJQUMzRixNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBQSxNQUFBLE9BQU8sQ0FBQyxHQUFHLDBDQUFFLFFBQVEsRUFBRSxtQ0FBSSxHQUFHLENBQUMsRUFBRSxDQUFDO0lBQ3BHLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7O1FBQzVCLE1BQU0sS0FBSyxHQUFHLElBQUEscUJBQUssRUFBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsU0FBUyxFQUFFLE1BQU0sRUFBRSxTQUFTLENBQUMsRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDMUYsTUFBTSxJQUFJLEdBQUcsSUFBSSxLQUFLLEVBQVUsQ0FBQztRQUNqQyxNQUFBLEtBQUssQ0FBQyxNQUFNLDBDQUFFLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFFcEQsS0FBSyxDQUFDLElBQUks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Q2Q7SUFFRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFORCxvQ0FNQztBQUVELFNBQWdCLGNBQWMsQ0FBQyxNQUE0QjtJQUN6RCxPQUFPLENBQUMsTUFBTSxhQUFOLE1BQU0sY0FBTixNQUFNLEdBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDckYsQ0FBQztBQUZELHdDQUVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgc3Bhd24sIFNwYXduT3B0aW9ucyB9IGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgQmluYXJ5VG9UZXh0RW5jb2RpbmcsIGNyZWF0ZUhhc2ggfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgZXhpc3RzU3luYywgcHJvbWlzZXMgfSBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBodHRwIGZyb20gJ2h0dHAnO1xuaW1wb3J0ICogYXMgaHR0cHMgZnJvbSAnaHR0cHMnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IHBhcnNlIH0gZnJvbSAndXJsJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCAqIGFzIHlhbWwgZnJvbSAneWFtbCc7XG5pbXBvcnQgeyBJbXBvcnRTcGVjLCBWYWxpZGF0aW9uQ29uZmlnIH0gZnJvbSAnLi9jb25maWcnO1xuaW1wb3J0IHsgbWF0Y2hDcmRzRGV2VXJsIH0gZnJvbSAnLi9pbXBvcnQvY3Jkcy1kZXYnO1xuaW1wb3J0IHsgUGx1Z2luTWFuYWdlciB9IGZyb20gJy4vcGx1Z2lucy9fbWFuYWdlcic7XG5pbXBvcnQgeyBWYWxpZGF0aW9uUGx1Z2luLCBWYWxpZGF0aW9uQ29udGV4dCwgVmFsaWRhdGlvblJlcG9ydCwgVmFsaWRhdGlvbiB9IGZyb20gJy4vcGx1Z2lucy92YWxpZGF0aW9uJztcbmltcG9ydCB7IFNhZmVSZXZpdmVyIH0gZnJvbSAnLi9yZXZpdmVyJztcblxuZXhwb3J0IGNvbnN0IFBSRUZJWF9ERUxJTSA9ICc6PSc7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaGVsbChwcm9ncmFtOiBzdHJpbmcsIGFyZ3M6IHN0cmluZ1tdID0gW10sIG9wdGlvbnM6IFNwYXduT3B0aW9ucyA9IHsgfSk6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGNvbW1hbmQgPSBgXCIke3Byb2dyYW19ICR7YXJncy5qb2luKCcgJyl9XCIgYXQgJHtwYXRoLnJlc29sdmUob3B0aW9ucy5jd2Q/LnRvU3RyaW5nKCkgPz8gJy4nKX1gO1xuICByZXR1cm4gbmV3IFByb21pc2UoKG9rLCBrbykgPT4ge1xuICAgIGNvbnN0IGNoaWxkID0gc3Bhd24ocHJvZ3JhbSwgYXJncywgeyBzdGRpbzogWydpbmhlcml0JywgJ3BpcGUnLCAnaW5oZXJpdCddLCAuLi5vcHRpb25zIH0pO1xuICAgIGNvbnN0IGRhdGEgPSBuZXcgQXJyYXk8QnVmZmVyPigpO1xuICAgIGNoaWxkLnN0ZG91dD8ub24oJ2RhdGEnLCBjaHVuayA9PiBkYXRhLnB1c2goY2h1bmspKTtcblxuICAgIGNoaWxkLm9uY2UoJ2Vycm9yJywgZXJyID0+IGtvKG5ldyBFcnJvcihgY29tbWFuZCAke2NvbW1hbmR9IGZhaWxlZDogJHtlcnJ9YCkpKTtcbiAgICBjaGlsZC5vbmNlKCdleGl0JywgY29kZSA9PiB7XG4gICAgICBpZiAoY29kZSA9PT0gMCkge1xuICAgICAgICByZXR1cm4gb2soQnVmZmVyLmNvbmNhdChkYXRhKS50b1N0cmluZygndXRmLTgnKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4ga28obmV3IEVycm9yKGBjb21tYW5kICR7Y29tbWFuZH0gcmV0dXJuZWQgYSBub24temVybyBleGl0IGNvZGUgJHtjb2RlfWApKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBta2R0ZW1wKGNsb3N1cmU6IChkaXI6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPikge1xuICBjb25zdCB3b3JrZGlyID0gYXdhaXQgZnMubWtkdGVtcChwYXRoLmpvaW4ob3MudG1wZGlyKCksICdjZGs4cy0nKSk7XG4gIHRyeSB7XG4gICAgYXdhaXQgY2xvc3VyZSh3b3JrZGlyKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBmcy5yZW1vdmUod29ya2Rpcik7XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN5bnRoQXBwKGNvbW1hbmQ6IHN0cmluZywgb3V0ZGlyOiBzdHJpbmcsIHN0ZG91dDogYm9vbGVhbiwgbWV0YWRhdGE6IGJvb2xlYW4pOiBQcm9taXNlPFN5bnRoZXNpemVkQXBwPiB7XG4gIGlmICghc3Rkb3V0KSB7XG4gICAgY29uc29sZS5sb2coJ1N5bnRoZXNpemluZyBhcHBsaWNhdGlvbicpO1xuICB9XG4gIGF3YWl0IHNoZWxsKGNvbW1hbmQsIFtdLCB7XG4gICAgc2hlbGw6IHRydWUsXG4gICAgZW52OiB7XG4gICAgICAuLi5wcm9jZXNzLmVudixcbiAgICAgIENESzhTX09VVERJUjogb3V0ZGlyLFxuICAgICAgLy8gcmVjb3JkIG1ldGFkYXRhIHNvIHRoYXQgdGhlIHZhbGlkYXRpb24gcmVwb3J0XG4gICAgICAvLyBoYXMgY29udHJ1Y3QgYXdhcmUgY29udGV4dC5cbiAgICAgIENESzhTX1JFQ09SRF9DT05TVFJVQ1RfTUVUQURBVEE6IHByb2Nlc3MuZW52LkNESzhTX1JFQ09SRF9DT05TVFJVQ1RfTUVUQURBVEEgPz8gKG1ldGFkYXRhID8gJ3RydWUnIDogJ2ZhbHNlJyksXG4gICAgfSxcbiAgfSk7XG5cbiAgaWYgKCFhd2FpdCBmcy5wYXRoRXhpc3RzKG91dGRpcikpIHtcbiAgICBjb25zb2xlLmVycm9yKGBFUlJPUjogc3ludGhlc2lzIGZhaWxlZCwgYXBwIGV4cGVjdGVkIHRvIGNyZWF0ZSBcIiR7b3V0ZGlyfVwiYCk7XG4gICAgcHJvY2Vzcy5leGl0KDEpO1xuICB9XG5cbiAgbGV0IGZvdW5kID0gZmFsc2U7XG4gIGNvbnN0IHlhbWxGaWxlcyA9IGF3YWl0IGZpbmRNYW5pZmVzdHMob3V0ZGlyKTtcbiAgaWYgKHlhbWxGaWxlcz8ubGVuZ3RoKSB7XG4gICAgaWYgKCFzdGRvdXQpIHtcbiAgICAgIGZvciAoY29uc3QgeWFtbEZpbGUgb2YgeWFtbEZpbGVzKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGAgIC0gJHt5YW1sRmlsZX1gKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZm91bmQgPSB0cnVlO1xuICB9XG5cbiAgaWYgKCFmb3VuZCkge1xuICAgIGNvbnNvbGUuZXJyb3IoJ05vIG1hbmlmZXN0cyBzeW50aGVzaXplZCcpO1xuICB9XG5cbiAgY29uc3QgY29uc3RydWN0TWV0YWRhdGEgPSBmaW5kQ29uc3RydWN0TWV0YWRhdGEob3V0ZGlyKTtcblxuICByZXR1cm4geyBtYW5pZmVzdHM6IHlhbWxGaWxlcywgY29uc3RydWN0TWV0YWRhdGEgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHZhbGlkYXRlQXBwKFxuICBhcHA6IFN5bnRoZXNpemVkQXBwLFxuICBzdGRvdXQ6IGJvb2xlYW4sXG4gIHZhbGlkYXRpb25zOiBWYWxpZGF0aW9uQ29uZmlnW10sXG4gIHBsdWdpbk1hbmFnZXI6IFBsdWdpbk1hbmFnZXIsXG4gIHJlcG9ydHNGaWxlPzogc3RyaW5nKSB7XG5cbiAgY29uc3QgdmFsaWRhdG9yczogeyBwbHVnaW46IFZhbGlkYXRpb247IGNvbnRleHQ6IFZhbGlkYXRpb25Db250ZXh0fVtdID0gW107XG5cbiAgZm9yIChjb25zdCB2YWxpZGF0aW9uIG9mIHZhbGlkYXRpb25zKSB7XG4gICAgY29uc3QgeyBwbHVnaW4sIGNvbnRleHQgfSA9IFZhbGlkYXRpb25QbHVnaW4ubG9hZCh2YWxpZGF0aW9uLCBhcHAsIHN0ZG91dCwgcGx1Z2luTWFuYWdlcik7XG4gICAgdmFsaWRhdG9ycy5wdXNoKHsgcGx1Z2luLCBjb250ZXh0IH0pO1xuICB9XG5cbiAgY29uc3QgcmVwb3J0czogVmFsaWRhdGlvblJlcG9ydFtdID0gW107XG4gIGxldCBzdWNjZXNzID0gdHJ1ZTtcblxuICBjb25zb2xlLmxvZygnUGVyZm9ybWluZyB2YWxpZGF0aW9ucycpO1xuXG4gIGZvciAoY29uc3QgdmFsaWRhdG9yIG9mIHZhbGlkYXRvcnMpIHtcbiAgICBhd2FpdCB2YWxpZGF0b3IucGx1Z2luLnZhbGlkYXRlKHZhbGlkYXRvci5jb250ZXh0KTtcbiAgICBjb25zdCByZXBvcnQgPSB2YWxpZGF0b3IuY29udGV4dC5yZXBvcnQ7XG4gICAgc3VjY2VzcyA9IHN1Y2Nlc3MgJiYgcmVwb3J0LnN1Y2Nlc3M7XG4gICAgcmVwb3J0cy5wdXNoKHJlcG9ydCk7XG4gIH1cblxuICBjb25zb2xlLmxvZygnVmFsaWRhdGlvbnMgZmluaXNoZWQnKTtcblxuICAvLyBub3cgd2UgY2FuIHByaW50IHRoZW0uIHdlIGRvbid0IGluY3JlbWVudGFsbHkgcHJpbnRcbiAgLy8gc28gdG8gbm90IGNsdXR0ZXIgdGhlIHRlcm1pbmFsIGluIGNhc2Ugb2YgZXJyb3JzLlxuICBmb3IgKGNvbnN0IHJlcG9ydCBvZiByZXBvcnRzKSB7XG4gICAgY29uc29sZS5sb2coJycpO1xuICAgIGNvbnNvbGUubG9nKHJlcG9ydC50b1N0cmluZygpKTtcbiAgICBjb25zb2xlLmxvZygnJyk7XG4gIH1cblxuICBpZiAocmVwb3J0c0ZpbGUpIHtcblxuICAgIGlmIChmcy5leGlzdHNTeW5jKHJlcG9ydHNGaWxlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gd3JpdGUgdmFsaWRhdGlvbiByZXBvcnRzIGZpbGUuIEFscmVhZHkgZXhpc3RzOiAke3JlcG9ydHNGaWxlfWApO1xuICAgIH1cbiAgICAvLyB3cml0ZSB0aGUgcmVwb3J0cyBpbiBKU09OIHRvIGEgZmlsZVxuICAgIGZzLndyaXRlRmlsZVN5bmMocmVwb3J0c0ZpbGUsIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgIHJlcG9ydHM6IHJlcG9ydHMubWFwKHIgPT4gci50b0pzb24oKSksXG4gICAgfSwgbnVsbCwgMikpO1xuICB9XG5cbiAgLy8gZXhpdCB3aXRoIGZhaWx1cmUgaWYgYW55IHJlcG9ydCByZXN1bHRlZCBpbiBhIGZhaWx1cmVcbiAgaWYgKCFzdWNjZXNzKSB7XG4gICAgY29uc29sZS5lcnJvcignVmFsaWRhdGlvbiBmYWlsZWQuIFNlZSBhYm92ZSByZXBvcnRzIGZvciBkZXRhaWxzJyk7XG4gICAgcHJvY2Vzcy5leGl0KDIpO1xuICB9XG5cbiAgY29uc29sZS5sb2coJ1ZhbGlkYXRpb25zIGVuZGVkIHN1Y2Nlc2Z1bGx5Jyk7XG5cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNhZmVQYXJzZUpzb24odGV4dDogc3RyaW5nLCByZXZpdmVyOiBTYWZlUmV2aXZlcik6IGFueSB7XG4gIGNvbnN0IGpzb24gPSBKU09OLnBhcnNlKHRleHQpO1xuICByZXZpdmVyLnNhbml0aXplKGpzb24pO1xuICByZXR1cm4ganNvbjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNhZmVQYXJzZVlhbWwodGV4dDogc3RyaW5nLCByZXZpdmVyOiBTYWZlUmV2aXZlcik6IGFueVtdIHtcblxuICAvLyBwYXJzZUFsbERvY3VtZW50cyBkb2VzbnQgYWNjZXB0IGEgcmV2aXZlclxuICAvLyBzbyB3ZSBmaXJzdCBwYXJzZSBub3JtYWxseSBhbmQgdGhhbiB0cmFuc2Zvcm1cbiAgLy8gdG8gSlMgdXNpbmcgdGhlIHJldml2ZXIuXG4gIGNvbnN0IHBhcnNlZCA9IHlhbWwucGFyc2VBbGxEb2N1bWVudHModGV4dCk7XG4gIGNvbnN0IGRvY3MgPSBbXTtcbiAgZm9yIChjb25zdCBkb2Mgb2YgcGFyc2VkKSB7XG4gICAgY29uc3QganNvbiA9IGRvYy50b0pTKCk7XG4gICAgcmV2aXZlci5zYW5pdGl6ZShqc29uKTtcbiAgICBkb2NzLnB1c2goanNvbik7XG4gIH1cbiAgcmV0dXJuIGRvY3M7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb3dubG9hZCh1cmw6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG5cbiAgbGV0IGNsaWVudDogdHlwZW9mIGh0dHAgfCB0eXBlb2YgaHR0cHM7XG4gIGNvbnN0IHByb3RvID0gcGFyc2UodXJsKS5wcm90b2NvbDtcblxuICBpZiAoIXByb3RvIHx8IHByb3RvID09PSAnZmlsZTonKSB7XG4gICAgcmV0dXJuIGZzLnJlYWRGaWxlKHVybCwgJ3V0Zi04Jyk7XG4gIH1cblxuICBzd2l0Y2ggKHByb3RvKSB7XG4gICAgY2FzZSAnaHR0cHM6JzpcbiAgICAgIGNsaWVudCA9IGh0dHBzO1xuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlICdodHRwOic6XG4gICAgICBjbGllbnQgPSBodHRwO1xuICAgICAgYnJlYWs7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBwcm90b2NvbCAke3Byb3RvfWApO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlKChvaywga28pID0+IHtcbiAgICBjb25zdCByZXEgPSBjbGllbnQuZ2V0KHVybCwgcmVzID0+IHtcbiAgICAgIHN3aXRjaCAocmVzLnN0YXR1c0NvZGUpIHtcbiAgICAgICAgY2FzZSAyMDA6IHtcbiAgICAgICAgICBjb25zdCBkYXRhID0gbmV3IEFycmF5PEJ1ZmZlcj4oKTtcbiAgICAgICAgICByZXMub24oJ2RhdGEnLCBjaHVuayA9PiBkYXRhLnB1c2goY2h1bmspKTtcbiAgICAgICAgICByZXMub25jZSgnZW5kJywgKCkgPT4gb2soQnVmZmVyLmNvbmNhdChkYXRhKS50b1N0cmluZygndXRmLTgnKSkpO1xuICAgICAgICAgIHJlcy5vbmNlKCdlcnJvcicsIGtvKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGNhc2UgMzAxOlxuICAgICAgICBjYXNlIDMwMjoge1xuICAgICAgICAgIGlmIChyZXMuaGVhZGVycy5sb2NhdGlvbikge1xuICAgICAgICAgICAgb2soZG93bmxvYWQocmVzLmhlYWRlcnMubG9jYXRpb24pKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAga28obmV3IEVycm9yKGAke3Jlcy5zdGF0dXNNZXNzYWdlfTogJHt1cmx9YCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXEub25jZSgnZXJyb3InLCBrbyk7XG4gICAgcmVxLmVuZCgpO1xuICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZpbmRNYW5pZmVzdHMoZGlyZWN0b3J5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gIC8vIEVuc3VyZSBwYXRoIGlzIHZhbGlkXG4gIHRyeSB7XG4gICAgYXdhaXQgcHJvbWlzZXMuYWNjZXNzKGRpcmVjdG9yeSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8vIFJlYWQgUGF0aCBjb250ZW50c1xuICBjb25zdCBlbnRyaWVzID0gYXdhaXQgcHJvbWlzZXMucmVhZGRpcihkaXJlY3RvcnksIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KTtcblxuICAvLyBHZXQgZmlsZXMgd2l0aGluIHRoZSBjdXJyZW50IGRpcmVjdG9yeVxuICBjb25zdCBmaWxlcyA9IGVudHJpZXNcbiAgICAuZmlsdGVyKGZpbGUgPT4gKCFmaWxlLmlzRGlyZWN0b3J5KCkgJiYgZmlsZS5uYW1lLmVuZHNXaXRoKCcueWFtbCcpKSlcbiAgICAubWFwKGZpbGUgPT4gKGRpcmVjdG9yeSArICcvJyArIGZpbGUubmFtZSkpO1xuXG4gIC8vIEdldCBzdWItZm9sZGVycyB3aXRoaW4gdGhlIGN1cnJlbnQgZm9sZGVyXG4gIGNvbnN0IGZvbGRlcnMgPSBlbnRyaWVzLmZpbHRlcihmb2xkZXIgPT4gZm9sZGVyLmlzRGlyZWN0b3J5KCkpO1xuXG4gIGZvciAoY29uc3QgZm9sZGVyIG9mIGZvbGRlcnMpIHtcbiAgICBmaWxlcy5wdXNoKC4uLmF3YWl0IGZpbmRNYW5pZmVzdHMoYCR7ZGlyZWN0b3J5fS8ke2ZvbGRlci5uYW1lfWApKTtcbiAgfVxuXG4gIHJldHVybiBmaWxlcztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRDb25zdHJ1Y3RNZXRhZGF0YShkaXJlY3Rvcnk6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIC8vIHRoaXMgZmlsZSBpcyBvcHRpb25hbGx5IGNyZWF0ZWQgZHVyaW5nIHN5bnRoZXNpc1xuICBjb25zdCBwID0gcGF0aC5qb2luKGRpcmVjdG9yeSwgJ2NvbnN0cnVjdC1tZXRhZGF0YS5qc29uJyk7XG4gIHJldHVybiBmcy5leGlzdHNTeW5jKHApID8gcCA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2Ygc3ludGhlc2l6aW5nIGFuIGFwcGxpY2F0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN5bnRoZXNpemVkQXBwIHtcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2YgbWFuaWZlc3RzIHByb2R1Y2VkIGJ5IHRoZSBhcHAuXG4gICAqL1xuICByZWFkb25seSBtYW5pZmVzdHM6IHJlYWRvbmx5IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgY29uc3RydWN0IG1ldGFkYXRhIGZpbGUgKGlmIGV4aXN0cykuXG4gICAqL1xuICByZWFkb25seSBjb25zdHJ1Y3RNZXRhZGF0YT86IHN0cmluZztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlSW1wb3J0cyhzcGVjOiBzdHJpbmcpOiBJbXBvcnRTcGVjIHtcbiAgY29uc3Qgc3BsaXRJbXBvcnQgPSBzcGVjLnNwbGl0KFBSRUZJWF9ERUxJTSk7XG5cbiAgLy8gazhzQHgueS56XG4gIC8vIGNyZC55YW1sXG4gIC8vIHVybC5jb20vY3JkLnlhbWxcbiAgaWYgKHNwbGl0SW1wb3J0Lmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiB7XG4gICAgICBzb3VyY2U6IHNwZWMsXG4gICAgfTtcbiAgfVxuXG4gIC8vIGNyZDo9Y3JkLnlhbWxcbiAgLy8gY3JkOj11cmwuY29tL2NyZC55YW1sXG4gIGlmIChzcGxpdEltcG9ydC5sZW5ndGggPT09IDIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgbW9kdWxlTmFtZVByZWZpeDogc3BsaXRJbXBvcnRbMF0sXG4gICAgICBzb3VyY2U6IHNwbGl0SW1wb3J0WzFdLFxuICAgIH07XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBwYXJzZSBpbXBvcnQgc3BlY2lmaWNhdGlvbi4gU3ludGF4IGlzIFtOQU1FOj1dU1BFQycpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzaEFuZEVuY29kZShpbnB1dDogc3RyaW5nLCBhbGdvcml0aG06IHN0cmluZyA9ICdzaGEyNTYnLCBlbmNvZGluZzogQmluYXJ5VG9UZXh0RW5jb2RpbmcgPSAnaGV4Jyk6IHN0cmluZyB7XG4gIGNvbnN0IGhhc2ggPSBjcmVhdGVIYXNoKGFsZ29yaXRobSk7XG4gIGhhc2gudXBkYXRlKGlucHV0KTtcbiAgcmV0dXJuIGhhc2guZGlnZXN0KGVuY29kaW5nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlcml2ZUZpbGVOYW1lKHVybDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgZGV2VXJsID0gbWF0Y2hDcmRzRGV2VXJsKHVybCk7XG4gIGxldCBmaWxlbmFtZSA9IHVuZGVmaW5lZDtcblxuICBpZiAoZGV2VXJsKSB7XG4gICAgY29uc3QgbGFzdEluZGV4T2ZTbGFzaCA9IGRldlVybC5sYXN0SW5kZXhPZignLycpO1xuICAgIGNvbnN0IGxhc3RJbmRleE9mQXQgPSBkZXZVcmwubGFzdEluZGV4T2YoJ0AnKTtcbiAgICBmaWxlbmFtZSA9IChsYXN0SW5kZXhPZlNsYXNoID4gMCAmJiBsYXN0SW5kZXhPZkF0ID4gMCkgPyBkZXZVcmwuc2xpY2UobGFzdEluZGV4T2ZTbGFzaCsxLCBsYXN0SW5kZXhPZkF0KTogdW5kZWZpbmVkO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IGxhc3RJbmRleE9mU2xhc2ggPSB1cmwubGFzdEluZGV4T2YoJy8nKTtcbiAgICBjb25zdCBsYXN0SW5kZXhPZllhbWwgPSB1cmwubGFzdEluZGV4T2YoJy55YW1sJykgPiAwID8gdXJsLmxhc3RJbmRleE9mKCcueWFtbCcpIDogdXJsLmxhc3RJbmRleE9mKCcueW1sJyk7XG5cbiAgICBmaWxlbmFtZSA9IChsYXN0SW5kZXhPZlNsYXNoID4gMCAmJiBsYXN0SW5kZXhPZllhbWwgPiAwKSA/IHVybC5zbGljZShsYXN0SW5kZXhPZlNsYXNoKzEsIGxhc3RJbmRleE9mWWFtbCk6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGlmICghZmlsZW5hbWUpIHtcbiAgICAvLyBJZiB0aGUgdXJsIGlmIGZvciBhIGxvY2FsIGZpbGUsIHRoZW4ganVzdCBlbmNvZGUgdGhlIGZpbGVuYW1lIGFuZCBub3QgdGhlIGVudGlyZSBwYXRoXG4gICAgLy8gU2luY2UgcGF0aCBjYW4gZGVwZW5kIG9uIHBsYXRmb3JtXG4gICAgbGV0IGZpbGUgPSBleGlzdHNTeW5jKHVybCkgPyBwYXRoLmJhc2VuYW1lKHVybCkgOiB1cmw7XG5cbiAgICBmaWxlbmFtZSA9IGhhc2hBbmRFbmNvZGUoZmlsZSk7XG4gIH1cblxuICByZXR1cm4gZmlsZW5hbWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0s4c0ltcG9ydCh2YWx1ZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGlmICh2YWx1ZSAhPT0gJ2s4cycgJiYgIXZhbHVlLnN0YXJ0c1dpdGgoJ2s4c0AnKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNIZWxtSW1wb3J0KHZhbHVlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKCF2YWx1ZS5zdGFydHNXaXRoKCdoZWxtOicpICYmICF2YWx1ZS5pbmNsdWRlcygnOj1oZWxtOicpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmRzQXJlUHJlc2VudChpbXBydHM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gIHJldHVybiAoaW1wcnRzID8/IFtdKS5zb21lKGltcHJ0ID0+ICghaXNLOHNJbXBvcnQoaW1wcnQpICYmICFpc0hlbG1JbXBvcnQoaW1wcnQpKSk7XG59Il19