Add '-d,--data DATA' option to triton cloudapi ...
Also fix '-H,--header' option to `triton cloudapi`. It never worked.
This commit is contained in:
parent
6e44318f00
commit
d25df7c011
@ -43,6 +43,7 @@ var vasync = require('vasync');
|
||||
var auth = require('smartdc-auth');
|
||||
|
||||
var bunyannoop = require('./bunyannoop');
|
||||
var common = require('./common');
|
||||
var errors = require('./errors');
|
||||
var SaferJsonClient = require('./SaferJsonClient');
|
||||
|
||||
@ -199,21 +200,24 @@ CloudApi.prototype._path = function _path(subpath /* , qparams, ... */) {
|
||||
/**
|
||||
* Cloud API request wrapper - modeled after http.request
|
||||
*
|
||||
* @param {Object|String} options - object or string for endpoint
|
||||
* @param {Object|String} opts - object or string for endpoint
|
||||
* - {String} path - URL endpoint to hit
|
||||
* - {String} method - HTTP(s) request method
|
||||
* - {Object} data - data to be passed
|
||||
* @param {Function} callback passed via the restify client
|
||||
* - {Object} headers - optional additional request headers
|
||||
* @param {Function} cb passed via the restify client
|
||||
*/
|
||||
CloudApi.prototype._request = function _request(options, callback) {
|
||||
CloudApi.prototype._request = function _request(opts, cb) {
|
||||
var self = this;
|
||||
if (typeof (options) === 'string')
|
||||
options = {path: options};
|
||||
assert.object(options, 'options');
|
||||
assert.func(callback, 'callback');
|
||||
assert.optionalObject(options.data, 'options.data');
|
||||
if (typeof (opts) === 'string')
|
||||
opts = {path: opts};
|
||||
assert.object(opts, 'opts');
|
||||
assert.optionalObject(opts.data, 'opts.data');
|
||||
assert.optionalString(opts.method, 'opts.method');
|
||||
assert.optionalObject(opts.headers, 'opts.headers');
|
||||
assert.func(cb, 'cb');
|
||||
|
||||
var method = (options.method || 'GET').toLowerCase();
|
||||
var method = (opts.method || 'GET').toLowerCase();
|
||||
assert.ok(['get', 'post', 'put', 'delete', 'head'].indexOf(method) >= 0,
|
||||
'invalid method given');
|
||||
switch (method) {
|
||||
@ -226,17 +230,20 @@ CloudApi.prototype._request = function _request(options, callback) {
|
||||
|
||||
self._getAuthHeaders(function (err, headers) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
cb(err);
|
||||
return;
|
||||
}
|
||||
var opts = {
|
||||
path: options.path,
|
||||
if (opts.headers) {
|
||||
common.objMerge(headers, opts.headers);
|
||||
}
|
||||
var reqOpts = {
|
||||
path: opts.path,
|
||||
headers: headers
|
||||
};
|
||||
if (options.data)
|
||||
self.client[method](opts, options.data, callback);
|
||||
if (opts.data)
|
||||
self.client[method](reqOpts, opts.data, cb);
|
||||
else
|
||||
self.client[method](opts, callback);
|
||||
self.client[method](reqOpts, cb);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -46,6 +46,32 @@ function deepObjCopy(obj) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Merge given objects into the given `target` object. Last one wins.
|
||||
* The `target` is modified in place.
|
||||
*
|
||||
* var foo = {bar: 32};
|
||||
* objMerge(foo, {bar: 42}, {bling: 'blam'});
|
||||
*
|
||||
* Adapted from tunnel-agent `mergeOptions`.
|
||||
*/
|
||||
function objMerge(target) {
|
||||
for (var i = 1, len = arguments.length; i < len; ++i) {
|
||||
var overrides = arguments[i];
|
||||
if (typeof (overrides) === 'object') {
|
||||
var keys = Object.keys(overrides);
|
||||
for (var j = 0, keyLen = keys.length; j < keyLen; ++j) {
|
||||
var k = keys[j];
|
||||
if (overrides[k] !== undefined) {
|
||||
target[k] = overrides[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
function zeroPad(n, width) {
|
||||
var s = String(n);
|
||||
assert.number(width, 'width');
|
||||
@ -852,6 +878,7 @@ function tildeSync(s) {
|
||||
module.exports = {
|
||||
objCopy: objCopy,
|
||||
deepObjCopy: deepObjCopy,
|
||||
objMerge: objMerge,
|
||||
zeroPad: zeroPad,
|
||||
boolFromString: boolFromString,
|
||||
jsonStream: jsonStream,
|
||||
|
@ -12,6 +12,9 @@
|
||||
|
||||
var http = require('http');
|
||||
|
||||
var errors = require('./errors');
|
||||
|
||||
|
||||
function do_cloudapi(subcmd, opts, args, callback) {
|
||||
if (opts.help) {
|
||||
this.do_help('help', {}, [subcmd], callback);
|
||||
@ -21,34 +24,50 @@ function do_cloudapi(subcmd, opts, args, callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
var path = args[0];
|
||||
|
||||
var reqopts = {
|
||||
method: opts.method.toLowerCase(),
|
||||
// Get `reqOpts` from given options.
|
||||
var method = opts.method;
|
||||
if (!method) {
|
||||
if (opts.data) {
|
||||
method = 'PUT';
|
||||
} else {
|
||||
method = 'GET';
|
||||
}
|
||||
}
|
||||
var reqOpts = {
|
||||
method: method.toLowerCase(),
|
||||
headers: {},
|
||||
path: path
|
||||
path: args[0]
|
||||
};
|
||||
|
||||
// parse -H headers
|
||||
for (var i = 0; i < opts.header.length; i++) {
|
||||
var raw = opts.header[i];
|
||||
var j = raw.indexOf(':');
|
||||
if (j < 0) {
|
||||
callback(new Error('failed to parse header: ' + raw));
|
||||
if (opts.header) {
|
||||
for (var i = 0; i < opts.header.length; i++) {
|
||||
var raw = opts.header[i];
|
||||
var j = raw.indexOf(':');
|
||||
if (j < 0) {
|
||||
callback(new errors.TritonError(
|
||||
'failed to parse header: ' + raw));
|
||||
return;
|
||||
}
|
||||
var header = raw.substr(0, j);
|
||||
var value = raw.substr(j + 1).trimLeft();
|
||||
reqOpts.headers[header] = value;
|
||||
}
|
||||
}
|
||||
if (opts.data) {
|
||||
try {
|
||||
reqOpts.data = JSON.parse(opts.data);
|
||||
} catch (parseErr) {
|
||||
callback(new errors.TritonError(parseErr,
|
||||
'given <data> is not valid JSON: ' + parseErr.message));
|
||||
return;
|
||||
}
|
||||
var header = raw.substr(0, j);
|
||||
var value = raw.substr(j + 1).leftTrim();
|
||||
|
||||
reqopts.headers[header] = value;
|
||||
}
|
||||
|
||||
this.tritonapi.cloudapi._request(reqopts, function (err, req, res, body) {
|
||||
this.tritonapi.cloudapi._request(reqOpts, function (err, req, res, body) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if (opts.headers || reqopts.method === 'head') {
|
||||
if (opts.headers || reqOpts.method === 'head') {
|
||||
console.error('%s/%s %d %s',
|
||||
req.connection.encrypted ? 'HTTPS' : 'HTTP',
|
||||
res.httpVersion,
|
||||
@ -60,7 +79,7 @@ function do_cloudapi(subcmd, opts, args, callback) {
|
||||
console.error();
|
||||
}
|
||||
|
||||
if (reqopts.method !== 'head')
|
||||
if (reqOpts.method !== 'head')
|
||||
console.log(JSON.stringify(body, null, 4));
|
||||
callback();
|
||||
});
|
||||
@ -75,26 +94,33 @@ do_cloudapi.options = [
|
||||
{
|
||||
names: ['method', 'X'],
|
||||
type: 'string',
|
||||
default: 'GET',
|
||||
helpArg: '<method>',
|
||||
help: 'Request method to use. Default is "GET".'
|
||||
},
|
||||
{
|
||||
names: ['header', 'H'],
|
||||
type: 'arrayOfString',
|
||||
default: [],
|
||||
helpArg: '<header>',
|
||||
help: 'Headers to send with request.'
|
||||
},
|
||||
{
|
||||
names: ['headers', 'i'],
|
||||
type: 'bool',
|
||||
help: 'Print response headers to stderr.'
|
||||
},
|
||||
{
|
||||
names: ['data', 'd'],
|
||||
type: 'string',
|
||||
helpArg: '<data>',
|
||||
help: 'Add POST data. This must be valid JSON.'
|
||||
}
|
||||
];
|
||||
do_cloudapi.help = (
|
||||
'Raw cloudapi request.\n'
|
||||
+ '\n'
|
||||
+ 'Usage:\n'
|
||||
+ ' {{name}} cloudapi [-X method] [-H header=value] <endpoint>\n'
|
||||
+ ' {{name}} cloudapi [-X <method>] [-H <header=value>] \\\n'
|
||||
+ ' [-d <data>] <endpoint>\n'
|
||||
+ '\n'
|
||||
+ '{{options}}'
|
||||
);
|
||||
|
Reference in New Issue
Block a user