UNPKG

zcatalyst-cli

Version:

Command Line Tool for CATALYST

259 lines (258 loc) 12.9 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FnHandler = void 0; const child_process_1 = require("child_process"); const fs_1 = require("../../../util_modules/fs"); const constants_1 = require("../../../util_modules/constants"); const http_1 = require("http"); const logger_1 = require("../../../util_modules/logger"); const server_1 = require("../../../util_modules/server"); const project_1 = require("../../../util_modules/project"); const error_1 = __importDefault(require("../../../error")); const path_1 = require("path"); class FnHandler { constructor(fn, localFnEvents) { this.closed = false; this.fn = fn; this.stack = (() => { var _a, _b, _c; if ((_a = fn === null || fn === void 0 ? void 0 : fn.target.stack) === null || _a === void 0 ? void 0 : _a.startsWith(constants_1.RUNTIME.language.node.value)) { return 'node'; } if ((_b = fn === null || fn === void 0 ? void 0 : fn.target.stack) === null || _b === void 0 ? void 0 : _b.startsWith(constants_1.RUNTIME.language.java.value)) { return 'java'; } if ((_c = fn === null || fn === void 0 ? void 0 : fn.target.stack) === null || _c === void 0 ? void 0 : _c.startsWith(constants_1.RUNTIME.language.python.value)) { return 'python'; } throw new error_1.default('Invalid stack for execute command: ' + fn.target.stack, { exit: 2 }); })(); this.localFnEvents = localFnEvents; const projectRoot = (0, project_1.getProjectRoot)(); this.responseFile = (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, '.catalyst', 'user_res_body'); this.metaFile = (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, '.catalyst', 'user_meta.json'); } writeResponse(response, status) { fs_1.SYNC.writeFile(this.responseFile, response); fs_1.SYNC.writeFile(this.metaFile, JSON.stringify({ response: { statusCode: status } })); } responseProcessor(statusCode, message) { switch (statusCode) { case 200: { this.writeResponse('SUCCESS', 200); break; } case 532: { this.writeResponse('CODE_EXCEPTION', 532); break; } case 530: { this.writeResponse('FAILURE', 530); break; } case 500: { this.writeResponse('INTERNAL_SERVER_ERROR', 500); break; } default: { throw new error_1.default('INVALID STATUS CODE', { context: { statusCode: statusCode, statusMessage: message } }); } } } processFlowHandler(data, listenPort) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { var _a; const jobDetailsServer = new http_1.Server((serverReq, serverRes) => __awaiter(this, void 0, void 0, function* () { var _b, _c; if ((_b = serverReq.url) === null || _b === void 0 ? void 0 : _b.includes('data')) { serverRes.writeHead(200); serverRes.write(JSON.stringify({ data })); serverRes.end(); } else if ((_c = serverReq.url) === null || _c === void 0 ? void 0 : _c.includes('callback')) { const reqData = yield new Promise((_resolve) => { const data = []; serverReq.on('data', (chunk) => data.push(chunk)); serverReq.on('end', () => _resolve(JSON.parse(Buffer.concat(data).toString()))); }); this.responseProcessor(reqData.job_status); serverRes.writeHead(200); serverRes.write(JSON.stringify({})); serverRes.end(); resolve(); return; } else { (0, logger_1.debug)(`Invalid request: (${serverReq.method}) ${serverReq.url}`); this.writeResponse('INTERNAL_SERVER_ERROR', 500); reject(`Invalid request: (${serverReq.method}) ${serverReq.url}`); return; } })); const jobConnDestroyer = new server_1.ConnectionDestroyer(jobDetailsServer); jobDetailsServer.listen(listenPort, '127.0.0.1', () => { (0, logger_1.debug)('server listening on port :' + listenPort); }); jobDetailsServer.on('error', reject); (_a = this.slave) === null || _a === void 0 ? void 0 : _a.once('exit', () => { jobConnDestroyer.destroy(); }); }); }); } fnRequestHandler({ httpPort, data = {}, accessToken }) { return __awaiter(this, void 0, void 0, function* () { data.project_details = Object.assign({ id: (0, project_1.getProjectId)(), project_name: (0, project_1.getProjectName)() }, (data.project_details || {})); const reqJson = JSON.stringify(data); return new Promise((resolve, reject) => { const req = (0, http_1.request)(`http://127.0.0.1:${httpPort}`, { headers: { 'x-zc-projectid': (0, project_1.getProjectId)(), 'x-zc-project-domain': (0, project_1.getDomainPrefix)() + '.' + constants_1.ORIGIN.app.replace('https://', ''), 'x-zc-project-key': (0, project_1.getDomainKey)(), 'x-zc-environment': (0, project_1.getEnvName)(), 'x-zc-user-cred-type': 'token', 'x-zc-user-cred-token': accessToken, 'x-zc-admin-cred-type': 'token', 'x-zc-admin-cred-token': accessToken, 'x-zc-user-type': 'admin', 'x-zc-instance-id': 'local', 'Content-Length': reqJson.length } }, (resp) => { var _a; if ([constants_1.REMOTE_REF.functions.type.cron, constants_1.REMOTE_REF.functions.type.event].includes(((_a = this.fn.target) === null || _a === void 0 ? void 0 : _a.type) + '')) { try { this.responseProcessor(resp.statusCode || -1, resp.statusMessage); return resolve(); } catch (er) { reject(er); } } resp.on('data', (data) => { const respStr = data.toString(); fs_1.SYNC.writeFile(this.responseFile, respStr); }); resp.on('close', () => { const metaJson = { response: { statusCode: resp.statusCode } }; fs_1.SYNC.writeFile(this.metaFile, JSON.stringify(metaJson)); resolve(); }); }).on('error', (err) => { if ('code' in err && err.code === 'ECONNRESET') { (0, logger_1.debug)('ECONNRESET - when sending request to container function'); return; } reject(new error_1.default('Error when trying to send the request to container function', { original: err, exit: 2, skipHelp: true })); }); req.write(reqJson); req.end(); }); }); } fnResponseHandler(code, sig) { var _a, _b, _c, _d, _e; return __awaiter(this, void 0, void 0, function* () { if (code === 0) { (0, logger_1.info)(`[CLI] Function ${(_a = this.fn.target) === null || _a === void 0 ? void 0 : _a.name} execution complete`); (0, logger_1.info)(); const response = yield fs_1.ASYNC.readFile(this.responseFile); let meta; try { meta = JSON.parse((yield fs_1.ASYNC.readFile(this.metaFile))).response; } catch (err) { meta = {}; } switch ((_b = this.fn.target) === null || _b === void 0 ? void 0 : _b.type) { case constants_1.FN_TYPE.basic: (0, logger_1.info)(`[response - ${this.fn.target.name}] ${response + ''}`); (0, logger_1.info)(`[status - ${this.fn.target.name}] ${(meta.statusCode || 200) + ''}`); this.localFnEvents.emit('response', { data: response, status: meta.statsCode }); break; case constants_1.FN_TYPE.cron: case constants_1.FN_TYPE.job: case constants_1.FN_TYPE.event: (0, logger_1.info)(`[status - ${this.fn.target.name}] ${response || 'Unknown'}`); if (!response) { (0, logger_1.info)(`[CLI] Make sure to close the ${this.fn.target.name} (${this.fn.target.type}) function.`); } this.localFnEvents.emit('response', { status: meta.statusCode }); break; case constants_1.FN_TYPE.integration: (0, logger_1.info)(`[response - ${this.fn.target.name}] ${response + ''}`); try { this.localFnEvents.emit('response', JSON.parse(response || '')); } catch (er) { (0, logger_1.debug)('Invalid integration response: ', er); } break; } } else { (code === 130 || sig === 'SIGINT') && (0, logger_1.info)(`[CLI] Function ${(_c = this.fn.target) === null || _c === void 0 ? void 0 : _c.name} interrupted`); (code === 143 || sig === 'SIGTERM' || sig === 'SIGQUIT' || sig === 'SIGKILL') && (0, logger_1.info)(`[CLI] Function ${(_d = this.fn.target) === null || _d === void 0 ? void 0 : _d.name} process killed`); this.localFnEvents.listenerCount('error') > 0 && this.localFnEvents.emit('error', new error_1.default(`Function(${(_e = this.fn.target) === null || _e === void 0 ? void 0 : _e.name}) process exited with ${code ? 'status: ' + code : 'signal: ' + sig}`, { skipHelp: true })); } }); } shutdown() { return __awaiter(this, void 0, void 0, function* () { return new Promise((res) => { this.closed = true; this.kill(); if (this.watcher) { this.watcher.close().then(res).catch(res); } else { res(); } }); }); } kill() { if (!this.slave) { return; } this.slave instanceof child_process_1.ChildProcess ? !this.slave.killed && this.slave.kill('SIGTERM') : this.slave.emit('close', this.fn); } } exports.FnHandler = FnHandler;