cdk8s-cli
Version:
This is the command line tool for Cloud Development Kit (CDK) for Kubernetes (cdk8s).
301 lines • 36.4 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 = {}) {
const command = `"${program} ${args.join(' ')}" at ${path.resolve(options.cwd?.toString() ?? '.')}`;
return new Promise((ok, ko) => {
const child = (0, child_process_1.spawn)(program, args, { stdio: ['inherit', 'pipe', 'inherit'], ...options });
const data = new Array();
child.stdout?.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) {
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: process.env.CDK8S_RECORD_CONSTRUCT_METADATA ?? (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?.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 ?? []).some(imprt => (!isK8sImport(imprt) && !isHelmImport(imprt)));
}
exports.crdsArePresent = crdsArePresent;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy91dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsaURBQW9EO0FBQ3BELG1DQUEwRDtBQUMxRCwyQkFBMEM7QUFDMUMsMkNBQTZCO0FBQzdCLDZDQUErQjtBQUMvQix1Q0FBeUI7QUFDekIsMkNBQTZCO0FBQzdCLDZCQUE0QjtBQUM1Qiw2Q0FBK0I7QUFDL0IsMkNBQTZCO0FBRTdCLGdEQUFvRDtBQUVwRCxxREFBeUc7QUFHNUYsUUFBQSxZQUFZLEdBQUcsSUFBSSxDQUFDO0FBRTFCLEtBQUssVUFBVSxLQUFLLENBQUMsT0FBZSxFQUFFLE9BQWlCLEVBQUUsRUFBRSxVQUF3QixFQUFHO0lBQzNGLE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLFFBQVEsRUFBRSxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUM7SUFDcEcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtRQUM1QixNQUFNLEtBQUssR0FBRyxJQUFBLHFCQUFLLEVBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsU0FBUyxDQUFDLEVBQUUsR0FBRyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzFGLE1BQU0sSUFBSSxHQUFHLElBQUksS0FBSyxFQUFVLENBQUM7UUFDakMsS0FBSyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBRXBELEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcs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LFNBQWdCLGNBQWMsQ0FBQyxNQUE0QjtJQUN6RCxPQUFPLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ3JGLENBQUM7QUFGRCx3Q0FFQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNwYXduLCBTcGF3bk9wdGlvbnMgfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCB7IEJpbmFyeVRvVGV4dEVuY29kaW5nLCBjcmVhdGVIYXNoIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IGV4aXN0c1N5bmMsIHByb21pc2VzIH0gZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgaHR0cCBmcm9tICdodHRwJztcbmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ2h0dHBzJztcbmltcG9ydCAqIGFzIG9zIGZyb20gJ29zJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBwYXJzZSB9IGZyb20gJ3VybCc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgKiBhcyB5YW1sIGZyb20gJ3lhbWwnO1xuaW1wb3J0IHsgSW1wb3J0U3BlYywgVmFsaWRhdGlvbkNvbmZpZyB9IGZyb20gJy4vY29uZmlnJztcbmltcG9ydCB7IG1hdGNoQ3Jkc0RldlVybCB9IGZyb20gJy4vaW1wb3J0L2NyZHMtZGV2JztcbmltcG9ydCB7IFBsdWdpbk1hbmFnZXIgfSBmcm9tICcuL3BsdWdpbnMvX21hbmFnZXInO1xuaW1wb3J0IHsgVmFsaWRhdGlvblBsdWdpbiwgVmFsaWRhdGlvbkNvbnRleHQsIFZhbGlkYXRpb25SZXBvcnQsIFZhbGlkYXRpb24gfSBmcm9tICcuL3BsdWdpbnMvdmFsaWRhdGlvbic7XG5pbXBvcnQgeyBTYWZlUmV2aXZlciB9IGZyb20gJy4vcmV2aXZlcic7XG5cbmV4cG9ydCBjb25zdCBQUkVGSVhfREVMSU0gPSAnOj0nO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2hlbGwocHJvZ3JhbTogc3RyaW5nLCBhcmdzOiBzdHJpbmdbXSA9IFtdLCBvcHRpb25zOiBTcGF3bk9wdGlvbnMgPSB7IH0pOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBjb21tYW5kID0gYFwiJHtwcm9ncmFtfSAke2FyZ3Muam9pbignICcpfVwiIGF0ICR7cGF0aC5yZXNvbHZlKG9wdGlvbnMuY3dkPy50b1N0cmluZygpID8/ICcuJyl9YDtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChvaywga28pID0+IHtcbiAgICBjb25zdCBjaGlsZCA9IHNwYXduKHByb2dyYW0sIGFyZ3MsIHsgc3RkaW86IFsnaW5oZXJpdCcsICdwaXBlJywgJ2luaGVyaXQnXSwgLi4ub3B0aW9ucyB9KTtcbiAgICBjb25zdCBkYXRhID0gbmV3IEFycmF5PEJ1ZmZlcj4oKTtcbiAgICBjaGlsZC5zdGRvdXQ/Lm9uKCdkYXRhJywgY2h1bmsgPT4gZGF0YS5wdXNoKGNodW5rKSk7XG5cbiAgICBjaGlsZC5vbmNlKCdlcnJvcicsIGVyciA9PiBrbyhuZXcgRXJyb3IoYGNvbW1hbmQgJHtjb21tYW5kfSBmYWlsZWQ6ICR7ZXJyfWApKSk7XG4gICAgY2hpbGQub25jZSgnZXhpdCcsIGNvZGUgPT4ge1xuICAgICAgaWYgKGNvZGUgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIG9rKEJ1ZmZlci5jb25jYXQoZGF0YSkudG9TdHJpbmcoJ3V0Zi04JykpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGtvKG5ldyBFcnJvcihgY29tbWFuZCAke2NvbW1hbmR9IHJldHVybmVkIGEgbm9uLXplcm8gZXhpdCBjb2RlICR7Y29kZX1gKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWtkdGVtcChjbG9zdXJlOiAoZGlyOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD4pIHtcbiAgY29uc3Qgd29ya2RpciA9IGF3YWl0IGZzLm1rZHRlbXAocGF0aC5qb2luKG9zLnRtcGRpcigpLCAnY2RrOHMtJykpO1xuICB0cnkge1xuICAgIGF3YWl0IGNsb3N1cmUod29ya2Rpcik7XG4gIH0gZmluYWxseSB7XG4gICAgYXdhaXQgZnMucmVtb3ZlKHdvcmtkaXIpO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzeW50aEFwcChjb21tYW5kOiBzdHJpbmcsIG91dGRpcjogc3RyaW5nLCBzdGRvdXQ6IGJvb2xlYW4sIG1ldGFkYXRhOiBib29sZWFuKTogUHJvbWlzZTxTeW50aGVzaXplZEFwcD4ge1xuICBpZiAoIXN0ZG91dCkge1xuICAgIGNvbnNvbGUubG9nKCdTeW50aGVzaXppbmcgYXBwbGljYXRpb24nKTtcbiAgfVxuICBhd2FpdCBzaGVsbChjb21tYW5kLCBbXSwge1xuICAgIHNoZWxsOiB0cnVlLFxuICAgIGVudjoge1xuICAgICAgLi4ucHJvY2Vzcy5lbnYsXG4gICAgICBDREs4U19PVVRESVI6IG91dGRpcixcbiAgICAgIC8vIHJlY29yZCBtZXRhZGF0YSBzbyB0aGF0IHRoZSB2YWxpZGF0aW9uIHJlcG9ydFxuICAgICAgLy8gaGFzIGNvbnRydWN0IGF3YXJlIGNvbnRleHQuXG4gICAgICBDREs4U19SRUNPUkRfQ09OU1RSVUNUX01FVEFEQVRBOiBwcm9jZXNzLmVudi5DREs4U19SRUNPUkRfQ09OU1RSVUNUX01FVEFEQVRBID8/IChtZXRhZGF0YSA/ICd0cnVlJyA6ICdmYWxzZScpLFxuICAgIH0sXG4gIH0pO1xuXG4gIGlmICghYXdhaXQgZnMucGF0aEV4aXN0cyhvdXRkaXIpKSB7XG4gICAgY29uc29sZS5lcnJvcihgRVJST1I6IHN5bnRoZXNpcyBmYWlsZWQsIGFwcCBleHBlY3RlZCB0byBjcmVhdGUgXCIke291dGRpcn1cImApO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxuXG4gIGxldCBmb3VuZCA9IGZhbHNlO1xuICBjb25zdCB5YW1sRmlsZXMgPSBhd2FpdCBmaW5kTWFuaWZlc3RzKG91dGRpcik7XG4gIGlmICh5YW1sRmlsZXM/Lmxlbmd0aCkge1xuICAgIGlmICghc3Rkb3V0KSB7XG4gICAgICBmb3IgKGNvbnN0IHlhbWxGaWxlIG9mIHlhbWxGaWxlcykge1xuICAgICAgICBjb25zb2xlLmxvZyhgICAtICR7eWFtbEZpbGV9YCk7XG4gICAgICB9XG4gICAgfVxuICAgIGZvdW5kID0gdHJ1ZTtcbiAgfVxuXG4gIGlmICghZm91bmQpIHtcbiAgICBjb25zb2xlLmVycm9yKCdObyBtYW5pZmVzdHMgc3ludGhlc2l6ZWQnKTtcbiAgfVxuXG4gIGNvbnN0IGNvbnN0cnVjdE1ldGFkYXRhID0gZmluZENvbnN0cnVjdE1ldGFkYXRhKG91dGRpcik7XG5cbiAgcmV0dXJuIHsgbWFuaWZlc3RzOiB5YW1sRmlsZXMsIGNvbnN0cnVjdE1ldGFkYXRhIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2YWxpZGF0ZUFwcChcbiAgYXBwOiBTeW50aGVzaXplZEFwcCxcbiAgc3Rkb3V0OiBib29sZWFuLFxuICB2YWxpZGF0aW9uczogVmFsaWRhdGlvbkNvbmZpZ1tdLFxuICBwbHVnaW5NYW5hZ2VyOiBQbHVnaW5NYW5hZ2VyLFxuICByZXBvcnRzRmlsZT86IHN0cmluZykge1xuXG4gIGNvbnN0IHZhbGlkYXRvcnM6IHsgcGx1Z2luOiBWYWxpZGF0aW9uOyBjb250ZXh0OiBWYWxpZGF0aW9uQ29udGV4dCB9W10gPSBbXTtcblxuICBmb3IgKGNvbnN0IHZhbGlkYXRpb24gb2YgdmFsaWRhdGlvbnMpIHtcbiAgICBjb25zdCB7IHBsdWdpbiwgY29udGV4dCB9ID0gVmFsaWRhdGlvblBsdWdpbi5sb2FkKHZhbGlkYXRpb24sIGFwcCwgc3Rkb3V0LCBwbHVnaW5NYW5hZ2VyKTtcbiAgICB2YWxpZGF0b3JzLnB1c2goeyBwbHVnaW4sIGNvbnRleHQgfSk7XG4gIH1cblxuICBjb25zdCByZXBvcnRzOiBWYWxpZGF0aW9uUmVwb3J0W10gPSBbXTtcbiAgbGV0IHN1Y2Nlc3MgPSB0cnVlO1xuXG4gIGNvbnNvbGUubG9nKCdQZXJmb3JtaW5nIHZhbGlkYXRpb25zJyk7XG5cbiAgZm9yIChjb25zdCB2YWxpZGF0b3Igb2YgdmFsaWRhdG9ycykge1xuICAgIGF3YWl0IHZhbGlkYXRvci5wbHVnaW4udmFsaWRhdGUodmFsaWRhdG9yLmNvbnRleHQpO1xuICAgIGNvbnN0IHJlcG9ydCA9IHZhbGlkYXRvci5jb250ZXh0LnJlcG9ydDtcbiAgICBzdWNjZXNzID0gc3VjY2VzcyAmJiByZXBvcnQuc3VjY2VzcztcbiAgICByZXBvcnRzLnB1c2gocmVwb3J0KTtcbiAgfVxuXG4gIGNvbnNvbGUubG9nKCdWYWxpZGF0aW9ucyBmaW5pc2hlZCcpO1xuXG4gIC8vIG5vdyB3ZSBjYW4gcHJpbnQgdGhlbS4gd2UgZG9uJ3QgaW5jcmVtZW50YWxseSBwcmludFxuICAvLyBzbyB0byBub3QgY2x1dHRlciB0aGUgdGVybWluYWwgaW4gY2FzZSBvZiBlcnJvcnMuXG4gIGZvciAoY29uc3QgcmVwb3J0IG9mIHJlcG9ydHMpIHtcbiAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgY29uc29sZS5sb2cocmVwb3J0LnRvU3RyaW5nKCkpO1xuICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgfVxuXG4gIGlmIChyZXBvcnRzRmlsZSkge1xuXG4gICAgaWYgKGZzLmV4aXN0c1N5bmMocmVwb3J0c0ZpbGUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byB3cml0ZSB2YWxpZGF0aW9uIHJlcG9ydHMgZmlsZS4gQWxyZWFkeSBleGlzdHM6ICR7cmVwb3J0c0ZpbGV9YCk7XG4gICAgfVxuICAgIC8vIHdyaXRlIHRoZSByZXBvcnRzIGluIEpTT04gdG8gYSBmaWxlXG4gICAgZnMud3JpdGVGaWxlU3luYyhyZXBvcnRzRmlsZSwgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgcmVwb3J0czogcmVwb3J0cy5tYXAociA9PiByLnRvSnNvbigpKSxcbiAgICB9LCBudWxsLCAyKSk7XG4gIH1cblxuICAvLyBleGl0IHdpdGggZmFpbHVyZSBpZiBhbnkgcmVwb3J0IHJlc3VsdGVkIGluIGEgZmFpbHVyZVxuICBpZiAoIXN1Y2Nlc3MpIHtcbiAgICBjb25zb2xlLmVycm9yKCdWYWxpZGF0aW9uIGZhaWxlZC4gU2VlIGFib3ZlIHJlcG9ydHMgZm9yIGRldGFpbHMnKTtcbiAgICBwcm9jZXNzLmV4aXQoMik7XG4gIH1cblxuICBjb25zb2xlLmxvZygnVmFsaWRhdGlvbnMgZW5kZWQgc3VjY2VzZnVsbHknKTtcblxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2FmZVBhcnNlSnNvbih0ZXh0OiBzdHJpbmcsIHJldml2ZXI6IFNhZmVSZXZpdmVyKTogYW55IHtcbiAgY29uc3QganNvbiA9IEpTT04ucGFyc2UodGV4dCk7XG4gIHJldml2ZXIuc2FuaXRpemUoanNvbik7XG4gIHJldHVybiBqc29uO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2FmZVBhcnNlWWFtbCh0ZXh0OiBzdHJpbmcsIHJldml2ZXI6IFNhZmVSZXZpdmVyKTogYW55W10ge1xuXG4gIC8vIHBhcnNlQWxsRG9jdW1lbnRzIGRvZXNudCBhY2NlcHQgYSByZXZpdmVyXG4gIC8vIHNvIHdlIGZpcnN0IHBhcnNlIG5vcm1hbGx5IGFuZCB0aGFuIHRyYW5zZm9ybVxuICAvLyB0byBKUyB1c2luZyB0aGUgcmV2aXZlci5cbiAgY29uc3QgcGFyc2VkID0geWFtbC5wYXJzZUFsbERvY3VtZW50cyh0ZXh0KTtcbiAgY29uc3QgZG9jcyA9IFtdO1xuICBmb3IgKGNvbnN0IGRvYyBvZiBwYXJzZWQpIHtcbiAgICBjb25zdCBqc29uID0gZG9jLnRvSlMoKTtcbiAgICByZXZpdmVyLnNhbml0aXplKGpzb24pO1xuICAgIGRvY3MucHVzaChqc29uKTtcbiAgfVxuICByZXR1cm4gZG9jcztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRvd25sb2FkKHVybDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcblxuICBsZXQgY2xpZW50OiB0eXBlb2YgaHR0cCB8IHR5cGVvZiBodHRwcztcbiAgY29uc3QgcHJvdG8gPSBwYXJzZSh1cmwpLnByb3RvY29sO1xuXG4gIGlmICghcHJvdG8gfHwgcHJvdG8gPT09ICdmaWxlOicpIHtcbiAgICByZXR1cm4gZnMucmVhZEZpbGUodXJsLCAndXRmLTgnKTtcbiAgfVxuXG4gIHN3aXRjaCAocHJvdG8pIHtcbiAgICBjYXNlICdodHRwczonOlxuICAgICAgY2xpZW50ID0gaHR0cHM7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgJ2h0dHA6JzpcbiAgICAgIGNsaWVudCA9IGh0dHA7XG4gICAgICBicmVhaztcblxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHByb3RvY29sICR7cHJvdG99YCk7XG4gIH1cblxuICByZXR1cm4gbmV3IFByb21pc2UoKG9rLCBrbykgPT4ge1xuICAgIGNvbnN0IHJlcSA9IGNsaWVudC5nZXQodXJsLCByZXMgPT4ge1xuICAgICAgc3dpdGNoIChyZXMuc3RhdHVzQ29kZSkge1xuICAgICAgICBjYXNlIDIwMDoge1xuICAgICAgICAgIGNvbnN0IGRhdGEgPSBuZXcgQXJyYXk8QnVmZmVyPigpO1xuICAgICAgICAgIHJlcy5vbignZGF0YScsIGNodW5rID0+IGRhdGEucHVzaChjaHVuaykpO1xuICAgICAgICAgIHJlcy5vbmNlKCdlbmQnLCAoKSA9PiBvayhCdWZmZXIuY29uY2F0KGRhdGEpLnRvU3RyaW5nKCd1dGYtOCcpKSk7XG4gICAgICAgICAgcmVzLm9uY2UoJ2Vycm9yJywga28pO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgY2FzZSAzMDE6XG4gICAgICAgIGNhc2UgMzAyOiB7XG4gICAgICAgICAgaWYgKHJlcy5oZWFkZXJzLmxvY2F0aW9uKSB7XG4gICAgICAgICAgICBvayhkb3dubG9hZChyZXMuaGVhZGVycy5sb2NhdGlvbikpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgICBrbyhuZXcgRXJyb3IoYCR7cmVzLnN0YXR1c01lc3NhZ2V9OiAke3VybH1gKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJlcS5vbmNlKCdlcnJvcicsIGtvKTtcbiAgICByZXEuZW5kKCk7XG4gIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZE1hbmlmZXN0cyhkaXJlY3Rvcnk6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgLy8gRW5zdXJlIHBhdGggaXMgdmFsaWRcbiAgdHJ5IHtcbiAgICBhd2FpdCBwcm9taXNlcy5hY2Nlc3MoZGlyZWN0b3J5KTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLy8gUmVhZCBQYXRoIGNvbnRlbnRzXG4gIGNvbnN0IGVudHJpZXMgPSBhd2FpdCBwcm9taXNlcy5yZWFkZGlyKGRpcmVjdG9yeSwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pO1xuXG4gIC8vIEdldCBmaWxlcyB3aXRoaW4gdGhlIGN1cnJlbnQgZGlyZWN0b3J5XG4gIGNvbnN0IGZpbGVzID0gZW50cmllc1xuICAgIC5maWx0ZXIoZmlsZSA9PiAoIWZpbGUuaXNEaXJlY3RvcnkoKSAmJiBmaWxlLm5hbWUuZW5kc1dpdGgoJy55YW1sJykpKVxuICAgIC5tYXAoZmlsZSA9PiAoZGlyZWN0b3J5ICsgJy8nICsgZmlsZS5uYW1lKSk7XG5cbiAgLy8gR2V0IHN1Yi1mb2xkZXJzIHdpdGhpbiB0aGUgY3VycmVudCBmb2xkZXJcbiAgY29uc3QgZm9sZGVycyA9IGVudHJpZXMuZmlsdGVyKGZvbGRlciA9PiBmb2xkZXIuaXNEaXJlY3RvcnkoKSk7XG5cbiAgZm9yIChjb25zdCBmb2xkZXIgb2YgZm9sZGVycykge1xuICAgIGZpbGVzLnB1c2goLi4uYXdhaXQgZmluZE1hbmlmZXN0cyhgJHtkaXJlY3Rvcnl9LyR7Zm9sZGVyLm5hbWV9YCkpO1xuICB9XG5cbiAgcmV0dXJuIGZpbGVzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZmluZENvbnN0cnVjdE1ldGFkYXRhKGRpcmVjdG9yeTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgLy8gdGhpcyBmaWxlIGlzIG9wdGlvbmFsbHkgY3JlYXRlZCBkdXJpbmcgc3ludGhlc2lzXG4gIGNvbnN0IHAgPSBwYXRoLmpvaW4oZGlyZWN0b3J5LCAnY29uc3RydWN0LW1ldGFkYXRhLmpzb24nKTtcbiAgcmV0dXJuIGZzLmV4aXN0c1N5bmMocCkgPyBwIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJlc3VsdCBvZiBzeW50aGVzaXppbmcgYW4gYXBwbGljYXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3ludGhlc2l6ZWRBcHAge1xuXG4gIC8qKlxuICAgKiBUaGUgbGlzdCBvZiBtYW5pZmVzdHMgcHJvZHVjZWQgYnkgdGhlIGFwcC5cbiAgICovXG4gIHJlYWRvbmx5IG1hbmlmZXN0czogcmVhZG9ubHkgc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBjb25zdHJ1Y3QgbWV0YWRhdGEgZmlsZSAoaWYgZXhpc3RzKS5cbiAgICovXG4gIHJlYWRvbmx5IGNvbnN0cnVjdE1ldGFkYXRhPzogc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VJbXBvcnRzKHNwZWM6IHN0cmluZyk6IEltcG9ydFNwZWMge1xuICBjb25zdCBzcGxpdEltcG9ydCA9IHNwZWMuc3BsaXQoUFJFRklYX0RFTElNKTtcblxuICAvLyBrOHNAeC55LnpcbiAgLy8gY3JkLnlhbWxcbiAgLy8gdXJsLmNvbS9jcmQueWFtbFxuICBpZiAoc3BsaXRJbXBvcnQubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNvdXJjZTogc3BlYyxcbiAgICB9O1xuICB9XG5cbiAgLy8gY3JkOj1jcmQueWFtbFxuICAvLyBjcmQ6PXVybC5jb20vY3JkLnlhbWxcbiAgaWYgKHNwbGl0SW1wb3J0Lmxlbmd0aCA9PT0gMikge1xuICAgIHJldHVybiB7XG4gICAgICBtb2R1bGVOYW1lUHJlZml4OiBzcGxpdEltcG9ydFswXSxcbiAgICAgIHNvdXJjZTogc3BsaXRJbXBvcnRbMV0sXG4gICAgfTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIHBhcnNlIGltcG9ydCBzcGVjaWZpY2F0aW9uLiBTeW50YXggaXMgW05BTUU6PV1TUEVDJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNoQW5kRW5jb2RlKGlucHV0OiBzdHJpbmcsIGFsZ29yaXRobTogc3RyaW5nID0gJ3NoYTI1NicsIGVuY29kaW5nOiBCaW5hcnlUb1RleHRFbmNvZGluZyA9ICdoZXgnKTogc3RyaW5nIHtcbiAgY29uc3QgaGFzaCA9IGNyZWF0ZUhhc2goYWxnb3JpdGhtKTtcbiAgaGFzaC51cGRhdGUoaW5wdXQpO1xuICByZXR1cm4gaGFzaC5kaWdlc3QoZW5jb2RpbmcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVyaXZlRmlsZU5hbWUodXJsOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBkZXZVcmwgPSBtYXRjaENyZHNEZXZVcmwodXJsKTtcbiAgbGV0IGZpbGVuYW1lID0gdW5kZWZpbmVkO1xuXG4gIGlmIChkZXZVcmwpIHtcbiAgICBjb25zdCBsYXN0SW5kZXhPZlNsYXNoID0gZGV2VXJsLmxhc3RJbmRleE9mKCcvJyk7XG4gICAgY29uc3QgbGFzdEluZGV4T2ZBdCA9IGRldlVybC5sYXN0SW5kZXhPZignQCcpO1xuICAgIGZpbGVuYW1lID0gKGxhc3RJbmRleE9mU2xhc2ggPiAwICYmIGxhc3RJbmRleE9mQXQgPiAwKSA/IGRldlVybC5zbGljZShsYXN0SW5kZXhPZlNsYXNoKzEsIGxhc3RJbmRleE9mQXQpOiB1bmRlZmluZWQ7XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgbGFzdEluZGV4T2ZTbGFzaCA9IHVybC5sYXN0SW5kZXhPZignLycpO1xuICAgIGNvbnN0IGxhc3RJbmRleE9mWWFtbCA9IHVybC5sYXN0SW5kZXhPZignLnlhbWwnKSA+IDAgPyB1cmwubGFzdEluZGV4T2YoJy55YW1sJykgOiB1cmwubGFzdEluZGV4T2YoJy55bWwnKTtcblxuICAgIGZpbGVuYW1lID0gKGxhc3RJbmRleE9mU2xhc2ggPiAwICYmIGxhc3RJbmRleE9mWWFtbCA+IDApID8gdXJsLnNsaWNlKGxhc3RJbmRleE9mU2xhc2grMSwgbGFzdEluZGV4T2ZZYW1sKTogdW5kZWZpbmVkO1xuICB9XG5cbiAgaWYgKCFmaWxlbmFtZSkge1xuICAgIC8vIElmIHRoZSB1cmwgaWYgZm9yIGEgbG9jYWwgZmlsZSwgdGhlbiBqdXN0IGVuY29kZSB0aGUgZmlsZW5hbWUgYW5kIG5vdCB0aGUgZW50aXJlIHBhdGhcbiAgICAvLyBTaW5jZSBwYXRoIGNhbiBkZXBlbmQgb24gcGxhdGZvcm1cbiAgICBsZXQgZmlsZSA9IGV4aXN0c1N5bmModXJsKSA/IHBhdGguYmFzZW5hbWUodXJsKSA6IHVybDtcblxuICAgIGZpbGVuYW1lID0gaGFzaEFuZEVuY29kZShmaWxlKTtcbiAgfVxuXG4gIHJldHVybiBmaWxlbmFtZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzSzhzSW1wb3J0KHZhbHVlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKHZhbHVlICE9PSAnazhzJyAmJiAhdmFsdWUuc3RhcnRzV2l0aCgnazhzQCcpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0hlbG1JbXBvcnQodmFsdWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBpZiAoIXZhbHVlLnN0YXJ0c1dpdGgoJ2hlbG06JykgJiYgIXZhbHVlLmluY2x1ZGVzKCc6PWhlbG06JykpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZHNBcmVQcmVzZW50KGltcHJ0czogc3RyaW5nW10gfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgcmV0dXJuIChpbXBydHMgPz8gW10pLnNvbWUoaW1wcnQgPT4gKCFpc0s4c0ltcG9ydChpbXBydCkgJiYgIWlzSGVsbUltcG9ydChpbXBydCkpKTtcbn0iXX0=
;