2023-07-26 14:05:53 +00:00
|
|
|
import * as plugins from './smartnginx.plugins.js';
|
|
|
|
import * as paths from './smartnginx.paths.js';
|
|
|
|
import * as snippets from './smartnginx.snippets.js';
|
|
|
|
import { NginxHost } from './smartnginx.classes.nginxhost.js';
|
|
|
|
import { NginxProcess } from './smartnginx.classes.nginxprocess.js';
|
|
|
|
import { type IHostConfig } from './interfaces/hostconfig.js';
|
2018-08-10 21:10:48 +00:00
|
|
|
|
2019-04-10 17:03:17 +00:00
|
|
|
export interface ISmartNginxContructorOptions {
|
|
|
|
logger?: plugins.smartlog.Smartlog;
|
|
|
|
defaultProxyUrl: string;
|
|
|
|
}
|
|
|
|
|
2018-08-10 21:10:48 +00:00
|
|
|
/**
|
|
|
|
* main class that manages a NginxInstance
|
|
|
|
*/
|
|
|
|
export class SmartNginx {
|
2019-04-10 17:03:17 +00:00
|
|
|
public options: ISmartNginxContructorOptions;
|
2019-01-09 11:15:28 +00:00
|
|
|
public logger: plugins.smartlog.Smartlog;
|
2019-01-17 23:45:29 +00:00
|
|
|
|
|
|
|
// the objectmaps
|
2023-07-26 14:05:53 +00:00
|
|
|
private deployedHosts = new plugins.lik.ObjectMap<NginxHost>();
|
|
|
|
private hostCandidates = new plugins.lik.ObjectMap<NginxHost>();
|
2019-01-17 23:45:29 +00:00
|
|
|
|
2019-01-09 11:15:28 +00:00
|
|
|
public nginxProcess: NginxProcess = new NginxProcess(this);
|
2019-04-10 17:03:17 +00:00
|
|
|
constructor(optionsArg: ISmartNginxContructorOptions) {
|
|
|
|
this.options = optionsArg;
|
|
|
|
this.options.logger
|
|
|
|
? (this.logger = this.options.logger)
|
2023-07-26 14:05:53 +00:00
|
|
|
: (this.logger = new plugins.smartlog.Smartlog({
|
|
|
|
logContext: null
|
|
|
|
}));
|
2019-01-09 11:15:28 +00:00
|
|
|
}
|
2018-08-10 21:10:48 +00:00
|
|
|
|
|
|
|
// ===================
|
|
|
|
// interact with Hosts
|
|
|
|
// ===================
|
|
|
|
|
|
|
|
/**
|
|
|
|
* add a host
|
|
|
|
* @param nginxHostArg
|
|
|
|
*/
|
2019-01-17 23:45:29 +00:00
|
|
|
public addHostCandidate(optionsArg: IHostConfig): NginxHost {
|
2019-01-09 11:15:28 +00:00
|
|
|
const nginxHost = new NginxHost(this, optionsArg);
|
2019-01-17 23:45:29 +00:00
|
|
|
this.hostCandidates.add(nginxHost);
|
2018-08-11 13:09:19 +00:00
|
|
|
return nginxHost;
|
2018-08-10 21:10:48 +00:00
|
|
|
}
|
|
|
|
|
2019-01-09 11:15:28 +00:00
|
|
|
/**
|
|
|
|
* Gets a NginxHost by hostname
|
|
|
|
* @param hostNameArg
|
|
|
|
*/
|
2019-01-17 23:45:29 +00:00
|
|
|
public getDeployedNginxHostByHostName(hostNameArg: string): NginxHost {
|
2023-07-26 14:05:53 +00:00
|
|
|
return this.deployedHosts.findSync((nginxHost) => {
|
2018-08-11 13:09:19 +00:00
|
|
|
return nginxHost.hostName === hostNameArg;
|
2019-01-09 11:15:28 +00:00
|
|
|
});
|
2018-08-11 13:09:19 +00:00
|
|
|
}
|
2018-08-10 21:10:48 +00:00
|
|
|
/**
|
|
|
|
* listHosts
|
|
|
|
*/
|
2019-01-17 23:45:29 +00:00
|
|
|
public async listDeployedHosts(): Promise<NginxHost[]> {
|
|
|
|
return this.deployedHosts.getArray();
|
2018-08-10 21:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* remove a Host
|
|
|
|
* @param nginxHostArg
|
|
|
|
*/
|
2019-01-17 23:45:29 +00:00
|
|
|
public async removeDeployedHost(nginxHostArg: NginxHost) {
|
|
|
|
if (this.hostCandidates.isEmpty()) {
|
2023-07-26 14:05:53 +00:00
|
|
|
this.deployedHosts.forEach((hostArg) => {
|
2019-01-17 23:45:29 +00:00
|
|
|
this.hostCandidates.add(hostArg);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
this.hostCandidates.remove(nginxHostArg);
|
|
|
|
this.deploy();
|
2019-01-09 11:15:28 +00:00
|
|
|
}
|
|
|
|
|
2018-08-10 21:10:48 +00:00
|
|
|
/**
|
2019-01-17 23:45:29 +00:00
|
|
|
* check wether there has been a diverging host configuration
|
|
|
|
* this function will only redeploy the nginx configuration in case there has been a change
|
2018-08-10 21:10:48 +00:00
|
|
|
*/
|
2019-01-18 00:33:01 +00:00
|
|
|
private async areHostsDiverged(): Promise<boolean> {
|
2019-01-17 23:45:29 +00:00
|
|
|
let hostCounter = 0;
|
|
|
|
let unfoundHosts = 0;
|
2023-07-26 14:05:53 +00:00
|
|
|
await this.hostCandidates.forEach(async (hostCandidateArg) => {
|
2019-01-17 23:45:29 +00:00
|
|
|
let foundHost = false;
|
2023-07-26 14:05:53 +00:00
|
|
|
await this.deployedHosts.forEach(async (deployedHostArg) => {
|
2019-01-17 23:45:29 +00:00
|
|
|
if (
|
|
|
|
hostCandidateArg.hostName === deployedHostArg.hostName &&
|
2019-01-19 14:41:51 +00:00
|
|
|
hostCandidateArg.destination === deployedHostArg.destination &&
|
|
|
|
hostCandidateArg.destinationPort === deployedHostArg.destinationPort
|
2019-01-17 23:45:29 +00:00
|
|
|
) {
|
|
|
|
hostCounter++;
|
|
|
|
foundHost = true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (!foundHost) {
|
|
|
|
unfoundHosts++;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return (
|
2019-01-18 00:33:01 +00:00
|
|
|
this.deployedHosts.getArray().length !== this.hostCandidates.getArray().length ||
|
2019-01-17 23:45:29 +00:00
|
|
|
hostCounter !== this.deployedHosts.getArray().length ||
|
|
|
|
unfoundHosts !== 0
|
|
|
|
);
|
2018-08-10 21:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* deploy the current stack and restart nginx
|
|
|
|
*/
|
2019-01-09 11:15:28 +00:00
|
|
|
public async deploy() {
|
2019-01-18 00:33:01 +00:00
|
|
|
if (await this.areHostsDiverged()) {
|
2019-01-17 23:45:29 +00:00
|
|
|
this.logger.log('ok', `hosts have diverged, trigger config deployment and nginx reload!`);
|
|
|
|
this.deployedHosts.wipe();
|
|
|
|
this.deployedHosts.addArray(this.hostCandidates.getArray());
|
|
|
|
this.hostCandidates.wipe();
|
|
|
|
|
|
|
|
// write base config
|
|
|
|
plugins.smartfile.fs.ensureDirSync(paths.nginxConfigDirPath);
|
2019-08-20 20:30:31 +00:00
|
|
|
plugins.smartfile.memory.toFsSync(
|
|
|
|
snippets.getBaseConfigString(this.options.defaultProxyUrl),
|
|
|
|
paths.nginxConfFile
|
|
|
|
);
|
2019-04-10 17:03:17 +00:00
|
|
|
|
|
|
|
// write standard self signed certificate
|
2019-08-20 20:30:31 +00:00
|
|
|
const selfsignedCert = plugins.selfsigned.generate(
|
|
|
|
[{ name: 'commonName', value: 'selfsigned.git.zone' }],
|
|
|
|
{ days: 365 }
|
|
|
|
);
|
|
|
|
|
2019-04-10 23:42:48 +00:00
|
|
|
// deploy hosts
|
|
|
|
plugins.smartfile.fs.ensureDirSync(paths.nginxHostDirPath);
|
2019-08-20 20:30:31 +00:00
|
|
|
plugins.smartfile.memory.toFsSync(
|
|
|
|
selfsignedCert.private,
|
|
|
|
plugins.path.join(paths.nginxHostDirPath, './default.private.pem')
|
|
|
|
);
|
|
|
|
plugins.smartfile.memory.toFsSync(
|
|
|
|
selfsignedCert.cert,
|
|
|
|
plugins.path.join(paths.nginxHostDirPath, './default.public.pem')
|
|
|
|
);
|
2019-01-17 23:45:29 +00:00
|
|
|
for (const host of this.deployedHosts.getArray()) {
|
|
|
|
await host.deploy();
|
|
|
|
this.logger.log('info', `Host ${host.hostName} deployed!`);
|
|
|
|
}
|
|
|
|
this.nginxProcess.reloadConfig();
|
|
|
|
} else {
|
|
|
|
this.logger.log('info', `hosts have not diverged, skipping nginx reload`);
|
2019-01-17 23:46:08 +00:00
|
|
|
this.hostCandidates.wipe();
|
2019-01-09 11:15:28 +00:00
|
|
|
}
|
2018-08-10 21:10:48 +00:00
|
|
|
}
|
2019-08-20 20:28:48 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* stops the smartnginx instance
|
|
|
|
*/
|
|
|
|
public async stop() {
|
|
|
|
if (this.nginxProcess) {
|
|
|
|
await this.nginxProcess.stop();
|
|
|
|
}
|
|
|
|
}
|
2018-08-10 21:10:48 +00:00
|
|
|
}
|