UNPKG

navy

Version:

Quick and powerful development environments using Docker and Docker Compose

136 lines (133 loc) 5.22 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.reconfigureHTTPProxy = reconfigureHTTPProxy; exports.resolveDockerSocketPath = resolveDockerSocketPath; exports.resolveProxyEnv = resolveProxyEnv; exports.resolveProxyEnvAllowlist = resolveProxyEnvAllowlist; exports.resolveProxyEnvFromNavyFile = resolveProxyEnvFromNavyFile; exports.resolveProxyImage = resolveProxyImage; var _os = _interopRequireDefault(require("os")); var _path = _interopRequireDefault(require("path")); var _jsYaml = _interopRequireDefault(require("js-yaml")); var _dockerClient = _interopRequireDefault(require("./util/docker-client")); var _fs = _interopRequireDefault(require("fs")); var _https = require("./util/https"); var _execAsync = require("./util/exec-async"); var _driverLogging = require("./driver-logging"); var _navy = require("./navy"); const DEFAULT_PROXY_IMAGE = 'navycloud/navy-proxy'; const DEFAULT_DOCKER_SOCKET = '/var/run/docker.sock'; function resolveProxyImage(navyFile) { return process.env.NAVY_HTTP_PROXY_IMAGE || navyFile && navyFile.httpProxyImage || DEFAULT_PROXY_IMAGE; } function resolveProxyEnvFromNavyFile(navyFile) { if (!navyFile) return {}; const raw = navyFile.httpProxyEnv; if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return {}; const result = {}; for (const key of Object.keys(raw)) { const value = raw[key]; if (value === null || value === undefined) continue; const coerced = String(value); if (coerced === '') continue; result[key] = coerced; } return result; } function resolveProxyEnvAllowlist() { const allowlist = process.env.NAVY_HTTP_PROXY_ENV; if (!allowlist) return {}; const seen = new Set(); const result = {}; for (const rawName of allowlist.split(',')) { const name = rawName.trim(); if (!name || seen.has(name)) continue; seen.add(name); const value = process.env[name]; if (typeof value !== 'string' || value === '') continue; result[name] = value; } return result; } function resolveProxyEnv(navyFile) { const merged = { ...resolveProxyEnvFromNavyFile(navyFile), ...resolveProxyEnvAllowlist() }; if (Object.keys(merged).length === 0) return null; return merged; } // Resolve the host path to the Docker socket. The proxy container needs to // read events from the same daemon as the rest of navy, so we honour // DOCKER_HOST when it points at a unix socket (e.g. on CI where // `docker/setup-docker-action` puts the daemon on a custom path) and fall // back to the conventional `/var/run/docker.sock` otherwise. function resolveDockerSocketPath() { const dockerHost = process.env.DOCKER_HOST; if (dockerHost && dockerHost.indexOf('unix://') === 0) { const socketPath = dockerHost.slice('unix://'.length); if (socketPath) return socketPath; } return DEFAULT_DOCKER_SOCKET; } async function updateComposeConfig(navies, navyFile) { const allNetworks = await _dockerClient.default.listNetworks(); const networks = allNetworks.filter(net => net.Name.indexOf('_') !== -1) // is docker-compose network? .filter(net => { for (const navy of navies) { if (net.Name.indexOf(navy + '_') === 0) { return true; } } return false; }); const networksConfig = {}; networks.forEach(net => networksConfig[net.Name] = { external: true }); const ports = ['80:80']; const volumes = [`${resolveDockerSocketPath()}:/tmp/docker.sock:ro`]; // Enable HTTPS for services that // match crt file names in tlsRootCaDir const certsPath = await (0, _https.getCertsPath)(true); if (certsPath) { ports.push('443:443'); volumes.push(`${certsPath}:/etc/nginx/certs`); volumes.push(`${certsPath}:/etc/nginx/dhparam`); // to persist DH params } const proxyEnv = resolveProxyEnv(navyFile); const config = { version: '2', services: { 'nginx-proxy': { image: resolveProxyImage(navyFile), ports, networks: networks.map(net => net.Name), volumes, ...(proxyEnv ? { environment: proxyEnv } : {}), restart: 'always' } }, networks: networksConfig }; _fs.default.writeFileSync(_path.default.join(_os.default.tmpdir(), 'navyinternaldockercompose.yml'), _jsYaml.default.dump(config)); } async function reconfigureHTTPProxy(opts = {}) { const navyInternalYamlFile = _path.default.join(_os.default.tmpdir(), 'navyinternaldockercompose.yml'); if (opts.restart) { // proxy needs to be recreated to detect changes (deletes) in /etc/nginx/certs if (_fs.default.existsSync(navyInternalYamlFile)) { (0, _driverLogging.log)('Restarting HTTP proxy...'); await (0, _execAsync.execAsync)('docker compose', ['-f', navyInternalYamlFile, '-p', 'navyinternal', 'rm', '-s', '-f', 'nginx-proxy']); } } if (!opts.navies) opts.navies = await (0, _navy.getLaunchedNavyNames)(); await updateComposeConfig(opts.navies, opts.navyFile); (0, _driverLogging.log)('Configuring HTTP proxy...'); await (0, _execAsync.execAsync)('docker compose', ['-f', navyInternalYamlFile, '-p', 'navyinternal', 'up', '-d']); }