Compare commits

...

26 Commits

Author SHA1 Message Date
67dd650dce 2.0.13 2019-01-17 02:50:32 +01:00
92eaf5f19a fix(core): update 2019-01-17 02:50:32 +01:00
fcf9a61b1d 2.0.12 2019-01-09 14:13:32 +01:00
fbd258a876 fix(core): update 2019-01-09 14:13:32 +01:00
c65b8fc1af 2.0.11 2019-01-09 14:10:57 +01:00
b7b588d713 fix(core): update 2019-01-09 14:10:57 +01:00
00d672c135 2.0.10 2019-01-09 12:18:56 +01:00
6a1e778b49 fix(core): update 2019-01-09 12:18:56 +01:00
4cfb26f62f 2.0.9 2019-01-09 12:18:07 +01:00
7ba3ad0b21 fix(core): update 2019-01-09 12:18:06 +01:00
cd93ec2560 2.0.8 2019-01-09 12:15:29 +01:00
ede884930e fix(core): update 2019-01-09 12:15:28 +01:00
1049920efd 2.0.7 2019-01-01 22:35:18 +01:00
b7a34403c5 fix(core): update 2019-01-01 22:35:18 +01:00
987e19372a 2.0.6 2019-01-01 22:34:37 +01:00
0b97aaee91 fix(core): update 2019-01-01 22:34:36 +01:00
b87ca1fa03 2.0.5 2018-08-11 15:10:28 +02:00
824f872fa5 fix(tests): update 2018-08-11 15:10:27 +02:00
80248c77d0 2.0.4 2018-08-11 15:09:19 +02:00
f592150646 fix(host handling): update 2018-08-11 15:09:19 +02:00
f24652936a 2.0.3 2018-08-11 00:29:16 +02:00
79af6c4a68 fix(CI): accessLevel 2018-08-11 00:29:16 +02:00
fafc757930 2.0.2 2018-08-11 00:25:20 +02:00
ead5e1a7bd fix(CI): now installing stufall alright 2018-08-11 00:25:20 +02:00
ad57be180a 2.0.1 2018-08-10 23:44:31 +02:00
7cc4ce02c9 fix(core): update 2018-08-10 23:44:31 +02:00
15 changed files with 1011 additions and 448 deletions

View File

@ -1,4 +1,4 @@
image: hosttoday/ht-docker-node:npmts image: hosttoday/ht-docker-node:npmci
stages: stages:
- test - test
@ -10,16 +10,19 @@ before_script:
testSTABLE: testSTABLE:
stage: test stage: test
script: script:
- npmci npm install
- npmci npm test stable - npmci npm test stable
only: only:
- tags - tags
tags: tags:
- docker - docker
- notpriv
release: release:
stage: release stage: release
environment: npmjs-com_registry environment: npmjs-com_registry
script: script:
- npmci npm prepare
- npmci npm publish - npmci npm publish
only: only:
- tags - tags

8
npmextra.json Normal file
View File

@ -0,0 +1,8 @@
{
"npmci": {
"npmAccessLevel": "public"
},
"npmdocker": {
}
}

1170
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
{ {
"name": "@pushrocks/smartnginx", "name": "@pushrocks/smartnginx",
"version": "2.0.0", "version": "2.0.13",
"private": false,
"description": "control nginx from node, TypeScript ready", "description": "control nginx from node, TypeScript ready",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "dist/index.d.ts", "typings": "dist/index.d.ts",
@ -23,18 +24,20 @@
}, },
"homepage": "https://gitlab.com/pushrocks/smartnginx#README", "homepage": "https://gitlab.com/pushrocks/smartnginx#README",
"dependencies": { "dependencies": {
"@pushrocks/smartfile": "^6.0.6", "@pushrocks/lik": "^3.0.4",
"@pushrocks/smartlog": "^2.0.1", "@pushrocks/smartfile": "^6.0.11",
"@pushrocks/smartlog": "^2.0.9",
"@pushrocks/smartpromise": "^2.0.5", "@pushrocks/smartpromise": "^2.0.5",
"@pushrocks/smartshell": "^2.0.6", "@pushrocks/smartshell": "^2.0.13",
"@pushrocks/smartstring": "^3.0.0" "@pushrocks/smartstring": "^3.0.5"
}, },
"devDependencies": { "devDependencies": {
"@gitzone/tsbuild": "^2.0.22", "@gitzone/tsbuild": "^2.1.4",
"@gitzone/tsrun": "^1.1.12", "@gitzone/tsrun": "^1.1.17",
"@gitzone/tstest": "^1.0.13", "@gitzone/tstest": "^1.0.18",
"@pushrocks/tapbundle": "^3.0.5", "@pushrocks/qenv": "^3.0.2",
"qenv": "^1.1.7" "@pushrocks/tapbundle": "^3.0.7",
}, "tslint": "^5.12.0",
"private": true "tslint-config-prettier": "^1.17.0"
}
} }

View File

@ -1,32 +1,34 @@
import { tap, expect } from '@pushrocks/tapbundle'; import { tap, expect } from '@pushrocks/tapbundle';
import path = require('path'); import path = require('path');
import { Qenv } from 'qenv'; import { Qenv } from '@pushrocks/qenv';
let testQenv = new Qenv(process.cwd(), path.join(process.cwd(), '.nogit')); const testQenv = new Qenv('./', './.nogit/');
import * as smartnginx from '../ts/index';
import * as smartnginx from '../ts';
let testSmartNginx: smartnginx.SmartNginx; let testSmartNginx: smartnginx.SmartNginx;
let testNginxZone01: smartnginx.NginxHost; let testNginxZone01: smartnginx.NginxHost;
let testNginxZone02: smartnginx.NginxHost; let testNginxZone02: smartnginx.NginxHost;
tap.test('should create a valid instance of SmartNginx', async () => { tap.test('should create a valid instance of SmartNginx', async () => {
testSmartNginx = new smartnginx.SmartNginx(); testSmartNginx = new smartnginx.SmartNginx({});
expect(testSmartNginx).to.be.instanceof(smartnginx.SmartNginx); expect(testSmartNginx).to.be.instanceof(smartnginx.SmartNginx);
}); });
tap.test(`should produce an instance of NginxConfig`, async () => { tap.test(`should produce an instance of NginxConfig`, async () => {
testNginxZone01 = new smartnginx.NginxHost(testSmartNginx, { testNginxZone01 = new smartnginx.NginxHost(testSmartNginx, {
hostName: 'test100.bleu.de', hostName: 'test100.bleu.de',
destination: '192.192.192.191' destination: '192.192.192.191',
privateKey: 'some private',
publicKey: 'some public'
}); });
testNginxZone02 = new smartnginx.NginxHost(testSmartNginx, { testNginxZone02 = new smartnginx.NginxHost(testSmartNginx, {
hostName: 'test102.bleu.de', hostName: 'test102.bleu.de',
destination: '192.192.192.192' destination: '192.192.192.192',
privateKey: 'some private',
publicKey: 'some public'
}); });
expect(testNginxZone01).to.be.instanceof(smartnginx.NginxHost); expect(testNginxZone01).to.be.instanceof(smartnginx.NginxHost);
console.log(testNginxZone01.configString);
}); });
tap.test('.addZone() should add a zone to NginxConfig Object', async () => { tap.test('.addZone() should add a zone to NginxConfig Object', async () => {

View File

@ -0,0 +1,6 @@
export interface IHostConfig {
hostName: string;
destination: string;
privateKey: string;
publicKey: string;
}

0
ts/interfaces/index.ts Normal file
View File

View File

@ -1,5 +0,0 @@
import * as plugins from './smartnginx.plugins';
export class CertHandler {
}

View File

@ -4,13 +4,7 @@ import * as snippets from './smartnginx.snippets';
import { SmartNginx } from './smartnginx.classes.smartnginx'; import { SmartNginx } from './smartnginx.classes.smartnginx';
/** import { IHostConfig } from './interfaces/hostconfig';
* the host config data that NginxHost needs to create a valid instance
*/
export interface IHostConfigData {
hostName: string;
destination: string;
}
export enum hostTypes { export enum hostTypes {
reverseProxy reverseProxy
@ -19,29 +13,41 @@ export enum hostTypes {
/** /**
* manages a single nginx host * manages a single nginx host
*/ */
export class NginxHost { export class NginxHost implements IHostConfig {
/** /**
* smartnginxInstance this NginHost belongs to * smartnginxInstance this NginHost belongs to
*/ */
smartnginxInstance: SmartNginx smartnginxInstance: SmartNginx;
hostName: string; // the host name e.g. domain name hostName: string; // the host name e.g. domain name
destination: string; destination: string;
configString: string; // the actual host config file as string configString: string; // the actual host config file as string
constructor(smartnginxInstanceArg: SmartNginx, optionsArg: IHostConfigData) { privateKey: string;
publicKey: string;
constructor(smartnginxInstanceArg: SmartNginx, optionsArg: IHostConfig) {
this.smartnginxInstance = smartnginxInstanceArg; this.smartnginxInstance = smartnginxInstanceArg;
this.hostName = optionsArg.hostName; this.hostName = optionsArg.hostName;
this.destination = optionsArg.destination; this.destination = optionsArg.destination;
this.configString = snippets.getHostConfigString(optionsArg.hostName, optionsArg.destination); this.configString = snippets.getHostConfigString(optionsArg.hostName, optionsArg.destination);
this.privateKey = optionsArg.privateKey;
this.publicKey = optionsArg.publicKey;
} }
/** /**
* *
* @param certInstanceArg * @param certInstanceArg
*/ */
async deploy() { public async deploy() {
let filePath = plugins.path.join(paths.nginxHostFileBase, this.hostName + '.conf'); const filePathConfig = plugins.path.join(paths.nginxHostDirPath, `${this.hostName}.conf`);
const filePathPrivate = plugins.path.join(paths.nginxHostDirPath, `${this.hostName}.private.pem`);
const filePathPublic = plugins.path.join(paths.nginxHostDirPath, `${this.hostName}.public.pem`);
// writeConfig // writeConfig
plugins.smartfile.memory.toFsSync(this.configString, filePath); plugins.smartfile.memory.toFsSync(this.configString, filePathConfig);
// write ssl
plugins.smartfile.memory.toFsSync(this.privateKey, filePathPrivate);
plugins.smartfile.memory.toFsSync(this.publicKey, filePathPublic);
} }
} }

View File

@ -5,78 +5,65 @@ import { NginxHost } from './smartnginx.classes.nginxhost';
import { Smartshell } from '@pushrocks/smartshell'; import { Smartshell } from '@pushrocks/smartshell';
import { ChildProcess } from 'child_process';
/** /**
* manages a nginxprocess for an NginxConfig * manages a nginxprocess for an NginxConfig
*/ */
export class NginxProcess { export class NginxProcess {
started: boolean = false; public started: boolean = false;
nginxConfig: SmartNginx; public smartNginxRef: SmartNginx;
nginxChildProcess: plugins.childProcess.ChildProcess; private nginxChildProcess: ChildProcess;
smartshellInstance = new Smartshell({ private smartshellInstance = new Smartshell({
executor: 'bash' executor: 'bash'
}); });
constructor(nginxConfigArg) {
this.nginxConfig = nginxConfigArg; constructor(nginxRefArg: SmartNginx) {
this.smartNginxRef = nginxRefArg;
} }
/** /**
* start nginx * start nginx
*/ */
start() { public async start() {
let done = plugins.smartpromise.defer(); if (!this.nginxChildProcess) {
if (typeof this.nginxChildProcess == 'undefined') { this.nginxChildProcess = (await this.smartshellInstance.execStreaming(
this.nginxChildProcess = plugins.childProcess.exec( `nginx -c ${paths.nginxConfFile}`
`nginx -c ${paths.nginxConfFile}`, )).childProcess;
function(error, stdout, stderr) {
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
if (error !== null) {
console.log(`exec error: ${error}`);
}
}
);
} }
this.started = true; this.started = true;
plugins.smartlog.defaultLogger.info('started Nginx!'); plugins.smartlog.defaultLogger.log('info', 'started Nginx!');
done.resolve();
return done.promise;
} }
/** /**
* reload config * reload config
*/ */
reloadConfig() { public async reloadConfig() {
let done = plugins.smartpromise.defer(); if (!this.started) {
if (this.started == false) {
this.start(); this.start();
} else { } else {
this.smartshellInstance.exec('nginx -s reload'); await this.smartshellInstance.exec('nginx -s reload');
} }
plugins.smartlog.defaultLogger.info('NginxProcess has loaded the new config!'); this.smartNginxRef.logger.log('info', 'NginxProcess has loaded the new config!');
done.resolve();
return done.promise;
} }
/** /**
* stop the nginx instance * stop the nginx instance
*/ */
stop() { public async stop() {
let done = plugins.smartpromise.defer(); if (this.nginxChildProcess) {
if (typeof this.nginxChildProcess != 'undefined') {
this.smartshellInstance.exec('nginx -s quit'); this.smartshellInstance.exec('nginx -s quit');
this.started = false; this.started = false;
plugins.smartlog.defaultLogger.info('stopped Nginx!'); this.smartNginxRef.logger.log('info', 'stopped Nginx!');
} else { } else {
plugins.smartlog.defaultLogger.info('nginx already stopped!'); this.smartNginxRef.logger.log('info', 'nginx already stopped!');
} }
done.resolve();
return done.promise;
} }
/** /**
* checks if nginx is in path * checks if nginx is in path
*/ */
check(): boolean { public check(): boolean {
return; return;
} }
} }

View File

@ -3,20 +3,20 @@ import * as paths from './smartnginx.paths';
import * as snippets from './smartnginx.snippets'; import * as snippets from './smartnginx.snippets';
import { NginxHost } from './smartnginx.classes.nginxhost'; import { NginxHost } from './smartnginx.classes.nginxhost';
import { NginxProcess } from './smartnginx.classes.nginxprocess'; import { NginxProcess } from './smartnginx.classes.nginxprocess';
import { CertHandler } from './smartnginx.classes.certhandler'; import { IHostConfig } from './interfaces/hostconfig';
let allConfigs: SmartNginx[] = [];
/** /**
* main class that manages a NginxInstance * main class that manages a NginxInstance
*/ */
export class SmartNginx { export class SmartNginx {
certHandler = new CertHandler(); public logger: plugins.smartlog.Smartlog;
hosts: NginxHost[] = []; private hosts = new plugins.lik.Objectmap<NginxHost>();
nginxProcess: NginxProcess = new NginxProcess(this); public nginxProcess: NginxProcess = new NginxProcess(this);
isDeployed: boolean = false; constructor(optionsArg: { logger?: plugins.smartlog.Smartlog }) {
constructor() { optionsArg.logger
? (this.logger = optionsArg.logger)
}; : (this.logger = plugins.smartlog.defaultLogger);
}
// =================== // ===================
// interact with Hosts // interact with Hosts
@ -26,49 +26,57 @@ export class SmartNginx {
* add a host * add a host
* @param nginxHostArg * @param nginxHostArg
*/ */
addHost(nginxHostArg: NginxHost) { public addHost(optionsArg: IHostConfig): NginxHost {
this.hosts.push(nginxHostArg); const nginxHost = new NginxHost(this, optionsArg);
this.hosts.add(nginxHost);
return nginxHost;
} }
/**
* Gets a NginxHost by hostname
* @param hostNameArg
*/
public getNginxHostByHostName(hostNameArg: string): NginxHost {
return this.hosts.find(nginxHost => {
return nginxHost.hostName === hostNameArg;
});
}
/** /**
* listHosts * listHosts
*/ */
listHosts(): NginxHost[] { public listHosts(): NginxHost[] {
return this.hosts; return this.hosts.getArray();
} }
/** /**
* remove a Host * remove a Host
* @param nginxHostArg * @param nginxHostArg
*/ */
removeHost(nginxHostArg: NginxHost) {} public removeHost(nginxHostArg: NginxHost) {
this.hosts.remove(nginxHostArg);
}
/** /**
* clean all hosts * clean all hosts
*/ */
clean() { public wipeHosts() {
this.hosts = []; this.hosts.wipe();
} }
/** /**
* deploy the current stack and restart nginx * deploy the current stack and restart nginx
*/ */
async deploy() { public async deploy() {
plugins.smartfile.fs.ensureDirSync(paths.nginxConfigBase);
plugins.smartfile.fs.ensureDirSync(paths.nginxHostFileBase);
plugins.smartfile.fs.ensureDirSync(paths.nginxCertBase);
for (let config of allConfigs) {
config.isDeployed = false;
}
this.isDeployed = true;
// write base config // write base config
plugins.smartfile.fs.ensureDirSync(paths.nginxConfigDirPath);
plugins.smartfile.memory.toFsSync(snippets.getBaseConfigString(), paths.nginxConfFile); plugins.smartfile.memory.toFsSync(snippets.getBaseConfigString(), paths.nginxConfFile);
// deploy hosts // deploy hosts
let promiseArray = []; plugins.smartfile.fs.ensureEmptyDirSync(paths.nginxHostDirPath);
for (let host of this.hosts) { for (const host of this.hosts.getArray()) {
await host.deploy(); await host.deploy();
plugins.smartlog.defaultLogger.info(`Host ${host.hostName} deployed!`); this.logger.log('info', `Host ${host.hostName} deployed!`);
}
this.nginxProcess.reloadConfig(); this.nginxProcess.reloadConfig();
};
} }
} }

View File

@ -1,11 +1,9 @@
import * as plugins from './smartnginx.plugins'; import * as plugins from './smartnginx.plugins';
// directories // directories
export let packageBase = plugins.path.join(__dirname, '../'); export const packageBase = plugins.path.join(__dirname, '../');
export let nginxConfigBase = plugins.path.join(packageBase, 'nginxconfig'); export const nginxConfigDirPath = plugins.path.join(packageBase, 'nginxconfig');
export const nginxHostDirPath = plugins.path.join(nginxConfigDirPath, 'hosts');
export let nginxHostFileBase = plugins.path.join(nginxConfigBase, 'hosts');
export let nginxCertBase = plugins.path.join(nginxConfigBase, 'cert');
// files // files
export let nginxConfFile = plugins.path.join(nginxConfigBase, 'nginx.conf'); export const nginxConfFile = plugins.path.join(nginxConfigDirPath, 'nginx.conf');

View File

@ -1,17 +1,14 @@
import * as smartlog from '@pushrocks/smartlog'; // native
import * as childProcess from 'child_process';
import * as path from 'path'; import * as path from 'path';
export { path };
// @pushrocks scope
import * as lik from '@pushrocks/lik';
import * as smartlog from '@pushrocks/smartlog';
import * as smartpromise from '@pushrocks/smartpromise'; import * as smartpromise from '@pushrocks/smartpromise';
import * as smartshell from '@pushrocks/smartshell'; import * as smartshell from '@pushrocks/smartshell';
import * as smartfile from '@pushrocks/smartfile'; import * as smartfile from '@pushrocks/smartfile';
import * as smartstring from '@pushrocks/smartstring'; import * as smartstring from '@pushrocks/smartstring';
export { export { lik, smartlog, smartpromise, smartshell, smartfile, smartstring };
smartlog,
childProcess,
path,
smartpromise,
smartshell,
smartfile,
smartstring
}

View File

@ -63,7 +63,7 @@ export let getBaseConfigString = () => {
# Virtual Host Configs # Virtual Host Configs
## ##
include ${paths.nginxHostFileBase}/*.conf; include ${paths.nginxHostDirPath}/*.conf;
include /etc/nginx/sites-enabled/*; include /etc/nginx/sites-enabled/*;
} }
daemon off; daemon off;
@ -86,12 +86,15 @@ export let getHostConfigString = (hostNameArg: string, destinationIpArg: string)
server { server {
listen *:443 ssl; listen *:443 ssl;
server_name ${hostNameArg}; server_name ${hostNameArg};
ssl_certificate ${paths.nginxCertBase}/${hostNameArg}/fullchain.pem; ssl_certificate ${paths.nginxHostDirPath}/${hostNameArg}.public.pem;
ssl_certificate_key ${paths.nginxCertBase}/${hostNameArg}/privkey.pem; ssl_certificate_key ${paths.nginxHostDirPath}/${hostNameArg}.private.pem;
location / { location / {
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}; proxy_pass http://${hostNameArg};
include /etc/nginx/proxy_params;
} }
location ~ /\.git { location ~ /\.git {
deny all; deny all;

17
tslint.json Normal file
View File

@ -0,0 +1,17 @@
{
"extends": ["tslint:latest", "tslint-config-prettier"],
"rules": {
"semicolon": [true, "always"],
"no-console": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"member-ordering": {
"options":{
"order": [
"static-method"
]
}
}
},
"defaultSeverity": "warning"
}