cdk8s-cli
Version:
This is the command line tool for Cloud Development Kit (CDK) for Kubernetes (cdk8s).
304 lines • 36.8 kB
JavaScript
;
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