UNPKG

@riddance/deploy

Version:

168 lines 31.8 kB
import { jsonResponse, okResponse } from '@riddance/fetch'; import { resolveCpu } from '@riddance/host/reflect'; import JSZip from 'jszip'; import { createHash } from 'node:crypto'; import { isDeepStrictEqual } from 'node:util'; import { compare } from '../diff.js'; import { awsRequest, retry, retryConflict } from '../lite.js'; export async function syncLambda(context, prefix, currentFunctions, reflection, environment, role, code) { const zipped = Object.fromEntries(await Promise.all(Object.entries(code).map(async ([name, c]) => [name, await zip(c)]))); const functions = [...reflection.http, ...reflection.events, ...reflection.timers]; const { missing, surplus, existing } = compare(functions, currentFunctions); const created = await Promise.all(missing.map(fn => createLambda(context, prefix, fn.name, reflection.name, reflection.revision, role, fn, environment, zipped[fn.name]))); await Promise.all(surplus.map(fn => deleteLambda(context, prefix, reflection.name, fn.name))); await Promise.all(existing.map(awsFn => updateLambda(context, prefix, awsFn.name, reflection.name, role, functions.find(fn => fn.name === awsFn.name), awsFn, environment, zipped[awsFn.name]))); return [...currentFunctions.map(fn => ({ id: fn.id, name: fn.name })), ...created]; } async function zip(code) { const buffer = await new JSZip() .file('index.js', code, { compression: 'DEFLATE', compressionOptions: { level: 9 }, date: new Date(2022, 8, 1), }) .generateAsync({ type: 'nodebuffer' }); return { zipped: buffer.toString('base64'), size: buffer.length < 1024 ? `${buffer.length} bytes` : `${Math.ceil(buffer.length / 102.4) / 10} KiB`, sha256: createHash('sha256').update(buffer).digest('base64'), }; } export async function getFunctions(context, prefix, service) { const funcs = []; let marker = ''; for (;;) { const page = await jsonResponse(awsRequest(context, 'GET', 'lambda', `/2015-03-31/functions/?${marker}`), 'Error listing functions'); funcs.push(...page.Functions); if (page.NextMarker === null) { break; } marker = `Marker=${encodeURIComponent(page.NextMarker)}`; } const fnPrefix = `${prefix}-${service}-`.toLowerCase(); return funcs .filter(fn => fn.FunctionName.startsWith(fnPrefix)) .map(fn => ({ id: fn.FunctionArn, name: fn.FunctionName.slice(fnPrefix.length), runtime: fn.Runtime, memory: fn.MemorySize, timeout: fn.Timeout, env: fn.Environment?.Variables ?? {}, cpus: fn.Architectures, hash: fn.CodeSha256, size: fn.CodeSize < 1024 ? `${fn.CodeSize} bytes` : `${Math.ceil(fn.CodeSize / 102.4) / 10} KiB`, })); } async function createLambda(context, prefix, name, service, revision, role, target, environment, code) { if (!code) { throw new Error('No code'); } context.log.trace(`creating lambda ${name} (${code.size})`); const response = await jsonResponse(retry(context.log, () => awsRequest(context, 'POST', 'lambda', '/2015-03-31/functions', { FunctionName: `${prefix}-${service}-${name}`, Code: { ZipFile: code.zipped }, PackageType: 'Zip', Architectures: lambdaArchitecture(target), ...lambdaConfig(target, role, environment), Tags: { framework: 'riddance', environment: prefix, service, revision, }, }), r => (r.status === 400 ? 25 : undefined)), 'Error creating lambda ' + name); return { name, id: response.FunctionArn }; } async function updateLambda(context, prefix, name, service, role, target, awsFn, environment, code) { if (!code) { throw new Error('No code'); } if (!target) { throw new Error('No config'); } const cpus = lambdaArchitecture(target); const awsConfig = lambdaConfig(target, role, environment); if (!isDeepStrictEqual({ cpus, hash: code.sha256 }, { cpus: awsFn.cpus, hash: awsFn.hash })) { context.log.trace(`updating code for lambda ${name} (${awsFn.size} -> ${code.size})`); await okResponse(awsRequest(context, 'PUT', 'lambda', `/2015-03-31/functions/${prefix}-${service}-${name}/code`, { ZipFile: code.zipped, Architectures: cpus, }), 'Error updating code for lambda ' + name); } if (!isDeepStrictEqual({ env: awsConfig.Environment.Variables, memory: awsConfig.MemorySize, timeout: awsConfig.Timeout, runtime: awsConfig.Runtime, }, { env: awsFn.env, memory: awsFn.memory, timeout: awsFn.timeout, runtime: awsFn.runtime, })) { context.log.trace('updating config for lambda ' + name); await retryConflict(() => okResponse(awsRequest(context, 'PUT', 'lambda', `/2015-03-31/functions/${prefix}-${service}-${name}/configuration`, awsConfig), 'Error updating config for lambda ' + name)); } } async function deleteLambda(context, prefix, service, name) { context.log.trace('deleting lambda ' + name); await okResponse(awsRequest(context, 'DELETE', 'lambda', `/2015-03-31/functions/${prefix}-${service}-${name}`), 'Error deleting lambda ' + name); } function lambdaConfig(target, role, environment) { return { Role: role, Runtime: getRuntime(target), Handler: 'index.handler', Timeout: target.config.timeout ?? 15, MemorySize: memorySize(target), TracingConfig: { Mode: 'PassThrough', }, Environment: { Variables: environment, }, }; } function getRuntime({ config }) { switch (config.nodeVersion?.slice(0, 4)) { case '>=24': return 'nodejs24.x'; case '>=22': return 'nodejs22.x'; case '>=20': return 'nodejs20.x'; case '>=18': return 'nodejs18.x'; default: throw new Error('Unsupported engine; please specify "node": ">=18", "node": ">=20", "node": ">=22", or "node": ">=24" as an engine in your package.json.'); } } function memorySize({ config, method }) { if (!config.compute && !config.memory && method) { return 256; } if (config.compute === 'high' || config.memory === 'high') { return 3008; } return 128; } function lambdaArchitecture({ config, method }) { switch (resolveCpu(config, config.compute === 'high' || (config.compute === undefined && method === 'GET') ? ['x64', 'x32', 'arm64', 'arm'] : ['arm64', 'arm', 'x64', 'x32'])) { case 'arm64': case 'arm': return ['arm64']; case 'x64': case 'x32': return ['x86_64']; default: throw new Error('Unsupported CPUs: ' + (config.cpus?.join(', ') ?? '')); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFtYmRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibGFtYmRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDMUQsT0FBTyxFQUF3QyxVQUFVLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQUN6RixPQUFPLEtBQUssTUFBTSxPQUFPLENBQUE7QUFDekIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUN4QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDN0MsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFlBQVksQ0FBQTtBQUNwQyxPQUFPLEVBQWdCLFVBQVUsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBRTNFLE1BQU0sQ0FBQyxLQUFLLFVBQVUsVUFBVSxDQUM1QixPQUFnQixFQUNoQixNQUFjLEVBQ2QsZ0JBQW1DLEVBQ25DLFVBQXNCLEVBQ3RCLFdBQXNDLEVBQ3RDLElBQVksRUFDWixJQUFnQztJQUVoQyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsV0FBVyxDQUM3QixNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQ2IsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBVSxDQUFDLENBQy9FLENBQ0osQ0FBQTtJQUVELE1BQU0sU0FBUyxHQUFHLENBQUMsR0FBRyxVQUFVLENBQUMsSUFBSSxFQUFFLEdBQUcsVUFBVSxDQUFDLE1BQU0sRUFBRSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUNsRixNQUFNLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUs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QUFFRCxTQUFTLGtCQUFrQixDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBVTtJQUNsRCxRQUNJLFVBQVUsQ0FDTixNQUFNLEVBQ04sTUFBTSxDQUFDLE9BQU8sS0FBSyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxLQUFLLFNBQVMsSUFBSSxNQUFNLEtBQUssS0FBSyxDQUFDO1FBQzNFLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQztRQUNoQyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FDdkMsRUFDSCxDQUFDO1FBQ0MsS0FBSyxPQUFPLENBQUM7UUFDYixLQUFLLEtBQUs7WUFDTixPQUFPLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDcEIsS0FBSyxLQUFLLENBQUM7UUFDWCxLQUFLLEtBQUs7WUFDTixPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDckI7WUFDSSxNQUFNLElBQUksS0FBSyxDQUFDLG9CQUFvQixHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUMvRSxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGpzb25SZXNwb25zZSwgb2tSZXNwb25zZSB9IGZyb20gJ0ByaWRkYW5jZS9mZXRjaCdcbmltcG9ydCB7IFBhY2thZ2VKc29uQ29uZmlndXJhdGlvbiwgUmVmbGVjdGlvbiwgcmVzb2x2ZUNwdSB9IGZyb20gJ0ByaWRkYW5jZS9ob3N0L3JlZmxlY3QnXG5pbXBvcnQgSlNaaXAgZnJvbSAnanN6aXAnXG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSAnbm9kZTpjcnlwdG8nXG5pbXBvcnQgeyBpc0RlZXBTdHJpY3RFcXVhbCB9IGZyb20gJ25vZGU6dXRpbCdcbmltcG9ydCB7IGNvbXBhcmUgfSBmcm9tICcuLi9kaWZmLmpzJ1xuaW1wb3J0IHsgdHlwZSBDb250ZXh0LCBhd3NSZXF1ZXN0LCByZXRyeSwgcmV0cnlDb25mbGljdCB9IGZyb20gJy4uL2xpdGUuanMnXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzeW5jTGFtYmRhKFxuICAgIGNvbnRleHQ6IENvbnRleHQsXG4gICAgcHJlZml4OiBzdHJpbmcsXG4gICAgY3VycmVudEZ1bmN0aW9uczogQXdzRnVuY3Rpb25MaXRlW10sXG4gICAgcmVmbGVjdGlvbjogUmVmbGVjdGlvbixcbiAgICBlbnZpcm9ubWVudDogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSxcbiAgICByb2xlOiBzdHJpbmcsXG4gICAgY29kZTogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0sXG4pIHtcbiAgICBjb25zdCB6aXBwZWQgPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMoY29kZSkubWFwKGFzeW5jIChbbmFtZSwgY10pID0+IFtuYW1lLCBhd2FpdCB6aXAoYyldIGFzIGNvbnN0KSxcbiAgICAgICAgKSxcbiAgICApXG5cbiAgICBjb25zdCBmdW5jdGlvbnMgPSBbLi4ucmVmbGVjdGlvbi5odHRwLCAuLi5yZWZsZWN0aW9uLmV2ZW50cywgLi4ucmVmbGVjdGlvbi50aW1lcnNdXG4gICAgY29uc3QgeyBtaXNzaW5nLCBzdXJwbHVzLCBleGlzdGluZyB9ID0gY29tcGFyZShmdW5jdGlvbnMsIGN1cnJlbnRGdW5jdGlvbnMpXG4gICAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBtaXNzaW5nLm1hcChmbiA9PlxuICAgICAgICAgICAgY3JlYXRlTGFtYmRhKFxuICAgICAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgICAgICAgcHJlZml4LFxuICAgICAgICAgICAgICAgIGZuLm5hbWUsXG4gICAgICAgICAgICAgICAgcmVmbGVjdGlvbi5uYW1lLFxuICAgICAgICAgICAgICAgIHJlZmxlY3Rpb24ucmV2aXNpb24sXG4gICAgICAgICAgICAgICAgcm9sZSxcbiAgICAgICAgICAgICAgICBmbixcbiAgICAgICAgICAgICAgICBlbnZpcm9ubWVudCxcbiAgICAgICAgICAgICAgICB6aXBwZWRbZm4ubmFtZV0sXG4gICAgICAgICAgICApLFxuICAgICAgICApLFxuICAgIClcbiAgICBhd2FpdCBQcm9taXNlLmFsbChzdXJwbHVzLm1hcChmbiA9PiBkZWxldGVMYW1iZGEoY29udGV4dCwgcHJlZml4LCByZWZsZWN0aW9uLm5hbWUsIGZuLm5hbWUpKSlcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgZXhpc3RpbmcubWFwKGF3c0ZuID0+XG4gICAgICAgICAgICB1cGRhdGVMYW1iZGEoXG4gICAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICAgICBwcmVmaXgsXG4gICAgICAgICAgICAgICAgYXdzRm4ubmFtZSxcbiAgICAgICAgICAgICAgICByZWZsZWN0aW9uLm5hbWUsXG4gICAgICAgICAgICAgICAgcm9sZSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvbnMuZmluZChmbiA9PiBmbi5uYW1lID09PSBhd3NGbi5uYW1lKSxcbiAgICAgICAgICAgICAgICBhd3NGbixcbiAgICAgICAgICAgICAgICBlbnZpcm9ubWVudCxcbiAgICAgICAgICAgICAgICB6aXBwZWRbYXdzRm4ubmFtZV0sXG4gICAgICAgICAgICApLFxuICAgICAgICApLFxuICAgIClcblxuICAgIHJldHVybiBbLi4uY3VycmVudEZ1bmN0aW9ucy5tYXAoZm4gPT4gKHsgaWQ6IGZuLmlkLCBuYW1lOiBmbi5uYW1lIH0pKSwgLi4uY3JlYXRlZF1cbn1cblxuYXN5bmMgZnVuY3Rpb24gemlwKGNvZGU6IHN0cmluZykge1xuICAgIGNvbnN0IGJ1ZmZlciA9IGF3YWl0IG5ldyBKU1ppcCgpXG4gICAgICAgIC5maWxlKCdpbmRleC5qcycsIGNvZGUsIHtcbiAgICAgICAgICAgIGNvbXByZXNzaW9uOiAnREVGTEFURScsXG4gICAgICAgICAgICBjb21wcmVzc2lvbk9wdGlvbnM6IHsgbGV2ZWw6IDkgfSxcbiAgICAgICAgICAgIGRhdGU6IG5ldyBEYXRlKDIwMjIsIDgsIDEpLFxuICAgICAgICB9KVxuICAgICAgICAuZ2VuZXJhdGVBc3luYyh7IHR5cGU6ICdub2RlYnVmZmVyJyB9KVxuICAgIHJldHVybiB7XG4gICAgICAgIHppcHBlZDogYnVmZmVyLnRvU3RyaW5nKCdiYXNlNjQnKSxcbiAgICAgICAgc2l6ZTpcbiAgICAgICAgICAgIGJ1ZmZlci5sZW5ndGggPCAxMDI0XG4gICAgICAgICAgICAgICAgPyBgJHtidWZmZXIubGVuZ3RofSBieXRlc2BcbiAgICAgICAgICAgICAgICA6IGAke01hdGguY2VpbChidWZmZXIubGVuZ3RoIC8gMTAyLjQpIC8gMTB9IEtpQmAsXG4gICAgICAgIHNoYTI1NjogY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGJ1ZmZlcikuZGlnZXN0KCdiYXNlNjQnKSxcbiAgICB9XG59XG5cbnR5cGUgQXJjaGl0ZWN0dXJlcyA9IFsnYXJtNjQnXSB8IFsneDg2XzY0J11cbmV4cG9ydCB0eXBlIEF3c0Z1bmN0aW9uTGl0ZSA9IHtcbiAgICBpZDogc3RyaW5nXG4gICAgbmFtZTogc3RyaW5nXG4gICAgcnVudGltZTogc3RyaW5nXG4gICAgbWVtb3J5OiBudW1iZXJcbiAgICB0aW1lb3V0OiBudW1iZXJcbiAgICBlbnY6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH1cbiAgICBjcHVzOiBBcmNoaXRlY3R1cmVzXG4gICAgaGFzaDogc3RyaW5nXG4gICAgc2l6ZTogc3RyaW5nXG59XG5cbnR5cGUgQXdzRnVuY3Rpb24gPSB7XG4gICAgRGVzY3JpcHRpb246IHN0cmluZ1xuICAgIFRyYWNpbmdDb25maWc6IHtcbiAgICAgICAgTW9kZTogJ1Bhc3NUaHJvdWdoJ1xuICAgIH1cbiAgICBSZXZpc2lvbklkOiBzdHJpbmdcbiAgICBMYXN0TW9kaWZpZWQ6IHN0cmluZ1xuICAgIEZ1bmN0aW9uQXJuOiBzdHJpbmdcbiAgICBGdW5jdGlvbk5hbWU6IHN0cmluZ1xuICAgIFJ1bnRpbWU6ICdub2RlanMxOC54JyB8ICdub2RlanMyMC54JyB8ICdub2RlanMyMi54JyB8ICdub2RlanMyNC54J1xuICAgIFZlcnNpb246ICckTEFURVNUJ1xuICAgIFBhY2thZ2VUeXBlOiAnWmlwJ1xuICAgIE1lbW9yeVNpemU6IG51bWJlclxuICAgIFRpbWVvdXQ6IG51bWJlclxuICAgIEhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJ1xuICAgIENvZGVTaGEyNTY6IHN0cmluZ1xuICAgIFJvbGU6IHN0cmluZ1xuICAgIFNpZ25pbmdQcm9maWxlVmVyc2lvbkFybjogbnVsbFxuICAgIE1hc3RlckFybjogbnVsbFxuICAgIENvZGVTaXplOiBudW1iZXJcbiAgICBTdGF0ZTogbnVsbFxuICAgIFN0YXRlUmVhc29uOiBudWxsXG4gICAgRW52aXJvbm1lbnQ/OiB7XG4gICAgICAgIFZhcmlhYmxlczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfVxuICAgICAgICBFcnJvcjogbnVsbFxuICAgIH1cbiAgICBFcGhlbWVyYWxTdG9yYWdlOiB7XG4gICAgICAgIFNpemU6IG51bWJlclxuICAgIH1cbiAgICBTdGF0ZVJlYXNvbkNvZGU6IG51bGxcbiAgICBMYXN0VXBkYXRlU3RhdHVzUmVhc29uQ29kZTogbnVsbFxuICAgIEFyY2hpdGVjdHVyZXM6IEFyY2hpdGVjdHVyZXNcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEZ1bmN0aW9ucyhcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIHByZWZpeDogc3RyaW5nLFxuICAgIHNlcnZpY2U6IHN0cmluZyxcbik6IFByb21pc2U8QXdzRnVuY3Rpb25MaXRlW10+IHtcbiAgICBjb25zdCBmdW5jcyA9IFtdXG4gICAgbGV0IG1hcmtlciA9ICcnXG4gICAgZm9yICg7Oykge1xuICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQganNvblJlc3BvbnNlPHtcbiAgICAgICAgICAgIEZ1bmN0aW9uczogQXdzRnVuY3Rpb25bXVxuICAgICAgICAgICAgTmV4dE1hcmtlcjogc3RyaW5nIHwgbnVsbFxuICAgICAgICB9PihcbiAgICAgICAgICAgIGF3c1JlcXVlc3QoY29udGV4dCwgJ0dFVCcsICdsYW1iZGEnLCBgLzIwMTUtMDMtMzEvZnVuY3Rpb25zLz8ke21hcmtlcn1gKSxcbiAgICAgICAgICAgICdFcnJvciBsaXN0aW5nIGZ1bmN0aW9ucycsXG4gICAgICAgIClcbiAgICAgICAgZnVuY3MucHVzaCguLi5wYWdlLkZ1bmN0aW9ucylcbiAgICAgICAgaWYgKHBhZ2UuTmV4dE1hcmtlciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgICBtYXJrZXIgPSBgTWFya2VyPSR7ZW5jb2RlVVJJQ29tcG9uZW50KHBhZ2UuTmV4dE1hcmtlcil9YFxuICAgIH1cbiAgICBjb25zdCBmblByZWZpeCA9IGAke3ByZWZpeH0tJHtzZXJ2aWNlfS1gLnRvTG93ZXJDYXNlKClcbiAgICByZXR1cm4gZnVuY3NcbiAgICAgICAgLmZpbHRlcihmbiA9PiBmbi5GdW5jdGlvbk5hbWUuc3RhcnRzV2l0aChmblByZWZpeCkpXG4gICAgICAgIC5tYXAoZm4gPT4gKHtcbiAgICAgICAgICAgIGlkOiBmbi5GdW5jdGlvbkFybixcbiAgICAgICAgICAgIG5hbWU6IGZuLkZ1bmN0aW9uTmFtZS5zbGljZShmblByZWZpeC5sZW5ndGgpLFxuICAgICAgICAgICAgcnVudGltZTogZm4uUnVudGltZSxcbiAgICAgICAgICAgIG1lbW9yeTogZm4uTWVtb3J5U2l6ZSxcbiAgICAgICAgICAgIHRpbWVvdXQ6IGZuLlRpbWVvdXQsXG4gICAgICAgICAgICBlbnY6IGZuLkVudmlyb25tZW50Py5WYXJpYWJsZXMgPz8ge30sXG4gICAgICAgICAgICBjcHVzOiBmbi5BcmNoaXRlY3R1cmVzLFxuICAgICAgICAgICAgaGFzaDogZm4uQ29kZVNoYTI1NixcbiAgICAgICAgICAgIHNpemU6XG4gICAgICAgICAgICAgICAgZm4uQ29kZVNpemUgPCAxMDI0XG4gICAgICAgICAgICAgICAgICAgID8gYCR7Zm4uQ29kZVNpemV9IGJ5dGVzYFxuICAgICAgICAgICAgICAgICAgICA6IGAke01hdGguY2VpbChmbi5Db2RlU2l6ZSAvIDEwMi40KSAvIDEwfSBLaUJgLFxuICAgICAgICB9KSlcbn1cblxudHlwZSBUYXJnZXQgPSB7XG4gICAgY29uZmlnOiB7XG4gICAgICAgIG1lbW9yeT86IHN0cmluZ1xuICAgICAgICBjb21wdXRlPzogc3RyaW5nXG4gICAgICAgIHRpbWVvdXQ/OiBudW1iZXJcbiAgICB9ICYgUGFja2FnZUpzb25Db25maWd1cmF0aW9uXG4gICAgbWV0aG9kPzogc3RyaW5nXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUxhbWJkYShcbiAgICBjb250ZXh0OiBDb250ZXh0LFxuICAgIHByZWZpeDogc3RyaW5nLFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBzZXJ2aWNlOiBzdHJpbmcsXG4gICAgcmV2aXNpb246IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICByb2xlOiBzdHJpbmcsXG4gICAgdGFyZ2V0OiBUYXJnZXQsXG4gICAgZW52aXJvbm1lbnQ6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0sXG4gICAgY29kZT86IHsgemlwcGVkOiBzdHJpbmc7IHNoYTI1Njogc3RyaW5nOyBzaXplOiBzdHJpbmcgfSxcbikge1xuICAgIGlmICghY29kZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGNvZGUnKVxuICAgIH1cbiAgICBjb250ZXh0LmxvZy50cmFjZShgY3JlYXRpbmcgbGFtYmRhICR7bmFtZX0gKCR7Y29kZS5zaXplfSlgKVxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQganNvblJlc3BvbnNlPHsgRnVuY3Rpb25Bcm46IHN0cmluZyB9PihcbiAgICAgICAgcmV0cnkoXG4gICAgICAgICAgICBjb250ZXh0LmxvZyxcbiAgICAgICAgICAgICgpID0+XG4gICAgICAgICAgICAgICAgYXdzUmVxdWVzdChjb250ZXh0LCAnUE9TVCcsICdsYW1iZGEnLCAnLzIwMTUtMDMtMzEvZnVuY3Rpb25zJywge1xuICAgICAgICAgICAgICAgICAgICBGdW5jdGlvbk5hbWU6IGAke3ByZWZpeH0tJHtzZXJ2aWNlfS0ke25hbWV9YCxcbiAgICAgICAgICAgICAgICAgICAgQ29kZTogeyBaaXBGaWxlOiBjb2RlLnppcHBlZCB9LFxuICAgICAgICAgICAgICAgICAgICBQYWNrYWdlVHlwZTogJ1ppcCcsXG4gICAgICAgICAgICAgICAgICAgIEFyY2hpdGVjdHVyZXM6IGxhbWJkYUFyY2hpdGVjdHVyZSh0YXJnZXQpLFxuICAgICAgICAgICAgICAgICAgICAuLi5sYW1iZGFDb25maWcodGFyZ2V0LCByb2xlLCBlbnZpcm9ubWVudCksXG4gICAgICAgICAgICAgICAgICAgIFRhZ3M6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyYW1ld29yazogJ3JpZGRhbmNlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudmlyb25tZW50OiBwcmVmaXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXJ2aWNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmV2aXNpb24sXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICByID0+IChyLnN0YXR1cyA9PT0gNDAwID8gMjUgOiB1bmRlZmluZWQpLFxuICAgICAgICApLFxuICAgICAgICAnRXJyb3IgY3JlYXRpbmcgbGFtYmRhICcgKyBuYW1lLFxuICAgIClcbiAgICByZXR1cm4geyBuYW1lLCBpZDogcmVzcG9uc2UuRnVuY3Rpb25Bcm4gfVxufVxuXG5hc3luYyBmdW5jdGlvbiB1cGRhdGVMYW1iZGEoXG4gICAgY29udGV4dDogQ29udGV4dCxcbiAgICBwcmVmaXg6IHN0cmluZyxcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgc2VydmljZTogc3RyaW5nLFxuICAgIHJvbGU6IHN0cmluZyxcbiAgICB0YXJnZXQ6IFRhcmdldCB8IHVuZGVmaW5lZCxcbiAgICBhd3NGbjogQXdzRnVuY3Rpb25MaXRlLFxuICAgIGVudmlyb25tZW50OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9LFxuICAgIGNvZGU/OiB7IHppcHBlZDogc3RyaW5nOyBzaGEyNTY6IHN0cmluZzsgc2l6ZTogc3RyaW5nIH0sXG4pIHtcbiAgICBpZiAoIWNvZGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjb2RlJylcbiAgICB9XG4gICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBjb25maWcnKVxuICAgIH1cbiAgICBjb25zdCBjcHVzID0gbGFtYmRhQXJjaGl0ZWN0dXJlKHRhcmdldClcbiAgICBjb25zdCBhd3NDb25maWcgPSBsYW1iZGFDb25maWcodGFyZ2V0LCByb2xlLCBlbnZpcm9ubWVudClcbiAgICBpZiAoIWlzRGVlcFN0cmljdEVxdWFsKHsgY3B1cywgaGFzaDogY29kZS5zaGEyNTYgfSwgeyBjcHVzOiBhd3NGbi5jcHVzLCBoYXNoOiBhd3NGbi5oYXNoIH0pKSB7XG4gICAgICAgIGNvbnRleHQubG9nLnRyYWNlKGB1cGRhdGluZyBjb2RlIGZvciBsYW1iZGEgJHtuYW1lfSAoJHthd3NGbi5zaXplfSAtPiAke2NvZGUuc2l6ZX0pYClcbiAgICAgICAgYXdhaXQgb2tSZXNwb25zZShcbiAgICAgICAgICAgIGF3c1JlcXVlc3QoXG4gICAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICAgICAnUFVUJyxcbiAgICAgICAgICAgICAgICAnbGFtYmRhJyxcbiAgICAgICAgICAgICAgICBgLzIwMTUtMDMtMzEvZnVuY3Rpb25zLyR7cHJlZml4fS0ke3NlcnZpY2V9LSR7bmFtZX0vY29kZWAsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBaaXBGaWxlOiBjb2RlLnppcHBlZCxcbiAgICAgICAgICAgICAgICAgICAgQXJjaGl0ZWN0dXJlczogY3B1cyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICdFcnJvciB1cGRhdGluZyBjb2RlIGZvciBsYW1iZGEgJyArIG5hbWUsXG4gICAgICAgIClcbiAgICB9XG4gICAgaWYgKFxuICAgICAgICAhaXNEZWVwU3RyaWN0RXF1YWwoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZW52OiBhd3NDb25maWcuRW52aXJvbm1lbnQuVmFyaWFibGVzLFxuICAgICAgICAgICAgICAgIG1lbW9yeTogYXdzQ29uZmlnLk1lbW9yeVNpemUsXG4gICAgICAgICAgICAgICAgdGltZW91dDogYXdzQ29uZmlnLlRpbWVvdXQsXG4gICAgICAgICAgICAgICAgcnVudGltZTogYXdzQ29uZmlnLlJ1bnRpbWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGVudjogYXdzRm4uZW52LFxuICAgICAgICAgICAgICAgIG1lbW9yeTogYXdzRm4ubWVtb3J5LFxuICAgICAgICAgICAgICAgIHRpbWVvdXQ6IGF3c0ZuLnRpbWVvdXQsXG4gICAgICAgICAgICAgICAgcnVudGltZTogYXdzRm4ucnVudGltZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIClcbiAgICApIHtcbiAgICAgICAgY29udGV4dC5sb2cudHJhY2UoJ3VwZGF0aW5nIGNvbmZpZyBmb3IgbGFtYmRhICcgKyBuYW1lKVxuICAgICAgICBhd2FpdCByZXRyeUNvbmZsaWN0KCgpID0+XG4gICAgICAgICAgICBva1Jlc3BvbnNlKFxuICAgICAgICAgICAgICAgIGF3c1JlcXVlc3QoXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgICdQVVQnLFxuICAgICAgICAgICAgICAgICAgICAnbGFtYmRhJyxcbiAgICAgICAgICAgICAgICAgICAgYC8yMDE1LTAzLTMxL2Z1bmN0aW9ucy8ke3ByZWZpeH0tJHtzZXJ2aWNlfS0ke25hbWV9L2NvbmZpZ3VyYXRpb25gLFxuICAgICAgICAgICAgICAgICAgICBhd3NDb25maWcsXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAnRXJyb3IgdXBkYXRpbmcgY29uZmlnIGZvciBsYW1iZGEgJyArIG5hbWUsXG4gICAgICAgICAgICApLFxuICAgICAgICApXG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBkZWxldGVMYW1iZGEoY29udGV4dDogQ29udGV4dCwgcHJlZml4OiBzdHJpbmcsIHNlcnZpY2U6IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gICAgY29udGV4dC5sb2cudHJhY2UoJ2RlbGV0aW5nIGxhbWJkYSAnICsgbmFtZSlcbiAgICBhd2FpdCBva1Jlc3BvbnNlKFxuICAgICAgICBhd3NSZXF1ZXN0KFxuICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICdERUxFVEUnLFxuICAgICAgICAgICAgJ2xhbWJkYScsXG4gICAgICAgICAgICBgLzIwMTUtMDMtMzEvZnVuY3Rpb25zLyR7cHJlZml4fS0ke3NlcnZpY2V9LSR7bmFtZX1gLFxuICAgICAgICApLFxuICAgICAgICAnRXJyb3IgZGVsZXRpbmcgbGFtYmRhICcgKyBuYW1lLFxuICAgIClcbn1cblxuZnVuY3Rpb24gbGFtYmRhQ29uZmlnKHRhcmdldDogVGFyZ2V0LCByb2xlOiBzdHJpbmcsIGVudmlyb25tZW50OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgUm9sZTogcm9sZSxcbiAgICAgICAgUnVudGltZTogZ2V0UnVudGltZSh0YXJnZXQpLFxuICAgICAgICBIYW5kbGVyOiAnaW5kZXguaGFuZGxlcicsXG4gICAgICAgIFRpbWVvdXQ6IHRhcmdldC5jb25maWcudGltZW91dCA/PyAxNSxcbiAgICAgICAgTWVtb3J5U2l6ZTogbWVtb3J5U2l6ZSh0YXJnZXQpLFxuICAgICAgICBUcmFjaW5nQ29uZmlnOiB7XG4gICAgICAgICAgICBNb2RlOiAnUGFzc1Rocm91Z2gnLFxuICAgICAgICB9LFxuICAgICAgICBFbnZpcm9ubWVudDoge1xuICAgICAgICAgICAgVmFyaWFibGVzOiBlbnZpcm9ubWVudCxcbiAgICAgICAgfSxcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldFJ1bnRpbWUoeyBjb25maWcgfTogVGFyZ2V0KSB7XG4gICAgc3dpdGNoIChjb25maWcubm9kZVZlcnNpb24/LnNsaWNlKDAsIDQpKSB7XG4gICAgICAgIGNhc2UgJz49MjQnOlxuICAgICAgICAgICAgcmV0dXJuICdub2RlanMyNC54J1xuICAgICAgICBjYXNlICc+PTIyJzpcbiAgICAgICAgICAgIHJldHVybiAnbm9kZWpzMjIueCdcbiAgICAgICAgY2FzZSAnPj0yMCc6XG4gICAgICAgICAgICByZXR1cm4gJ25vZGVqczIwLngnXG4gICAgICAgIGNhc2UgJz49MTgnOlxuICAgICAgICAgICAgcmV0dXJuICdub2RlanMxOC54J1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICdVbnN1cHBvcnRlZCBlbmdpbmU7IHBsZWFzZSBzcGVjaWZ5IFwibm9kZVwiOiBcIj49MThcIiwgXCJub2RlXCI6IFwiPj0yMFwiLCBcIm5vZGVcIjogXCI+PTIyXCIsIG9yIFwibm9kZVwiOiBcIj49MjRcIiBhcyBhbiBlbmdpbmUgaW4geW91ciBwYWNrYWdlLmpzb24uJyxcbiAgICAgICAgICAgIClcbiAgICB9XG59XG5cbmZ1bmN0aW9uIG1lbW9yeVNpemUoeyBjb25maWcsIG1ldGhvZCB9OiBUYXJnZXQpIHtcbiAgICBpZiAoIWNvbmZpZy5jb21wdXRlICYmICFjb25maWcubWVtb3J5ICYmIG1ldGhvZCkge1xuICAgICAgICByZXR1cm4gMjU2XG4gICAgfVxuICAgIGlmIChjb25maWcuY29tcHV0ZSA9PT0gJ2hpZ2gnIHx8IGNvbmZpZy5tZW1vcnkgPT09ICdoaWdoJykge1xuICAgICAgICByZXR1cm4gMzAwOFxuICAgIH1cbiAgICByZXR1cm4gMTI4XG59XG5cbmZ1bmN0aW9uIGxhbWJkYUFyY2hpdGVjdHVyZSh7IGNvbmZpZywgbWV0aG9kIH06IFRhcmdldCkge1xuICAgIHN3aXRjaCAoXG4gICAgICAgIHJlc29sdmVDcHUoXG4gICAgICAgICAgICBjb25maWcsXG4gICAgICAgICAgICBjb25maWcuY29tcHV0ZSA9PT0gJ2hpZ2gnIHx8IChjb25maWcuY29tcHV0ZSA9PT0gdW5kZWZpbmVkICYmIG1ldGhvZCA9PT0gJ0dFVCcpXG4gICAgICAgICAgICAgICAgPyBbJ3g2NCcsICd4MzInLCAnYXJtNjQnLCAnYXJtJ11cbiAgICAgICAgICAgICAgICA6IFsnYXJtNjQnLCAnYXJtJywgJ3g2NCcsICd4MzInXSxcbiAgICAgICAgKVxuICAgICkge1xuICAgICAgICBjYXNlICdhcm02NCc6XG4gICAgICAgIGNhc2UgJ2FybSc6XG4gICAgICAgICAgICByZXR1cm4gWydhcm02NCddXG4gICAgICAgIGNhc2UgJ3g2NCc6XG4gICAgICAgIGNhc2UgJ3gzMic6XG4gICAgICAgICAgICByZXR1cm4gWyd4ODZfNjQnXVxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBDUFVzOiAnICsgKGNvbmZpZy5jcHVzPy5qb2luKCcsICcpID8/ICcnKSlcbiAgICB9XG59XG4iXX0=