refactor: apply @openstapps/eslint-config rules

This commit is contained in:
Rainer Killinger
2022-05-09 11:14:36 +02:00
parent 1fcf7340d4
commit ac144095bf
8 changed files with 1264 additions and 231 deletions

View File

@@ -20,8 +20,10 @@ import {render} from 'mustache';
import {asyncReadFile, asyncWriteFile} from './common';
import {getContainers, getTemplateView} from './main';
/* eslint-disable unicorn/prefer-module */
// handle unhandled promise rejections
process.on('unhandledRejection', async (error) => {
process.on('unhandledRejection', async error => {
await Logger.error(error);
process.exit(1);
});
@@ -42,6 +44,7 @@ async function updateNginxConfig() {
.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);
@@ -50,7 +53,10 @@ async function updateNginxConfig() {
Logger.log('Generating new NGINX configuration');
// render nginx config file
const nginxConfig = render(await asyncReadFile('nginx.conf.template', 'utf8'), await getTemplateView(containers));
const nginxConfig = render(
await asyncReadFile('nginx.conf.template', 'utf8'),
await getTemplateView(containers),
);
containerHashCache = containerHash;
configHashCache = configHash;
@@ -65,9 +71,9 @@ async function updateNginxConfig() {
execSync('nginx -s reload');
}
// tslint:disable-next-line:no-magic-numbers - set timeout to update configuration again in 30s
setTimeout(updateNginxConfig, 30000);
// set timeout to update configuration again in 30s
setTimeout(updateNginxConfig, 30_000);
}
// tslint:disable-next-line:no-floating-promises - start the process that checks the docker socket periodically
// start the process that checks the docker socket periodically
updateNginxConfig();

View File

@@ -17,7 +17,7 @@ import {Logger} from '@openstapps/logger';
import Dockerode from 'dockerode';
import isCidr from 'is-cidr';
import {render} from 'mustache';
import {join} from 'path';
import path from 'path';
import * as semver from 'semver';
import {
asyncReadFile,
@@ -29,6 +29,9 @@ import {
TemplateView,
} from './common';
/* eslint-disable unicorn/prefer-module */
/* eslint-disable unicorn/no-await-expression-member */
/**
* Checks if a ContainerInfo matches a name and version regex
*
@@ -36,11 +39,17 @@ import {
* @param versionRegex Version regex to check
* @param container Container info for check
*/
export function containerMatchesRegex(name: string, versionRegex: RegExp, container: Dockerode.ContainerInfo): boolean {
return typeof container.Labels['stapps.version'] === 'string'
&& container.Labels['stapps.version'].match(versionRegex) !== null
&& typeof container.Labels['com.docker.compose.service'] === 'string'
&& container.Labels['com.docker.compose.service'] === name;
export function containerMatchesRegex(
name: string,
versionRegex: RegExp,
container: Dockerode.ContainerInfo,
): boolean {
return (
typeof container.Labels['stapps.version'] === 'string' &&
container.Labels['stapps.version'].match(versionRegex) !== null &&
typeof container.Labels['com.docker.compose.service'] === 'string' &&
container.Labels['com.docker.compose.service'] === name
);
}
/**
@@ -83,37 +92,46 @@ export async function generateUpstreamMap(
let foundMatchingContainer = false;
// active versions
result += (await Promise.all(
activeVersions
.map(async (activeVersionRegex) => {
result += (
await Promise.all(
activeVersions.map(async activeVersionRegex => {
const upstreamName = activeVersionRegex.replace(/[\\|.+]/g, '_');
let activeBackends = containers.filter((container) => {
let activeBackends = containers.filter(container => {
return containerMatchesRegex('backend', new RegExp(activeVersionRegex), container);
});
// .Labels['stapps.version'] is available
if (activeBackends.length > 0) {
activeBackends = activeBackends.sort((a, b) => semver.rcompare(a.Labels['stapps.version'],b.Labels['stapps.version']));
const activeBackendsVersions = activeBackends.map((container) => container.Labels['stapps.version'])
// tslint:disable-next-line: strict-boolean-expressions
.reduce((map, e) => map.set(e, (map.get(e) || 0) + 1), new Map<string, number>());
activeBackends = activeBackends.sort((a, b) =>
semver.rcompare(a.Labels['stapps.version'], b.Labels['stapps.version']),
);
const activeBackendsVersions = activeBackends
.map(container => container.Labels['stapps.version'])
// eslint-disable-next-line unicorn/no-array-reduce
.reduce(
(map, element) => map.set(element, (map.get(element) || 0) + 1),
new Map<string, number>(),
);
for (const [version, occurrences] of activeBackendsVersions) {
if (occurrences > 1) {
await Logger.error(`Omitting running version ${version} ! Multiple backends with this exact version are running`);
activeBackends = activeBackends.filter((container) => container.Labels['stapps.version'] !== version);
await Logger.error(
`Omitting running version ${version} ! Multiple backends with this exact version are running.`,
);
activeBackends = activeBackends.filter(
container => container.Labels['stapps.version'] !== version,
);
}
}
if (activeBackends.length !== 0) {
if (activeBackends.length > 0) {
// not only duplicates
foundMatchingContainer = true;
const gateWayOfContainer = await getGatewayOfStAppsBackend(activeBackends[0]);
const gatewayOfContainer = await getGatewayOfStAppsBackend(activeBackends[0]);
if (gateWayOfContainer.length !== 0) {
upstreams += `\nupstream ${upstreamName} {\n server ${gateWayOfContainer};\n}`;
if (gatewayOfContainer.length > 0) {
upstreams += `\nupstream ${upstreamName} {\n server ${gatewayOfContainer};\n}`;
return ` \"~${activeVersionRegex}\" ${upstreamName};\n`;
}
@@ -123,15 +141,17 @@ export async function generateUpstreamMap(
return ` \"~${activeVersionRegex}\" unavailable;\n`;
}),
)).join('');
)
).join('');
// outdated versions
result += outdatedVersions
.map((outdatedVersionRegex) => {
.map(outdatedVersionRegex => {
return ` \"~${outdatedVersionRegex}\" outdated;`;
})
.join('');
// eslint-disable-next-line prettier/prettier
result += '\n\}';
if (!foundMatchingContainer) {
@@ -149,11 +169,16 @@ export async function generateUpstreamMap(
export function generateListener(sslFilePaths: SSLFilePaths) {
let listener = '';
if (typeof sslFilePaths !== 'undefined' &&
typeof sslFilePaths.certificate !== 'undefined' && isFileType(sslFilePaths.certificate,'crt') &&
typeof sslFilePaths.certificateChain !== 'undefined' && isFileType(sslFilePaths.certificateChain,'crt') &&
typeof sslFilePaths.certificateKey !== 'undefined' && isFileType(sslFilePaths.certificateKey,'key') &&
typeof sslFilePaths.dhparam !== 'undefined' && isFileType(sslFilePaths.dhparam,'pem')
if (
typeof sslFilePaths !== 'undefined' &&
typeof sslFilePaths.certificate !== 'undefined' &&
isFileType(sslFilePaths.certificate, 'crt') &&
typeof sslFilePaths.certificateChain !== 'undefined' &&
isFileType(sslFilePaths.certificateChain, 'crt') &&
typeof sslFilePaths.certificateKey !== 'undefined' &&
isFileType(sslFilePaths.certificateKey, 'key') &&
typeof sslFilePaths.dhparam !== 'undefined' &&
isFileType(sslFilePaths.dhparam, 'pem')
) {
// https listener
listener = ` listen 443 ssl default_server;
@@ -161,7 +186,7 @@ export function generateListener(sslFilePaths: SSLFilePaths) {
ssl_certificate_key ${sslFilePaths.certificateKey};
ssl_trusted_certificate ${sslFilePaths.certificateChain};
ssl_dhparam ${sslFilePaths.dhparam};
${sslHardeningParameters}`;
${sslHardeningParameters}`;
} else {
// default http listener
listener = 'listen 80 default_server;';
@@ -194,7 +219,8 @@ async function renderTemplate(path: string, view: unknown): Promise<string> {
* @param entries Allow list entries that should be in CIDR notation
*/
function generateRateLimitAllowList(entries: string[]): string {
return entries.filter(entry => isCidr(entry))
return entries
.filter(entry => isCidr(entry))
.map(entry => `${entry} 0;`)
.join('\n');
}
@@ -206,31 +232,36 @@ function generateRateLimitAllowList(entries: string[]): string {
*/
export async function getTemplateView(containers: Dockerode.ContainerInfo[]): Promise<TemplateView> {
delete require.cache[require.resolve('config')];
// eslint-disable-next-line @typescript-eslint/no-var-requires
const config = require('config');
const configFile = config as ConfigFile;
const cors = await asyncReadFile('./fixtures/cors.template', 'utf8');
const visibleRoutesPromises = ['/'].map(async (route) => {
return renderTemplate(join('fixtures', 'visibleRoute.template'), {
const visibleRoutesPromises = ['/'].map(async route => {
return renderTemplate(path.join('fixtures', 'visibleRoute.template'), {
cors,
route,
});
});
const hiddenRoutesPromises = configFile.hiddenRoutes.map(async (route) => {
return renderTemplate(join('fixtures', 'hiddenRoute.template'), {
const hiddenRoutesPromises = configFile.hiddenRoutes.map(async route => {
return renderTemplate(path.join('fixtures', 'hiddenRoute.template'), {
cors,
route,
});
});
return {
dockerVersionMap: await generateUpstreamMap(configFile.activeVersions, configFile.outdatedVersions, containers),
dockerVersionMap: await generateUpstreamMap(
configFile.activeVersions,
configFile.outdatedVersions,
containers,
),
hiddenRoutes: (await Promise.all(hiddenRoutesPromises)).join(''),
listener: generateListener(configFile.sslFilePaths),
rateLimitAllowList: generateRateLimitAllowList(configFile.rateLimitAllowList),
staticRoute: await renderTemplate(join('fixtures', 'staticRoute.template'), {cors}),
staticRoute: await renderTemplate(path.join('fixtures', 'staticRoute.template'), {cors}),
visibleRoutes: (await Promise.all(visibleRoutesPromises)).join(''),
};
}
@@ -240,7 +271,9 @@ export async function getTemplateView(containers: Dockerode.ContainerInfo[]): Pr
*
* @param pathToDockerSocket Path to docker socket
*/
export async function getContainers(pathToDockerSocket = '/var/run/docker.sock'): Promise<Dockerode.ContainerInfo[]> {
export async function getContainers(
pathToDockerSocket = '/var/run/docker.sock',
): Promise<Dockerode.ContainerInfo[]> {
const docker = new Dockerode({
socketPath: pathToDockerSocket,
});