UNPKG

zcatalyst-cli

Version:

Command Line Tool for CATALYST

261 lines (260 loc) 15.2 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; 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.FnExecutionHandler = void 0; const child_process_1 = require("child_process"); const fn_handler_1 = require("./fn-handler"); const fn_utils_1 = require("../../../fn-utils"); const path_1 = require("path"); const node_1 = __importDefault(require("./node")); const java_1 = __importDefault(require("./java")); const python_1 = __importDefault(require("./python")); const project_1 = require("../../../util_modules/project"); const constants_1 = require("../../../util_modules/constants"); const error_1 = __importDefault(require("../../../error")); const port_resolver_1 = __importDefault(require("../../../port-resolver")); const http_functions_1 = require("../http-functions"); const logger_1 = require("../../../util_modules/logger"); const container_plugin_1 = require("@zcatalyst/container-plugin"); const ansi_colors_1 = require("ansi-colors"); const env_1 = require("../../../util_modules/env"); const server_1 = require("../../../util_modules/server"); const utils_1 = require("../../../serve/server/lib/master/utils"); const readline_1 = __importDefault(require("readline")); class FnExecutionHandler extends fn_handler_1.FnHandler { constructor(serverDetails, localFnEvents) { super(serverDetails, localFnEvents); } execute(data, accessToken) { var _a, _b, _c, _d, _e; return __awaiter(this, void 0, void 0, function* () { const projectRoot = (0, project_1.getProjectRoot)(); const slaveFnTarget = { index: (_b = (_a = this.fn.target) === null || _a === void 0 ? void 0 : _a.index) === null || _b === void 0 ? void 0 : _b.replace((0, path_1.join)(projectRoot, constants_1.FOLDERNAME.functions, this.fn.target.name) + path_1.sep, ''), name: (_c = this.fn.target) === null || _c === void 0 ? void 0 : _c.name }; switch (this.stack) { case 'node': { this.slave = (0, node_1.default)(this.fn, JSON.stringify(data), { slaveFnTarget, accessToken }); break; } case 'java': { const javaInvoker = (0, path_1.join)(projectRoot, constants_1.FOLDERNAME.build, '.catalyst', this.fn.target.stack, 'Java' + this.fn.target.type + 'Invoker'); fn_utils_1.fnUtils.java.ensureJavaInvoker(javaInvoker, (0, path_1.normalize)((0, path_1.join)(__dirname, '../invoker', this.fn.target.type, 'java', 'Java' + this.fn.target.type + 'Invoker.java')), this.fn.target); this.slave = (0, java_1.default)(this.fn, JSON.stringify(data), { javaInvoker, slaveFnTarget, accessToken }); break; } case 'python': { const pyFn = this.fn; this.slave = yield (0, python_1.default)(pyFn); const attachVsCodeDebugger = (port) => __awaiter(this, void 0, void 0, function* () { try { yield (0, server_1.isPortListening)(port, 25, env_1.isWindows ? 1000 : 500).catch((er) => (0, logger_1.debug)('error listening for port: ' + port, er)); utils_1.serverEvent.emit('connection'); yield new Promise((res, rej) => { const connTimeout = setTimeout(() => rej('debugger connection timeout'), 10000); utils_1.serverEvent.once('attach', () => { clearTimeout(connTimeout); res(); }); }); } catch (er) { utils_1.serverEvent.emit('error', er); this.kill(); return; } }); if (!(this.slave instanceof child_process_1.ChildProcess)) { throw new error_1.default('Slave not an instance of Child process', { context: this.slave, exit: 2 }); } const debugConfig = (_d = pyFn.target.additionalInfo) === null || _d === void 0 ? void 0 : _d.debug; if (this.fn.target.type === 'job') { if (debugConfig && env_1.isVsCode) { yield attachVsCodeDebugger(debugConfig.port); } const httpPort = yield port_resolver_1.default.getFreePort(constants_1.DEFAULT.serve_port.http[(_e = this.fn.target) === null || _e === void 0 ? void 0 : _e.type], 200); this.processFlowHandler(data, httpPort); break; } new Promise((resolve, reject) => { var _a; (_a = this.slave) === null || _a === void 0 ? void 0 : _a.once('spawn', () => __awaiter(this, void 0, void 0, function* () { try { if (debugConfig) { if (env_1.isVsCode) { yield attachVsCodeDebugger(debugConfig.port); } else { yield new Promise((res, rej) => { try { const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout, terminal: true }); rl.on('line', () => { rl.close(); res(); }); (0, logger_1.info)(); (0, logger_1.info)(`${(0, ansi_colors_1.dim)('>> ')} Please attach a ${(0, ansi_colors_1.bold)('DEBUGGER')} and press ${(0, ansi_colors_1.bold)('ANY KEY')} to continue executing the ${(0, ansi_colors_1.bold)(pyFn.target.name)} function`); (0, logger_1.info)(); } catch (er) { rej(er); } }); } } yield (0, http_functions_1.checkIfRuntimeServerRunning)(this.fn.httpPort.toString()); yield this.fnRequestHandler({ httpPort: this.fn.httpPort, data, accessToken }).finally(() => this.kill()); resolve(); } catch (er) { const _er = error_1.default.getErrorInstance(er); reject(_er); } })); }).catch((err) => { (0, logger_1.debug)('Error with fnRequestHandling flow: ', err); this.localFnEvents.emit('error', err); }); break; } default: { throw new error_1.default('Invalid stack for fn execution handling: ' + this.stack, { exit: 2 }); } } return this.slave; }); } executeWithContainer(data, accessToken) { var _a, _b, _c, _d, _e; return __awaiter(this, void 0, void 0, function* () { (0, logger_1.debug)('using container to serve the function: ' + ((_a = this.fn.target) === null || _a === void 0 ? void 0 : _a.name)); const container = yield Promise.resolve().then(() => __importStar(require('@zcatalyst/container-plugin'))); const httpPort = yield port_resolver_1.default.getFreePort(constants_1.DEFAULT.serve_port.http[(_b = this.fn.target) === null || _b === void 0 ? void 0 : _b.type], 200); this.fn.target.env_var = Object.assign({ X_ZOHO_CATALYST_ACCOUNTS_URL: constants_1.ORIGIN.auth, X_ZOHO_CATALYST_CONSOLE_URL: constants_1.ORIGIN.admin, X_ZOHO_CATALYST_RESOURCE_ID: (_c = this.fn.target) === null || _c === void 0 ? void 0 : _c.id, X_ZOHO_STRATUS_RESOURCE_SUFFIX: constants_1.ORIGIN.stratusSuffix, X_ZOHO_CATALYST_CODE_LOCATION: '/catalyst/', CATALYST_PROJECT_TIMEZONE: (0, project_1.getProjectTimezone)(Intl.DateTimeFormat().resolvedOptions().timeZone), X_ZOHO_CATALYST_ORG: (0, project_1.getEnvId)(), X_ZOHO_ADMIN_CRED_TOKEN: accessToken, CATALYST_FUNCTION_TYPE: constants_1.REMOTE_REF.functions.type[(_d = this.fn.target) === null || _d === void 0 ? void 0 : _d.type] }, (_e = this.fn.target) === null || _e === void 0 ? void 0 : _e.env_var); if (this.fn.target.type === 'job') { const hostIp = 'host.docker.internal'; const sysEnvs = { X_ZOHO_DATA_URL: `http://${hostIp}:${httpPort}/data`, X_ZOHO_CALLBACK_URL: `http://${hostIp}:${httpPort}/callback`, X_ZOHO_ADMIN_CRED_TYPE: 'token', X_ZOHO_ADMIN_CRED_TOKEN: accessToken, X_ZOHO_USER_CRED_TYPE: 'token', X_ZOHO_USER_CRED_TOKEN: accessToken, X_ZOHO_USER_TYPE: 'admin', X_ZOHO_PROJECT_KEY: (0, project_1.getDomainKey)(), X_ZOHO_PROJECTID: (0, project_1.getProjectId)(), X_ZOHO_PROJECT_DOMAIN: (0, project_1.getDomainPrefix)() + '.' + constants_1.ORIGIN.app.replace('https://', ''), X_ZOHO_CATALYST_ENVIRONMENT: 'Development', CATALYST_API_DOMAIN: constants_1.ORIGIN.admin }; this.fn.target.env_var = Object.assign(Object.assign({}, this.fn.target.env_var), sysEnvs); } else { this.fn.httpPort = httpPort; } const pluginEvent = yield container.start({ details: this.fn, projectId: (0, project_1.getProjectId)(), ruok: this.fn.target.type === 'job' ? container_plugin_1.RUOK.SKIP : this.fn.debugPort !== undefined && this.fn.debugPort !== -1 ? container_plugin_1.RUOK.INFINITE : container_plugin_1.RUOK.FINITE }); pluginEvent.on('error', (er) => { var _a; (0, logger_1.debug)('Container Error: ', er); (0, logger_1.info)(); (0, logger_1.error)(`Error running the function ${(0, ansi_colors_1.bold)(((_a = this.fn.target) === null || _a === void 0 ? void 0 : _a.name) + '')} in container`); (0, logger_1.info)(); }); pluginEvent.emit('start', this.fn); pluginEvent.once('ready', () => __awaiter(this, void 0, void 0, function* () { var _f, _g; try { if (((_f = this.fn.target) === null || _f === void 0 ? void 0 : _f.type) === 'job') { yield this.processFlowHandler(data, httpPort).finally(() => this.kill()); return; } if (((_g = this.fn.target) === null || _g === void 0 ? void 0 : _g.type) === 'cron') { const cronData = { project_details: {}, cron_details: {}, data, remaining_count: 0 }; data = cronData; } yield this.fnRequestHandler({ httpPort: this.fn.httpPort, data, accessToken }).finally(() => this.kill()); } catch (er) { pluginEvent.emit('error', er instanceof error_1.default ? er : error_1.default.getErrorInstance(er, { message: 'Error when communicating with the container function ', skipHelp: true })); } })); this.slave = pluginEvent; return this.slave; }); } } exports.FnExecutionHandler = FnExecutionHandler;