UNPKG

cdk8s-cli

Version:

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

308 lines • 47.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateHelmConstruct = exports.emitHelmHeader = exports.generateConstruct = exports.getPropsTypeName = exports.getConstructTypeName = exports.getTypeName = exports.emitHeader = void 0; const codemaker_1 = require("codemaker"); const json2jsii_1 = require("json2jsii"); const MANIFEST_STATIC_METHOD = 'manifest'; const GVK_STATIC = 'GVK'; /** * Emits the header for a generated imports file. * * @param custom - whether the header is being emitted for a custom resource * (imported from a CRD) or a core API object */ function emitHeader(code, custom) { code.line('// generated by cdk8s'); if (custom) { code.line('import { ApiObject, ApiObjectMetadata, GroupVersionKind } from \'cdk8s\';'); } else { code.line('import { ApiObject, GroupVersionKind } from \'cdk8s\';'); } code.line('import { Construct } from \'constructs\';'); code.line(); } exports.emitHeader = emitHeader; function getTypeName(custom, kind, version) { // add an API version postfix only if this is core API (`import k8s`). // TODO = what about the rest of the namespace? the same resource can exist in multiple // api groups (Ingress for example exists in 'extensions' and 'networking') const postfix = (custom || version === 'v1') ? '' : (0, codemaker_1.toPascalCase)(version); return `${kind}${postfix}`; } exports.getTypeName = getTypeName; function getConstructTypeName(def) { const prefix = def.prefix ?? ''; const suffix = def.suffix ?? ''; return json2jsii_1.TypeGenerator.normalizeTypeName(`${prefix}${getTypeName(def.custom, def.kind, def.version)}${suffix}`); } exports.getConstructTypeName = getConstructTypeName; function getPropsTypeName(def) { const constructName = getConstructTypeName(def); return json2jsii_1.TypeGenerator.normalizeTypeName(`${constructName}Props`); } exports.getPropsTypeName = getPropsTypeName; function generateConstruct(typegen, def) { const constructName = getConstructTypeName(def); if (def.custom) { typegen.emitCustomType('ApiObjectMetadata', () => { }); } typegen.emitCustomType(constructName, code => { const schema = def.schema; // `propsTypeName` could also be "any" if we can't parse the schema for some reason const propsTypeName = emitPropsStruct(); const groupPrefix = def.group ? `${def.group}/` : ''; const hasRequired = hasRequiredProps(schema); const defaultProps = hasRequired ? '' : ' = {}'; emitConstruct(); function emitPropsStruct() { const propsSchema = createPropsStructSchema(); const propsStructName = getPropsTypeName(def); return typegen.emitType(propsStructName, propsSchema, def.fqn); } function createPropsStructSchema() { const copy = { ...def.schema || {} }; const props = copy.properties = copy.properties || {}; delete props.apiVersion; delete props.kind; delete props.status; delete copy['x-kubernetes-group-version-kind']; copy.required = copy.required || []; if (Array.isArray(copy.required)) { copy.required = copy.required.filter(x => x !== 'apiVersion' && x !== 'kind' && x !== 'status'); } if (def.custom) { // add "metadata" field for all CRDs, overriding any existing typings copy.properties.metadata = { $ref: '#/definitions/ApiObjectMetadata' }; } // reorder top-level keys so that we have "metadata" first and then all the rest // This matches the behavior in the ApiObject's toJson function (https://github.com/cdk8s-team/cdk8s-core/blob/58fb8c0882ddd95a9b9dedb4107e12f601443cf4/src/api-object.ts#L185) const result = {}; for (const k of ['metadata', ...Object.keys(copy.properties)]) { if (k in copy.properties) { result[k] = copy.properties[k]; } } copy.properties = result; return copy; } function emitConstruct() { code.line('/**'); code.line(` * ${def.schema?.description ?? ''}`); code.line(' *'); code.line(` * @schema ${def.fqn}`); code.line(' */'); code.openBlock(`export class ${constructName} extends ApiObject`); emitGVK(); code.line(''); emitManifestFactory(); code.line(''); emitInitializer(); code.line(''); emitToJson(); code.closeBlock(); } function emitGVK() { code.line('/**'); code.line(` * Returns the apiVersion and kind for "${def.fqn}"`); code.line(' */'); code.openBlock(`public static readonly ${GVK_STATIC}: GroupVersionKind =`); code.line(`apiVersion: '${groupPrefix}${def.version}',`); code.line(`kind: '${def.kind}',`); code.closeBlock(); } function emitInitializer() { code.line('/**'); code.line(` * Defines a "${def.fqn}" API object`); code.line(' * @param scope the scope in which to define this object'); code.line(' * @param id a scope-local name for the object'); code.line(' * @param props initialization props'); code.line(' */'); code.openBlock(`public constructor(scope: Construct, id: string, props: ${propsTypeName}${defaultProps})`); code.open('super(scope, id, {'); code.line(`...${constructName}.${GVK_STATIC},`); code.line('...props,'); code.close('});'); code.closeBlock(); } function emitManifestFactory() { code.line('/**'); code.line(` * Renders a Kubernetes manifest for "${def.fqn}".`); code.line(' *'); code.line(' * This can be used to inline resource manifests inside other objects (e.g. as templates).'); code.line(' *'); code.line(' * @param props initialization props'); code.line(' */'); code.openBlock(`public static ${MANIFEST_STATIC_METHOD}(props: ${propsTypeName}${defaultProps}): any`); code.open('return {'); code.line(`...${constructName}.${GVK_STATIC},`); code.line(`...toJson_${propsTypeName}(props),`); code.close('};'); code.closeBlock(); } function emitToJson() { code.line('/**'); code.line(' * Renders the object to Kubernetes JSON.'); code.line(' */'); code.openBlock('public toJson(): any'); code.line('const resolved = super.toJson();'); code.line(); code.open('return {'); code.line(`...${constructName}.${GVK_STATIC},`); code.line(`...toJson_${propsTypeName}(resolved),`); code.close('};'); code.closeBlock(); } }); } exports.generateConstruct = generateConstruct; /** * Emit imports for generated helm construct * @param code CodeMaker istance */ function emitHelmHeader(code) { code.line('// generated by cdk8s'); code.line('import { Helm, HelmProps } from \'cdk8s\';'); code.line('import { Construct } from \'constructs\';'); code.line(); } exports.emitHelmHeader = emitHelmHeader; function generateHelmConstruct(typegen, def) { const noSpecialChars = def.chartName.replace(/([^\w ]|_)/g, ''); const chartName = json2jsii_1.TypeGenerator.normalizeTypeName(noSpecialChars); const schema = def.schema; const repoUrl = def.chartUrl; const chartVersion = def.chartVersion; // Create custom type typegen.emitCustomType(chartName, code => { const valuesInterface = `${chartName}Values`; if (schema !== undefined) { // Creating values interface emitValuesInterface(); function emitValuesInterface() { const copyOfSchema = schema ? addAdditionalValuesToProps(schema) : undefined; if (copyOfSchema && copyOfSchema.properties) { // Sub charts or dependencies for (const dependency of def.chartDependencies) { copyOfSchema.properties[dependency] = { type: 'object', additionalProperties: { type: 'object' } }; } copyOfSchema.properties.global = { type: 'object', additionalProperties: { type: 'object' } }; copyOfSchema.properties.additionalValues = { type: 'object', description: 'Values that are not available in values.schema.json will not be code generated. You can add such values to this property.', additionalProperties: { type: 'object' }, }; } typegen.emitType(valuesInterface, copyOfSchema, def.fqn); } function addAdditionalValuesToProps(schma) { const tempSchema = schma; if (!tempSchema.properties) { return tempSchema; } Object.values(tempSchema.properties).forEach((prop) => { if (prop.type !== 'object') { return; } if (prop.properties) { prop.properties.additionalValues = { type: 'object', description: 'Values that are not available in values.schema.json will not be code generated. You can add such values to this property.', additionalProperties: { type: 'object' }, }; addAdditionalValuesToProps(prop); } }); return tempSchema; } } // Creating construct properties emitPropsInterface(); code.line(); // Creating construct for helm chart emitConstruct(); function emitPropsInterface() { code.openBlock(`export interface ${chartName}Props`); code.line('readonly namespace?: string;'); code.line('readonly releaseName?: string;'); code.line('readonly helmExecutable?: string;'); code.line('readonly helmFlags?: string[];'); if (schema === undefined) { code.line('readonly values?: { [key: string]: any };'); } else { const doValuesHaveReqProps = hasRequiredProps(schema) ? '' : '?'; code.line(`readonly values${doValuesHaveReqProps}: ${valuesInterface};`); } code.closeBlock(); } function emitConstruct() { code.openBlock(`export class ${chartName} extends Construct`); emitInitializer(); code.line(); emitAdditionalValuesFlattenFunc(); code.closeBlock(); } function emitInitializer() { const propsDefinition = schema && hasRequiredProps(schema) ? `${chartName}Props` : `${chartName}Props = {}`; code.openBlock(`public constructor(scope: Construct, id: string, props: ${propsDefinition})`); code.line('super(scope, id);'); code.line('let updatedProps = {};'); code.line(); code.openBlock('if (props.values)'); code.line('const { additionalValues, ...valuesWithoutAdditionalValues } = props.values;'); code.open('updatedProps = {'); code.line('...props,'); code.open('values: {'); code.line('...this.flattenAdditionalValues(valuesWithoutAdditionalValues),'); code.line('...additionalValues,'); code.close('},'); code.close('};'); code.closeBlock(); code.line(); code.open('const finalProps: HelmProps = {'); if (repoUrl.startsWith('oci://')) { code.line(`chart: \'${repoUrl}\',`); } else { code.line(`chart: \'${def.chartName}\',`); code.line(`repo: \'${repoUrl}\',`); } code.line(`version: \'${chartVersion}\',`); code.line('...(Object.keys(updatedProps).length !== 0 ? updatedProps : props),'); code.close('};'); code.line(); code.line('new Helm(this, \'Helm\', finalProps);'); code.closeBlock(); } function emitAdditionalValuesFlattenFunc() { code.openBlock('private flattenAdditionalValues(props: { [key: string]: any }): { [key: string]: any }'); code.open('for (let prop in props) {'); code.open('if (Array.isArray(props[prop])) {'); code.open('props[prop].map((item: any) => {'); code.open('if (typeof item === \'object\' && prop !== \'additionalValues\') {'); code.line('return this.flattenAdditionalValues(item);'); code.close('}'); code.line('return item;'); code.close('});'); code.close('}'); code.open('else if (typeof props[prop] === \'object\' && prop !== \'additionalValues\') {'); code.line('props[prop] = this.flattenAdditionalValues(props[prop]);'); code.close('}'); code.close('}'); code.line(); code.line('const { additionalValues, ...valuesWithoutAdditionalValues } = props;'); code.line(); code.open('return {'); code.line('...valuesWithoutAdditionalValues,'); code.line('...additionalValues,'); code.close('};'); code.closeBlock(); } }); } exports.generateHelmConstruct = generateHelmConstruct; function hasRequiredProps(schema) { return schema?.required && Array.isArray(schema.required) && schema.required.length > 0; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZWdlbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbXBvcnQvY29kZWdlbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5Q0FBb0Q7QUFJcEQseUNBQTBDO0FBRTFDLE1BQU0sc0JBQXNCLEdBQUcsVUFBVSxDQUFDO0FBQzFDLE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQztBQStCekI7Ozs7O0dBS0c7QUFDSCxTQUFnQixVQUFVLENBQUMsSUFBZSxFQUFFLE1BQWU7SUFDekQsSUFBSSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0lBQ25DLElBQUksTUFBTSxFQUFFO1FBQ1YsSUFBSSxDQUFDLElBQUksQ0FBQywyRUFBMkUsQ0FBQyxDQUFDO0tBQ3hGO1NBQU07UUFDTCxJQUFJLENBQUMsSUFBSSxDQUFDLHdEQUF3RCxDQUFDLENBQUM7S0FDckU7SUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxDQUFDLENBQUM7SUFDdkQsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0FBQ2QsQ0FBQztBQVRELGdDQVNDO0FBRUQsU0FBZ0IsV0FBVyxDQUFDLE1BQWUsRUFBRSxJQUFZLEVBQUUsT0FBZTtJQUN4RSxzRUFBc0U7SUFDdEUsdUZBQXVGO0lBQ3ZGLDJFQUEyRTtJQUMzRSxNQUFNLE9BQU8sR0FBRyxDQUFDLE1BQU0sSUFBSSxPQUFPLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBQSx3QkFBWSxFQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFFLE9BQU8sR0FBRyxJQUFJLEdBQUcsT0FBTyxFQUFFLENBQUM7QUFDN0IsQ0FBQztBQU5ELGtDQU1DO0FBRUQsU0FBZ0Isb0JBQW9CLENBQUMsR0FBd0I7SUFDM0QsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFDaEMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1B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TSxHQUFHLENBQUMsQ0FBQztBQUMxRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29kZU1ha2VyLCB0b1Bhc2NhbENhc2UgfSBmcm9tICdjb2RlbWFrZXInO1xuLy8gd2UganVzdCBuZWVkIHRoZSB0eXBlcyBmcm9tIGpzb24tc2NoZW1hXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzXG5pbXBvcnQgeyBKU09OU2NoZW1hNCB9IGZyb20gJ2pzb24tc2NoZW1hJztcbmltcG9ydCB7IFR5cGVHZW5lcmF0b3IgfSBmcm9tICdqc29uMmpzaWknO1xuXG5jb25zdCBNQU5JRkVTVF9TVEFUSUNfTUVUSE9EID0gJ21hbmlmZXN0JztcbmNvbnN0IEdWS19TVEFUSUMgPSAnR1ZLJztcblxuZXhwb3J0IGludGVyZmFjZSBBcGlPYmplY3REZWZpbml0aW9uIHtcbiAgcmVhZG9ubHkgZnFuOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGdyb3VwOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHZlcnNpb246IHN0cmluZztcbiAgcmVhZG9ubHkga2luZDogc3RyaW5nO1xuICByZWFkb25seSBzY2hlbWE6IEpTT05TY2hlbWE0O1xuXG4gIC8qKlxuICAgKiBJcyB0aGlzIGlzIGEgY3VzdG9tIHJlc291cmNlIChpbXBvcnRlZCBmcm9tIGEgQ1JEKSBvciBhIGNvcmUgQVBJIG9iamVjdD9cbiAgICovXG4gIHJlYWRvbmx5IGN1c3RvbTogYm9vbGVhbjtcblxuICAvKlxuICAgKiBJbmRpY2F0ZXMgaWYgYSBwcmVmaXggc2hvdWxkIGJlIGFkZGVkIHRvIHRoZSBjb25zdHJ1Y3QgY2xhc3MgbmFtZS4gRm9yXG4gICAqIGV4YW1wbGUsIGZvciBuYXRpdmUgazhzIGFwaSBvYmplY3RzLCB3ZSBhZGQgYEt1YmVgIGJ5IGRlZmF1bHQuXG4gICAqXG4gICAqIEBkZWZhdWx0IFwiXCJcbiAgICovXG4gIHJlYWRvbmx5IHByZWZpeD86IHN0cmluZztcblxuICAvKlxuICAgKiBJbmRpY2F0ZXMgaWYgYSBzdWZmaXggc2hvdWxkIGJlIGFkZGVkIHRvIHRoZSBjb25zdHJ1Y3QgY2xhc3MgbmFtZS4gRm9yXG4gICAqIGV4YW1wbGUsIGZvciBtdWx0aS12ZXJzaW9uZWQgY3Jkcywgd2UgYWRkIHRoZSB2ZXJzaW9uIGFzIHRoZSBzdWZmaXguXG4gICAqXG4gICAqIEBkZWZhdWx0IFwiXCJcbiAgICovXG4gIHJlYWRvbmx5IHN1ZmZpeD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBFbWl0cyB0aGUgaGVhZGVyIGZvciBhIGdlbmVyYXRlZCBpbXBvcnRzIGZpbGUuXG4gKlxuICogQHBhcmFtIGN1c3RvbSAtIHdoZXRoZXIgdGhlIGhlYWRlciBpcyBiZWluZyBlbWl0dGVkIGZvciBhIGN1c3RvbSByZXNvdXJjZVxuICogKGltcG9ydGVkIGZyb20gYSBDUkQpIG9yIGEgY29yZSBBUEkgb2JqZWN0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbWl0SGVhZGVyKGNvZGU6IENvZGVNYWtlciwgY3VzdG9tOiBib29sZWFuKSB7XG4gIGNvZGUubGluZSgnLy8gZ2VuZXJhdGVkIGJ5IGNkazhzJyk7XG4gIGlmIChjdXN0b20pIHtcbiAgICBjb2RlLmxpbmUoJ2ltcG9ydCB7IEFwaU9iamVjdCwgQXBpT2JqZWN0TWV0YWRhdGEsIEdyb3VwVmVyc2lvbktpbmQgfSBmcm9tIFxcJ2NkazhzXFwnOycpO1xuICB9IGVsc2Uge1xuICAgIGNvZGUubGluZSgnaW1wb3J0IHsgQXBpT2JqZWN0LCBHcm91cFZlcnNpb25LaW5kIH0gZnJvbSBcXCdjZGs4c1xcJzsnKTtcbiAgfVxuICBjb2RlLmxpbmUoJ2ltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXFwnY29uc3RydWN0c1xcJzsnKTtcbiAgY29kZS5saW5lKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUeXBlTmFtZShjdXN0b206IGJvb2xlYW4sIGtpbmQ6IHN0cmluZywgdmVyc2lvbjogc3RyaW5nKSB7XG4gIC8vIGFkZCBhbiBBUEkgdmVyc2lvbiBwb3N0Zml4IG9ubHkgaWYgdGhpcyBpcyBjb3JlIEFQSSAoYGltcG9ydCBrOHNgKS5cbiAgLy8gVE9ETyA9IHdoYXQgYWJvdXQgdGhlIHJlc3Qgb2YgdGhlIG5hbWVzcGFjZT8gdGhlIHNhbWUgcmVzb3VyY2UgY2FuIGV4aXN0IGluIG11bHRpcGxlXG4gIC8vIGFwaSBncm91cHMgKEluZ3Jlc3MgZm9yIGV4YW1wbGUgZXhpc3RzIGluICdleHRlbnNpb25zJyBhbmQgJ25ldHdvcmtpbmcnKVxuICBjb25zdCBwb3N0Zml4ID0gKGN1c3RvbSB8fCB2ZXJzaW9uID09PSAndjEnKSA/ICcnIDogdG9QYXNjYWxDYXNlKHZlcnNpb24pO1xuICByZXR1cm4gYCR7a2luZH0ke3Bvc3RmaXh9YDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldENvbnN0cnVjdFR5cGVOYW1lKGRlZjogQXBpT2JqZWN0RGVmaW5pdGlvbikge1xuICBjb25zdCBwcmVmaXggPSBkZWYucHJlZml4ID8/ICcnO1xuICBjb25zdCBzdWZmaXggPSBkZWYuc3VmZml4ID8/ICcnO1xuICByZXR1cm4gVHlwZUdlbmVyYXRvci5ub3JtYWxpemVUeXBlTmFtZShgJHtwcmVmaXh9JHtnZXRUeXBlTmFtZShkZWYuY3VzdG9tLCBkZWYua2luZCwgZGVmLnZlcnNpb24pfSR7c3VmZml4fWApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHJvcHNUeXBlTmFtZShkZWY6IEFwaU9iamVjdERlZmluaXRpb24pIHtcbiAgY29uc3QgY29uc3RydWN0TmFtZSA9IGdldENvbnN0cnVjdFR5cGVOYW1lKGRlZik7XG4gIHJldHVybiBUeXBlR2VuZXJhdG9yLm5vcm1hbGl6ZVR5cGVOYW1lKGAke2NvbnN0cnVjdE5hbWV9UHJvcHNgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlQ29uc3RydWN0KHR5cGVnZW46IFR5cGVHZW5lcmF0b3IsIGRlZjogQXBpT2JqZWN0RGVmaW5pdGlvbikge1xuICBjb25zdCBjb25zdHJ1Y3ROYW1lID0gZ2V0Q29uc3RydWN0VHlwZU5hbWUoZGVmKTtcblxuICBpZiAoZGVmLmN1c3RvbSkge1xuICAgIHR5cGVnZW4uZW1pdEN1c3RvbVR5cGUoJ0FwaU9iamVjdE1ldGFkYXRhJywgKCkgPT4ge30pO1xuICB9XG5cbiAgdHlwZWdlbi5lbWl0Q3VzdG9tVHlwZShjb25zdHJ1Y3ROYW1lLCBjb2RlID0+IHtcbiAgICBjb25zdCBzY2hlbWEgPSBkZWYuc2NoZW1hO1xuXG4gICAgLy8gYHByb3BzVHlwZU5hbWVgIGNvdWxkIGFsc28gYmUgXCJhbnlcIiBpZiB3ZSBjYW4ndCBwYXJzZSB0aGUgc2NoZW1hIGZvciBzb21lIHJlYXNvblxuICAgIGNvbnN0IHByb3BzVHlwZU5hbWUgPSBlbWl0UHJvcHNTdHJ1Y3QoKTtcbiAgICBjb25zdCBncm91cFByZWZpeCA9IGRlZi5ncm91cCA/IGAke2RlZi5ncm91cH0vYCA6ICcnO1xuICAgIGNvbnN0IGhhc1JlcXVpcmVkID0gaGFzUmVxdWlyZWRQcm9wcyhzY2hlbWEpO1xuICAgIGNvbnN0IGRlZmF1bHRQcm9wcyA9IGhhc1JlcXVpcmVkID8gJycgOiAnID0ge30nO1xuICAgIGVtaXRDb25zdHJ1Y3QoKTtcblxuICAgIGZ1bmN0aW9uIGVtaXRQcm9wc1N0cnVjdCgpIHtcbiAgICAgIGNvbnN0IHByb3BzU2NoZW1hID0gY3JlYXRlUHJvcHNTdHJ1Y3RTY2hlbWEoKTtcbiAgICAgIGNvbnN0IHByb3BzU3RydWN0TmFtZSA9IGdldFByb3BzVHlwZU5hbWUoZGVmKTtcbiAgICAgIHJldHVybiB0eXBlZ2VuLmVtaXRUeXBlKHByb3BzU3RydWN0TmFtZSwgcHJvcHNTY2hlbWEsIGRlZi5mcW4pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVByb3BzU3RydWN0U2NoZW1hKCkge1xuICAgICAgY29uc3QgY29weTogSlNPTlNjaGVtYTQgPSB7IC4uLmRlZi5zY2hlbWEgfHwge30gfTtcbiAgICAgIGNvbnN0IHByb3BzID0gY29weS5wcm9wZXJ0aWVzID0gY29weS5wcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgZGVsZXRlIHByb3BzLmFwaVZlcnNpb247XG4gICAgICBkZWxldGUgcHJvcHMua2luZDtcbiAgICAgIGRlbGV0ZSBwcm9wcy5zdGF0dXM7XG4gICAgICBkZWxldGUgY29weVsneC1rdWJlcm5ldGVzLWdyb3VwLXZlcnNpb24ta2luZCddO1xuXG4gICAgICBjb3B5LnJlcXVpcmVkID0gY29weS5yZXF1aXJlZCB8fCBbXTtcblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29weS5yZXF1aXJlZCkpIHtcbiAgICAgICAgY29weS5yZXF1aXJlZCA9IGNvcHkucmVxdWlyZWQuZmlsdGVyKHggPT4geCAhPT0gJ2FwaVZlcnNpb24nICYmIHggIT09ICdraW5kJyAmJiB4ICE9PSAnc3RhdHVzJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChkZWYuY3VzdG9tKSB7XG4gICAgICAgIC8vIGFkZCBcIm1ldGFkYXRhXCIgZmllbGQgZm9yIGFsbCBDUkRzLCBvdmVycmlkaW5nIGFueSBleGlzdGluZyB0eXBpbmdzXG4gICAgICAgIGNvcHkucHJvcGVydGllcy5tZXRhZGF0YSA9IHsgJHJlZjogJyMvZGVmaW5pdGlvbnMvQXBpT2JqZWN0TWV0YWRhdGEnIH07XG4gICAgICB9XG5cbiAgICAgIC8vIHJlb3JkZXIgdG9wLWxldmVsIGtleXMgc28gdGhhdCB3ZSBoYXZlIFwibWV0YWRhdGFcIiBmaXJzdCBhbmQgdGhlbiBhbGwgdGhlIHJlc3RcbiAgICAgIC8vIFRoaXMgbWF0Y2hlcyB0aGUgYmVoYXZpb3IgaW4gdGhlIEFwaU9iamVjdCdzIHRvSnNvbiBmdW5jdGlvbiAoaHR0cHM6Ly9naXRodWIuY29tL2NkazhzLXRlYW0vY2RrOHMtY29yZS9ibG9iLzU4ZmI4YzA4ODJkZGQ5NWE5YjlkZWRiNDEwN2UxMmY2MDE0NDNjZjQvc3JjL2FwaS1vYmplY3QudHMjTDE4NSlcbiAgICAgIGNvbnN0IHJlc3VsdDogYW55ID0ge307XG4gICAgICBmb3IgKGNvbnN0IGsgb2YgWydtZXRhZGF0YScsIC4uLk9iamVjdC5rZXlzKGNvcHkucHJvcGVydGllcyldKSB7XG4gICAgICAgIGlmIChrIGluIGNvcHkucHJvcGVydGllcykge1xuICAgICAgICAgIHJlc3VsdFtrXSA9IGNvcHkucHJvcGVydGllc1trXTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb3B5LnByb3BlcnRpZXMgPSByZXN1bHQ7XG4gICAgICByZXR1cm4gY29weTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbWl0Q29uc3RydWN0KCkge1xuICAgICAgY29kZS5saW5lKCcvKionKTtcbiAgICAgIGNvZGUubGluZShgICogJHtkZWYuc2NoZW1hPy5kZXNjcmlwdGlvbiA/PyAnJ31gKTtcbiAgICAgIGNvZGUubGluZSgnIConKTtcbiAgICAgIGNvZGUubGluZShgICogQHNjaGVtYSAke2RlZi5mcW59YCk7XG4gICAgICBjb2RlLmxpbmUoJyAqLycpO1xuICAgICAgY29kZS5vcGVuQmxvY2soYGV4cG9ydCBjbGFzcyAke2NvbnN0cnVjdE5hbWV9IGV4dGVuZHMgQXBpT2JqZWN0YCk7XG5cbiAgICAgIGVtaXRHVksoKTtcblxuICAgICAgY29kZS5saW5lKCcnKTtcblxuICAgICAgZW1pdE1hbmlmZXN0RmFjdG9yeSgpO1xuXG4gICAgICBjb2RlLmxpbmUoJycpO1xuXG4gICAgICBlbWl0SW5pdGlhbGl6ZXIoKTtcblxuICAgICAgY29kZS5saW5lKCcnKTtcblxuICAgICAgZW1pdFRvSnNvbigpO1xuXG4gICAgICBjb2RlLmNsb3NlQmxvY2soKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbWl0R1ZLKCkge1xuICAgICAgY29kZS5saW5lKCcvKionKTtcbiAgICAgIGNvZGUubGluZShgICogUmV0dXJucyB0aGUgYXBpVmVyc2lvbiBhbmQga2luZCBmb3IgXCIke2RlZi5mcW59XCJgKTtcbiAgICAgIGNvZGUubGluZSgnICovJyk7XG4gICAgICBjb2RlLm9wZW5CbG9jayhgcHVibGljIHN0YXRpYyByZWFkb25seSAke0dWS19TVEFUSUN9OiBHcm91cFZlcnNpb25LaW5kID1gKTtcbiAgICAgIGNvZGUubGluZShgYXBpVmVyc2lvbjogJyR7Z3JvdXBQcmVmaXh9JHtkZWYudmVyc2lvbn0nLGApO1xuICAgICAgY29kZS5saW5lKGBraW5kOiAnJHtkZWYua2luZH0nLGApO1xuICAgICAgY29kZS5jbG9zZUJsb2NrKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW1pdEluaXRpYWxpemVyKCkge1xuXG4gICAgICBjb2RlLmxpbmUoJy8qKicpO1xuICAgICAgY29kZS5saW5lKGAgKiBEZWZpbmVzIGEgXCIke2RlZi5mcW59XCIgQVBJIG9iamVjdGApO1xuICAgICAgY29kZS5saW5lKCcgKiBAcGFyYW0gc2NvcGUgdGhlIHNjb3BlIGluIHdoaWNoIHRvIGRlZmluZSB0aGlzIG9iamVjdCcpO1xuICAgICAgY29kZS5saW5lKCcgKiBAcGFyYW0gaWQgYSBzY29wZS1sb2NhbCBuYW1lIGZvciB0aGUgb2JqZWN0Jyk7XG4gICAgICBjb2RlLmxpbmUoJyAqIEBwYXJhbSBwcm9wcyBpbml0aWFsaXphdGlvbiBwcm9wcycpO1xuICAgICAgY29kZS5saW5lKCcgKi8nKTtcblxuICAgICAgY29kZS5vcGVuQmxvY2soYHB1YmxpYyBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogJHtwcm9wc1R5cGVOYW1lfSR7ZGVmYXVsdFByb3BzfSlgKTtcblxuICAgICAgY29kZS5vcGVuKCdzdXBlcihzY29wZSwgaWQsIHsnKTtcbiAgICAgIGNvZGUubGluZShgLi4uJHtjb25zdHJ1Y3ROYW1lfS4ke0dWS19TVEFUSUN9LGApO1xuICAgICAgY29kZS5saW5lKCcuLi5wcm9wcywnKTtcbiAgICAgIGNvZGUuY2xvc2UoJ30pOycpO1xuXG4gICAgICBjb2RlLmNsb3NlQmxvY2soKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlbWl0TWFuaWZlc3RGYWN0b3J5KCkge1xuICAgICAgY29kZS5saW5lKCcvKionKTtcbiAgICAgIGNvZGUubGluZShgICogUmVuZGVycyBhIEt1YmVybmV0ZXMgbWFuaWZlc3QgZm9yIFwiJHtkZWYuZnFufVwiLmApO1xuICAgICAgY29kZS5saW5lKCcgKicpO1xuICAgICAgY29kZS5saW5lKCcgKiBUaGlzIGNhbiBiZSB1c2VkIHRvIGlubGluZSByZXNvdXJjZSBtYW5pZmVzdHMgaW5zaWRlIG90aGVyIG9iamVjdHMgKGUuZy4gYXMgdGVtcGxhdGVzKS4nKTtcbiAgICAgIGNvZGUubGluZSgnIConKTtcbiAgICAgIGNvZGUubGluZSgnICogQHBhcmFtIHByb3BzIGluaXRpYWxpemF0aW9uIHByb3BzJyk7XG4gICAgICBjb2RlLmxpbmUoJyAqLycpO1xuXG4gICAgICBjb2RlLm9wZW5CbG9jayhgcHVibGljIHN0YXRpYyAke01BTklGRVNUX1NUQVRJQ19NRVRIT0R9KHByb3BzOiAke3Byb3BzVHlwZU5hbWV9JHtkZWZhdWx0UHJvcHN9KTogYW55YCk7XG4gICAgICBjb2RlLm9wZW4oJ3JldHVybiB7Jyk7XG4gICAgICBjb2RlLmxpbmUoYC4uLiR7Y29uc3RydWN0TmFtZX0uJHtHVktfU1RBVElDfSxgKTtcbiAgICAgIGNvZGUubGluZShgLi4udG9Kc29uXyR7cHJvcHNUeXBlTmFtZX0ocHJvcHMpLGApO1xuICAgICAgY29kZS5jbG9zZSgnfTsnKTtcbiAgICAgIGNvZGUuY2xvc2VCbG9jaygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVtaXRUb0pzb24oKSB7XG4gICAgICBjb2RlLmxpbmUoJy8qKicpO1xuICAgICAgY29kZS5saW5lKCcgKiBSZW5kZXJzIHRoZSBvYmplY3QgdG8gS3ViZXJuZXRlcyBKU09OLicpO1xuICAgICAgY29kZS5saW5lKCcgKi8nKTtcbiAgICAgIGNvZGUub3BlbkJsb2NrKCdwdWJsaWMgdG9Kc29uKCk6IGFueScpO1xuICAgICAgY29kZS5saW5lKCdjb25zdCByZXNvbHZlZCA9IHN1cGVyLnRvSnNvbigpOycpO1xuICAgICAgY29kZS5saW5lKCk7XG4gICAgICBjb2RlLm9wZW4oJ3JldHVybiB7Jyk7XG4gICAgICBjb2RlLmxpbmUoYC4uLiR7Y29uc3RydWN0TmFtZX0uJHtHVktfU1RBVElDfSxgKTtcbiAgICAgIGNvZGUubGluZShgLi4udG9Kc29uXyR7cHJvcHNUeXBlTmFtZX0ocmVzb2x2ZWQpLGApO1xuICAgICAgY29kZS5jbG9zZSgnfTsnKTtcbiAgICAgIGNvZGUuY2xvc2VCbG9jaygpO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogRW1pdCBpbXBvcnRzIGZvciBnZW5lcmF0ZWQgaGVsbSBjb25zdHJ1Y3RcbiAqIEBwYXJhbSBjb2RlIENvZGVNYWtlciBpc3RhbmNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbWl0SGVsbUhlYWRlcihjb2RlOiBDb2RlTWFrZXIpIHtcbiAgY29kZS5saW5lKCcvLyBnZW5lcmF0ZWQgYnkgY2RrOHMnKTtcbiAgY29kZS5saW5lKCdpbXBvcnQgeyBIZWxtLCBIZWxtUHJvcHMgfSBmcm9tIFxcJ2NkazhzXFwnOycpO1xuICBjb2RlLmxpbmUoJ2ltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXFwnY29uc3RydWN0c1xcJzsnKTtcbiAgY29kZS5saW5lKCk7XG59XG5cbi8qKlxuICogSGVsbSBPYmplY3QgRGVmaW5pdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIEhlbG1PYmplY3REZWZpbml0aW9uIHtcbiAgLyoqXG4gICAqIGB2YWx1ZXMuc2NoZW1hLmpzb25gIGZvciB0aGUgaGVsbSBjaGFydFxuICAgKi9cbiAgcmVhZG9ubHkgc2NoZW1hOiBKU09OU2NoZW1hNCB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIENoYXJ0IG5hbWVcbiAgICovXG4gIHJlYWRvbmx5IGNoYXJ0TmFtZTogc3RyaW5nO1xuICAvKipcbiAgICogQ2hhcnQgdXJsXG4gICAqL1xuICByZWFkb25seSBjaGFydFVybDogc3RyaW5nO1xuICAvKipcbiAgICogQ2hhcnQgdmVyc2lvblxuICAgKi9cbiAgcmVhZG9ubHkgY2hhcnRWZXJzaW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBDaGFydCBkZXBlbmRlbmNpZXNcbiAgICovXG4gIHJlYWRvbmx5IGNoYXJ0RGVwZW5kZW5jaWVzOiBzdHJpbmdbXTtcbiAgLyoqXG4gICAqIEZ1bGx5IHF1YWxpZmllZCBuYW1lIGZvciB0aGUgY29uc3RydWN0XG4gICAqL1xuICByZWFkb25seSBmcW4/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUhlbG1Db25zdHJ1Y3QodHlwZWdlbjogVHlwZUdlbmVyYXRvciwgZGVmOiBIZWxtT2JqZWN0RGVmaW5pdGlvbikge1xuICBjb25zdCBub1NwZWNpYWxDaGFycyA9IGRlZi5jaGFydE5hbWUucmVwbGFjZSgvKFteXFx3IF18XykvZywgJycpO1xuICBjb25zdCBjaGFydE5hbWUgPSBUeXBlR2VuZXJhdG9yLm5vcm1hbGl6ZVR5cGVOYW1lKG5vU3BlY2lhbENoYXJzKTtcbiAgY29uc3Qgc2NoZW1hID0gZGVmLnNjaGVtYTtcbiAgY29uc3QgcmVwb1VybCA9IGRlZi5jaGFydFVybDtcbiAgY29uc3QgY2hhcnRWZXJzaW9uID0gZGVmLmNoYXJ0VmVyc2lvbjtcblxuICAvLyBDcmVhdGUgY3VzdG9tIHR5cGVcbiAgdHlwZWdlbi5lbWl0Q3VzdG9tVHlwZShjaGFydE5hbWUsIGNvZGUgPT4ge1xuXG4gICAgY29uc3QgdmFsdWVzSW50ZXJmYWNlID0gYCR7Y2hhcnROYW1lfVZhbHVlc2A7XG4gICAgaWYgKHNjaGVtYSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBDcmVhdGluZyB2YWx1ZXMgaW50ZXJmYWNlXG4gICAgICBlbWl0VmFsdWVzSW50ZXJmYWNlKCk7XG5cbiAgICAgIGZ1bmN0aW9uIGVtaXRWYWx1ZXNJbnRlcmZhY2UoKSB7XG5cbiAgICAgICAgY29uc3QgY29weU9mU2NoZW1hID0gc2NoZW1hID8gYWRkQWRkaXRpb25hbFZhbHVlc1RvUHJvcHMoc2NoZW1hKSA6IHVuZGVmaW5lZDtcblxuICAgICAgICBpZiAoY29weU9mU2NoZW1hICYmIGNvcHlPZlNjaGVtYS5wcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgLy8gU3ViIGNoYXJ0cyBvciBkZXBlbmRlbmNpZXNcbiAgICAgICAgICBmb3IgKGNvbnN0IGRlcGVuZGVuY3kgb2YgZGVmLmNoYXJ0RGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICBjb3B5T2ZTY2hlbWEucHJvcGVydGllc1tkZXBlbmRlbmN5XSA9IHsgdHlwZTogJ29iamVjdCcsIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IHR5cGU6ICdvYmplY3QnIH0gfTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb3B5T2ZTY2hlbWEucHJvcGVydGllcy5nbG9iYWwgPSB7IHR5cGU6ICdvYmplY3QnLCBhZGRpdGlvbmFsUHJvcGVydGllczogeyB0eXBlOiAnb2JqZWN0JyB9IH07XG4gICAgICAgICAgY29weU9mU2NoZW1hLnByb3BlcnRpZXMuYWRkaXRpb25hbFZhbHVlcyA9IHtcbiAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246ICdWYWx1ZXMgdGhhdCBhcmUgbm90IGF2YWlsYWJsZSBpbiB2YWx1ZXMuc2NoZW1hLmpzb24gd2lsbCBub3QgYmUgY29kZSBnZW5lcmF0ZWQuIFlvdSBjYW4gYWRkIHN1Y2ggdmFsdWVzIHRvIHRoaXMgcHJvcGVydHkuJyxcbiAgICAgICAgICAgIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiB7IHR5cGU6ICdvYmplY3QnIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHR5cGVnZW4uZW1pdFR5cGUodmFsdWVzSW50ZXJmYWNlLCBjb3B5T2ZTY2hlbWEsIGRlZi5mcW4pO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBhZGRBZGRpdGlvbmFsVmFsdWVzVG9Qcm9wcyhzY2htYTogSlNPTlNjaGVtYTQpOiBKU09OU2NoZW1hNCB7XG4gICAgICAgIGNvbnN0IHRlbXBTY2hlbWEgPSBzY2htYTtcblxuICAgICAgICBpZiAoIXRlbXBTY2hlbWEucHJvcGVydGllcykge1xuICAgICAgICAgIHJldHVybiB0ZW1wU2NoZW1hO1xuICAgICAgICB9XG5cbiAgICAgICAgT2JqZWN0LnZhbHVlcyh0ZW1wU2NoZW1hLnByb3BlcnRpZXMpLmZvckVhY2goKHByb3ApID0+IHtcbiAgICAgICAgICBpZiAocHJvcC50eXBlICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChwcm9wLnByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHByb3AucHJvcGVydGllcy5hZGRpdGlvbmFsVmFsdWVzID0ge1xuICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb246ICdWYWx1ZXMgdGhhdCBhcmUgbm90IGF2YWlsYWJsZSBpbiB2YWx1ZXMuc2NoZW1hLmpzb24gd2lsbCBub3QgYmUgY29kZSBnZW5lcmF0ZWQuIFlvdSBjYW4gYWRkIHN1Y2ggdmFsdWVzIHRvIHRoaXMgcHJvcGVydHkuJyxcbiAgICAgICAgICAgICAgYWRkaXRpb25hbFByb3BlcnRpZXM6IHsgdHlwZTogJ29iamVjdCcgfSxcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGFkZEFkZGl0aW9uYWxWYWx1ZXNUb1Byb3BzKHByb3ApO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRlbXBTY2hlbWE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRpbmcgY29uc3RydWN0IHByb3BlcnRpZXNcbiAgICBlbWl0UHJvcHNJbnRlcmZhY2UoKTtcblxuICAgIGNvZGUubGluZSgpO1xuXG4gICAgLy8gQ3JlYXRpbmcgY29uc3RydWN0IGZvciBoZWxtIGNoYXJ0XG4gICAgZW1pdENvbnN0cnVjdCgpO1xuXG4gICAgZnVuY3Rpb24gZW1pdFByb3BzSW50ZXJmYWNlKCkge1xuICAgICAgY29kZS5vcGVuQmxvY2soYGV4cG9ydCBpbnRlcmZhY2UgJHtjaGFydE5hbWV9UHJvcHNgKTtcblxuICAgICAgY29kZS5saW5lKCdyZWFkb25seSBuYW1lc3BhY2U/OiBzdHJpbmc7Jyk7XG4gICAgICBjb2RlLmxpbmUoJ3JlYWRvbmx5IHJlbGVhc2VOYW1lPzogc3RyaW5nOycpO1xuICAgICAgY29kZS5saW5lKCdyZWFkb25seSBoZWxtRXhlY3V0YWJsZT86IHN0cmluZzsnKTtcbiAgICAgIGNvZGUubGluZSgncmVhZG9ubHkgaGVsbUZsYWdzPzogc3RyaW5nW107Jyk7XG5cbiAgICAgIGlmIChzY2hlbWEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb2RlLmxpbmUoJ3JlYWRvbmx5IHZhbHVlcz86IHsgW2tleTogc3RyaW5nXTogYW55IH07Jyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBkb1ZhbHVlc0hhdmVSZXFQcm9wcyA9IGhhc1JlcXVpcmVkUHJvcHMoc2NoZW1hKSA/ICcnIDogJz8nO1xuICAgICAgICBjb2RlLmxpbmUoYHJlYWRvbmx5IHZhbHVlcyR7ZG9WYWx1ZXNIYXZlUmVxUHJvcHN9OiAke3ZhbHVlc0ludGVyZmFjZX07YCk7XG4gICAgICB9XG5cbiAgICAgIGNvZGUuY2xvc2VCbG9jaygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVtaXRDb25zdHJ1Y3QoKSB7XG4gICAgICBjb2RlLm9wZW5CbG9jayhgZXhwb3J0IGNsYXNzICR7Y2hhcnROYW1lfSBleHRlbmRzIENvbnN0cnVjdGApO1xuXG4gICAgICBlbWl0SW5pdGlhbGl6ZXIoKTtcblxuICAgICAgY29kZS5saW5lKCk7XG5cbiAgICAgIGVtaXRBZGRpdGlvbmFsVmFsdWVzRmxhdHRlbkZ1bmMoKTtcblxuICAgICAgY29kZS5jbG9zZUJsb2NrKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW1pdEluaXRpYWxpemVyKCkge1xuICAgICAgY29uc3QgcHJvcHNEZWZpbml0aW9uID0gc2NoZW1hICYmIGhhc1JlcXVpcmVkUHJvcHMoc2NoZW1hKSA/IGAke2NoYXJ0TmFtZX1Qcm9wc2AgOiBgJHtjaGFydE5hbWV9UHJvcHMgPSB7fWA7XG5cbiAgICAgIGNvZGUub3BlbkJsb2NrKGBwdWJsaWMgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6ICR7cHJvcHNEZWZpbml0aW9ufSlgKTtcbiAgICAgIGNvZGUubGluZSgnc3VwZXIoc2NvcGUsIGlkKTsnKTtcblxuICAgICAgY29kZS5saW5lKCdsZXQgdXBkYXRlZFByb3BzID0ge307Jyk7XG4gICAgICBjb2RlLmxpbmUoKTtcbiAgICAgIGNvZGUub3BlbkJsb2NrKCdpZiAocHJvcHMudmFsdWVzKScpO1xuICAgICAgY29kZS5saW5lKCdjb25zdCB7IGFkZGl0aW9uYWxWYWx1ZXMsIC4uLnZhbHVlc1dpdGhvdXRBZGRpdGlvbmFsVmFsdWVzIH0gPSBwcm9wcy52YWx1ZXM7Jyk7XG4gICAgICBjb2RlLm9wZW4oJ3VwZGF0ZWRQcm9wcyA9IHsnKTtcbiAgICAgIGNvZGUubGluZSgnLi4ucHJvcHMsJyk7XG4gICAgICBjb2RlLm9wZW4oJ3ZhbHVlczogeycpO1xuICAgICAgY29kZS5saW5lKCcuLi50aGlzLmZsYXR0ZW5BZGRpdGlvbmFsVmFsdWVzKHZhbHVlc1dpdGhvdXRBZGRpdGlvbmFsVmFsdWVzKSwnKTtcbiAgICAgIGNvZGUubGluZSgnLi4uYWRkaXRpb25hbFZhbHVlcywnKTtcbiAgICAgIGNvZGUuY2xvc2UoJ30sJyk7XG4gICAgICBjb2RlLmNsb3NlKCd9OycpO1xuICAgICAgY29kZS5jbG9zZUJsb2NrKCk7XG4gICAgICBjb2RlLmxpbmUoKTtcblxuICAgICAgY29kZS5vcGVuKCdjb25zdCBmaW5hbFByb3BzOiBIZWxtUHJvcHMgPSB7Jyk7XG4gICAgICBpZiAocmVwb1VybC5zdGFydHNXaXRoKCdvY2k6Ly8nKSkge1xuICAgICAgICBjb2RlLmxpbmUoYGNoYXJ0OiBcXCcke3JlcG9Vcmx9XFwnLGApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29kZS5saW5lKGBjaGFydDogXFwnJHtkZWYuY2hhcnROYW1lfVxcJyxgKTtcbiAgICAgICAgY29kZS5saW5lKGByZXBvOiBcXCcke3JlcG9Vcmx9XFwnLGApO1xuICAgICAgfVxuICAgICAgY29kZS5saW5lKGB2ZXJzaW9uOiBcXCcke2NoYXJ0VmVyc2lvbn1cXCcsYCk7XG4gICAgICBjb2RlLmxpbmUoJy4uLihPYmplY3Qua2V5cyh1cGRhdGVkUHJvcHMpLmxlbmd0aCAhPT0gMCA/IHVwZGF0ZWRQcm9wcyA6IHByb3BzKSwnKTtcbiAgICAgIGNvZGUuY2xvc2UoJ307Jyk7XG5cbiAgICAgIGNvZGUubGluZSgpO1xuICAgICAgY29kZS5saW5lKCduZXcgSGVsbSh0aGlzLCBcXCdIZWxtXFwnLCBmaW5hbFByb3BzKTsnKTtcbiAgICAgIGNvZGUuY2xvc2VCbG9jaygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVtaXRBZGRpdGlvbmFsVmFsdWVzRmxhdHRlbkZ1bmMoKSB7XG4gICAgICBjb2RlLm9wZW5CbG9jaygncHJpdmF0ZSBmbGF0dGVuQWRkaXRpb25hbFZhbHVlcyhwcm9wczogeyBba2V5OiBzdHJpbmddOiBhbnkgfSk6IHsgW2tleTogc3RyaW5nXTogYW55IH0nKTtcbiAgICAgIGNvZGUub3BlbignZm9yIChsZXQgcHJvcCBpbiBwcm9wcykgeycpO1xuICAgICAgY29kZS5vcGVuKCdpZiAoQXJyYXkuaXNBcnJheShwcm9wc1twcm9wXSkpIHsnKTtcbiAgICAgIGNvZGUub3BlbigncHJvcHNbcHJvcF0ubWFwKChpdGVtOiBhbnkpID0+IHsnKTtcbiAgICAgIGNvZGUub3BlbignaWYgKHR5cGVvZiBpdGVtID09PSBcXCdvYmplY3RcXCcgJiYgcHJvcCAhPT0gXFwnYWRkaXRpb25hbFZhbHVlc1xcJykgeycpO1xuICAgICAgY29kZS5saW5lKCdyZXR1cm4gdGhpcy5mbGF0dGVuQWRkaXRpb25hbFZhbHVlcyhpdGVtKTsnKTtcbiAgICAgIGNvZGUuY2xvc2UoJ30nKTtcbiAgICAgIGNvZGUubGluZSgncmV0dXJuIGl0ZW07Jyk7XG4gICAgICBjb2RlLmNsb3NlKCd9KTsnKTtcbiAgICAgIGNvZGUuY2xvc2UoJ30nKTtcbiAgICAgIGNvZGUub3BlbignZWxzZSBpZiAodHlwZW9mIHByb3BzW3Byb3BdID09PSBcXCdvYmplY3RcXCcgJiYgcHJvcCAhPT0gXFwnYWRkaXRpb25hbFZhbHVlc1xcJykgeycpO1xuICAgICAgY29kZS5saW5lKCdwcm9wc1twcm9wXSA9IHRoaXMuZmxhdHRlbkFkZGl0aW9uYWxWYWx1ZXMocHJvcHNbcHJvcF0pOycpO1xuICAgICAgY29kZS5jbG9zZSgnfScpO1xuICAgICAgY29kZS5jbG9zZSgnfScpO1xuICAgICAgY29kZS5saW5lKCk7XG4gICAgICBjb2RlLmxpbmUoJ2NvbnN0IHsgYWRkaXRpb25hbFZhbHVlcywgLi4udmFsdWVzV2l0aG91dEFkZGl0aW9uYWxWYWx1ZXMgfSA9IHByb3BzOycpO1xuICAgICAgY29kZS5saW5lKCk7XG4gICAgICBjb2RlLm9wZW4oJ3JldHVybiB7Jyk7XG4gICAgICBjb2RlLmxpbmUoJy4uLnZhbHVlc1dpdGhvdXRBZGRpdGlvbmFsVmFsdWVzLCcpO1xuICAgICAgY29kZS5saW5lKCcuLi5hZGRpdGlvbmFsVmFsdWVzLCcpO1xuICAgICAgY29kZS5jbG9zZSgnfTsnKTtcbiAgICAgIGNvZGUuY2xvc2VCbG9jaygpO1xuICAgIH1cbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGhhc1JlcXVpcmVkUHJvcHMoc2NoZW1hOiBKU09OU2NoZW1hNCk6Ym9vbGVhbiB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBzY2hlbWE/LnJlcXVpcmVkICYmIEFycmF5LmlzQXJyYXkoc2NoZW1hLnJlcXVpcmVkKSAmJiBzY2hlbWEucmVxdWlyZWQubGVuZ3RoID4gMDtcbn0iXX0=