/* * Copyright (c) 2016 MariaDB Corporation Ab * * Use of this software is governed by the Business Source License included * in the LICENSE.TXT file and at www.mariadb.com/bsl11. * * Change Date: 2023-10-29 * * On the date above, in accordance with the Business Source License, use * of this software will be governed by version 2 or later of the General * Public License. */ require('./common.js')() const list_servers_fields = [ { name: 'Server', path: 'id', description: 'Server name' }, { name: 'Address', path: 'attributes.parameters.address', description: 'Address where the server listens' }, { name: 'Port', path: 'attributes.parameters.port', description: 'The port on which the server listens' }, { name: 'Connections', path: 'attributes.statistics.connections', description: 'Current connection count' }, { name: 'State', path: 'attributes.state', description: 'Server state' }, { name: 'GTID', path: 'attributes.gtid_current_pos', description: 'Current value of @@gtid_current_pos' } ] const list_services_fields = [ { name: 'Service', path: 'id', description: 'Service name' }, { name: 'Router', path: 'attributes.router', description: 'Router used by the service' }, { name: 'Connections', path: 'attributes.connections', description: 'Current connection count' }, { name: 'Total Connections', path: 'attributes.total_connections', description: 'Total connection count' }, { name: 'Servers', path: 'relationships.servers.data[].id', description: 'Servers that the service uses' } ] const list_listeners_fields = [ { name: 'Name', path: 'id', description: 'Listener name' }, { name: 'Port', path: 'attributes.parameters.port', description: 'The port where the listener listens' }, { name: 'Host', path: 'attributes.parameters.host', description: 'The address or socket where the listener listens' }, { name: 'State', path: 'attributes.state', description: 'Listener state' } ] const list_monitors_fields = [ { name: 'Monitor', path: 'id', description: 'Monitor name' }, { name: 'State', path: 'attributes.state', description: 'Monitor state' }, { name: 'Servers', path: 'relationships.servers.data[].id', description: 'The servers that this monitor monitors' } ] const list_sessions_fields = [ { name: 'Id', path: 'id', description: 'Session ID' }, { name: 'User', path: 'attributes.user', description: 'Username' }, { name: 'Host', path: 'attributes.remote', description: 'Client host address' }, { name: 'Connected', path: 'attributes.connected', description: 'Time when the session started' }, { name: 'Idle', path: 'attributes.idle', description: 'How long the session has been idle, in seconds' }, { name: 'Service', path: 'relationships.services.data[].id', description: 'The service where the session connected' } ] const list_filters_fields = [ { name: 'Filter', path: 'id', description: 'Filter name' }, { name: 'Service', path: 'relationships.services.data[].id', description: 'Services that use the filter' }, { name: 'Module', path: 'attributes.module', description: 'The module that the filter uses' } ] const list_modules_fields = [ { name: 'Module', path: 'id', description: 'Module name' }, { name: 'Type', path: 'attributes.module_type', description: 'Module type' }, { name: 'Version', path: 'attributes.version', description: 'Module version' } ] const list_threads_fields = [ { name: 'Id', path: 'id', description: 'Thread ID' }, { name: 'Current FDs', path: 'attributes.stats.current_descriptors', description: 'Current number of managed file descriptors' }, { name: 'Total FDs', path: 'attributes.stats.total_descriptors', description: 'Total number of managed file descriptors' }, { name: 'Load (1s)', path: 'attributes.stats.load.last_second', description: 'Load percentage over the last second' }, { name: 'Load (1m)', path: 'attributes.stats.load.last_minute', description: 'Load percentage over the last minute' }, { name: 'Load (1h)', path: 'attributes.stats.load.last_hour', description: 'Load percentage over the last hour' } ] const list_users_fields = [ { name: 'Name', path: 'id', description: 'User name' }, { name: 'Type', path: 'type', description: 'User type' }, { name: 'Privileges', path: 'attributes.account', description: 'User privileges' }, ] const list_commands_fields = [ { name: 'Module', path: 'id', description: 'Module name' }, { name: 'Commands', path: 'attributes.commands[].id', description: 'Available commands' } ] exports.command = 'list ' exports.desc = 'List objects' exports.handler = function() {} exports.builder = function(yargs) { yargs .command('servers', 'List servers', function(yargs) { return yargs.epilog('List all servers in MaxScale.' + fieldDescriptions(list_servers_fields)) .usage('Usage: list servers') }, function(argv) { maxctrl(argv, function(host) { // First, get the list of all servers return getJson(host, 'servers') .then((res) => { // Build a set of unique monitors, flatten it into an array of strings and // filter out any duplicate or undefined values (from servers that aren't // monitored). var v = _.uniq(_.flatten(_.getPath(res, 'data[].relationships.monitors.data[].id'))).filter(i => i) // Get the server_info object for each monitor (if it defines one) var infos = [] var promises = v.map((i) => getJson(host, 'monitors/' + i) .then((j) => { info = _.get(j, 'data.attributes.monitor_diagnostics.server_info') if (info) { info.forEach((k) => infos.push(k)) } })) // Wait for promises to resolve return Promise.all(promises) .then(() => { res.data.forEach((i) => { // Get the gtid_current_pos value for each server from the server_info list var idx = infos.findIndex((info) => info.name == i.id) if (idx != -1 && infos[idx].gtid_current_pos) { // Found the GTID position of this server i.attributes.gtid_current_pos = infos[idx].gtid_current_pos } else { // Assign an empty value so we always have something to print i.attributes.gtid_current_pos = '' } }) }) .then(() => filterResource(res, list_servers_fields)) .then((res) => rawCollectionAsTable(res, list_servers_fields)) }) }) }) .command('services', 'List services', function(yargs) { return yargs.epilog('List all services and the servers they use.' + fieldDescriptions(list_services_fields)) .usage('Usage: list services') }, function(argv) { maxctrl(argv, function(host) { return getCollection(host, 'services', list_services_fields) }) }) .command('listeners ', 'List listeners of a service', function(yargs) { return yargs.epilog('List listeners for a service.' + fieldDescriptions(list_listeners_fields)) .usage('Usage: list listeners ') }, function(argv) { maxctrl(argv, function(host) { return getSubCollection(host, 'services/' + argv.service, 'attributes.listeners', list_listeners_fields) }) }) .command('monitors', 'List monitors', function(yargs) { return yargs.epilog('List all monitors in MaxScale.' + fieldDescriptions(list_monitors_fields)) .usage('Usage: list monitors') }, function(argv) { maxctrl(argv, function(host) { return getCollection(host, 'monitors', list_monitors_fields) }) }) .command('sessions', 'List sessions', function(yargs) { return yargs.epilog('List all client sessions.' + fieldDescriptions(list_sessions_fields)) .usage('Usage: list sessions') }, function(argv) { maxctrl(argv, function(host) { return getCollection(host, 'sessions', list_sessions_fields) }) }) .command('filters', 'List filters', function(yargs) { return yargs.epilog('List all filters in MaxScale.' + fieldDescriptions(list_filters_fields)) .usage('Usage: list filters') }, function(argv) { maxctrl(argv, function(host) { return getCollection(host, 'filters', list_filters_fields) }) }) .command('modules', 'List loaded modules', function(yargs) { return yargs.epilog('List all currently loaded modules.' + fieldDescriptions(list_modules_fields)) .usage('Usage: list modules') }, function(argv) { maxctrl(argv, function(host) { return getCollection(host, 'maxscale/modules', list_modules_fields) }) }) .command('threads', 'List threads', function(yargs) { return yargs.epilog('List all worker threads.' + fieldDescriptions(list_threads_fields)) .usage('Usage: list threads') }, function(argv) { maxctrl(argv, function(host) { return getCollection(host, 'maxscale/threads', list_threads_fields) }) }) .command('users', 'List created users', function(yargs) { return yargs.epilog('List network the users that can be used to connect to the MaxScale REST API' + ' as well as enabled local accounts.' + fieldDescriptions(list_users_fields)) .usage('Usage: list users') }, function(argv) { maxctrl(argv, function(host) { return getCollection(host, 'users', list_users_fields) }) }) .command('commands', 'List module commands', function(yargs) { return yargs.epilog('List all available module commands.' + fieldDescriptions(list_commands_fields)) .usage('Usage: list commands') }, function(argv) { maxctrl(argv, function(host) { return getCollection(host, 'maxscale/modules', list_commands_fields) }) }) .usage('Usage: list ') .help() .command('*', 'the default command', {}, function(argv) { maxctrl(argv, function(host) { return error('Unknown command. See output of `help list` for a list of commands.') }) }) }