diff --git a/client/maxctrl/common.js b/client/maxctrl/common.js new file mode 100644 index 000000000..976012d7e --- /dev/null +++ b/client/maxctrl/common.js @@ -0,0 +1,155 @@ +/* + * 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: 2020-01-01 + * + * 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. + */ + +var _ = require('lodash-getpath') +var request = require('request'); +var colors = require('colors/safe'); +var Table = require('cli-table'); +var assert = require('assert') + +module.exports = function() { + const maxctrl_version = '1.0.0'; + + // Common options for all commands + this.program = require('yargs'); + this.program + .group(['u', 'p', 'h', 'p', 'P', 's'], 'Global Options:') + .option('u', { + alias:'user', + global: true, + default: 'mariadb', + describe: 'Username to use', + type: 'string' + }) + .option('p', { + alias: 'password', + describe: 'Password for the user', + default: 'admin', + type: 'string' + }) + .option('h', { + alias: 'host', + describe: 'The hostname or address where MaxScale is located', + default: 'localhost', + type: 'string' + }) + .option('P', { + alias: 'port', + describe: 'The port where MaxScale REST API listens on', + default: 8989, + type: 'number' + }) + .option('s', { + alias: 'secure', + describe: 'Enable TLS encryption of connections', + default: 'false', + type: 'boolean' + }) + .version(maxctrl_version) + .help() + + // Request a resource collection and format it as a table + this.getCollection = function (resource, headers, parts) { + + doRequest(resource, function(res) { + var table = getTable(headers) + + res.data.forEach(function(i) { + row = [] + + parts.forEach(function(p) { + var v = _.getPath(i, p, "") + + if (Array.isArray(v)) { + v = v.join(", ") + } + row.push(v) + }) + + table.push(row) + }) + + console.log(table.toString()) + }) + } + + // Request a single resource and format it as a key-value list + this.getResource = function (resource, fields) { + + doRequest(resource, function(res) { + var table = new Table() + + fields.forEach(function(i) { + var k = Object.keys(i)[0] + var path = i[k] + var v = _.getPath(res.data, path, "") + + if (Array.isArray(v) && typeof(v[0]) != 'object') { + v = v.join(", ") + } else if (typeof(v) == 'object') { + v = JSON.stringify(v, null, 4) + } + + var o = {} + o[k] = v + table.push(o) + }) + + console.log(table.toString()) + }) + } + + // Helper for converting endpoints to acutal URLs + this.getUri = function(endpoint, options) { + var base = 'http://'; + var argv = this.program.argv + + if (argv.secure) { + base = 'https://'; + } + + return base + argv.user + ':' + argv.password + '@' + + argv.host + ':' + argv.port + '/v1/' + endpoint; + } + + // Helper for executing requests and handling their responses + this.doRequest = function(resource, cb) { + request({ + uri: getUri(resource), + json: true + }, function(err, resp, res) { + if (resp.statusCode == 200) { + cb(res) + } else if (resp.statusCode == 204) { + console.log(colors.green("OK")) + } else { + console.log("Error:", resp.statusCode, resp.statusMessage) + if (res) { + console.log(res) + } + } + }) + } +} + +// Creates a table-like array for output. The parameter is an array of header names +function getTable(headobj) { + + for (i = 0; i < headobj.length; i++) { + headobj[i] = colors.cyan(headobj[i]) + } + + return new Table({ + head: headobj + }) +} diff --git a/client/maxctrl/lib/list.js b/client/maxctrl/lib/list.js new file mode 100644 index 000000000..212afdb3c --- /dev/null +++ b/client/maxctrl/lib/list.js @@ -0,0 +1,70 @@ +/* + * 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: 2020-01-01 + * + * 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')() + +exports.command = 'list ' +exports.desc = 'List objects' +exports.handler = function() {} +exports.builder = function(yargs) { + yargs + .command('servers', 'List servers', {}, function() { + + getCollection('servers', + ['Server', 'Address', 'Port', 'Connections', 'Status'], + ['id', + 'attributes.parameters.address', + 'attributes.parameters.port', + 'attributes.statistics.connections', + 'attributes.status']) + }) + .command('services', 'List services', {}, function() { + getCollection('services', + ['Service', 'Router', 'Connections', 'Total Connections', 'Servers'], + ['id', + 'attributes.router', + 'attributes.connections', + 'attributes.total_connections', + 'relationships.servers.data[].id']) + }) + .command('monitors', 'List monitors', {}, function() { + getCollection('monitors', + ['Monitor', 'Status', 'Servers'], + ['id', + 'attributes.state', + 'relationships.servers.data[].id']) + }) + .command('sessions', 'List sessions', {}, function() { + getCollection('sessions', + ['Id', 'Service', 'User', 'Host'], + ['id', + 'relationships.services.data[].id', + 'attributes.user', + 'attributes.remote']) + }) + .command('filters', 'List filters', {}, function() { + getCollection('filters', + ['Filter', 'Service', 'Module'], + ['id', + 'relationships.services.data[].id', + 'attributes.module']) + }) + .command('modules', 'List loaded modules', {}, function() { + getCollection('maxscale/modules', + ['Module', 'Type', 'Version'], + ['id', + 'attributes.module_type', + 'attributes.version']) + }) + .help() +} diff --git a/client/maxctrl/lib/show.js b/client/maxctrl/lib/show.js new file mode 100644 index 000000000..eb845c618 --- /dev/null +++ b/client/maxctrl/lib/show.js @@ -0,0 +1,87 @@ +/* + * 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: 2020-01-01 + * + * 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')() + +exports.command = 'show ' +exports.desc = 'Show objects' +exports.handler = function() {} +exports.builder = function(yargs) { + yargs + .command('server ', 'Show server', {}, function(argv) { + getResource('servers/' + argv.server, [ + {'Server': 'id'}, + {'Address': 'attributes.parameters.address'}, + {'Port': 'attributes.parameters.port'}, + {'Status': 'attributes.status'}, + {'Services': 'relationships.services.data[].id'}, + {'Monitors': 'relationships.monitors.data[].id'}, + {'Master ID': 'attributes.master_id'}, + {'Node ID': 'attributes.node_id'}, + {'Slave Server IDs': 'attributes.slaves'}, + {'Statistics': 'attributes.statistics'} + ]) + }) + .command('service ', 'Show service', {}, function(argv) { + getResource('services/' + argv.service, [ + {'Service': 'id'}, + {'Router': 'attributes.router'}, + {'Started At': 'attributes.started'}, + {'Current Connections': 'attributes.connections'}, + {'Total Connections': 'attributes.total_connections'}, + {'Servers': 'relationships.servers.data[].id'}, + {'Parameters': 'attributes.parameters'}, + {'Router Diagnostics': 'attributes.router_diagnostics'} + ]) + }) + .command('monitor ', 'Show monitor', {}, function(argv) { + getResource('monitors/' + argv.monitor, [ + {'Monitor': 'id'}, + {'Status': 'attributes.state'}, + {'Servers': 'relationships.servers.data[].id'}, + {'Parameters': 'attributes.parameters'}, + {'Monitor Diagnostics': 'attributes.monitor_diagnostics'} + ]) + }) + .command('session ', 'Show session', {}, function(argv) { + getResource('sessions/' + argv.session, [ + {'Id': 'id'}, + {'Service': 'relationships.services.data[].id'}, + {'Status': 'attributes.state'}, + {'User': 'attributes.user'}, + {'Host': 'attributes.remote'}, + {'Connected': 'attributes.connected'}, + {'Idle': 'attributes.idle'} + ]) + }) + .command('filter ', 'Show filter', {}, function(argv) { + getResource('filters/' + argv.filter, [ + {'Filter': 'id'}, + {'Module': 'attributes.module'}, + {'Services': 'relationships.services.data[].id'}, + {'Parameters': 'attributes.parameters'} + ]) + }) + .command('module ', 'Show loaded module', {}, function(argv) { + getResource('maxscale/modules/' + argv.module, [ + {'Module': 'id'}, + {'Type': 'attributes.module_type'}, + {'Version': 'attributes.version'}, + {'Maturity': 'attributes.status'}, + {'Description': 'attributes.description'}, + {'Parameters': 'attributes.parameters'}, + {'Commands': 'attributes.commands'} + ]) + }) + .help() +} diff --git a/client/maxctrl/maxctrl.js b/client/maxctrl/maxctrl.js new file mode 100644 index 000000000..67068f9b6 --- /dev/null +++ b/client/maxctrl/maxctrl.js @@ -0,0 +1,21 @@ +/* + * 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: 2020-01-01 + * + * 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')() + +'use strict'; + +program + .command(require('./lib/list.js')) + .command(require('./lib/show.js')) + .demandCommand(1, 'At least one command is required') + .argv diff --git a/client/maxctrl/package.json b/client/maxctrl/package.json new file mode 100644 index 000000000..791ae18c7 --- /dev/null +++ b/client/maxctrl/package.json @@ -0,0 +1,25 @@ +{ + "name": "maxctrl", + "version": "1.0.0", + "description": "MaxScale Administrative Client", + "repository": "https://github.com/mariadb-corporation/MaxScale", + "main": "maxctrl.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "maxscale" + ], + "bin": { + "maxctrl": "./maxctrl.js" + }, + "author": "MariaDB Corporation Ab", + "license": "SEE LICENSE IN ../../LICENSE.TXT", + "dependencies": { + "cli-table": "^0.3.1", + "lodash": "^4.17.4", + "lodash-getpath": "^0.2.4", + "request": "^2.81.0", + "yargs": "^8.0.2" + } +}