From 3a9bfa380e213b28dbbd19b8cf8ef38c1272a1ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 28 May 2019 11:05:46 +0300 Subject: [PATCH] MXS-2307: Allow multi-parameter updates Multiple parameters can now be updated with a single call in MaxCtrl. This makes alterations more convenient and prevents intermediate states when multiple parameters are changed at the same time. The changes are backwards compatible so it should not affect existing programs. --- maxctrl/lib/alter.js | 87 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 16 deletions(-) diff --git a/maxctrl/lib/alter.js b/maxctrl/lib/alter.js index 88bd3eee8..b4179d28f 100644 --- a/maxctrl/lib/alter.js +++ b/maxctrl/lib/alter.js @@ -70,37 +70,87 @@ function setFilters(host, argv){ return doAsyncRequest(host, 'services/' + argv.service, null, {method: 'PATCH', body: payload}) } +function parseValue(value) { + if (value == 'null' || value == '') { + // JSON null (empty value not strictly null but we treat it like that) + return null + } else if (value == 'true') { + // JSON true + return true + } else if (value == 'false') { + // JSON false + return false + } + + var n = Number(value) + + if (!Number.isNaN(n)) { + return n + } + + return value +} + +function processArgs(key, value, extra) { + var arr = [key, value].concat(extra) + + if (arr.length % 2 != 0) { + // Odd number of arguments, return null for error + return null + } + + var keys = arr.filter((v, i) => i % 2 == 0) + var values = arr.filter((v, i) => i % 2 != 0) + var params = {} + + keys.forEach((k, i) => { + params[k] = parseValue(values[i]) + }) + + return params +} + +function updateParams(host, resource, key, value, extra){ + var params = processArgs(key, value, extra) + + if (params) { + return updateValue(host, resource, 'data.attributes.parameters', params) + } else { + return error('No value defined for parameter `' + argv.params[argv.params.length - 1] + '`') + } +} + exports.command = 'alter ' exports.desc = 'Alter objects' exports.handler = function() {} exports.builder = function(yargs) { yargs - .command('server ', 'Alter server parameters', function(yargs) { - return yargs.epilog('To display the server parameters, execute `show server `') - .usage('Usage: alter server ') + .command('server [params...]', 'Alter server parameters', function(yargs) { + return yargs.epilog('To display the server parameters, execute `show server `.') + .usage('Usage: alter server ...') }, function(argv) { maxctrl(argv, function(host) { - return updateValue(host, 'servers/' + argv.server, 'data.attributes.parameters.' + argv.key, argv.value) + return updateParams(host, 'servers/' + argv.server, argv.key, argv.value, argv.params) }) }) - .command('monitor ', 'Alter monitor parameters', function(yargs) { + .command('monitor [params...]', 'Alter monitor parameters', function(yargs) { return yargs.epilog('To display the monitor parameters, execute `show monitor `') - .usage('Usage: alter monitor ') + .usage('Usage: alter monitor ...') }, function(argv) { maxctrl(argv, function(host) { - return updateValue(host, 'monitors/' + argv.monitor, 'data.attributes.parameters.' + argv.key, argv.value) + return updateParams(host, 'monitors/' + argv.monitor, argv.key, argv.value, argv.params) }) }) - .command('service ', 'Alter service parameters', function(yargs) { + .command('service [params...]', 'Alter service parameters', function(yargs) { return yargs.epilog('To display the service parameters, execute `show service `. ' + 'Some routers support runtime configuration changes to all parameters. ' + 'Currently all readconnroute, readwritesplit and schemarouter parameters ' + 'can be changed at runtime. In addition to module specific parameters, ' + 'the following list of common service parameters can be altered at runtime:\n\n' + JSON.stringify(service_params, null, 4)) - .usage('Usage: alter service ') + .usage('Usage: alter service ...') }, function(argv) { maxctrl(argv, function(host) { - return updateValue(host, 'services/' + argv.service, 'data.attributes.parameters.' + argv.key, argv.value) + return updateParams(host, 'services/' + argv.service, argv.key, argv.value, argv.params) }) }) .command('service-filters [filters...]', 'Alter filters of a service', function(yargs) { @@ -118,21 +168,21 @@ exports.builder = function(yargs) { return setFilters(host, argv) }) }) - .command('logging ', 'Alter logging parameters', function(yargs) { + .command('logging [params...]', 'Alter logging parameters', function(yargs) { return yargs.epilog('To display the logging parameters, execute `show logging`') - .usage('Usage: alter logging ') + .usage('Usage: alter logging ...') }, function(argv) { maxctrl(argv, function(host) { - return updateValue(host, 'maxscale/logs', 'data.attributes.parameters.' + argv.key, argv.value) + return updateParams(host, 'maxscale/logs', argv.key, argv.value, argv.params) }) }) - .command('maxscale ', 'Alter MaxScale parameters', function(yargs) { + .command('maxscale [params...]', 'Alter MaxScale parameters', function(yargs) { return yargs.epilog('To display the MaxScale parameters, execute `show maxscale`. ' + 'The following list of parameters can be altered at runtime:\n\n' + JSON.stringify(maxscale_params, null, 4)) - .usage('Usage: alter maxscale ') + .usage('Usage: alter maxscale ...') }, function(argv) { maxctrl(argv, function(host) { - return updateValue(host, 'maxscale', 'data.attributes.parameters.' + argv.key, argv.value) + return updateParams(host, 'maxscale', argv.key, argv.value, argv.params) }) }) .command('user ', 'Alter admin user passwords', function(yargs) { @@ -158,6 +208,11 @@ exports.builder = function(yargs) { }) }) .usage('Usage: alter ') + .epilog('Multiple values can be updated at a time by providing the parameter ' + + 'name followed by the new value. For example, the following command ' + + 'would change both the `address` and the `port` parameter of a server:\n\n' + + ' alter server server1 address 127.0.0.1 port 3306\n\n' + + 'All alter commands except `alter user` and `alter service-filters` support multiple parameters.') .help() .command('*', 'the default command', {}, function(argv) { maxctrl(argv, function(host) {