From 7e01748e8a46d05e27ad86d9b95ef124c044c22f Mon Sep 17 00:00:00 2001 From: geek Date: Wed, 7 Jun 2017 16:35:45 -0500 Subject: [PATCH] feat(portal-data): support sub-queries --- packages/portal-api/test/index.js | 117 +++++++++++++++++++++++++ packages/portal-data/lib/index.js | 121 +++++++++++++++++++++----- packages/portal-data/lib/transform.js | 10 +-- packages/portal-data/test/index.js | 17 ---- 4 files changed, 217 insertions(+), 48 deletions(-) diff --git a/packages/portal-api/test/index.js b/packages/portal-api/test/index.js index 40ceee8c..3acd0714 100644 --- a/packages/portal-api/test/index.js +++ b/packages/portal-api/test/index.js @@ -3,12 +3,15 @@ const Code = require('code'); const Hapi = require('hapi'); const Lab = require('lab'); +const PortalData = require('portal-data'); const PortalApi = require('../'); // Test shortcuts const lab = exports.lab = Lab.script(); +const afterEach = lab.afterEach; +const beforeEach = lab.beforeEach; const describe = lab.describe; const it = lab.it; const expect = Code.expect; @@ -48,4 +51,118 @@ describe('graphql', () => { }); }); }); + + it('can query for a deployment group inside a portal', (done) => { + const server = new Hapi.Server(); + server.connection(); + server.register(internals.register, (err) => { + expect(err).to.not.exist(); + + // internals.bootstrap(server.plugins['portal-api'].data, (err) => { + const payload = { + query: '{ portal { datacenter { region }, deploymentGroups(name: "test1") { name, slug } } }' + }; + + server.inject({ method: 'POST', url: '/graphql', payload }, (res) => { + expect(res.statusCode).to.equal(200); + const result = JSON.parse(res.result); + expect(result.data).to.exist(); + expect(result.data.portal.deploymentGroups[0].name).to.equal('test1'); + done(); + }); + }); + }); + + it('defaults to all deployment groups inside a portal', (done) => { + const server = new Hapi.Server(); + server.connection(); + server.register(internals.register, (err) => { + expect(err).to.not.exist(); + + // internals.bootstrap(server.plugins['portal-api'].data, (err) => { + const payload = { + query: '{ portal { datacenter { region }, deploymentGroups { name, slug } } }' + }; + + server.inject({ method: 'POST', url: '/graphql', payload }, (res) => { + expect(res.statusCode).to.equal(200); + const result = JSON.parse(res.result); + expect(result.data).to.exist(); + expect(result.data.portal.deploymentGroups.length).to.equal(2); + done(); + }); + }); + }); + + it('can sub-filter services for a deployment group', (done) => { + const server = new Hapi.Server(); + server.connection(); + server.register(internals.register, (err) => { + expect(err).to.not.exist(); + + // internals.bootstrap(server.plugins['portal-api'].data, (err) => { + const payload = { + query: '{ portal { datacenter { region }, deploymentGroups(name: "test2") { name, services(name: "service") { name } } } }' + }; + + server.inject({ method: 'POST', url: '/graphql', payload }, (res) => { + expect(res.statusCode).to.equal(200); + const result = JSON.parse(res.result); + const deploymentGroup = result.data.portal.deploymentGroups[0]; + + expect(deploymentGroup.name).to.equal('test2'); + expect(deploymentGroup.services[0].name).to.equal('service'); + done(); + }); + }); + }); + + beforeEach((done) => { + const data = new PortalData({ name: 'test', db: { test: true } }); + data.connect(() => { + data.createDatacenter({ region: 'us-sw', name: 'us-sw' }, (err, datacenter) => { + if (err) { + return done(err); + } + + data.createUser({ firstName: 'Nikola', lastName: 'Tesla', email: 'nikola@tesla.com', login: 'nikola' }, (err, user) => { + if (err) { + return done(err); + } + + data.createPortal({ + user, + datacenter + }, (err, portal) => { + if (err) { + return done(err); + } + + data.createDeploymentGroup({ name: 'test1' }, () => { + data.createDeploymentGroup({ name: 'test2' }, (err, deploymentGroup) => { + if (err) { + return done(err); + } + + data.createService({ + name: 'service', + slug: 'service_slug', + deploymentGroupId: deploymentGroup.id + }, () => { done(); }); + }); + }); + }); + }); + }); + }); + }); + + afterEach((done) => { + const data = new PortalData({ name: 'test', db: { test: true } }); + data.connect(() => { + data._db.r.dbDrop('test').run(data._db._connection, () => { + done(); + }); + }); + }); }); diff --git a/packages/portal-data/lib/index.js b/packages/portal-data/lib/index.js index a8002fc9..cdb80abf 100644 --- a/packages/portal-data/lib/index.js +++ b/packages/portal-data/lib/index.js @@ -78,9 +78,6 @@ module.exports = class Data extends EventEmitter { (next) => { this.getDatacenter({ id: portal.datacenter_id }, next); }, - (next) => { - this._db.deployment_groups.all(next); - }, (next) => { this.getUser({}, next); } @@ -90,11 +87,24 @@ module.exports = class Data extends EventEmitter { return cb(err); } + // Sub query/filter for deploymentGroups + const deploymentGroups = (args) => { + return new Promise((resolve, reject) => { + this.getDeploymentGroups(args, (err, groups) => { + if (err) { + return reject(err); + } + + resolve(groups); + }); + }); + }; + cb(null, Transform.fromPortal({ portal, - datacenter: results.successes[0], - deploymentGroups: results.successes[1], - user: results.successes[2] + deploymentGroups, + datacenter: results.operations[0].result, + user: results.operations[1].result })); }); }); @@ -201,7 +211,27 @@ module.exports = class Data extends EventEmitter { return cb(err); } - cb(null, deploymentGroups ? deploymentGroups.map(Transform.fromDeploymentGroup) : null); + const getServices = (service_ids) => { + return (args) => { + args = args || {}; + args.ids = service_ids; + return new Promise((resolve, reject) => { + this.getServices(args, (err, services) => { + if (err) { + return reject(err); + } + + resolve(services); + }); + }); + }; + }; + + const convertedGroups = deploymentGroups ? deploymentGroups.map((deploymentGroup) => { + return Transform.fromDeploymentGroup(deploymentGroup, getServices(deploymentGroup.service_ids)); + }) : []; + + cb(null, convertedGroups); }; if (ids) { @@ -216,28 +246,38 @@ module.exports = class Data extends EventEmitter { return this._db.deployment_groups.query({ slug }, finish); } - finish(); + return this._db.deployment_groups.all(finish); } getDeploymentGroup (query, cb) { - this._db.deployment_groups.sync(() => { - this._db.deployment_groups.single(query, (err, deploymentGroup) => { - if (err) { - return cb(err); - } + this._db.deployment_groups.single(query, (err, deploymentGroup) => { + if (err) { + return cb(err); + } - if (!deploymentGroup) { - return cb(null, {}); - } + if (!deploymentGroup) { + return cb(null, {}); + } - if (!deploymentGroup.service_ids || !deploymentGroup.service_ids.length) { - return cb(null, Transform.fromDeploymentGroup(deploymentGroup)); - } + if (!deploymentGroup.service_ids || !deploymentGroup.service_ids.length) { + return cb(null, Transform.fromDeploymentGroup(deploymentGroup)); + } - this._db.services.get(deploymentGroup.service_ids, (err, services) => { - cb(err, Transform.fromDeploymentGroup(deploymentGroup, services)); + const getServices = (args) => { + args = args || {}; + args.ids = deploymentGroup.service_ids; + return new Promise((resolve, reject) => { + this.getServices(args, (err, services) => { + if (err) { + return reject(err); + } + + resolve(services); + }); }); - }); + }; + + cb(err, Transform.fromDeploymentGroup(deploymentGroup, getServices)); }); } @@ -673,7 +713,42 @@ module.exports = class Data extends EventEmitter { }); } - // TODO: get services with join/merge + getServices (options, cb) { + const query = {}; + if (options.ids && options.ids.length) { + query.id = this._db.or(options.ids); + } + + if (options.name) { + query.name = options.name; + } + + if (options.slug) { + query.slug = options.slug; + } + + if (options.parentId) { + query.parent_id = options.parentId; + } + + if (options.deploymentGroupId) { + query.deployment_group_id = options.deploymentGroupId; + } + + this._db.services.query(query, (err, services) => { + if (err) { + return cb(err); + } + + if (!services || !services.length) { + return cb(); + } + + return cb(null, services.map((service) => { + return Transform.fromService({ service }); + })); + }); + } // instances diff --git a/packages/portal-data/lib/transform.js b/packages/portal-data/lib/transform.js index eb60833e..82111a80 100644 --- a/packages/portal-data/lib/transform.js +++ b/packages/portal-data/lib/transform.js @@ -4,13 +4,11 @@ const Yamljs = require('yamljs'); exports.fromPortal = function ({ portal, datacenter, deploymentGroups, user }) { - deploymentGroups = Array.isArray(deploymentGroups) ? deploymentGroups : []; - return { id: portal.id, user, datacenter, - deploymentGroups: deploymentGroups.map(exports.fromDeploymentGroup) + deploymentGroups }; }; @@ -26,15 +24,11 @@ exports.toPortal = function (clientPortal) { exports.fromDeploymentGroup = function (deploymentGroup, services) { - if (!Array.isArray(services)) { - services = []; - } - return { id: deploymentGroup.id, name: deploymentGroup.name, slug: deploymentGroup.slug, - services: services ? services.map((service) => { return exports.fromService({ service }); }) : [], + services, version: deploymentGroup.version_id, history: deploymentGroup.history_version_ids || [] }; diff --git a/packages/portal-data/test/index.js b/packages/portal-data/test/index.js index 19c1ecf9..a893e5d9 100644 --- a/packages/portal-data/test/index.js +++ b/packages/portal-data/test/index.js @@ -24,23 +24,6 @@ describe('connect()', () => { }); describe('portals', () => { - describe('createPortal()', () => { - it('creates a new portal', (done) => { - const data = new PortalData(internals.options); - data.connect((err) => { - expect(err).to.not.exist(); - - const portal = {}; - - data.createPortal(portal, (err, result) => { - expect(err).to.not.exist(); - expect(result.id).to.exist(); - done(); - }); - }); - }); - }); - describe('getPortal()', () => { it('retrieves a single portal record', (done) => { const data = new PortalData(internals.options);