diff --git a/packages/portal-api/lib/watch/container-pilot.js b/packages/portal-api/lib/watch/container-pilot.js index d149cc0f..1ce69fa9 100644 --- a/packages/portal-api/lib/watch/container-pilot.js +++ b/packages/portal-api/lib/watch/container-pilot.js @@ -23,7 +23,9 @@ module.exports = class ContainerPilotWatcher extends Events { this._data = options.data; this._frequency = options.frequency || 1000; - Triton.createClient({ + const TritonClient = options.Triton || Triton; + + TritonClient.createClient({ profile: { url: options.url || process.env.SDC_URL, account: options.account || process.env.SDC_ACCOUNT, @@ -489,7 +491,13 @@ module.exports = class ContainerPilotWatcher extends Events { }); }); } - }, cb); + }, (err) => { + if (err) { + this.emit('error', err); + } + + cb(null, dgs); + }); }; const fetchStatuses = (err, dgs) => { diff --git a/packages/portal-api/package.json b/packages/portal-api/package.json index fec96853..3dab0b1e 100644 --- a/packages/portal-api/package.json +++ b/packages/portal-api/package.json @@ -27,6 +27,7 @@ "hapi-swagger": "^7.7.0", "inert": "^4.2.0", "lab": "^14.0.1", + "lodash.findindex": "^4.6.0", "vision": "^4.1.1", "wreck": "^12.2.2" }, diff --git a/packages/portal-api/test/_mocks/data.js b/packages/portal-api/test/_mocks/data.js new file mode 100644 index 00000000..9b5b9d55 --- /dev/null +++ b/packages/portal-api/test/_mocks/data.js @@ -0,0 +1,67 @@ +const FindIndex = require('lodash.findindex'); + +module.exports = ({ deploymentGroups = [], services = [], instances = [] }) => { + const getInstances = serviceId => (opts, cb) => { + cb(null, instances + .filter(instance => { + return instance.serviceId === serviceId; + }) + ); + }; + + const getServices = deploymentGroupId => (opts, cb) => { + cb(null, services + .filter(service => { + return service.deploymentGroupId === deploymentGroupId; + }) + .map(service => { + return Object.assign({}, service, { + instances: getInstances(service.id) + }); + }) + ); + }; + + const getDeploymentGroups = (opts, cb) => { + cb(null, deploymentGroups + .map(dg => { + return Object.assign({}, dg, { + services: getServices(dg.id) + }); + }) + ); + }; + + const getPortal = (opts, cb) => { + cb(null, { + deploymentGroups: getDeploymentGroups + }); + }; + + const updateInstance = (instance, cb) => { + const instanceIndex = FindIndex(instances, ['id', instance.id]); + const updatedInstance = Object.assign( + {}, + instances[instanceIndex], + instance + ); + + instances[instanceIndex] = updatedInstance; + return updatedInstance; + }; + + const updateService = (service, cb) => { + const serviceIndex = FindIndex(service, ['id', service.id]); + const updatedService = Object.assign({}, services[serviceIndex], service); + + services[serviceIndex] = updateService; + return updateService; + }; + + return { + getPortal, + updateInstance, + updateService + }; +}; + diff --git a/packages/portal-api/test/_mocks/triton.js b/packages/portal-api/test/_mocks/triton.js new file mode 100644 index 00000000..f32b8817 --- /dev/null +++ b/packages/portal-api/test/_mocks/triton.js @@ -0,0 +1,24 @@ +const Find = require('lodash.find'); + +module.exports = ({ machines = [], networks = [] }) => { + const getMachine = (machineId, cb) => { + cb(null, Find(machines, ['id', machineId])); + }; + + const getNetwork = (networkId, cb) => { + cb(null, Find(networks, ['id', networkId])); + }; + + const createClient = (opts, cb) => { + return cb(null, { + cloudapi: { + getMachine, + getNetwork + } + }); + }; + + return { + createClient + }; +}; diff --git a/packages/portal-api/test/watch/container-pilot.js b/packages/portal-api/test/watch/container-pilot.js new file mode 100644 index 00000000..1f8b69c1 --- /dev/null +++ b/packages/portal-api/test/watch/container-pilot.js @@ -0,0 +1,148 @@ +'use strict'; + +const Lab = require('lab'); +const Uuid = require('uuid/v4'); + +const ContainerPilotWatch = require('../../lib/watch/container-pilot'); +const DataMock = require('../_mocks/data'); +const TritonMock = require('../_mocks/triton'); + + +const lab = exports.lab = Lab.script(); +const it = lab.it; +const expect = Lab.expect; + + +it('sets instance health statuses appropriately', (done) => { + const networks = [{ + id: Uuid(), + 'public': false, + subnet: '192.168.1.0/24' + }, { + id: Uuid(), + 'public': true + }]; + + const machines = [{ + id: Uuid(), + ips: ['192.168.1.1', '72.2.119.1'], + networks: networks.map(({ id }) => { + return id; + }) + }, { + id: Uuid(), + ips: ['192.168.1.2', '72.2.119.2'], + networks: networks.map(({ id }) => { + return id; + }) + }, { + id: Uuid(), + ips: ['192.168.1.3', '72.2.119.3'], + networks: networks.map(({ id }) => { + return id; + }) + }, { + id: Uuid(), + ips: ['192.168.1.4', '72.2.119.4'], + networks: networks.map(({ id }) => { + return id; + }) + }, { + id: Uuid(), + ips: ['192.168.1.5', '72.2.119.5'], + networks: networks.map(({ id }) => { + return id; + }) + }, { + id: Uuid(), + ips: ['192.168.1.6', '72.2.119.6'], + networks: networks.map(({ id }) => { + return id; + }) + }, { + id: Uuid(), + ips: ['192.168.1.7', '72.2.119.7'], + networks: networks.map(({ id }) => { + return id; + }) + }]; + + const deploymentGroups = [{ + id: Uuid() + }, { + id: Uuid() + }]; + + const services = [{ + name: 'mysql', + id: Uuid(), + deploymentGroupId: deploymentGroups[0].id + }, { + name: 'api', + id: Uuid(), + deploymentGroupId: deploymentGroups[0].id + }, { + name: 'frontend', + id: Uuid(), + deploymentGroupId: deploymentGroups[0].id + }, { + name: 'redis', + id: Uuid(), + deploymentGroupId: deploymentGroups[1].id + }, { + name: 'auth', + id: Uuid(), + deploymentGroupId: deploymentGroups[1].id + }]; + + const instances = [{ + id: Uuid(), + serviceId: services[0].id, + machineId: machines[0].id + }, { + id: Uuid(), + serviceId: services[0].id, + machineId: machines[1].id + }, { + id: Uuid(), + serviceId: services[0].id, + machineId: machines[2].id + }, { + id: Uuid(), + serviceId: services[1].id, + machineId: machines[3].id + }, { + id: Uuid(), + serviceId: services[2].id, + machineId: machines[4].id + }, { + id: Uuid(), + serviceId: services[3].id, + machineId: machines[5].id + }, { + id: Uuid(), + serviceId: services[4].id, + machineId: machines[6].id + }]; + + const watch = new ContainerPilotWatch({ + data: DataMock({ + deploymentGroups, + services, + instances + }), + Triton: TritonMock({ + machines, + networks + }) + }); + + watch.on('error', (err) => { + done(err); + }); + + watch.check((err, data) => { + console.log(err, data); + done(err); + }); +}); diff --git a/packages/portal-api/test/watch/index.js b/packages/portal-api/test/watch/machines.js similarity index 100% rename from packages/portal-api/test/watch/index.js rename to packages/portal-api/test/watch/machines.js