UNPKG

@axway/axway-central-cli

Version:

Manage APIs, services and publish to the Amplify Marketplace

272 lines (262 loc) 11.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.get = void 0; var _chalk = _interopRequireDefault(require("chalk")); var _snooplogg = _interopRequireDefault(require("snooplogg")); var _ApiServerClient = require("../../common/ApiServerClient"); var _DefinitionsManager = require("../../common/DefinitionsManager"); var _Renderer = _interopRequireDefault(require("../../common/Renderer")); var _resultsRenderers = require("../../common/resultsRenderers"); var _types = require("../../common/types"); var _utils = require("../../common/utils"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const { log } = (0, _snooplogg.default)('engage: get'); const getListOrByName = async (resourceDef, client, scopeName, resourceName, scopeDef, query, progressListener, expand, langDef, fieldSet) => { return resourceName ? await client.getResourceByName({ resourceDef, resourceName, scopeDef, scopeName, expand, langDef, fieldSet }) : await client.getResourcesList({ resourceDef, scopeDef, scopeName, query, progressListener, expand, langDef, fieldSet }); }; const get = exports.get = { action: async function ({ argv, console }) { if (!argv.team && argv.owner === false) { // no --team set and --no-owner was set, so we set the team to `null` which will know // to get teams that do not have an owner argv.team = null; } const { args, attribute, baseUrl, cache, account, region, tag, team, title } = argv; // will be set to true and exit 1 if any get result contains an error or args invalid let isCmdError = true; // name can be provided or not (args[0] is the resource type) const resourceName = args[1]; // verify output argument if (!!argv.output && !(argv.output in _types.OutputTypes)) throw Error(`invalid "output" (-o,--output) value provided, allowed: ${_types.OutputTypes.yaml} | ${_types.OutputTypes.json}`); const renderer = new _Renderer.default(console, argv.output); const getResults = []; try { // get specs and allowed words const client = new _ApiServerClient.ApiServerClient({ baseUrl, account, region, team, useCache: cache }); const defsManager = await new _DefinitionsManager.DefinitionsManager(client).init(); const scope = (0, _utils.parseScopeParam)(argv.scope); let languageExpand = argv.language; const languageDefinition = argv.languageDefinition; const formattedFilter = (0, _utils.transformSimpleFilters)(title, attribute, tag); const query = argv.query ? argv.query : formattedFilter; // verify either "--language" or "--languageDefinition" argument is passed and error when both are passed if (languageExpand && languageDefinition) { throw Error('You must specify either of the "--language" or "--languageDefinition" argument and not both.'); } if (languageDefinition && !argv.output) { throw Error('The "--languageDefinition" argument can only be used with output(-o,--output) argument'); } if (languageExpand) { // when "*" is provided, expand all supported languages let lang = ""; let i = 0; if (languageExpand.trim() === "*") { lang = "languages-*"; } else { let langCodeArr = languageExpand.split(','); langCodeArr.forEach(v => { if (i < langCodeArr.length - 1) { lang = lang + "languages-" + v.trim() + ","; } else { lang = lang + "languages-" + v.trim(); } i++; }); } languageExpand = 'languages,' + lang; } if (argv.query && formattedFilter) { console.log(`${_chalk.default.yellow('Both simple queries and advanced query parameters have been provided. Only the advanced query parameter will be applied.')}`); } // verify passed args if (!args.length) { renderer.error('Error: You must specify the type of resource to get.'); console.log(`\nUSAGE: Get a list of the resources: ${_chalk.default.cyan(`axway engage get <Resource>`)}\n Get a list of multiple resources: ${_chalk.default.cyan(`axway engage get <Resource1>,<Resource2>,...,<ResourceN>`)}\n Get a list of resources in a specific scope: ${_chalk.default.cyan(`axway engage get <Resource> -s/--scope <Scope Kind>/<Scope Name>`)}\n Get a list of resources matching a specific RSQL query: ${_chalk.default.cyan(`axway engage get <Resource> -q/--query "<RSQL query>"`)}\n Get a specific resource by name in all scopes with a specific name: ${_chalk.default.cyan(`axway engage get <Resource> <Name> -s/--scope <Scope Name>`)}\n Get a specific resource by name in a specific scope: ${_chalk.default.cyan(`axway engage get <Resource> <Name> -s/--scope <Scope Kind>/<Scope Name>`)}\n The server supports the following resources: ${defsManager.getDefsTableForHelpMsg()}`); process.exit(1); } // Start showing download progress. const downloadMessage = 'Retrieving resource(s)'; renderer.startSpin(downloadMessage); const progressListener = percent => { renderer.updateSpinText(`${downloadMessage} - ${percent}%`); }; // parse passed resources types (if passed comma-separated) for (const typedResource of args[0].split(',')) { const defs = defsManager.findDefsByWord(typedResource); // is typed resource known? if (!defs) throw Error(`the server doesn't have a resource type "${typedResource}"`); // check if a user is trying to get a scoped-only resource by name without providing a scope name if (defs.every(defs => !!defs.scope) && resourceName && !scope) throw Error(`scope name param (-s/--scope) is required for the scoped "${defs[0].resource.spec.kind}" resource.`); // verify passed scope param kind (0, _utils.verifyScopeParam)(defsManager.getAllKindsList(), defs, scope); /** 1) If "scope" param provided: execute getByName or getList calls for every definition that match this scope name/kind. 2) If "scope" param is not provided: execute list (get all) api calls for scoped resources without providing the scope in the path so api-server returns the entire list in all scopes. For example, using "Document" kind and calling https://apicentral.axway.com/apis/catalog/v1alpha1/documents returns a list of documents in Asset and AssetRelease scopes in a single api call. So getting unique list of groups and finding first matching definitions to do a call Note: this logic might have some edge cases if same kind can be used for "scoped" and "scope" resources and api-server is not handling this case correctly anymore. */ if (scope) { const results = await Promise.all(defs.filter(defs => !scope.kind || !defs.scope || defs.scope.spec.kind === scope.kind).map(async defs => ({ response: await getListOrByName(defs.resource, client, scope.name, resourceName, defs.scope, query, progressListener, languageExpand, languageDefinition, argv.output ? undefined : getFieldSetFromDefinitionColumns(defs)), cli: defs.cli }))); results.forEach(({ response, cli }) => { getResults.push({ columns: cli.spec.columns, response }); }); } else { const defsMatchingGroup = {}; defs.forEach(def => { if (!defsMatchingGroup[def.resource.metadata.scope.name]) { defsMatchingGroup[def.resource.metadata.scope.name] = def; } }); const results = await Promise.all(Object.values(defsMatchingGroup).map(async defs => ({ response: await getListOrByName(defs.resource, client, undefined, resourceName, undefined, query, progressListener, languageExpand, languageDefinition, argv.output ? undefined : getFieldSetFromDefinitionColumns(defs)), cli: defs.cli }))); results.forEach(({ response, cli }) => { getResults.push({ columns: cli.spec.columns, response }); }); } } // resolve team guids for (const obj of getResults) { await (0, _resultsRenderers.resolveTeamNames)(obj); } // considering the command successful if at least 1 response found isCmdError = !getResults.filter(res => res.response.data !== null).length; renderer.renderGetResults(getResults, 'Resource(s) successfully retrieved', languageDefinition); } catch (e) { log('command error', e); isCmdError = true; renderer.anyError(e); } finally { log('command complete'); renderer.stopSpin(); if (isCmdError) process.exit(1); } }, desc: 'List one or more resources', args: [{ name: 'args', desc: 'Command arguments, run "axway engage get" to see the examples', multiple: true, required: false }], options: { ..._types.commonCmdArgsDescription, '-o, --output [value]': { desc: `Additional output formats. One of: ${_types.OutputTypes.yaml} | ${_types.OutputTypes.json}` }, '-s, --scope [name|kind/name]': { desc: 'Scope name or kind/name for scoped resources' }, '-q, --query [RSQL query]': { desc: 'RSQL-formatted query to search for filters that match specific parameters' }, '--title [title]': { desc: 'Title of resource(s) to fetch' }, '--attribute [key=value]': { desc: 'Attribute in key=value pair format to filter by' }, '--tag [tag]': { desc: 'Tag of resource(s) to fetch' }, '--team [guid|name]': 'The team name or guid to use', '--no-owner': 'Returns resources which do not have an owner', '--language=[langCode]': { desc: `Show the language detail of the retruned object. One of: * | Comma Separated values of ${_types.LanguageTypes.French} | ${_types.LanguageTypes.US} | ${_types.LanguageTypes.German} | ${_types.LanguageTypes.Portugese}` }, '--languageDefinition=[langCode]': { desc: `Show the language definition constraint of the returned object. One of: Comma Separated values of ${_types.LanguageTypes.French} | ${_types.LanguageTypes.US} | ${_types.LanguageTypes.German} | ${_types.LanguageTypes.Portugese}` } } }; /** * Gets the resource field names to be shown when outputting the resource as a table. * These names are to be assigned to the api-server HTTP GET request's "fields" query param. * @param def The resource definition providing the columns to be shown in the outputed table. * @returns Returns a set set of field names. */ function getFieldSetFromDefinitionColumns(def) { var _def$cli, _def$cli$spec, _def$cli$spec$columns; const fieldSet = new Set(); (_def$cli = def.cli) === null || _def$cli === void 0 ? void 0 : (_def$cli$spec = _def$cli.spec) === null || _def$cli$spec === void 0 ? void 0 : (_def$cli$spec$columns = _def$cli$spec.columns) === null || _def$cli$spec$columns === void 0 ? void 0 : _def$cli$spec$columns.forEach(column => { let fieldName = column.jsonPath; if (fieldName.startsWith('.')) { fieldName = fieldName.substring(1); } fieldSet.add(fieldName); }); return fieldSet; }