From 98f2329fa0eff5c00a73e60dbaef12923e9defe0 Mon Sep 17 00:00:00 2001 From: geek Date: Mon, 15 May 2017 13:18:18 -0500 Subject: [PATCH] Initial implementation --- control-tower/README.md | 6 +++ control-tower/bin/control-tower | 8 +++- control-tower/lib/index.js | 69 +++++++++++++++++++++++++++------ control-tower/package.json | 2 +- control-tower/test/index.js | 8 +--- 5 files changed, 72 insertions(+), 21 deletions(-) diff --git a/control-tower/README.md b/control-tower/README.md index 02e6170a..d6b71068 100644 --- a/control-tower/README.md +++ b/control-tower/README.md @@ -1 +1,7 @@ # command-tower + +## Usage + +```bash +$ CMON_CERT_PATH=us-sw-1_api_joyent_com/cert.pem CMON_KEY_PATH=us-sw-1_api_joyent_com/key.pem control-tower +``` diff --git a/control-tower/bin/control-tower b/control-tower/bin/control-tower index 770a6e66..32545226 100644 --- a/control-tower/bin/control-tower +++ b/control-tower/bin/control-tower @@ -2,9 +2,15 @@ 'use strict'; +const Fs = require('fs'); const ControlTower = require('../'); -const tower = new ControlTower(); + +const cert = process.env.CMON_CERT_PATH ? Fs.readFileSync(process.env.CMON_CERT_PATH) : process.env.CMON_CERT; +const key = process.env.CMON_KEY_PATH ? Fs.readFileSync(process.env.CMON_KEY_PATH) : process.env.CMON_KEY; +const datacenter = 'cmon.us-sw-1.triton.zone:9163'; + +const tower = new ControlTower({ cmon: { cert, key, datacenter } }); tower.start((err) => { if (err) { console.error(err); diff --git a/control-tower/lib/index.js b/control-tower/lib/index.js index 5ba778d7..883e1537 100644 --- a/control-tower/lib/index.js +++ b/control-tower/lib/index.js @@ -5,12 +5,10 @@ const PortalData = require('portal-data'); const VAsync = require('vasync'); -const internals = {}; - - module.exports = class { constructor (options) { options = options || {}; + this._settings = options; this._data = new PortalData(options.data); this._cmon = new CMonClient(options.cmon); this._deployments = {}; @@ -25,6 +23,10 @@ module.exports = class { this._poll(); this._data.deploymentChanges((err, changes) => { + if (err) { + console.error(err); + } + if (changes) { this._refreshContainers(changes.id); } @@ -34,14 +36,13 @@ module.exports = class { _refreshContainers (deploymentId) { this._data.getServices(deploymentId).then((services) => { - this._deployments[deploymentId] = services.containers; + this._deployments[deploymentId] = services[0].containers; }); } _listContainers () { let containers = []; const deploymentIds = Object.keys(this._deployments); - deploymentIds.forEach((deploymentId) => { containers = containers.concat(this._deployments[deploymentId]); }); @@ -56,24 +57,68 @@ module.exports = class { const finish = () => { this._isPolling = false; - setTimeout(() => this._poll(), 1000); + setTimeout(() => { this._poll(); }, this._settings.frequency || 5000); }; + const containers = this._listContainers(); + if (!containers || !containers.length) { + return finish(); + } + + this._isPolling = true; VAsync.forEachParallel({ - func: this._cmon.metrics, - inputs: this._listContainers() + func: (containerId, next) => { + this._cmon.metrics(containerId, (err, metrics) => { + if (err) { + return next(err); + } + + next(null, { containerId, metrics }); + }); + }, + inputs: containers }, (err, results) => { if (err) { console.error(err); return finish(); } - this._saveMetrics(results, finish); + if (!results.successes || !results.successes.length) { + return finish(); + } + this._saveMetrics(results.successes, finish); }); } - _saveMetrics (metrics, cb) { - cb(); + _saveMetrics (successes, cb) { + const metricOperations = successes.map((success) => { + const metrics = this._formatMetrics(success); + return this._data.insertMetrics(success.containerId, metrics); + }); + + Promise.all(metricOperations).then(() => { + cb(); + }).catch((err) => { + cb(err); + }); } -} + + _formatMetrics (success) { + const time = success.metrics.find((metric) => { + if (metric.name === 'time_of_day') { + return metric; + } + }); + + const formatted = success.metrics.map((metric) => { + return { + name: metric.name, + value: metric.metrics[0].value, + time: time.metrics[0].value + }; + }); + + return formatted; + } +}; diff --git a/control-tower/package.json b/control-tower/package.json index c4c9f00a..d9288b9c 100644 --- a/control-tower/package.json +++ b/control-tower/package.json @@ -10,7 +10,7 @@ "lint": "belly-button", "rethinkdb-up": "docker run -d -p 8080:8080 -p 28015:28015 -p 29015:29015 --name rethinkdb rethinkdb", "rethinkdb-down": "docker rm -f rethinkdb", - "test": "npm run lint && lab -t 40" + "test": "npm run lint && lab" }, "keywords": [], "author": "wyatt", diff --git a/control-tower/test/index.js b/control-tower/test/index.js index b405a8ed..84cf6c52 100644 --- a/control-tower/test/index.js +++ b/control-tower/test/index.js @@ -2,7 +2,6 @@ const Code = require('code'); const Lab = require('lab'); -const ControlTower = require('../'); // Test shortcuts @@ -13,14 +12,9 @@ const it = lab.it; const expect = Code.expect; -const internals = { - options: { data: { test: true, name: 'test' } } -}; - - describe('start()', () => { it.skip('starts to listen for service changes and monitors metrics', (done) => { - const controlTower = new ControlTower(internals.options); + expect(done).to.exist(); done(); }); });