swarmerode
Version:
Swarm Client Extension for Dockerode
275 lines (246 loc) • 10.4 kB
JavaScript
var assert = require('chai').assert
var clone = require('101/clone')
var sinon = require('sinon')
var exampleHosts = [ '10.0.0.1:4242', '10.0.0.2:4242', '10.0.0.3:4242' ]
var swarmInfoMock = require('./fixtures/swarm-info')
var testInfo = swarmInfoMock([
{ host: exampleHosts[0] },
{ host: exampleHosts[1] },
{ host: exampleHosts[2] }
])
var Consul = require('../consul')
var Swarmerode = require('../')
describe('Swarmerode', function () {
var MockClass
var instance
var prevConsulHost = process.env.CONSUL_HOST
beforeEach(function () {
process.env.CONSUL_HOST = 'somehost'
MockClass = function () {}
MockClass.prototype.info = function (cb) { cb(null, clone(testInfo)) }
MockClass = Swarmerode(MockClass)
instance = new MockClass()
sinon.stub(Consul.prototype, 'getSwarmNodes').yieldsAsync(null, exampleHosts)
})
afterEach(function () {
Consul.prototype.getSwarmNodes.restore()
process.env.CONSUL_HOST = prevConsulHost
})
it('should extend a given class', function () {
assert.isFunction(MockClass.prototype.swarmHosts)
assert.isFunction(MockClass.prototype.swarmHostExists)
assert.isFunction(instance.swarmHosts)
assert.isFunction(instance.swarmHostExists)
})
it('should not allow being instantiate directly', function () {
var SwarmerodeClass = Swarmerode._Swarmerode
assert.throws(
function () { return new SwarmerodeClass() },
Error,
/cannot instantiate swarmerode directly/i
)
})
it('should not override existing prototype properties', function () {
var sampleObject = { foo: 'bar' }
var SampleClass = function () {}
SampleClass.prototype.swarmHostExists = sampleObject
SampleClass = Swarmerode(SampleClass)
var sampleInstance = new SampleClass()
assert.isObject(sampleInstance.swarmHostExists)
assert.equal(sampleInstance.swarmHostExists, sampleObject)
})
it('should not override existing prototype functions', function () {
var sampleFunction = function () {}
var SampleClass = function () {}
SampleClass.prototype.swarmHostExists = sampleFunction
SampleClass = Swarmerode(SampleClass)
var sampleInstance = new SampleClass()
assert.isFunction(sampleInstance.swarmHostExists)
assert.equal(sampleInstance.swarmHostExists, sampleFunction)
})
it('should not override existing class properties', function () {
var sampleObject = { foo: 'bar' }
var SampleClass = function () {}
SampleClass.swarmHostExists = sampleObject
SampleClass = Swarmerode(SampleClass)
assert.isObject(SampleClass.swarmHostExists)
assert.equal(SampleClass.swarmHostExists, sampleObject)
})
it('should not override existing class functions', function () {
var sampleFunction = function () {}
var SampleClass = function () {}
SampleClass.swarmHostExists = sampleFunction
SampleClass = Swarmerode(SampleClass)
assert.isFunction(SampleClass.swarmHostExists)
assert.equal(SampleClass.swarmHostExists, sampleFunction)
})
describe('swarmHosts', function () {
it('should return any error from consul', function (done) {
var error = new Error('robot')
Consul.prototype.getSwarmNodes.yieldsAsync(error)
instance.swarmHosts(function (err) {
assert.equal(err, error)
done()
})
})
it('should return a list of swarm hosts', function (done) {
instance.swarmHosts(function (err, hosts) {
assert.isNull(err)
assert.lengthOf(hosts, 3)
assert.includeMembers(hosts, exampleHosts)
done()
})
})
})
describe('swarmInfo', function () {
it('should call the class info function', function (done) {
sinon.spy(MockClass.prototype, 'info')
instance.swarmInfo(function (err) {
assert.isNull(err)
sinon.assert.calledOnce(MockClass.prototype.info)
done()
})
})
it('should pass through any info error', function (done) {
var error = new Error('foobar')
sinon.stub(MockClass.prototype, 'info').yieldsAsync(error)
instance.swarmInfo(function (err) {
assert.equal(err, error)
done()
})
})
})
describe('swarmHostExists', function () {
it('should return any error from consul', function (done) {
var error = new Error('robot')
Consul.prototype.getSwarmNodes.yieldsAsync(error)
instance.swarmHostExists('10.0.0.1:4242', function (err) {
assert.equal(err, error)
done()
})
})
it('should return a boolean if host in swarm (true)', function (done) {
instance.swarmHostExists('10.0.0.1:4242', function (err, exists) {
assert.isNull(err)
assert.isTrue(exists)
done()
})
})
it('should return a boolean if host in swarm (false)', function (done) {
instance.swarmHostExists('10.0.0.4:4242', function (err, exists) {
assert.isNull(err)
assert.isFalse(exists)
done()
})
})
})
describe('_parseSwarmSystemStatus', function () {
it('should not parse node that has incorrect nodename', function (done) {
var coolNode = {
Labels: 'env=test, hd=ssd',
Containers: 100,
nodeName: ' cool.node',
host: '10.42.42.42:4242'
}
var uncoolNode = {
Labels: 'env=prod, hd=disk',
Containers: 4,
nodeName: ' un.cool.node',
host: '10.7.7.7:4242'
}
var testHosts = swarmInfoMock([coolNode, uncoolNode])
var out = Swarmerode._Swarmerode._parseSwarmSystemStatus(testHosts.SystemStatus)
assert.equal(out.Role, 'primary')
assert.equal(out.Strategy, 'spread')
assert.equal(out.Filters, 'health, port, dependency, affinity, constraint')
assert.isNumber(out.Nodes)
assert.equal(out.Nodes, 2)
assert.equal(Object.keys(out.ParsedNodes).length, 0)
done()
})
it('should parse node with `(unknown)` nodename', function (done) {
var firstNode = {
Labels: 'env=test, hd=ssd',
Containers: 100,
nodeName: '(unknown)',
host: '10.42.42.42:4242'
}
var secondNode = {
Containers: 4,
nodeName: '(unknown)',
host: '10.7.7.7:4242'
}
var testHosts = swarmInfoMock([firstNode, secondNode])
delete testHosts.SystemStatus[18]
var out = Swarmerode._Swarmerode._parseSwarmSystemStatus(testHosts.SystemStatus)
assert.equal(out.Role, 'primary')
assert.equal(out.Strategy, 'spread')
assert.equal(out.Filters, 'health, port, dependency, affinity, constraint')
assert.isNumber(out.Nodes)
assert.equal(out.Nodes, 2)
assert.equal(Object.keys(out.ParsedNodes).length, 2)
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Host, firstNode.host)
assert.isNumber(out.ParsedNodes['10.42.42.42:4242'].Containers)
assert.isString(out.ParsedNodes['10.42.42.42:4242'].ID)
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Containers, 100)
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Status, 'Healthy')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].ReservedCpus, '0 / 1')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].ReservedMem, '10 GiB / 1.021 GiB')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].UpdatedAt, '2016-03-08T19:02:41Z')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Labels.env, 'test')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Labels.hd, 'ssd')
assert.equal(out.ParsedNodes['10.7.7.7:4242'].Host, secondNode.host)
assert.isNumber(out.ParsedNodes['10.7.7.7:4242'].Containers)
assert.isString(out.ParsedNodes['10.7.7.7:4242'].ID)
assert.equal(out.ParsedNodes['10.7.7.7:4242'].Containers, 4)
assert.equal(out.ParsedNodes['10.7.7.7:4242'].Status, 'Healthy')
assert.equal(out.ParsedNodes['10.7.7.7:4242'].ReservedCpus, '0 / 1')
assert.isUndefined(out.ParsedNodes['10.7.7.7:4242'].ReservedMem)
assert.equal(out.ParsedNodes['10.7.7.7:4242'].UpdatedAt, '2016-03-08T19:02:41Z')
done()
})
it('should parse node with `(unknown)` nodename and error', function (done) {
var firstNode = {
Labels: 'env=test, hd=ssd',
Containers: 100,
nodeName: '(unknown)',
host: '10.42.42.42:4242'
}
var secondNode = {
Containers: 4,
nodeName: '(unknown)',
host: '10.7.7.7:4242'
}
var isError = true
var testHosts = swarmInfoMock([firstNode, secondNode], isError)
var out = Swarmerode._Swarmerode._parseSwarmSystemStatus(testHosts.SystemStatus)
assert.equal(out.Role, 'primary')
assert.equal(out.Strategy, 'spread')
assert.equal(out.Filters, 'health, port, dependency, affinity, constraint')
assert.isNumber(out.Nodes)
assert.equal(out.Nodes, 2)
assert.equal(Object.keys(out.ParsedNodes).length, 2)
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Host, firstNode.host)
assert.isNumber(out.ParsedNodes['10.42.42.42:4242'].Containers)
assert.isString(out.ParsedNodes['10.42.42.42:4242'].ID)
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Containers, 100)
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Status, 'Pending')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Error, 'Docker daemon is unavailable')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].ReservedCpus, '0 / 1')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].ReservedMem, '10 GiB / 1.021 GiB')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].UpdatedAt, '2016-03-08T19:02:41Z')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Labels.env, 'test')
assert.equal(out.ParsedNodes['10.42.42.42:4242'].Labels.hd, 'ssd')
assert.equal(out.ParsedNodes['10.7.7.7:4242'].Host, secondNode.host)
assert.isNumber(out.ParsedNodes['10.7.7.7:4242'].Containers)
assert.isString(out.ParsedNodes['10.7.7.7:4242'].ID)
assert.equal(out.ParsedNodes['10.7.7.7:4242'].Containers, 4)
assert.equal(out.ParsedNodes['10.7.7.7:4242'].Status, 'Pending')
assert.equal(out.ParsedNodes['10.7.7.7:4242'].Error, 'Docker daemon is unavailable')
assert.equal(out.ParsedNodes['10.7.7.7:4242'].ReservedCpus, '0 / 1')
assert.equal(out.ParsedNodes['10.7.7.7:4242'].UpdatedAt, '2016-03-08T19:02:41Z')
done()
})
}) // end _parseSwarmSystemStatus
})