MXS-1300: Send requests to multiple hosts
The host and port options were replace with one hosts option which combines the two. This allows a single command to be executed on multiple maxscale instances. Added accompanying code for checking responsiveness of all maxscale instances and handling synchronization of the check results. The code uses ECMAScript 2016 native promises to do this. Added a configurable timeout to all requests. This should allow users to interact with MaxScale over slow and laggy networks. Before each executed command, all hosts given as parameters are pinged to make sure they are alive. This should reduce the possibility of partial execution of commands due to failed MaxScales. The results of requests are grouped by the values of the hosts option. This allows users to compare results of multiple servers with relative ease. Fixed reversion of the default credentials from mariadb:admin to admin:mariadb.
This commit is contained in:
parent
11c8493167
commit
2670ca36a0
@ -114,44 +114,52 @@ module.exports = function() {
|
||||
}
|
||||
|
||||
// Helper for converting endpoints to acutal URLs
|
||||
this.getUri = function(endpoint, options) {
|
||||
var base = 'http://';
|
||||
this.getUri = function(host, endpoint) {
|
||||
var base = 'http://'
|
||||
var argv = this.program.argv
|
||||
|
||||
if (argv.secure) {
|
||||
base = 'https://';
|
||||
base = 'https://'
|
||||
}
|
||||
|
||||
return base + argv.user + ':' + argv.password + '@' +
|
||||
argv.host + ':' + argv.port + '/v1/' + endpoint;
|
||||
return base + argv.user + ':' + argv.password + '@' + host + '/v1/' + endpoint
|
||||
}
|
||||
|
||||
// Helper for executing requests and handling their responses
|
||||
this.doRequest = function(resource, cb, obj) {
|
||||
pingCluster()
|
||||
.then(function() {
|
||||
var argv = this.program.argv
|
||||
argv.hosts.forEach(function(host) {
|
||||
args = obj || {}
|
||||
args.uri = getUri(host, resource)
|
||||
args.json = true
|
||||
args.timeout = argv.timeout
|
||||
|
||||
args = obj || {}
|
||||
args.uri = getUri(resource),
|
||||
args.json = true
|
||||
|
||||
request(args, function(err, resp, res) {
|
||||
if (err) {
|
||||
// Failed to request
|
||||
logError(JSON.stringify(err, null, 4))
|
||||
} else if (resp.statusCode == 200 && cb) {
|
||||
// Request OK, returns data
|
||||
cb(res)
|
||||
} else if (resp.statusCode == 204) {
|
||||
// Request OK, no data
|
||||
console.log(colors.green('OK'))
|
||||
} else {
|
||||
// Unexpected return code, probably an error
|
||||
var errstr = resp.statusCode + ' ' + resp.statusMessage
|
||||
if (res) {
|
||||
errstr += ' ' + JSON.stringify(res, null, 4)
|
||||
}
|
||||
logError(errstr)
|
||||
}
|
||||
})
|
||||
request(args, function(err, resp, res) {
|
||||
if (err) {
|
||||
// Failed to request
|
||||
console.log(colors.yellow(host) + ':')
|
||||
logError(JSON.stringify(err, null, 4))
|
||||
} else if (resp.statusCode == 200 && cb) {
|
||||
// Request OK, returns data
|
||||
console.log(colors.yellow(host) + ':')
|
||||
cb(res)
|
||||
} else if (resp.statusCode == 204) {
|
||||
// Request OK, no data
|
||||
console.log(colors.yellow(host) + ': ' + colors.green('OK'))
|
||||
} else {
|
||||
// Unexpected return code, probably an error
|
||||
var errstr = resp.statusCode + ' ' + resp.statusMessage
|
||||
if (res) {
|
||||
errstr += ' ' + JSON.stringify(res, null, 4)
|
||||
}
|
||||
console.log(colors.yellow(host) + ':')
|
||||
logError(errstr)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
this.updateValue = function(resource, key, value) {
|
||||
@ -180,3 +188,27 @@ function getTable(headobj) {
|
||||
head: headobj
|
||||
})
|
||||
}
|
||||
|
||||
function pingMaxScale(host) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
request('http://' + host + '/v1', function(err, resp, res) {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else if (resp.statusCode != 200) {
|
||||
reject(resp.statusCode + ' ' + resp.statusMessage)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function pingCluster() {
|
||||
var promises = []
|
||||
|
||||
this.program.argv.hosts.forEach(function(i) {
|
||||
promises.push(pingMaxScale(i))
|
||||
})
|
||||
|
||||
return Promise.all(promises)
|
||||
}
|
||||
|
@ -18,31 +18,26 @@ const maxctrl_version = '1.0.0';
|
||||
|
||||
program
|
||||
.version(maxctrl_version)
|
||||
.group(['u', 'p', 'h', 'p', 'P', 's'], 'Global Options:')
|
||||
.group(['u', 'p', 'h', 's', 't'], 'Global Options:')
|
||||
.option('u', {
|
||||
alias:'user',
|
||||
global: true,
|
||||
default: 'mariadb',
|
||||
default: 'admin',
|
||||
describe: 'Username to use',
|
||||
type: 'string'
|
||||
})
|
||||
.option('p', {
|
||||
alias: 'password',
|
||||
describe: 'Password for the user',
|
||||
default: 'admin',
|
||||
default: 'mariadb',
|
||||
type: 'string'
|
||||
})
|
||||
.option('h', {
|
||||
alias: 'host',
|
||||
describe: 'MaxScale hostname',
|
||||
default: 'localhost',
|
||||
type: 'string'
|
||||
})
|
||||
.option('P', {
|
||||
alias: 'port',
|
||||
describe: 'MaxScale REST API port',
|
||||
default: 8989,
|
||||
type: 'number'
|
||||
alias: 'hosts',
|
||||
describe: 'List of MaxScale hosts. The hosts must be in ' +
|
||||
'<hostname>:<port> format and each host must be separated by spaces.',
|
||||
default: 'localhost:8989',
|
||||
type: 'array'
|
||||
})
|
||||
.option('s', {
|
||||
alias: 'secure',
|
||||
@ -50,6 +45,13 @@ program
|
||||
default: 'false',
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('t', {
|
||||
alias: 'timeout',
|
||||
describe: 'Request timeout in milliseconds',
|
||||
default: '10000',
|
||||
type: 'number'
|
||||
})
|
||||
|
||||
.command(require('./lib/list.js'))
|
||||
.command(require('./lib/show.js'))
|
||||
.command(require('./lib/set.js'))
|
||||
|
Loading…
x
Reference in New Issue
Block a user