From 77acb731ac88025f30c509c1dc7a3f48c29da52e Mon Sep 17 00:00:00 2001 From: geek Date: Tue, 22 Aug 2017 11:55:37 -0500 Subject: [PATCH] feat: can query metrics on instance --- packages/cp-gql-schema/package.json | 2 +- packages/portal-api/lib/data/index.js | 24 +++++++- packages/portal-api/lib/data/transform.js | 5 +- packages/portal-api/package.json | 2 +- packages/portal-api/test/data/unit.js | 72 ++++++++++++++++++++++- 5 files changed, 98 insertions(+), 7 deletions(-) diff --git a/packages/cp-gql-schema/package.json b/packages/cp-gql-schema/package.json index 7c103af3..428ad67f 100644 --- a/packages/cp-gql-schema/package.json +++ b/packages/cp-gql-schema/package.json @@ -1,6 +1,6 @@ { "name": "joyent-cp-gql-schema", - "version": "1.5.2", + "version": "1.6.0", "license": "MPL-2.0", "repository": "github:yldio/joyent-portal", "main": "index.js", diff --git a/packages/portal-api/lib/data/index.js b/packages/portal-api/lib/data/index.js index 2c031eb3..6791241c 100644 --- a/packages/portal-api/lib/data/index.js +++ b/packages/portal-api/lib/data/index.js @@ -1999,6 +1999,24 @@ class Data extends EventEmitter { }); } + getMetricsForInstance (instance) { + return ({ names, start, end }) => { + return new Promise((resolve, reject) => { + const options = { + deploymentGroupId: instance.deployment_group_id, + instances: [instance.name], + names, + start, + end + }; + + this.getMetrics(options, (err, metrics) => { + return err ? reject(err) : resolve(metrics); + }); + }); + }; + } + getInstance ({ id }, cb) { this._db.instances.single({ id }, (err, instance) => { if (err) { @@ -2009,7 +2027,7 @@ class Data extends EventEmitter { return cb(Boom.notFound()); } - cb(null, Transform.fromInstance(instance)); + cb(null, Transform.fromInstance({ instance, metrics: this.getMetricsForInstance(instance) })); }); } @@ -2045,7 +2063,9 @@ class Data extends EventEmitter { return cb(null, []); } - cb(null, instances.map(Transform.fromInstance)); + cb(null, instances.map((instance) => { + return Transform.fromInstance({ instance, metrics: this.getMetricsForInstance(instance) }); + })); }); } diff --git a/packages/portal-api/lib/data/transform.js b/packages/portal-api/lib/data/transform.js index cb5b6031..d4bf7557 100644 --- a/packages/portal-api/lib/data/transform.js +++ b/packages/portal-api/lib/data/transform.js @@ -165,7 +165,7 @@ exports.toPackage = function (packages) { }; -exports.fromInstance = function (instance) { +exports.fromInstance = function ({ instance, metrics }) { return { id: instance.id, name: instance.name, @@ -175,7 +175,8 @@ exports.fromInstance = function (instance) { status: instance.status, healthy: instance.healthy, watches: instance.watches, - jobs: instance.jobs + jobs: instance.jobs, + metrics }; }; diff --git a/packages/portal-api/package.json b/packages/portal-api/package.json index 14525def..9f16d153 100644 --- a/packages/portal-api/package.json +++ b/packages/portal-api/package.json @@ -39,7 +39,7 @@ "force-array": "^3.1.0", "graphi": "^2.2.1", "hoek": "^4.1.1", - "joyent-cp-gql-schema": "^1.5.1", + "joyent-cp-gql-schema": "^1.6.0", "lodash.find": "^4.6.0", "lodash.flatten": "^4.4.0", "lodash.get": "^4.4.2", diff --git a/packages/portal-api/test/data/unit.js b/packages/portal-api/test/data/unit.js index 75abbc8c..677f42bf 100644 --- a/packages/portal-api/test/data/unit.js +++ b/packages/portal-api/test/data/unit.js @@ -52,7 +52,77 @@ describe('getMetrics()', () => { expect(err).to.not.be.an.error(); expect(metrics.length).to.equal(1); expect(metrics[0].name).to.equal('AVG_MEM_BYTES'); - done(); + server.close(() => done()); + }); + }); + }); +}); + + +describe('getInstance()', () => { + it('retrieves an instance that can also be used to query for metrics', (done) => { + const server = Http.createServer((req, res) => { + const payload = JSON.stringify({ 'status': 'success', 'data': { 'resultType': 'matrix', 'result': [{ 'metric': { '__name__': 'mem_agg_usage', 'instance': 'joyentportal_compose-api_1', 'job': 'triton' }, 'values': [[1502896217.371, '60518400'], [1502899817.371, '60641280'], [1502903417.371, '60575744']] }] } }); + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(payload); + }); + + server.listen(9090, (err) => { + expect(err).to.not.exist(); + + const FakePortalData = function () { + this._db = { + instances: { + single: (options, next) => { + expect(options.id).to.exist(); + const instance = { + id: options.id, + deployment_group_id: 'deploymentGroup', + service_id: 'service', + machine_id: 'joyentportal_compose-api_1' + }; + + next(null, instance); + } + } + }; + + this._triton = { + getInstance: (id, next) => { + const tritonInstance = { + primaryIp: 'localhost' + }; + + next(null, tritonInstance); + } + }; + }; + FakePortalData.prototype = PortalData.prototype; + + FakePortalData.prototype.getServices = ({ deploymentGroupId, name }, next) => { + const instance = { + machine_id: 'machineId' + }; + + const service = { + instances: () => { return Promise.resolve([instance]); } + }; + + next(null, [service]); + }; + + const fakePortalData = new FakePortalData(); + + fakePortalData.getInstance({ id: 'joyentportal_compose-api_1' }, (err, instance) => { + expect(err).to.not.be.an.error(); + expect(instance).to.exist(); + instance.metrics({ names: ['AVG_MEM_BYTES'], start: new Date(Date.now() - 10000).toISOString(), end: new Date(Date.now()).toISOString() }).catch((err) => { + expect(err).to.not.exist(); + }).then((metrics) => { + expect(metrics.length).to.equal(1); + expect(metrics[0].name).to.equal('AVG_MEM_BYTES'); + server.close(() => done()); + }); }); }); });