Compare commits
5 Commits
developmen
...
S3C-150/ft
Author | SHA1 | Date |
---|---|---|
Bennett Buchanan | 529da4315e | |
Bennett Buchanan | fef6da1445 | |
Bennett Buchanan | a97971f448 | |
Bennett Buchanan | 32aae80c0b | |
Bennett Buchanan | 53bef46a42 |
|
@ -1,5 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
'use strict'; // eslint-disable-line strict
|
|
||||||
|
|
||||||
require('babel-core/register');
|
|
||||||
require('../lib/utapi/utilities.js').listMetrics('buckets');
|
|
|
@ -1,5 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
'use strict'; // eslint-disable-line strict
|
|
||||||
|
|
||||||
require('babel-core/register');
|
|
||||||
require('../lib/utapi/utilities.js').listMetrics();
|
|
|
@ -294,12 +294,7 @@ class Config {
|
||||||
'bad config: utapi port must be a positive integer');
|
'bad config: utapi port must be a positive integer');
|
||||||
this.utapi.port = config.utapi.port;
|
this.utapi.port = config.utapi.port;
|
||||||
}
|
}
|
||||||
if (config.utapi.workers !== undefined) {
|
|
||||||
assert(Number.isInteger(config.utapi.workers)
|
|
||||||
&& config.utapi.workers > 0,
|
|
||||||
'bad config: utapi workers must be a positive integer');
|
|
||||||
this.utapi.workers = config.utapi.workers;
|
|
||||||
}
|
|
||||||
// Utapi uses the same localCache config defined for S3 to avoid
|
// Utapi uses the same localCache config defined for S3 to avoid
|
||||||
// config duplication.
|
// config duplication.
|
||||||
assert(config.localCache, 'missing required property of utapi ' +
|
assert(config.localCache, 'missing required property of utapi ' +
|
||||||
|
@ -340,22 +335,6 @@ class Config {
|
||||||
if (config.utapi.component) {
|
if (config.utapi.component) {
|
||||||
this.utapi.component = config.utapi.component;
|
this.utapi.component = config.utapi.component;
|
||||||
}
|
}
|
||||||
// (optional) The value of the replay schedule should be cron-style
|
|
||||||
// scheduling. For example, every five minutes: '*/5 * * * *'.
|
|
||||||
if (config.utapi.replaySchedule) {
|
|
||||||
assert(typeof config.utapi.replaySchedule === 'string', 'bad' +
|
|
||||||
'config: utapi.replaySchedule must be a string');
|
|
||||||
this.utapi.replaySchedule = config.utapi.replaySchedule;
|
|
||||||
}
|
|
||||||
// (optional) The number of elements processed by each call to the
|
|
||||||
// Redis local cache during a replay. For example, 50.
|
|
||||||
if (config.utapi.batchSize) {
|
|
||||||
assert(typeof config.utapi.batchSize === 'number', 'bad' +
|
|
||||||
'config: utapi.batchSize must be a number');
|
|
||||||
assert(config.utapi.batchSize > 0, 'bad config:' +
|
|
||||||
'utapi.batchSize must be a number greater than 0');
|
|
||||||
this.utapi.batchSize = config.utapi.batchSize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log = { logLevel: 'debug', dumpLevel: 'error' };
|
this.log = { logLevel: 'debug', dumpLevel: 'error' };
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
|
|
||||||
const utapiServer = require('utapi').UtapiServer;
|
|
||||||
const _config = require('../Config').default;
|
|
||||||
|
|
||||||
// start utapi server
|
|
||||||
export default function main() {
|
|
||||||
if (_config.utapi) {
|
|
||||||
const fullConfig = Object.assign({}, _config.utapi);
|
|
||||||
if (_config.vaultd) {
|
|
||||||
Object.assign(fullConfig, { vaultd: _config.vaultd });
|
|
||||||
}
|
|
||||||
if (_config.https) {
|
|
||||||
Object.assign(fullConfig, { https: _config.https });
|
|
||||||
}
|
|
||||||
// copy healthcheck IPs
|
|
||||||
if (_config.healthChecks) {
|
|
||||||
Object.assign(fullConfig, { healthChecks: _config.healthChecks });
|
|
||||||
}
|
|
||||||
utapiServer(fullConfig);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
const UtapiReplay = require('utapi').UtapiReplay;
|
|
||||||
const _config = require('../Config').default;
|
|
||||||
|
|
||||||
// start utapi server
|
|
||||||
export default function main() {
|
|
||||||
const replay = new UtapiReplay(_config.utapi);
|
|
||||||
replay.start();
|
|
||||||
}
|
|
|
@ -1,180 +1,8 @@
|
||||||
import { auth } from 'arsenal';
|
|
||||||
import { UtapiClient } from 'utapi';
|
import { UtapiClient } from 'utapi';
|
||||||
import commander from 'commander';
|
|
||||||
import http from 'http';
|
|
||||||
import https from 'https';
|
|
||||||
import { logger } from '../utilities/logger';
|
|
||||||
import _config from '../Config';
|
import _config from '../Config';
|
||||||
// setup utapi client
|
// setup utapi client
|
||||||
const utapi = new UtapiClient(_config.utapi);
|
const utapi = new UtapiClient(_config.utapi);
|
||||||
|
|
||||||
function _listMetrics(host,
|
|
||||||
port,
|
|
||||||
metric,
|
|
||||||
metricType,
|
|
||||||
timeRange,
|
|
||||||
accessKey,
|
|
||||||
secretKey,
|
|
||||||
verbose,
|
|
||||||
recent,
|
|
||||||
ssl) {
|
|
||||||
const listAction = recent ? 'ListRecentMetrics' : 'ListMetrics';
|
|
||||||
const options = {
|
|
||||||
host,
|
|
||||||
port,
|
|
||||||
method: 'POST',
|
|
||||||
path: `/${metric}?Action=${listAction}`,
|
|
||||||
headers: {
|
|
||||||
'content-type': 'application/json',
|
|
||||||
'cache-control': 'no-cache',
|
|
||||||
},
|
|
||||||
rejectUnauthorized: false,
|
|
||||||
};
|
|
||||||
const transport = ssl ? https : http;
|
|
||||||
const request = transport.request(options, response => {
|
|
||||||
if (verbose) {
|
|
||||||
logger.info('response status code', {
|
|
||||||
statusCode: response.statusCode,
|
|
||||||
});
|
|
||||||
logger.info('response headers', { headers: response.headers });
|
|
||||||
}
|
|
||||||
const body = [];
|
|
||||||
response.setEncoding('utf8');
|
|
||||||
response.on('data', chunk => body.push(chunk));
|
|
||||||
response.on('end', () => {
|
|
||||||
const responseBody = JSON.parse(body.join(''));
|
|
||||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
|
||||||
process.stdout.write(JSON.stringify(responseBody, null, 2));
|
|
||||||
process.stdout.write('\n');
|
|
||||||
process.exit(0);
|
|
||||||
} else {
|
|
||||||
logger.error('request failed with HTTP Status ', {
|
|
||||||
statusCode: response.statusCode,
|
|
||||||
body: responseBody,
|
|
||||||
});
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// TODO: cleanup with refactor of generateV4Headers
|
|
||||||
request.path = `/${metric}`;
|
|
||||||
auth.client.generateV4Headers(request, { Action: listAction },
|
|
||||||
accessKey, secretKey, 's3');
|
|
||||||
request.path = `/${metric}?Action=${listAction}`;
|
|
||||||
if (verbose) {
|
|
||||||
logger.info('request headers', { headers: request._headers });
|
|
||||||
}
|
|
||||||
// If recent listing, we do not provide `timeRange` in the request
|
|
||||||
const requestObj = recent ? {} : { timeRange };
|
|
||||||
requestObj[metric] = metricType;
|
|
||||||
request.write(JSON.stringify(requestObj));
|
|
||||||
request.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function is used as a binary to send a request to utapi server
|
|
||||||
* to list metrics for buckets or accounts
|
|
||||||
* @param {string} [metricType] - (optional) Defined as 'buckets' if old style
|
|
||||||
* bucket metrics listing
|
|
||||||
* @return {undefined}
|
|
||||||
*/
|
|
||||||
export function listMetrics(metricType) {
|
|
||||||
commander
|
|
||||||
.version('0.0.1')
|
|
||||||
.option('-a, --access-key <accessKey>', 'Access key id')
|
|
||||||
.option('-k, --secret-key <secretKey>', 'Secret access key');
|
|
||||||
// We want to continue support of previous bucket listing. Hence the ability
|
|
||||||
// to specify `metricType`. Remove `if` statement and
|
|
||||||
// bin/list_bucket_metrics.js when prior method of listing bucket metrics is
|
|
||||||
// no longer supported.
|
|
||||||
if (metricType === 'buckets') {
|
|
||||||
commander
|
|
||||||
.option('-b, --buckets <buckets>', 'Name of bucket(s) with ' +
|
|
||||||
'a comma separator if more than one');
|
|
||||||
} else {
|
|
||||||
commander
|
|
||||||
.option('-m, --metric <metric>', 'Metric type')
|
|
||||||
.option('--buckets <buckets>', 'Name of bucket(s) with a comma ' +
|
|
||||||
'separator if more than one')
|
|
||||||
.option('--accounts <accounts>', 'Account ID(s) with a comma ' +
|
|
||||||
'separator if more than one')
|
|
||||||
.option('--users <users>', 'User ID(s) with a comma separator if ' +
|
|
||||||
'more than one')
|
|
||||||
.option('--service <service>', 'Name of service');
|
|
||||||
}
|
|
||||||
commander
|
|
||||||
.option('-s, --start <start>', 'Start of time range')
|
|
||||||
.option('-r, --recent', 'List metrics including the previous and ' +
|
|
||||||
'current 15 minute interval')
|
|
||||||
.option('-e --end <end>', 'End of time range')
|
|
||||||
.option('-h, --host <host>', 'Host of the server')
|
|
||||||
.option('-p, --port <port>', 'Port of the server')
|
|
||||||
.option('--ssl', 'Enable ssl')
|
|
||||||
.option('-v, --verbose')
|
|
||||||
.parse(process.argv);
|
|
||||||
|
|
||||||
const { host, port, accessKey, secretKey, start, end, verbose, recent,
|
|
||||||
ssl } =
|
|
||||||
commander;
|
|
||||||
const requiredOptions = { host, port, accessKey, secretKey };
|
|
||||||
// If not old style bucket metrics, we require usage of the metric option
|
|
||||||
if (metricType !== 'buckets') {
|
|
||||||
requiredOptions.metric = commander.metric;
|
|
||||||
const validMetrics = ['buckets', 'accounts', 'users', 'service'];
|
|
||||||
if (validMetrics.indexOf(commander.metric) < 0) {
|
|
||||||
logger.error('metric must be \'buckets\', \'accounts\', ' +
|
|
||||||
'\'users\', or \'service\'');
|
|
||||||
commander.outputHelp();
|
|
||||||
process.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If old style bucket metrics, `metricType` will be 'buckets'. Otherwise,
|
|
||||||
// `commander.metric` should be defined.
|
|
||||||
const metric = metricType === 'buckets' ? 'buckets' : commander.metric;
|
|
||||||
requiredOptions[metric] = commander[metric];
|
|
||||||
// If not recent listing, the start option must be provided
|
|
||||||
if (!recent) {
|
|
||||||
requiredOptions.start = commander.start;
|
|
||||||
}
|
|
||||||
Object.keys(requiredOptions).forEach(option => {
|
|
||||||
if (!requiredOptions[option]) {
|
|
||||||
logger.error(`missing required option: ${option}`);
|
|
||||||
commander.outputHelp();
|
|
||||||
process.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const timeRange = [];
|
|
||||||
// If recent listing, we disregard any start or end option given
|
|
||||||
if (!recent) {
|
|
||||||
const numStart = Number.parseInt(start, 10);
|
|
||||||
if (!numStart) {
|
|
||||||
logger.error('start must be a number');
|
|
||||||
commander.outputHelp();
|
|
||||||
process.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
timeRange.push(numStart);
|
|
||||||
if (end) {
|
|
||||||
const numEnd = Number.parseInt(end, 10);
|
|
||||||
if (!numEnd) {
|
|
||||||
logger.error('end must be a number');
|
|
||||||
commander.outputHelp();
|
|
||||||
process.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
timeRange.push(numEnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// The string `commander[metric]` is a comma-separated list of resources
|
|
||||||
// given by the user.
|
|
||||||
const resources = commander[metric].split(',');
|
|
||||||
_listMetrics(host, port, metric, resources, timeRange, accessKey, secretKey,
|
|
||||||
verbose, recent, ssl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call the Utapi Client `pushMetric` method with the associated parameters
|
* Call the Utapi Client `pushMetric` method with the associated parameters
|
||||||
* @param {string} action - the metric action to push a metric for
|
* @param {string} action - the metric action to push a metric for
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
"node-uuid": "^1.4.3",
|
"node-uuid": "^1.4.3",
|
||||||
"ready-set-stream": "1.0.7",
|
"ready-set-stream": "1.0.7",
|
||||||
"sproxydclient": "scality/sproxydclient",
|
"sproxydclient": "scality/sproxydclient",
|
||||||
"utapi": "scality/utapi",
|
"utapi": "scality/utapi#S3C-150/ft-separate-utapi-from-s3",
|
||||||
"utf8": "~2.1.1",
|
"utf8": "~2.1.1",
|
||||||
"vaultclient": "scality/vaultclient",
|
"vaultclient": "scality/vaultclient",
|
||||||
"werelogs": "scality/werelogs",
|
"werelogs": "scality/werelogs",
|
||||||
|
@ -73,8 +73,6 @@
|
||||||
"mem_backend": "S3BACKEND=mem node index.js",
|
"mem_backend": "S3BACKEND=mem node index.js",
|
||||||
"perf": "mocha --compilers js:babel-core/register tests/performance/s3standard.js",
|
"perf": "mocha --compilers js:babel-core/register tests/performance/s3standard.js",
|
||||||
"start": "node init.js && node index.js",
|
"start": "node init.js && node index.js",
|
||||||
"start_utapi": "node utapiServer.js",
|
|
||||||
"utapi_replay": "node utapiReplay.js",
|
|
||||||
"test": "S3BACKEND=mem mocha --compilers js:babel-core/register --recursive tests/unit",
|
"test": "S3BACKEND=mem mocha --compilers js:babel-core/register --recursive tests/unit",
|
||||||
"multiple_backend_test": "node init.js && S3BACKEND=mem S3DATA=multiple mocha --compilers js:babel-core/register --recursive tests/multipleBackend",
|
"multiple_backend_test": "node init.js && S3BACKEND=mem S3DATA=multiple mocha --compilers js:babel-core/register --recursive tests/multipleBackend",
|
||||||
"unit_coverage": "mkdir -p coverage/unit/ && S3BACKEND=mem MOCHA_FILE=$CIRCLE_TEST_REPORTS/unit/unit.xml istanbul cover --dir coverage/unit _mocha -- --compilers js:babel-core/register --reporter mocha-junit-reporter --recursive tests/unit"
|
"unit_coverage": "mkdir -p coverage/unit/ && S3BACKEND=mem MOCHA_FILE=$CIRCLE_TEST_REPORTS/unit/unit.xml istanbul cover --dir coverage/unit _mocha -- --compilers js:babel-core/register --reporter mocha-junit-reporter --recursive tests/unit"
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
'use strict'; // eslint-disable-line strict
|
|
||||||
|
|
||||||
require('babel-core/register')();
|
|
||||||
require('./lib/utapi/utapiReplay.js').default();
|
|
|
@ -1,4 +0,0 @@
|
||||||
'use strict'; // eslint-disable-line strict
|
|
||||||
|
|
||||||
require('babel-core/register')();
|
|
||||||
require('./lib/utapi/utapi.js').default();
|
|
Loading…
Reference in New Issue