/* * Copyright (C) 2022 StApps * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ import {Logger} from '@openstapps/logger'; import {execSync} from 'child_process'; import * as Dockerode from 'dockerode'; import mustache from 'mustache'; import {asyncReadFile, asyncWriteFile} from './common.js'; import {getContainers, getTemplateView} from './main.js'; /* eslint-disable unicorn/prefer-module */ // handle unhandled promise rejections process.on('unhandledRejection', async error => { await Logger.error(error); process.exit(1); }); let containerHashCache = ''; let configHashCache = ''; const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); /** * Reads the container information from the docker socket and updates the nginx config if necessary */ async function updateNginxConfig() { const containers = await getContainers(); const containerHash = containers .map((container: Dockerode.ContainerInfo) => { return container.Id; }) .join(','); delete require.cache[require.resolve('config')]; // eslint-disable-next-line @typescript-eslint/no-var-requires const configFile = require('config'); const configHash = JSON.stringify(configFile); // if containers changed -> write config file, reload nginx if (containerHash !== containerHashCache || configHash !== configHashCache) { Logger.log('Generating new NGINX configuration'); Logger.log('Waiting for Docker network to settle...'); await delay(10_000); // render nginx config file const nginxConfig = mustache.render( await asyncReadFile('nginx.conf.template', 'utf8'), await getTemplateView(containers), ); containerHashCache = containerHash; configHashCache = configHash; Logger.log(`Writing new config file "${configFile.output}"`); // overwrite nginx config file with our rendered one await asyncWriteFile(configFile.output, nginxConfig, 'utf8'); Logger.log('Executing "nginx -s reload" to tell nginx to reload the configuration file'); execSync('nginx -s reload'); } // set timeout to update configuration again in 30s setTimeout(updateNginxConfig, 30_000); } // start the process that checks the docker socket periodically // eslint-disable-next-line unicorn/prefer-top-level-await updateNginxConfig();