UNPKG

@cloudsnorkel/cdk-github-runners

Version:

CDK construct to create GitHub Actions self-hosted runners. Creates ephemeral runners on demand. Easy to deploy and highly customizable.

154 lines 17.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MINIMAL_EC2_SSM_SESSION_MANAGER_POLICY_STATEMENT = exports.MINIMAL_ECS_SSM_SESSION_MANAGER_POLICY_STATEMENT = exports.MINIMAL_SSM_SESSION_MANAGER_POLICY_STATEMENT = exports.SingletonLogType = void 0; exports.singletonLambda = singletonLambda; exports.singletonLogGroup = singletonLogGroup; exports.discoverCertificateFiles = discoverCertificateFiles; exports.isGpuInstanceType = isGpuInstanceType; const fs = require("fs"); const path = require("path"); const aws_cdk_lib_1 = require("aws-cdk-lib"); const cdk = require("aws-cdk-lib"); /** * Initialize or return a singleton Lambda function instance. * * @internal */ function singletonLambda(functionType, scope, id, props) { const constructName = `${id}-dcc036c8-876b-451e-a2c1-552f9e06e9e1`; const existing = cdk.Stack.of(scope).node.tryFindChild(constructName); if (existing) { // Just assume this is true return existing; } return new functionType(cdk.Stack.of(scope), constructName, props); } /** * Central log group type. * * @internal */ var SingletonLogType; (function (SingletonLogType) { SingletonLogType["RUNNER_IMAGE_BUILD"] = "Runner Image Build Helpers Log"; SingletonLogType["ORCHESTRATOR"] = "Orchestrator Log"; SingletonLogType["SETUP"] = "Setup Log"; })(SingletonLogType || (exports.SingletonLogType = SingletonLogType = {})); /** * Initialize or return central log group instance. * * @internal */ function singletonLogGroup(scope, type) { const existing = cdk.Stack.of(scope).node.tryFindChild(type); if (existing) { // Just assume this is true return existing; } return new aws_cdk_lib_1.aws_logs.LogGroup(cdk.Stack.of(scope), type, { retention: aws_cdk_lib_1.aws_logs.RetentionDays.ONE_MONTH, removalPolicy: cdk.RemovalPolicy.DESTROY, }); } /** * The absolute minimum permissions required for SSM Session Manager to work. Unlike `AmazonSSMManagedInstanceCore`, it doesn't give permission to read all SSM parameters. * * @internal */ exports.MINIMAL_SSM_SESSION_MANAGER_POLICY_STATEMENT = new aws_cdk_lib_1.aws_iam.PolicyStatement({ actions: [ 'ssmmessages:CreateControlChannel', 'ssmmessages:CreateDataChannel', 'ssmmessages:OpenControlChannel', 'ssmmessages:OpenDataChannel', ], resources: ['*'], }); /** * The absolute minimum permissions required for SSM Session Manager on ECS to work. Unlike `AmazonSSMManagedInstanceCore`, it doesn't give permission to read all SSM parameters. * * @internal */ exports.MINIMAL_ECS_SSM_SESSION_MANAGER_POLICY_STATEMENT = new aws_cdk_lib_1.aws_iam.PolicyStatement({ actions: [ 'ssmmessages:CreateControlChannel', 'ssmmessages:CreateDataChannel', 'ssmmessages:OpenControlChannel', 'ssmmessages:OpenDataChannel', 's3:GetEncryptionConfiguration', ], resources: ['*'], }); /** * The absolute minimum permissions required for SSM Session Manager on EC2 to work. Unlike `AmazonSSMManagedInstanceCore`, it doesn't give permission to read all SSM parameters. * * @internal */ exports.MINIMAL_EC2_SSM_SESSION_MANAGER_POLICY_STATEMENT = new aws_cdk_lib_1.aws_iam.PolicyStatement({ actions: [ 'ssmmessages:CreateControlChannel', 'ssmmessages:CreateDataChannel', 'ssmmessages:OpenControlChannel', 'ssmmessages:OpenDataChannel', 's3:GetEncryptionConfiguration', 'ssm:UpdateInstanceInformation', ], resources: ['*'], }); /** * Discovers certificate files from a given path (file or directory). * * If the path is a directory, finds all .pem and .crt files in it. * If the path is a file, returns it as a single certificate file. * * @param sourcePath path to a certificate file or directory containing certificate files * @returns array of certificate file paths, sorted alphabetically * @throws Error if path doesn't exist, is neither file nor directory, or directory has no certificate files * * @internal */ function discoverCertificateFiles(sourcePath) { let certificateFiles = []; try { const stat = fs.statSync(sourcePath); if (stat.isDirectory()) { // Read directory and find all .pem and .crt files const files = fs.readdirSync(sourcePath); certificateFiles = files .filter(file => file.endsWith('.pem') || file.endsWith('.crt')) .map(file => path.join(sourcePath, file)) .sort(); // Sort for consistent ordering if (certificateFiles.length === 0) { throw new Error(`No certificate files (.pem or .crt) found in directory: ${sourcePath}`); } } else if (stat.isFile()) { // Single file - backwards compatible certificateFiles = [sourcePath]; } else { throw new Error(`Certificate source path is neither a file nor a directory: ${sourcePath}`); } } catch (error) { if (error.code === 'ENOENT') { throw new Error(`Certificate source path does not exist: ${sourcePath}`); } throw error; } return certificateFiles; } /** * Returns true if the instance type has an NVIDIA GPU. * * Uses AWS naming convention: most NVIDIA GPU instances use 'g' (g4dn, g5, g6, g9...) or 'p' (p3, p4d, p5, p6...) * prefix followed by a digit. Explicitly excludes known non-NVIDIA GPU families such as g4ad (AMD). * * @internal */ function isGpuInstanceType(instanceType) { const s = instanceType.toString().toLowerCase(); // Match GPU instance families starting with g/p + digit, but exclude known non-NVIDIA GPU families. return /^[gp]\d+(?!ad)/.test(s); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBV0EsMENBWUM7QUFrQkQsOENBV0M7QUE4REQsNERBOEJDO0FBVUQsOENBSUM7QUE5SkQseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qiw2Q0FBcUc7QUFDckcsbUNBQW1DO0FBR25DOzs7O0dBSUc7QUFDSCxTQUFnQixlQUFlLENBQzdCLFlBQXVGLEVBQ3ZGLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQThCO0lBRTVELE1BQU0sYUFBYSxHQUFHLEdBQUcsRUFBRSx1Q0FBdUMsQ0FBQztJQUNuRSxNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3RFLElBQUksUUFBUSxFQUFFLENBQUM7UUFDYiwyQkFBMkI7UUFDM0IsT0FBTyxRQUF3QixDQUFDO0lBQ2xDLENBQUM7SUFFRCxPQUFPLElBQUksWUFBWSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNyRSxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILElBQVksZ0JBSVg7QUFKRCxXQUFZLGdCQUFnQjtJQUMxQix5RUFBcUQsQ0FBQTtJQUNyRCxxREFBaUMsQ0FBQTtJQUNqQyx1Q0FBbUIsQ0FBQTtBQUNyQixDQUFDLEVBSlcsZ0JBQWdCLGdDQUFoQixnQkFBZ0IsUUFJM0I7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsS0FBZ0IsRUFBRSxJQUFzQjtJQUN4RSxNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdE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RCxNQUFNLEtBQUssQ0FBQztJQUNkLENBQUM7SUFFRCxPQUFPLGdCQUFnQixDQUFDO0FBQzFCLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsU0FBZ0IsaUJBQWlCLENBQUMsWUFBOEI7SUFDOUQsTUFBTSxDQUFDLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2hELG9HQUFvRztJQUNwRyxPQUFPLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNsQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGF3c19lYzIgYXMgZWMyLCBhd3NfaWFtIGFzIGlhbSwgYXdzX2xhbWJkYSBhcyBsYW1iZGEsIGF3c19sb2dzIGFzIGxvZ3MgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBvciByZXR1cm4gYSBzaW5nbGV0b24gTGFtYmRhIGZ1bmN0aW9uIGluc3RhbmNlLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2luZ2xldG9uTGFtYmRhPEZ1bmN0aW9uVHlwZSBleHRlbmRzIGxhbWJkYS5GdW5jdGlvbj4oXG4gIGZ1bmN0aW9uVHlwZTogbmV3IChzOiBDb25zdHJ1Y3QsIGk6IHN0cmluZywgcD86IGxhbWJkYS5GdW5jdGlvbk9wdGlvbnMpID0+IEZ1bmN0aW9uVHlwZSxcbiAgc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM/OiBsYW1iZGEuRnVuY3Rpb25PcHRpb25zKTogRnVuY3Rpb25UeXBlIHtcblxuICBjb25zdCBjb25zdHJ1Y3ROYW1lID0gYCR7aWR9LWRjYzAzNmM4LTg3NmItNDUxZS1hMmMxLTU1MmY5ZTA2ZTllMWA7XG4gIGNvbnN0IGV4aXN0aW5nID0gY2RrLlN0YWNrLm9mKHNjb3BlKS5ub2RlLnRyeUZpbmRDaGlsZChjb25zdHJ1Y3ROYW1lKTtcbiAgaWYgKGV4aXN0aW5nKSB7XG4gICAgLy8gSnVzdCBhc3N1bWUgdGhpcyBpcyB0cnVlXG4gICAgcmV0dXJuIGV4aXN0aW5nIGFzIEZ1bmN0aW9uVHlwZTtcbiAgfVxuXG4gIHJldHVybiBuZXcgZnVuY3Rpb25UeXBlKGNkay5TdGFjay5vZihzY29wZSksIGNvbnN0cnVjdE5hbWUsIHByb3BzKTtcbn1cblxuLyoqXG4gKiBDZW50cmFsIGxvZyBncm91cCB0eXBlLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZW51bSBTaW5nbGV0b25Mb2dUeXBlIHtcbiAgUlVOTkVSX0lNQUdFX0JVSUxEID0gJ1J1bm5lciBJbWFnZSBCdWlsZCBIZWxwZXJzIExvZycsXG4gIE9SQ0hFU1RSQVRPUiA9ICdPcmNoZXN0cmF0b3IgTG9nJyxcbiAgU0VUVVAgPSAnU2V0dXAgTG9nJyxcbn1cblxuLyoqXG4gKiBJbml0aWFsaXplIG9yIHJldHVybiBjZW50cmFsIGxvZyBncm91cCBpbnN0YW5jZS5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNpbmdsZXRvbkxvZ0dyb3VwKHNjb3BlOiBDb25zdHJ1Y3QsIHR5cGU6IFNpbmdsZXRvbkxvZ1R5cGUpOiBsb2dzLklMb2dHcm91cCB7XG4gIGNvbnN0IGV4aXN0aW5nID0gY2RrLlN0YWNrLm9mKHNjb3BlKS5ub2RlLnRyeUZpbmRDaGlsZCh0eXBlKTtcbiAgaWYgKGV4aXN0aW5nKSB7XG4gICAgLy8gSnVzdCBhc3N1bWUgdGhpcyBpcyB0cnVlXG4gICAgcmV0dXJuIGV4aXN0aW5nIGFzIGxvZ3MuSUxvZ0dyb3VwO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBsb2dzLkxvZ0dyb3VwKGNkay5TdGFjay5vZihzY29wZSksIHR5cGUsIHtcbiAgICByZXRlbnRpb246IGxvZ3MuUmV0ZW50aW9uRGF5cy5PTkVfTU9OVEgsXG4gICAgcmVtb3ZhbFBvbGljeTogY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgfSk7XG59XG5cbi8qKlxuICogVGhlIGFic29sdXRlIG1pbmltdW0gcGVybWlzc2lvbnMgcmVxdWlyZWQgZm9yIFNTTSBTZXNzaW9uIE1hbmFnZXIgdG8gd29yay4gVW5saWtlIGBBbWF6b25TU01NYW5hZ2VkSW5zdGFuY2VDb3JlYCwgaXQgZG9lc24ndCBnaXZlIHBlcm1pc3Npb24gdG8gcmVhZCBhbGwgU1NNIHBhcmFtZXRlcnMuXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjb25zdCBNSU5JTUFMX1NTTV9TRVNTSU9OX01BTkFHRVJfUE9MSUNZX1NUQVRFTUVOVCA9IG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgYWN0aW9uczogW1xuICAgICdzc21tZXNzYWdlczpDcmVhdGVDb250cm9sQ2hhbm5lbCcsXG4gICAgJ3NzbW1lc3NhZ2VzOkNyZWF0ZURhdGFDaGFubmVsJyxcbiAgICAnc3NtbWVzc2FnZXM6T3BlbkNvbnRyb2xDaGFubmVsJyxcbiAgICAnc3NtbWVzc2FnZXM6T3BlbkRhdGFDaGFubmVsJyxcbiAgXSxcbiAgcmVzb3VyY2VzOiBbJyonXSxcbn0pO1xuXG4vKipcbiAqIFRoZSBhYnNvbHV0ZSBtaW5pbXVtIHBlcm1pc3Npb25zIHJlcXVpcmVkIGZvciBTU00gU2Vzc2lvbiBNYW5hZ2VyIG9uIEVDUyB0byB3b3JrLiBVbmxpa2UgYEFtYXpvblNTTU1hbmFnZWRJbnN0YW5jZUNvcmVgLCBpdCBkb2Vzbid0IGdpdmUgcGVybWlzc2lvbiB0byByZWFkIGFsbCBTU00gcGFyYW1ldGVycy5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGNvbnN0IE1JTklNQUxfRUNTX1NTTV9TRVNTSU9OX01BTkFHRVJfUE9MSUNZX1NUQVRFTUVOVCA9IG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgYWN0aW9uczogW1xuICAgICdzc21tZXNzYWdlczpDcmVhdGVDb250cm9sQ2hhbm5lbCcsXG4gICAgJ3NzbW1lc3NhZ2VzOkNyZWF0ZURhdGFDaGFubmVsJyxcbiAgICAnc3NtbWVzc2FnZXM6T3BlbkNvbnRyb2xDaGFubmVsJyxcbiAgICAnc3NtbWVzc2FnZXM6T3BlbkRhdGFDaGFubmVsJyxcbiAgICAnczM6R2V0RW5jcnlwdGlvbkNvbmZpZ3VyYXRpb24nLFxuICBdLFxuICByZXNvdXJjZXM6IFsnKiddLFxufSk7XG5cbi8qKlxuICogVGhlIGFic29sdXRlIG1pbmltdW0gcGVybWlzc2lvbnMgcmVxdWlyZWQgZm9yIFNTTSBTZXNzaW9uIE1hbmFnZXIgb24gRUMyIHRvIHdvcmsuIFVubGlrZSBgQW1hem9uU1NNTWFuYWdlZEluc3RhbmNlQ29yZWAsIGl0IGRvZXNuJ3QgZ2l2ZSBwZXJtaXNzaW9uIHRvIHJlYWQgYWxsIFNTTSBwYXJhbWV0ZXJzLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY29uc3QgTUlOSU1BTF9FQzJfU1NNX1NFU1NJT05fTUFOQUdFUl9QT0xJQ1lfU1RBVEVNRU5UID0gbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICBhY3Rpb25zOiBbXG4gICAgJ3NzbW1lc3NhZ2VzOkNyZWF0ZUNvbnRyb2xDaGFubmVsJyxcbiAgICAnc3NtbWVzc2FnZXM6Q3JlYXRlRGF0YUNoYW5uZWwnLFxuICAgICdzc21tZXNzYWdlczpPcGVuQ29udHJvbENoYW5uZWwnLFxuICAgICdzc21tZXNzYWdlczpPcGVuRGF0YUNoYW5uZWwnLFxuICAgICdzMzpHZXRFbmNyeXB0aW9uQ29uZmlndXJhdGlvbicsXG4gICAgJ3NzbTpVcGRhdGVJbnN0YW5jZUluZm9ybWF0aW9uJyxcbiAgXSxcbiAgcmVzb3VyY2VzOiBbJyonXSxcbn0pO1xuXG4vKipcbiAqIERpc2NvdmVycyBjZXJ0aWZpY2F0ZSBmaWxlcyBmcm9tIGEgZ2l2ZW4gcGF0aCAoZmlsZSBvciBkaXJlY3RvcnkpLlxuICpcbiAqIElmIHRoZSBwYXRoIGlzIGEgZGlyZWN0b3J5LCBmaW5kcyBhbGwgLnBlbSBhbmQgLmNydCBmaWxlcyBpbiBpdC5cbiAqIElmIHRoZSBwYXRoIGlzIGEgZmlsZSwgcmV0dXJucyBpdCBhcyBhIHNpbmdsZSBjZXJ0aWZpY2F0ZSBmaWxlLlxuICpcbiAqIEBwYXJhbSBzb3VyY2VQYXRoIHBhdGggdG8gYSBjZXJ0aWZpY2F0ZSBmaWxlIG9yIGRpcmVjdG9yeSBjb250YWluaW5nIGNlcnRpZmljYXRlIGZpbGVzXG4gKiBAcmV0dXJucyBhcnJheSBvZiBjZXJ0aWZpY2F0ZSBmaWxlIHBhdGhzLCBzb3J0ZWQgYWxwaGFiZXRpY2FsbHlcbiAqIEB0aHJvd3MgRXJyb3IgaWYgcGF0aCBkb2Vzbid0IGV4aXN0LCBpcyBuZWl0aGVyIGZpbGUgbm9yIGRpcmVjdG9yeSwgb3IgZGlyZWN0b3J5IGhhcyBubyBjZXJ0aWZpY2F0ZSBmaWxlc1xuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgZnVuY3Rpb24gZGlzY292ZXJDZXJ0aWZpY2F0ZUZpbGVzKHNvdXJjZVBhdGg6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgbGV0IGNlcnRpZmljYXRlRmlsZXM6IHN0cmluZ1tdID0gW107XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBzdGF0ID0gZnMuc3RhdFN5bmMoc291cmNlUGF0aCk7XG4gICAgaWYgKHN0YXQuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgLy8gUmVhZCBkaXJlY3RvcnkgYW5kIGZpbmQgYWxsIC5wZW0gYW5kIC5jcnQgZmlsZXNcbiAgICAgIGNvbnN0IGZpbGVzID0gZnMucmVhZGRpclN5bmMoc291cmNlUGF0aCk7XG4gICAgICBjZXJ0aWZpY2F0ZUZpbGVzID0gZmlsZXNcbiAgICAgICAgLmZpbHRlcihmaWxlID0+IGZpbGUuZW5kc1dpdGgoJy5wZW0nKSB8fCBmaWxlLmVuZHNXaXRoKCcuY3J0JykpXG4gICAgICAgIC5tYXAoZmlsZSA9PiBwYXRoLmpvaW4oc291cmNlUGF0aCwgZmlsZSkpXG4gICAgICAgIC5zb3J0KCk7IC8vIFNvcnQgZm9yIGNvbnNpc3RlbnQgb3JkZXJpbmdcblxuICAgICAgaWYgKGNlcnRpZmljYXRlRmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gY2VydGlmaWNhdGUgZmlsZXMgKC5wZW0gb3IgLmNydCkgZm91bmQgaW4gZGlyZWN0b3J5OiAke3NvdXJjZVBhdGh9YCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChzdGF0LmlzRmlsZSgpKSB7XG4gICAgICAvLyBTaW5nbGUgZmlsZSAtIGJhY2t3YXJkcyBjb21wYXRpYmxlXG4gICAgICBjZXJ0aWZpY2F0ZUZpbGVzID0gW3NvdXJjZVBhdGhdO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENlcnRpZmljYXRlIHNvdXJjZSBwYXRoIGlzIG5laXRoZXIgYSBmaWxlIG5vciBhIGRpcmVjdG9yeTogJHtzb3VyY2VQYXRofWApO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoKGVycm9yIGFzIE5vZGVKUy5FcnJub0V4Y2VwdGlvbikuY29kZSA9PT0gJ0VOT0VOVCcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2VydGlmaWNhdGUgc291cmNlIHBhdGggZG9lcyBub3QgZXhpc3Q6ICR7c291cmNlUGF0aH1gKTtcbiAgICB9XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICByZXR1cm4gY2VydGlmaWNhdGVGaWxlcztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIGluc3RhbmNlIHR5cGUgaGFzIGFuIE5WSURJQSBHUFUuXG4gKlxuICogVXNlcyBBV1MgbmFtaW5nIGNvbnZlbnRpb246IG1vc3QgTlZJRElBIEdQVSBpbnN0YW5jZXMgdXNlICdnJyAoZzRkbiwgZzUsIGc2LCBnOS4uLikgb3IgJ3AnIChwMywgcDRkLCBwNSwgcDYuLi4pXG4gKiBwcmVmaXggZm9sbG93ZWQgYnkgYSBkaWdpdC4gRXhwbGljaXRseSBleGNsdWRlcyBrbm93biBub24tTlZJRElBIEdQVSBmYW1pbGllcyBzdWNoIGFzIGc0YWQgKEFNRCkuXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0dwdUluc3RhbmNlVHlwZShpbnN0YW5jZVR5cGU6IGVjMi5JbnN0YW5jZVR5cGUpOiBib29sZWFuIHtcbiAgY29uc3QgcyA9IGluc3RhbmNlVHlwZS50b1N0cmluZygpLnRvTG93ZXJDYXNlKCk7XG4gIC8vIE1hdGNoIEdQVSBpbnN0YW5jZSBmYW1pbGllcyBzdGFydGluZyB3aXRoIGcvcCArIGRpZ2l0LCBidXQgZXhjbHVkZSBrbm93biBub24tTlZJRElBIEdQVSBmYW1pbGllcy5cbiAgcmV0dXJuIC9eW2dwXVxcZCsoPyFhZCkvLnRlc3Qocyk7XG59XG4iXX0=