@riddance/deploy
Version:
168 lines • 31.8 kB
JavaScript
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=