UNPKG

navy

Version:

Quick and powerful development environments using Docker and Docker Compose

258 lines (256 loc) 9.26 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _chai = require("chai"); var _sinon = _interopRequireDefault(require("sinon")); var serviceHostModule = _interopRequireWildcard(require("../../util/service-host")); var httpsModule = _interopRequireWildcard(require("../../util/https")); var _addServiceProxyConfig = _interopRequireDefault(require("../add-service-proxy-config")); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /* eslint-env mocha */ function makeNavy({ navyFile = null, externalIP = '10.0.0.1' } = {}) { return { name: 'env', normalisedName: 'env', getNavyFile: _sinon.default.stub().resolves(navyFile), externalIP: _sinon.default.stub().resolves(externalIP) }; } describe('add-service-proxy-config middleware', function () { let sandbox; let createCertStub; let createHostStub; beforeEach(function () { sandbox = _sinon.default.createSandbox(); createCertStub = sandbox.stub(httpsModule, 'createCert').resolves(); createHostStub = sandbox.stub(serviceHostModule, 'createHostForService').callsFake(async (svc, navyName) => `${svc}.${navyName}.test.local`); }); afterEach(function () { sandbox.restore(); }); describe('factory', function () { it('should return an async middleware function when invoked with a navy', function () { const fn = (0, _addServiceProxyConfig.default)(makeNavy()); (0, _chai.expect)(fn).to.be.a('function'); }); }); describe('auto-proxy of port 80', function () { it('should add VIRTUAL_HOST/VIRTUAL_PORT for services exposing port 80 by default', async function () { const middleware = (0, _addServiceProxyConfig.default)(makeNavy()); const config = { services: { web: { ports: ['80:80'] } } }; const result = await middleware(config, {}); (0, _chai.expect)(result.services.web.environment.VIRTUAL_HOST).to.equal('web.env.test.local'); (0, _chai.expect)(result.services.web.environment.VIRTUAL_PORT).to.equal(80); }); it('should not auto-proxy services that do not expose port 80', async function () { const middleware = (0, _addServiceProxyConfig.default)(makeNavy()); const config = { services: { worker: { ports: ['8080:8080'] } } }; const result = await middleware(config, {}); (0, _chai.expect)(result.services.worker).to.eql({ ports: ['8080:8080'] }); }); it('should not auto-proxy services that have no ports declared', async function () { const middleware = (0, _addServiceProxyConfig.default)(makeNavy()); const config = { services: { worker: {} } }; const result = await middleware(config, {}); (0, _chai.expect)(result.services.worker).to.eql({}); }); }); describe('explicit httpProxy config in navyFile', function () { it('should use the explicit httpProxy config to set VIRTUAL_HOST and VIRTUAL_PORT', async function () { const navy = makeNavy({ navyFile: { httpProxy: { api: { port: 3000 } } } }); const middleware = (0, _addServiceProxyConfig.default)(navy); const result = await middleware({ services: { api: { ports: ['3000:3000'] } } }, {}); (0, _chai.expect)(result.services.api.environment.VIRTUAL_PORT).to.equal(3000); (0, _chai.expect)(result.services.api.environment.VIRTUAL_HOST).to.equal('api.env.test.local'); }); it('should issue a TLS cert when proxyConfig.enableHttps is set', async function () { const navy = makeNavy({ navyFile: { httpProxy: { api: { port: 3000, enableHttps: true } } } }); const middleware = (0, _addServiceProxyConfig.default)(navy); await middleware({ services: { api: {} } }, {}); (0, _chai.expect)(createCertStub.calledOnce).to.equal(true); (0, _chai.expect)(createCertStub.firstCall.args[0]).to.eql({ hostName: 'api.env.test.local' }); }); it('should not issue a TLS cert when proxyConfig is implicit (no enableHttps)', async function () { const middleware = (0, _addServiceProxyConfig.default)(makeNavy()); await middleware({ services: { web: { ports: ['80:80'] } } }, {}); (0, _chai.expect)(createCertStub.called).to.equal(false); }); }); describe('httpProxyAutoPorts navyFile config', function () { it('should auto-proxy a different port when configured via httpProxyAutoPorts', async function () { const navy = makeNavy({ navyFile: { httpProxyAutoPorts: ['3000'] } }); const middleware = (0, _addServiceProxyConfig.default)(navy); const result = await middleware({ services: { api: { ports: ['3000:3000'] } } }, {}); (0, _chai.expect)(result.services.api.environment.VIRTUAL_PORT).to.equal(3000); }); it('should fall back to ["80"] when httpProxyAutoPorts is not an array', async function () { const navy = makeNavy({ navyFile: { httpProxyAutoPorts: 'not-an-array' } }); const middleware = (0, _addServiceProxyConfig.default)(navy); const result = await middleware({ services: { web: { ports: ['80:80'] } } }, {}); (0, _chai.expect)(result.services.web.environment.VIRTUAL_PORT).to.equal(80); }); }); describe('port matching forms', function () { it('should match a numeric port equal to the auto port', async function () { const middleware = (0, _addServiceProxyConfig.default)(makeNavy()); const result = await middleware({ services: { web: { ports: [80] } } }, {}); // eslint-disable-next-line no-unused-expressions (0, _chai.expect)(result.services.web.environment).to.exist; }); it('should match a "80/tcp" protocol-suffixed port', async function () { const middleware = (0, _addServiceProxyConfig.default)(makeNavy()); const result = await middleware({ services: { web: { ports: ['80/tcp'] } } }, {}); // eslint-disable-next-line no-unused-expressions (0, _chai.expect)(result.services.web.environment).to.exist; }); it('should match a port object with a target field equal to the auto port', async function () { const middleware = (0, _addServiceProxyConfig.default)(makeNavy()); const result = await middleware({ services: { web: { ports: [{ target: 80, published: 8080 }] } } }, {}); // eslint-disable-next-line no-unused-expressions (0, _chai.expect)(result.services.web.environment).to.exist; }); }); describe('environment merge', function () { it('should not overwrite existing env vars with VIRTUAL_HOST/VIRTUAL_PORT', async function () { const middleware = (0, _addServiceProxyConfig.default)(makeNavy()); const result = await middleware({ services: { web: { ports: ['80:80'], environment: { VIRTUAL_HOST: 'preset.host', OTHER: 'x' } } } }, {}); (0, _chai.expect)(result.services.web.environment.VIRTUAL_HOST).to.equal('preset.host'); (0, _chai.expect)(result.services.web.environment.OTHER).to.equal('x'); }); }); it('should preserve other top-level config keys', async function () { const middleware = (0, _addServiceProxyConfig.default)(makeNavy()); const result = await middleware({ version: '3.7', services: { web: { ports: ['80:80'] } }, networks: { default: {} } }, {}); (0, _chai.expect)(result.version).to.equal('3.7'); (0, _chai.expect)(result.networks).to.eql({ default: {} }); }); it('should not call externalIP/createHostForService for services without proxy config', async function () { const middleware = (0, _addServiceProxyConfig.default)(makeNavy()); await middleware({ services: { worker: { ports: ['9000:9000'] } } }, {}); (0, _chai.expect)(createHostStub.called).to.equal(false); }); });