Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
a672bb920f | |||
c3fabb6107 | |||
b4ebdbae47 | |||
c55d2dcf10 | |||
7274d5ea8a | |||
1ec733c2a9 | |||
3ef14d8ac7 | |||
f332bf95fe | |||
6acad8a306 | |||
6ae672f707 | |||
3d263e2181 | |||
85639f29af | |||
85448a21fc | |||
3b85c4a37e | |||
67dd650dce | |||
92eaf5f19a |
44
package-lock.json
generated
44
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@pushrocks/smartnginx",
|
||||
"version": "2.0.12",
|
||||
"version": "2.0.20",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -90,9 +90,9 @@
|
||||
}
|
||||
},
|
||||
"@pushrocks/qenv": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fqenv/-/qenv-3.0.2.tgz",
|
||||
"integrity": "sha512-gXW9Cib6izqY7W1MssryFBrjIoKwadftjv5G3y/BE4LboCkGazqjMJsea6z6G79rwvX1M+yxEEcIdIsDvBBSiA==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fqenv/-/qenv-4.0.0.tgz",
|
||||
"integrity": "sha512-3/odPJaGp3ALtcSG/+N3dGtFX/CVBed9a5XKDa0bv7LoKCgYZeQwpF3jkCnNPjs7GKyzOzALHHID1L+zcb1RXw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@pushrocks/smartfile": "^6.0.6",
|
||||
@ -162,11 +162,11 @@
|
||||
}
|
||||
},
|
||||
"@pushrocks/smartlog": {
|
||||
"version": "2.0.9",
|
||||
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartlog/-/smartlog-2.0.9.tgz",
|
||||
"integrity": "sha512-F2u3O8OOQ7QXgg9o0lI7HnqEhSQZo2A8u0EuNbQH+Kj2oL62xDwjAg6KkINwH7ObSWpaldZ+I28prG0JxaRzvg==",
|
||||
"version": "2.0.11",
|
||||
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartlog/-/smartlog-2.0.11.tgz",
|
||||
"integrity": "sha512-V8SMzAAqDpl1+CJ9b3w5e/1ARjk4JOPZ35qZIllVBhHr8meCqnPE2immlfBYWmEp1xy3ntdAA+Lgewtu+iVk6A==",
|
||||
"requires": {
|
||||
"@pushrocks/smartlog-interfaces": "^2.0.2"
|
||||
"@pushrocks/smartlog-interfaces": "^2.0.5"
|
||||
}
|
||||
},
|
||||
"@pushrocks/smartlog-interfaces": {
|
||||
@ -227,12 +227,12 @@
|
||||
}
|
||||
},
|
||||
"@pushrocks/smartstring": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartstring/-/smartstring-3.0.5.tgz",
|
||||
"integrity": "sha512-Bws2s6+Pc0HIXA35QH6cl6LJywhZ1U5icjyYMx+1kH8nURG+njzkacfarr9NWqyVYYOVu7SgXLzp9sR0eH7k9g==",
|
||||
"version": "3.0.8",
|
||||
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartstring/-/smartstring-3.0.8.tgz",
|
||||
"integrity": "sha512-twmCGF47+TJoiCpj6t5MxwcKDDJEATuKqJXxftcHOlXWW743LJ/1bCpMueDdtumo5EheUfSxb43aRse3DU3wig==",
|
||||
"requires": {
|
||||
"crypto-random-string": "^1.0.0",
|
||||
"js-base64": "^2.4.9",
|
||||
"js-base64": "^2.5.0",
|
||||
"normalize-newline": "^3.0.0",
|
||||
"randomatic": "^3.1.1",
|
||||
"strip-indent": "^2.0.0"
|
||||
@ -332,7 +332,7 @@
|
||||
},
|
||||
"@types/which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://verdaccio.lossless.one/@types%2fwhich/-/which-1.3.1.tgz",
|
||||
"resolved": "https://registry.npmjs.org/@types/which/-/which-1.3.1.tgz",
|
||||
"integrity": "sha512-ZrJDWpvg75LTGX4XwuneY9s6bF3OeZcGTpoGh3zDV9ytzcHMFsRrMIaLBRJZQMBoGyKs6unBQfVdrLZiYfb1zQ=="
|
||||
},
|
||||
"@types/yargs": {
|
||||
@ -774,9 +774,9 @@
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://verdaccio.lossless.one/glob/-/glob-7.1.3.tgz",
|
||||
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
@ -965,9 +965,9 @@
|
||||
}
|
||||
},
|
||||
"math-random": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz",
|
||||
"integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w="
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://verdaccio.lossless.one/math-random/-/math-random-1.0.4.tgz",
|
||||
"integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A=="
|
||||
},
|
||||
"mem": {
|
||||
"version": "4.0.0",
|
||||
@ -1410,9 +1410,9 @@
|
||||
"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
|
||||
},
|
||||
"tslint": {
|
||||
"version": "5.12.0",
|
||||
"resolved": "https://verdaccio.lossless.one/tslint/-/tslint-5.12.0.tgz",
|
||||
"integrity": "sha512-CKEcH1MHUBhoV43SA/Jmy1l24HJJgI0eyLbBNSRyFlsQvb9v6Zdq+Nz2vEOH00nC5SUx4SneJ59PZUS/ARcokQ==",
|
||||
"version": "5.12.1",
|
||||
"resolved": "https://verdaccio.lossless.one/tslint/-/tslint-5.12.1.tgz",
|
||||
"integrity": "sha512-sfodBHOucFg6egff8d1BvuofoOQ/nOeYNfbp7LDlKBcLNrL3lmS5zoiDGyOMdT7YsEXAwWpTdAHwOGOc8eRZAw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-code-frame": "^6.22.0",
|
||||
|
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@pushrocks/smartnginx",
|
||||
"version": "2.0.12",
|
||||
"version": "2.0.20",
|
||||
"private": false,
|
||||
"description": "control nginx from node, TypeScript ready",
|
||||
"main": "dist/index.js",
|
||||
@ -26,18 +26,18 @@
|
||||
"dependencies": {
|
||||
"@pushrocks/lik": "^3.0.4",
|
||||
"@pushrocks/smartfile": "^6.0.11",
|
||||
"@pushrocks/smartlog": "^2.0.9",
|
||||
"@pushrocks/smartlog": "^2.0.11",
|
||||
"@pushrocks/smartpromise": "^2.0.5",
|
||||
"@pushrocks/smartshell": "^2.0.13",
|
||||
"@pushrocks/smartstring": "^3.0.5"
|
||||
"@pushrocks/smartstring": "^3.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@gitzone/tsbuild": "^2.1.4",
|
||||
"@gitzone/tsrun": "^1.1.17",
|
||||
"@gitzone/tstest": "^1.0.18",
|
||||
"@pushrocks/qenv": "^3.0.2",
|
||||
"@pushrocks/qenv": "^4.0.0",
|
||||
"@pushrocks/tapbundle": "^3.0.7",
|
||||
"tslint": "^5.12.0",
|
||||
"tslint": "^5.12.1",
|
||||
"tslint-config-prettier": "^1.17.0"
|
||||
}
|
||||
}
|
||||
|
12
test/test.ts
12
test/test.ts
@ -31,15 +31,21 @@ tap.test(`should produce an instance of NginxConfig`, async () => {
|
||||
expect(testNginxZone01).to.be.instanceof(smartnginx.NginxHost);
|
||||
});
|
||||
|
||||
tap.test('.addZone() should add a zone to NginxConfig Object', async () => {
|
||||
testSmartNginx.addHost(testNginxZone01);
|
||||
testSmartNginx.addHost(testNginxZone02);
|
||||
tap.test('.addHostCandidate() should add a zone to NginxConfig Object', async () => {
|
||||
testSmartNginx.addHostCandidate(testNginxZone01);
|
||||
testSmartNginx.addHostCandidate(testNginxZone02);
|
||||
});
|
||||
|
||||
tap.test('.deploy() should deploy a config from an instance', async () => {
|
||||
await testSmartNginx.deploy();
|
||||
});
|
||||
|
||||
tap.test('should not redeploy', async () => {
|
||||
testSmartNginx.addHostCandidate(testNginxZone01);
|
||||
testSmartNginx.addHostCandidate(testNginxZone02);
|
||||
await testSmartNginx.deploy();
|
||||
});
|
||||
|
||||
tap.test('.stop() should end the process', async () => {
|
||||
testSmartNginx.nginxProcess.stop();
|
||||
});
|
||||
|
@ -17,13 +17,13 @@ export class NginxHost implements IHostConfig {
|
||||
/**
|
||||
* smartnginxInstance this NginHost belongs to
|
||||
*/
|
||||
smartnginxInstance: SmartNginx;
|
||||
public smartnginxInstance: SmartNginx;
|
||||
|
||||
hostName: string; // the host name e.g. domain name
|
||||
destination: string;
|
||||
configString: string; // the actual host config file as string
|
||||
privateKey: string;
|
||||
publicKey: string;
|
||||
public hostName: string; // the host name e.g. domain name
|
||||
public destination: string;
|
||||
public configString: string; // the actual host config file as string
|
||||
public privateKey: string;
|
||||
public publicKey: string;
|
||||
|
||||
constructor(smartnginxInstanceArg: SmartNginx, optionsArg: IHostConfig) {
|
||||
this.smartnginxInstance = smartnginxInstanceArg;
|
||||
|
@ -10,7 +10,11 @@ import { IHostConfig } from './interfaces/hostconfig';
|
||||
*/
|
||||
export class SmartNginx {
|
||||
public logger: plugins.smartlog.Smartlog;
|
||||
private hosts = new plugins.lik.Objectmap<NginxHost>();
|
||||
|
||||
// the objectmaps
|
||||
private deployedHosts = new plugins.lik.Objectmap<NginxHost>();
|
||||
private hostCandidates = new plugins.lik.Objectmap<NginxHost>();
|
||||
|
||||
public nginxProcess: NginxProcess = new NginxProcess(this);
|
||||
constructor(optionsArg: { logger?: plugins.smartlog.Smartlog }) {
|
||||
optionsArg.logger
|
||||
@ -26,9 +30,9 @@ export class SmartNginx {
|
||||
* add a host
|
||||
* @param nginxHostArg
|
||||
*/
|
||||
public addHost(optionsArg: IHostConfig): NginxHost {
|
||||
public addHostCandidate(optionsArg: IHostConfig): NginxHost {
|
||||
const nginxHost = new NginxHost(this, optionsArg);
|
||||
this.hosts.add(nginxHost);
|
||||
this.hostCandidates.add(nginxHost);
|
||||
return nginxHost;
|
||||
}
|
||||
|
||||
@ -36,47 +40,85 @@ export class SmartNginx {
|
||||
* Gets a NginxHost by hostname
|
||||
* @param hostNameArg
|
||||
*/
|
||||
public getNginxHostByHostName(hostNameArg: string): NginxHost {
|
||||
return this.hosts.find(nginxHost => {
|
||||
public getDeployedNginxHostByHostName(hostNameArg: string): NginxHost {
|
||||
return this.deployedHosts.find(nginxHost => {
|
||||
return nginxHost.hostName === hostNameArg;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* listHosts
|
||||
*/
|
||||
public listHosts(): NginxHost[] {
|
||||
return this.hosts.getArray();
|
||||
public async listDeployedHosts(): Promise<NginxHost[]> {
|
||||
return this.deployedHosts.getArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a Host
|
||||
* @param nginxHostArg
|
||||
*/
|
||||
public removeHost(nginxHostArg: NginxHost) {
|
||||
this.hosts.remove(nginxHostArg);
|
||||
public async removeDeployedHost(nginxHostArg: NginxHost) {
|
||||
if (this.hostCandidates.isEmpty()) {
|
||||
this.deployedHosts.forEach(hostArg => {
|
||||
this.hostCandidates.add(hostArg);
|
||||
});
|
||||
}
|
||||
this.hostCandidates.remove(nginxHostArg);
|
||||
this.deploy();
|
||||
}
|
||||
|
||||
/**
|
||||
* clean all hosts
|
||||
* check wether there has been a diverging host configuration
|
||||
* this function will only redeploy the nginx configuration in case there has been a change
|
||||
*/
|
||||
public wipeHosts() {
|
||||
this.hosts.wipe();
|
||||
private async areHostsDiverged(): Promise<boolean> {
|
||||
let hostCounter = 0;
|
||||
let unfoundHosts = 0;
|
||||
await this.hostCandidates.forEach(async hostCandidateArg => {
|
||||
let foundHost = false;
|
||||
await this.deployedHosts.forEach(async deployedHostArg => {
|
||||
if (
|
||||
hostCandidateArg.hostName === deployedHostArg.hostName &&
|
||||
hostCandidateArg.destination === deployedHostArg.destination
|
||||
) {
|
||||
hostCounter++;
|
||||
foundHost = true;
|
||||
}
|
||||
});
|
||||
if (!foundHost) {
|
||||
unfoundHosts++;
|
||||
}
|
||||
});
|
||||
return (
|
||||
this.deployedHosts.getArray().length !== this.hostCandidates.getArray().length ||
|
||||
hostCounter !== this.deployedHosts.getArray().length ||
|
||||
unfoundHosts !== 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* deploy the current stack and restart nginx
|
||||
*/
|
||||
public async deploy() {
|
||||
// write base config
|
||||
plugins.smartfile.fs.ensureDirSync(paths.nginxConfigDirPath);
|
||||
plugins.smartfile.memory.toFsSync(snippets.getBaseConfigString(), paths.nginxConfFile);
|
||||
if (await this.areHostsDiverged()) {
|
||||
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();
|
||||
|
||||
// deploy hosts
|
||||
plugins.smartfile.fs.ensureEmptyDirSync(paths.nginxHostDirPath);
|
||||
for (const host of this.hosts.getArray()) {
|
||||
await host.deploy();
|
||||
this.logger.log('info', `Host ${host.hostName} deployed!`);
|
||||
// write base config
|
||||
plugins.smartfile.fs.ensureDirSync(paths.nginxConfigDirPath);
|
||||
plugins.smartfile.memory.toFsSync(snippets.getBaseConfigString(), paths.nginxConfFile);
|
||||
|
||||
// deploy hosts
|
||||
plugins.smartfile.fs.ensureEmptyDirSync(paths.nginxHostDirPath);
|
||||
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`);
|
||||
this.hostCandidates.wipe();
|
||||
}
|
||||
this.nginxProcess.reloadConfig();
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ export let getBaseConfigString = () => {
|
||||
let baseConfig = plugins.smartstring.indent.normalize(`
|
||||
user www-data;
|
||||
worker_processes auto;
|
||||
pid /run/nginx.pid;
|
||||
pid /run/nginx/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 768;
|
||||
@ -74,10 +74,14 @@ export let getBaseConfigString = () => {
|
||||
export let getHostConfigString = (hostNameArg: string, destinationIpArg: string) => {
|
||||
let hostConfig = plugins.smartstring.indent.normalize(`
|
||||
upstream ${hostNameArg} {
|
||||
keepalive 100;
|
||||
server ${destinationIpArg};
|
||||
}
|
||||
|
||||
server {
|
||||
# The keepalive parameter sets the maximum number of idle keepalive connections
|
||||
# to upstream servers that are preserved in the cache of each worker process. When
|
||||
# this number is exceeded, the least recently used connections are closed.
|
||||
listen *:80 ;
|
||||
server_name ${hostNameArg};
|
||||
rewrite ^ https://${hostNameArg}$request_uri? permanent;
|
||||
@ -90,11 +94,12 @@ export let getHostConfigString = (hostNameArg: string, destinationIpArg: string)
|
||||
ssl_certificate_key ${paths.nginxHostDirPath}/${hostNameArg}.private.pem;
|
||||
|
||||
location / {
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass http://${hostNameArg};
|
||||
include /etc/nginx/proxy_params;
|
||||
}
|
||||
location ~ /\.git {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
Reference in New Issue
Block a user