UNPKG

@cap-js-community/mtx-tool

Version:

Multitenancy and Extensibility Tool is a cli to reduce operational overhead for multitenant Cloud Foundry applications

102 lines (90 loc) 4.02 kB
"use strict"; const { orderedStringify, writeTextSync } = require("../shared/static"); const { assert } = require("../shared/error"); const { request } = require("../shared/request"); const { Logger } = require("../shared/logger"); const BUILDPACK_INFO = { nodejs_buildpack: { runtime: "node", debugPort: 9229 }, java_buildpack: { runtime: "java", debugPort: 8000 }, }; const DEFAULT_ENV_FILENAME = "default-env.json"; const logger = Logger.getInstance(); const _serverDebug = async (context, { appName, appInstance } = {}) => { const { cfBuildpack, cfAppGuid, cfRouteUrl, cfSsh } = appName ? await context.getAppNameInfoCached(appName) : await context.getSrvInfo(); const cfBuildpackInfoKey = cfBuildpack && Object.keys(BUILDPACK_INFO).find( (cfBuildpackName) => cfBuildpack.includes(cfBuildpackName) || cfBuildpack.includes(cfBuildpackName.replace(/_/g, "-")) ); const { runtime, debugPort: inferredPort } = (cfBuildpackInfoKey && BUILDPACK_INFO[cfBuildpackInfoKey]) || {}; const localPort = inferredPort || 8000; let responseData = {}; if (cfRouteUrl) { try { const token = await context.getCachedUaaToken(); const response = await request({ url: cfRouteUrl, pathname: "/info", auth: { token }, headers: { "X-Cf-App-Instance": `${cfAppGuid}:${appInstance}`, }, logged: false, checkStatus: false, }); responseData = response.ok && (await response.json()); } catch (err) {} // eslint-disable-line no-empty } const { debugPort } = responseData; const remotePort = debugPort || inferredPort; assert(remotePort, `could not determine remote debugPort from /info or infer from buildpack`); logger.info(); if (!debugPort) { logger.info( `could not determine remote debugPort from /info, falling back to ${cfBuildpack} default ${remotePort}` ); } logger.info(`connect ${runtime ? runtime + " debugger" : "debugger"} on port ${localPort}`); logger.info(`use request header "X-Cf-App-Instance: ${cfAppGuid}:${appInstance}" to target this app instance`); logger.info(); await cfSsh({ localPort, remotePort, appInstance }); }; const serverDebug = async (context, [appName, appInstance = "0"]) => { assert(/\d+/.test(appInstance), `argument "${appInstance}" is not a valid app instance`); return _serverDebug(context, { appName, appInstance }); }; const serverEnvironment = async (context, [appName]) => { const { cfEnvServices, cfEnvApp, cfEnvVariables } = appName ? await context.getAppNameInfoCached(appName) : await context.getSrvInfo(); writeTextSync( DEFAULT_ENV_FILENAME, orderedStringify({ VCAP_SERVICES: cfEnvServices, VCAP_APPLICATION: cfEnvApp, ...cfEnvVariables }, null, 2) + "\n" ); logger.info(`saved system environment to ${DEFAULT_ENV_FILENAME}`); }; const serverCertificates = async (context, [appName, appInstance = "0"]) => { assert(/\d+/.test(appInstance), `argument "${appInstance}" is not a valid app instance`); const { cfSsh, cfAppName } = appName ? await context.getAppNameInfoCached(appName) : await context.getSrvInfo(); const dumpFile = async (cfFilename, localFilename) => { const [file] = await cfSsh({ command: `cat ${cfFilename}`, appInstance }); writeTextSync(localFilename, file); }; await dumpFile("$CF_INSTANCE_CERT", `certificate-${cfAppName}-${appInstance}.crt`); await dumpFile("$CF_INSTANCE_KEY", `certificate-${cfAppName}-${appInstance}.key`); logger.info("saved instance certificates"); }; const serverStartDebugger = async (context, [appName, appInstance = "0"]) => { assert(/\d+/.test(appInstance), `argument "${appInstance}" is not a valid app instance`); const { cfSsh } = appName ? await context.getAppNameInfoCached(appName) : await context.getSrvInfo(); await cfSsh({ command: "pkill --signal SIGUSR1 node", appInstance }); }; module.exports = { serverDebug, serverEnvironment, serverCertificates, serverStartDebugger, };