UNPKG

@zowe/imperative

Version:
526 lines 27.3 kB
"use strict"; /* * This program and the accompanying materials are made available under the terms of the * Eclipse Public License v2.0 which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-v20.html * * SPDX-License-Identifier: EPL-2.0 * * Copyright Contributors to the Zowe Project. * */ 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.EnvQuery = void 0; const os = require("os"); const lodash = require("lodash"); const path = require("path"); const spawn = require("cross-spawn"); const config_1 = require("../../../../../config"); const utilities_1 = require("../../../../../utilities"); const operations_1 = require("../../../../../operations"); const CliUtils_1 = require("../../../../../utilities/src/CliUtils"); const PluginIssues_1 = require("../../../plugins/utilities/PluginIssues"); const EnvItems_1 = require("./EnvItems"); const censor_1 = require("../../../../../censor"); /** * This class encapulates operations for Zowe CLI environment information. * We use the term environment loosely. Sometimes it is an environment variable. * It can also be something in the runtime environment, like version of NodeJS. */ class EnvQuery { // __________________________________________________________________________ /** * For the specified itemId, get its value. * * @param itemId ID of the environmental item for which we want get the value. * @param getItemOpts options that affect our behavior. * * @returns An object with the item value, a display message, and a problem message. */ static getEnvItemVal(itemId_1) { return __awaiter(this, arguments, void 0, function* (itemId, getItemOpts = {}) { const getResult = { itemVal: null, itemValMsg: "", itemProbMsg: "" }; switch (itemId) { case EnvItems_1.ItemId.ZOWE_VER: { EnvQuery.getZoweVer(getResult); break; } case EnvItems_1.ItemId.NODEJS_VER: { getResult.itemVal = process.versions.node; getResult.itemValMsg = "Node.js version = " + getResult.itemVal; break; } case EnvItems_1.ItemId.PLATFORM: { getResult.itemVal = os.platform(); getResult.itemValMsg = "O.S. platform = " + getResult.itemVal; break; } case EnvItems_1.ItemId.ARCHITECTURE: { getResult.itemVal = os.arch(); getResult.itemValMsg = "O.S. architecture = " + getResult.itemVal; break; } case EnvItems_1.ItemId.OS_PATH: { getResult.itemVal = process.env.PATH; getResult.itemValMsg = os.EOL + "O.S. PATH = " + getResult.itemVal; break; } case EnvItems_1.ItemId.ZOWE_CLI_HOME: { getResult.itemVal = process.env.ZOWE_CLI_HOME; if (getResult.itemVal === undefined) { getResult.itemVal += os.EOL + EnvQuery.indent + "Default = " + path.normalize(utilities_1.ImperativeConfig.instance.cliHome); } getResult.itemValMsg = os.EOL + "ZOWE_CLI_HOME = " + getResult.itemVal; break; } case EnvItems_1.ItemId.ZOWE_APP_LOG_LEVEL: { getResult.itemVal = process.env.ZOWE_APP_LOG_LEVEL; getResult.itemValMsg = "ZOWE_APP_LOG_LEVEL = " + getResult.itemVal; break; } case EnvItems_1.ItemId.ZOWE_IMPERATIVE_LOG_LEVEL: { getResult.itemVal = process.env.ZOWE_IMPERATIVE_LOG_LEVEL; getResult.itemValMsg = "ZOWE_IMPERATIVE_LOG_LEVEL = " + getResult.itemVal; break; } case EnvItems_1.ItemId.OTHER_ZOWE_VARS: { EnvQuery.getOtherZoweEnvVars(getResult); break; } case EnvItems_1.ItemId.NPM_VER: { yield EnvQuery.getNpmInfo(getResult, getItemOpts); break; } case EnvItems_1.ItemId.ZOWE_CONFIG_INFO: { yield EnvQuery.getConfigInfo(getResult, getItemOpts); break; } case EnvItems_1.ItemId.ZOWE_PLUGINS: { yield EnvQuery.getPluginInfo(getResult, getItemOpts); break; } default: { getResult.itemProbMsg = "An unknown item ID was supplied = " + itemId; return getResult; } } getResult.itemProbMsg = EnvQuery.getEnvItemProblems(itemId, getResult.itemVal); return getResult; }); } // __________________________________________________________________________ /** * Detect if a specified problem test finds a problem for the specified value. * * @param itemVal The value of the environmental item. * @param probTest A problem test to be evaluated. * * @returns True if we find a problem. False otherwise. */ static detectProbVal(value, probTest) { // eslint-disable-next-line unused-imports/no-unused-vars,@typescript-eslint/no-unused-vars const semver = require('semver'); const probExprWithVals = probTest.probExpr.replace(/{val}/g, value); return eval(probExprWithVals); } // __________________________________________________________________________ /** * Run a command that displays output. * * @param cmdToRun The command name to be run. * @param args The arguments to the command. * * @return The output of the command. */ static getCmdOutput(cmdToRun, args) { let cmdOutput = ""; const ioOpts = ["pipe", "pipe", "pipe"]; try { const spawnResult = spawn.sync(cmdToRun, args, { stdio: ioOpts, shell: true }); if (spawnResult.stdout && spawnResult.stdout.length > 0) { // remove any trailing newline from the output cmdOutput = spawnResult.stdout.toString(); } else { cmdOutput = cmdToRun + " failed to display any output."; if (spawnResult.stderr) { cmdOutput += `${os.EOL}Reason = ` + spawnResult.stderr.toString(); } } } catch (err) { cmdOutput = "Failed to run command = " + cmdToRun + " " + args.join(" "); if (err.message) { cmdOutput += `${os.EOL}Details = ` + err.message; } cmdOutput = utilities_1.TextUtils.chalk.red(cmdOutput); } // remove any trailing newline from the output cmdOutput = cmdOutput.replace(EnvQuery.lastEolRegex, ""); if (cmdOutput.length == 0) { cmdOutput = "Failed to get any information from " + cmdToRun + " " + args.join(" "); } return cmdOutput; } // __________________________________________________________________________ /** * Get information about the Zowe configuration. * * @param getResult The itemVal and itemValMsg properties are filled * by this function. * @param getItemOpts options that affect our behavior. */ static getConfigInfo(getResult, getItemOpts) { return __awaiter(this, void 0, void 0, function* () { var _a; const teamCfg = "Zowe Client Config"; const doesProgBarExist = (getItemOpts === null || getItemOpts === void 0 ? void 0 : getItemOpts.progressApi) ? true : false; // setup progress bar const configProgress = { percentComplete: operations_1.TaskProgress.TEN_PERCENT, statusMessage: "No value yet", stageName: operations_1.TaskStage.IN_PROGRESS }; if ((_a = utilities_1.ImperativeConfig.instance.config) === null || _a === void 0 ? void 0 : _a.exists) { getResult.itemVal = teamCfg; configProgress.statusMessage = "Retrieving Zowe client configuration"; configProgress.percentComplete = operations_1.TaskProgress.TWENTY_PERCENT; } if (doesProgBarExist) { getItemOpts.progressApi.startBar({ task: configProgress }); yield EnvQuery.updateProgressBar(doesProgBarExist, true); } getResult.itemValMsg = "Zowe daemon mode = "; if (utilities_1.ImperativeConfig.instance.loadedConfig.daemonMode) { getResult.itemValMsg += "on"; configProgress.statusMessage = "Retrieving Zowe executable version"; yield EnvQuery.updateProgressBar(doesProgBarExist); const cliCmdName = utilities_1.ImperativeConfig.instance.rootCommandName; const exeVerOutput = EnvQuery.getCmdOutput(cliCmdName, ["--version-exe"]); if (exeVerOutput.match(/DESCRIPTION/) == null) { getResult.itemValMsg += `${os.EOL}Zowe daemon executable version = ` + exeVerOutput; } getResult.itemValMsg += `${os.EOL}Default Zowe daemon executable directory = ` + path.normalize(utilities_1.ImperativeConfig.instance.cliHome + "/bin"); } else { getResult.itemValMsg += "off"; } if (getResult.itemVal == teamCfg) { // Display all relevant zowe team config files. configProgress.statusMessage = "Retrieving active Zowe client config files"; configProgress.percentComplete = operations_1.TaskProgress.THIRTY_PERCENT; yield EnvQuery.updateProgressBar(doesProgBarExist); const config = utilities_1.ImperativeConfig.instance.config; /* Get our list of config files. * Logic stolen from "config list" handler. */ const configListObj = {}; for (const layer of config.layers) { if (layer.exists) { configListObj[layer.path] = layer.properties; if (configListObj[layer.path] != null) { for (const secureProp of config.api.secure.secureFields(layer)) { if (lodash.has(configListObj[layer.path], secureProp)) { lodash.set(configListObj[layer.path], secureProp, config_1.ConfigConstants.SECURE_VALUE); } } } } } getResult.itemValMsg += `${os.EOL}Zowe client config files in use:${os.EOL}`; for (const configLoc of Object.keys(configListObj)) { getResult.itemValMsg += EnvQuery.indent + configLoc + os.EOL; } // get default profile names configProgress.statusMessage = "Retrieving default profile names"; configProgress.percentComplete = operations_1.TaskProgress.SIXTY_PERCENT; yield EnvQuery.updateProgressBar(doesProgBarExist); getResult.itemValMsg += "Default profile names: " + os.EOL; let maxSpace = 1; for (const profType of Object.keys(config.mProperties.defaults)) { // calculate the max space we need between profile type and name maxSpace = maxSpace < profType.length ? profType.length + 1 : maxSpace; } for (const profType of Object.keys(config.mProperties.defaults)) { getResult.itemValMsg += EnvQuery.indent + profType + " ="; for (let count = 1; count <= maxSpace - profType.length; count++) { getResult.itemValMsg += " "; } getResult.itemValMsg += config.mProperties.defaults[profType] + os.EOL; } // get all available zowe profile names configProgress.statusMessage = "Retrieving available profile names"; configProgress.percentComplete = operations_1.TaskProgress.NINETY_PERCENT; yield EnvQuery.updateProgressBar(doesProgBarExist); /* Recursive function to get our list of profiles. * Logic stolen from "config profiles" handler. */ const getProfList = function (profiles, startLoc, profPathNms) { const currLoc = startLoc; for (const [profNm, profObj] of Object.entries(profiles)) { const currPathNm = currLoc + `${currLoc.length > 0 ? "." : ""}${profNm}`; profPathNms.push(currPathNm); if (profObj.profiles != null) { getProfList(profObj.profiles, currPathNm, profPathNms); } } }; const profPathNms = []; getProfList(config.properties.profiles, "", profPathNms); getResult.itemValMsg += `Available profile names:${os.EOL}`; for (const profPathNm of profPathNms) { getResult.itemValMsg += EnvQuery.indent + profPathNm + os.EOL; } } else { getResult.itemValMsg += `${os.EOL}No Zowe client configuration detected.${os.EOL}`; } // add indent to each line getResult.itemValMsg = EnvQuery.divider + "Zowe CLI configuration information:" + os.EOL + os.EOL + EnvQuery.indent + getResult.itemValMsg.replace(EnvQuery.allEolRegex, "$1" + EnvQuery.indent); configProgress.statusMessage = "Complete"; configProgress.percentComplete = operations_1.TaskProgress.ONE_HUNDRED_PERCENT; configProgress.stageName = operations_1.TaskStage.COMPLETE; yield EnvQuery.updateProgressBar(doesProgBarExist); if (doesProgBarExist) { getItemOpts.progressApi.endBar(); } }); } // end getConfigInfo // __________________________________________________________________________ /** * For the specified itemId, get any known problems. * * @param itemId ID of the environmental item for which we want to detect problems. * @param itemVal The value of the environmental item. * @returns A string with a message about the problems. An empty string if no problems are detected. */ static getEnvItemProblems(itemId, itemVal) { let probMsgs = ""; for (const nextProbTest of EnvItems_1.probTests) { if (itemId === nextProbTest.itemId) { if (EnvQuery.detectProbVal(itemVal, nextProbTest)) { if (probMsgs.length > 0) { probMsgs += os.EOL; } probMsgs += nextProbTest.probMsg; } } } return probMsgs; } // __________________________________________________________________________ /** * Get information about the NPM configuration. * * @param getResult The itemVal and itemValMsg properties are filled * by this function. * @param getItemOpts options that affect our behavior. */ static getNpmInfo(getResult, getItemOpts) { return __awaiter(this, void 0, void 0, function* () { const percentIncr = 10; const doesProgBarExist = (getItemOpts === null || getItemOpts === void 0 ? void 0 : getItemOpts.progressApi) ? true : false; // setup progress bar const npmProgress = { percentComplete: operations_1.TaskProgress.TEN_PERCENT, statusMessage: "Retrieving NPM Version", stageName: operations_1.TaskStage.IN_PROGRESS }; if (doesProgBarExist) { getItemOpts.progressApi.startBar({ task: npmProgress }); yield EnvQuery.updateProgressBar(doesProgBarExist, true); } getResult.itemVal = EnvQuery.getCmdOutput("npm", ["--version"]); getResult.itemValMsg = `${os.EOL}NPM version = ` + getResult.itemVal; npmProgress.statusMessage = "Retrieving current shell"; npmProgress.percentComplete += percentIncr; yield EnvQuery.updateProgressBar(doesProgBarExist); // `npm config` commands fail hard when used with workspaces getResult.itemValMsg += `${os.EOL}Shell = ` + EnvQuery.getCmdOutput("npm", ["config", "get", "shell", "--no-workspaces"]); npmProgress.statusMessage = "Retrieving NPM global prefix"; npmProgress.percentComplete += percentIncr; yield EnvQuery.updateProgressBar(doesProgBarExist); getResult.itemValMsg += `${os.EOL}Global prefix = ` + EnvQuery.getCmdOutput("npm", ["prefix", "-g"]); getResult.itemValMsg += os.EOL + EnvQuery.indent + "The directory above contains the Zowe Node.js command script."; npmProgress.statusMessage = "Retrieving NPM global root node modules"; npmProgress.percentComplete += percentIncr; yield EnvQuery.updateProgressBar(doesProgBarExist); getResult.itemValMsg += `${os.EOL}Global root node modules = ` + EnvQuery.getCmdOutput("npm", ["root", "-g"]); npmProgress.statusMessage = "Retrieving NPM global config"; npmProgress.percentComplete += percentIncr; yield EnvQuery.updateProgressBar(doesProgBarExist); // `npm config` commands fail hard when used with workspaces getResult.itemValMsg += `${os.EOL}Global config = ` + EnvQuery.getCmdOutput("npm", ["config", "get", "globalconfig", "--no-workspaces"]); npmProgress.statusMessage = "Retrieving NPM local prefix"; npmProgress.percentComplete += percentIncr; yield EnvQuery.updateProgressBar(doesProgBarExist); getResult.itemValMsg += `${os.EOL}Local prefix = ` + EnvQuery.getCmdOutput("npm", ["prefix"]); npmProgress.statusMessage = "Retrieving NPM local root node modules"; npmProgress.percentComplete += percentIncr; yield EnvQuery.updateProgressBar(doesProgBarExist); getResult.itemValMsg += `${os.EOL}Local root node modules = ` + EnvQuery.getCmdOutput("npm", ["root"]); npmProgress.statusMessage = "Retrieving NPM user config"; npmProgress.percentComplete += percentIncr; yield EnvQuery.updateProgressBar(doesProgBarExist); // `npm config` commands fail hard when used with workspaces getResult.itemValMsg += `${os.EOL}User config = ` + EnvQuery.getCmdOutput("npm", ["config", "get", "userconfig", "--no-workspaces"]); npmProgress.statusMessage = "Retrieving NPM registry info"; npmProgress.percentComplete += percentIncr; yield EnvQuery.updateProgressBar(doesProgBarExist); // Filter the output of "npm config list" command to only include lines we are interested in. // Also remove "; " prefix from lines where it was added by npm and is not a user-added comment. // `npm config` commands fail hard when used with workspaces getResult.itemValMsg += os.EOL + os.EOL + EnvQuery.getCmdOutput("npm", ["config", "list", "--no-workspaces"]) .split(EnvQuery.allEolRegex) .filter(line => /registry =|"project"|node bin location =|cwd =|HOME =/.test(line)) .map(line => line.includes("registry =") ? line : line.replace(/^; /, "")) .join(os.EOL); // add indent to each line getResult.itemValMsg = EnvQuery.divider + "NPM information:" + os.EOL + EnvQuery.indent + getResult.itemValMsg.replace(EnvQuery.allEolRegex, "$1" + EnvQuery.indent); npmProgress.statusMessage = "Complete"; npmProgress.percentComplete = operations_1.TaskProgress.ONE_HUNDRED_PERCENT; npmProgress.stageName = operations_1.TaskStage.COMPLETE; yield EnvQuery.updateProgressBar(doesProgBarExist); if (doesProgBarExist) { getItemOpts.progressApi.endBar(); } }); } // end getNpmInfo // __________________________________________________________________________ /** * Get other Zowe variables, beyond the ones we check for problem values. * * @param getResult The itemValMsg property is filled by this function. * The itemVal property is given no value by this function. */ static getOtherZoweEnvVars(getResult) { getResult.itemValMsg = ""; const envVars = process.env; const secureCredsList = censor_1.Censor.CENSORED_OPTIONS.map(opt => opt.toUpperCase().replaceAll("-", "_")); for (const nextVar of Object.keys(envVars)) { if (nextVar.startsWith("ZOWE_") && nextVar != "ZOWE_CLI_HOME" && nextVar != "ZOWE_APP_LOG_LEVEL" && nextVar != "ZOWE_IMPERATIVE_LOG_LEVEL") { getResult.itemValMsg += nextVar + " = "; if (secureCredsList.some(secureOpt => nextVar.toUpperCase().includes(secureOpt))) { getResult.itemValMsg += "******"; } else { getResult.itemValMsg += envVars[nextVar]; } getResult.itemValMsg += os.EOL; } } // remove the last newline getResult.itemValMsg = getResult.itemValMsg.replace(EnvQuery.lastEolRegex, ""); if (getResult.itemValMsg.length == 0) { getResult.itemValMsg += "No other 'ZOWE_' variables have been set."; } } // __________________________________________________________________________ /** * Get information about Zowe plugins. * Logic stolen from plugins list command handler. * * @param getResult The itemVal and itemValMsg properties are filled * by this function. */ static getPluginInfo(getResult, getItemOpts) { return __awaiter(this, void 0, void 0, function* () { const doesProgBarExist = (getItemOpts === null || getItemOpts === void 0 ? void 0 : getItemOpts.progressApi) ? true : false; // setup progress bar const configProgress = { percentComplete: operations_1.TaskProgress.FIFTY_PERCENT, statusMessage: "Retrieving installed plugins", stageName: operations_1.TaskStage.IN_PROGRESS }; if (doesProgBarExist) { getItemOpts.progressApi.startBar({ task: configProgress }); yield EnvQuery.updateProgressBar(doesProgBarExist, true); } const installedPlugins = PluginIssues_1.PluginIssues.instance.getInstalledPlugins(); getResult.itemValMsg = EnvQuery.divider + "Installed plugins:" + os.EOL; for (const nextPluginNm of Object.keys(installedPlugins) .sort((a, b) => a.localeCompare(b))) { getResult.itemValMsg += os.EOL + EnvQuery.indent + nextPluginNm + os.EOL + EnvQuery.indent + EnvQuery.indent + "Version = " + installedPlugins[nextPluginNm].version + os.EOL + EnvQuery.indent + EnvQuery.indent + "Package = " + installedPlugins[nextPluginNm].package + os.EOL; } getResult.itemValMsg += EnvQuery.divider; if (doesProgBarExist) { configProgress.percentComplete = operations_1.TaskProgress.ONE_HUNDRED_PERCENT; yield EnvQuery.updateProgressBar(doesProgBarExist); getItemOpts.progressApi.endBar(); } }); } // __________________________________________________________________________ /** * Get the Zowe version number. * * @param getResult The itemVal and itemValMsg properties are filled * by this function. */ static getZoweVer(getResult) { const cliPackageJson = utilities_1.ImperativeConfig.instance.callerPackageJson; if (Object.prototype.hasOwnProperty.call(cliPackageJson, "version")) { getResult.itemVal = cliPackageJson.version; } else { getResult.itemVal = "No version found in CLI package.json!"; } getResult.itemValMsg = EnvQuery.divider + "Zowe CLI version = " + getResult.itemVal; } // __________________________________________________________________________ /** * If a progress bar is in use, pause long enough to let it update its status. * * @param doesProgBarExist * Is the progress bar availbale for use? * @param firstUpdate * Is this our first progress bar update? * Initialization of the progress bar takes extra time. */ static updateProgressBar(doesProgBarExist_1) { return __awaiter(this, arguments, void 0, function* (doesProgBarExist, firstUpdate = false) { if (doesProgBarExist) { const firstUpdateTime = 300; // millis const laterUpdateTime = 100; // millis let timeToUpdate; if (firstUpdate) { timeToUpdate = firstUpdateTime; } else { timeToUpdate = laterUpdateTime; } yield CliUtils_1.CliUtils.sleep(timeToUpdate); } }); } } exports.EnvQuery = EnvQuery; EnvQuery.divider = `______________________________________________${os.EOL}`; EnvQuery.indent = " "; EnvQuery.eolMatch = "(\r?\n|\n)"; EnvQuery.allEolRegex = new RegExp(EnvQuery.eolMatch, "g"); EnvQuery.lastEolRegex = new RegExp(EnvQuery.eolMatch + "$"); //# sourceMappingURL=EnvQuery.js.map