Compare commits

...

23 Commits

Author SHA1 Message Date
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
70dace595b 2.0.0 2018-08-10 23:10:48 +02:00
9b043d0e0d BREAKING CHANGE(scope): change scope to @pushrocks 2018-08-10 23:10:48 +02:00
381227406b 1.0.6 2016-08-03 14:10:09 +02:00
08d1c292c3 update dependencies 2016-08-03 14:10:03 +02:00
64b0a2deb7 1.0.5 2016-08-03 12:05:18 +02:00
9b661c0ee5 update types versions 2016-08-03 12:05:03 +02:00
8ca91a48e8 1.0.4 2016-08-02 23:58:47 +02:00
39a5683b9e improve snippets 2016-08-02 23:58:00 +02:00
7967334e7d 1.0.3 2016-08-02 23:50:48 +02:00
5a875d1e22 Merge branch 'master' of gitlab.com:pushrocks/smartnginx 2016-08-02 23:48:30 +02:00
4c68d27b6d 1.0.2 2016-08-02 23:47:33 +02:00
1cca4f95bc fix interface name 2016-08-02 23:47:27 +02:00
a533fa5de1 Add license 2016-07-25 01:53:33 +00:00
22 changed files with 1434 additions and 356 deletions

View File

@ -1,4 +1,4 @@
image: hosttoday/ht-docker-node:npmts image: hosttoday/ht-docker-node:npmci
stages: stages:
- test - test
@ -10,17 +10,19 @@ before_script:
testSTABLE: testSTABLE:
stage: test stage: test
script: script:
- npmci test stable - npmci npm install
- 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 publish - npmci npm publish
only: only:
- tags - tags
tags: tags:

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Lossless GmbH
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,27 +1,30 @@
# smartnginx # smartnginx
control nginx from node, TypeScript ready control nginx from node, TypeScript ready
## Status ## Status
[![build status](https://gitlab.com/pushrocks/smartnginx/badges/master/build.svg)](https://gitlab.com/pushrocks/smartnginx/commits/master) [![build status](https://gitlab.com/pushrocks/smartnginx/badges/master/build.svg)](https://gitlab.com/pushrocks/smartnginx/commits/master)
## Features ## Features
* easy reverse configuration - easy reverse configuration
* automatic letsencrypt DNS01 challenge based ssl cert generation - automatic letsencrypt DNS01 challenge based ssl cert generation
* automatic nginx process handling zero-downtime config reloading - automatic nginx process handling zero-downtime config reloading
* works in Docker environements - works in Docker environements
## Usage ## Usage
We recommend the use of TypeScript! :) We recommend the use of TypeScript! :)
```typescript ```typescript
import * as smartnginx from "smartnginx"; import * as smartnginx from 'smartnginx';
myNginxConfig = new smartnginx.NginxConfig(); const smartnginxInstance = new smartnginx.SmartNginx();
myNginxZone = new smartnginx.NginxZone({ myNginxHost = new smartnginx.NginxHost({
zoneName:"some.example.com", hostName: 'some.example.com',
type:"reverseProxy", type: 'reverseProxy',
destination:"192.192.192.192" // some destination IP destination: '192.192.192.192' // some destination IP
}); });
myNginxConfig.addZone(myNginxZone); // adds the zone to the config myNginxConfig.addZone(myNginxZone); // adds the zone to the config
myNginxConfig.deploy(); // deploys the referenced NginxConfig and gracefully reloads it myNginxConfig.deploy(); // deploys the referenced NginxConfig and gracefully reloads it
``` ```

View File

@ -3,7 +3,7 @@ import * as plugins from "./smartnginx.plugins";
/** /**
* the host config data that NginxHost needs to create a valid instance * the host config data that NginxHost needs to create a valid instance
*/ */
export interface hostConfigData { export interface IHostConfigData {
hostName: string; hostName: string;
type: hostTypes; type: hostTypes;
destination: string; destination: string;
@ -20,6 +20,6 @@ export declare class NginxHost {
type: hostTypes; type: hostTypes;
destination: string; destination: string;
configString: string; configString: string;
constructor(optionsArg: hostConfigData); constructor(optionsArg: IHostConfigData);
deploy(certInstanceArg: plugins.cert.Cert): plugins.q.Promise<{}>; deploy(certInstanceArg: plugins.cert.Cert): plugins.q.Promise<{}>;
} }

View File

@ -32,4 +32,4 @@ class NginxHost {
} }
exports.NginxHost = NginxHost; exports.NginxHost = NginxHost;
; ;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZ2lueC5jbGFzc2VzLm5naW54aG9zdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0bmdpbnguY2xhc3Nlcy5uZ2lueGhvc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE1BQVksT0FBTyxXQUFNLHNCQUFzQixDQUFDLENBQUE7QUFDaEQsTUFBWSxLQUFLLFdBQU0sb0JBQW9CLENBQUMsQ0FBQTtBQUM1QyxNQUFZLFFBQVEsV0FBTSx1QkFLMUIsQ0FBQyxDQUxnRDtBQVdqRCxXQUFZLFNBQVM7SUFDakIseURBQVksQ0FBQTtJQUNaLDZDQUFNLENBQUE7QUFDVixDQUFDLEVBSFcsaUJBQVMsS0FBVCxpQkFBUyxRQUdwQjtBQUhELElBQVksU0FBUyxHQUFULGlCQUdYLENBQUE7QUFFRDs7R0FFRztBQUNIO0lBS0ksWUFBWSxVQUF5QjtRQUNqQyxJQUFJLENBQUMsUUFBUSxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUM7UUFDcEMsSUFBSSxDQUFDLElBQUksR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDO1FBQzVCLElBQUksQ0FBQyxXQUFXLEdBQUcsVUFBVSxDQUFDLFdBQVcsQ0FBQztRQUMxQyxJQUFJLENBQUMsWUFBWSxHQUFHLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNsRyxDQUFDOztJQUNELE1BQU0sQ0FBQyxlQUFrQztRQUNyQyxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzdCLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxDQUFDO1FBQ25GLGNBQWM7UUFDZCxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQztRQUMvRCxXQUFXO1FBQ1gsZUFBZSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO2FBQ3ZDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDeEIsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQzs7QUFDTCxDQUFDO0FBckJZLGlCQUFTLFlBcUJyQixDQUFBO0FBQUEsQ0FBQyJ9 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZ2lueC5jbGFzc2VzLm5naW54aG9zdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0bmdpbnguY2xhc3Nlcy5uZ2lueGhvc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE1BQVksT0FBTyxXQUFNLHNCQUFzQixDQUFDLENBQUE7QUFDaEQsTUFBWSxLQUFLLFdBQU0sb0JBQW9CLENBQUMsQ0FBQTtBQUM1QyxNQUFZLFFBQVEsV0FBTSx1QkFLMUIsQ0FBQyxDQUxnRDtBQVdqRCxXQUFZLFNBQVM7SUFDakIseURBQVksQ0FBQTtJQUNaLDZDQUFNLENBQUE7QUFDVixDQUFDLEVBSFcsaUJBQVMsS0FBVCxpQkFBUyxRQUdwQjtBQUhELElBQVksU0FBUyxHQUFULGlCQUdYLENBQUE7QUFFRDs7R0FFRztBQUNIO0lBS0ksWUFBWSxVQUEwQjtRQUNsQyxJQUFJLENBQUMsUUFBUSxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUM7UUFDcEMsSUFBSSxDQUFDLElBQUksR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFDO1FBQzVCLElBQUksQ0FBQyxXQUFXLEdBQUcsVUFBVSxDQUFDLFdBQVcsQ0FBQztRQUMxQyxJQUFJLENBQUMsWUFBWSxHQUFHLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNsRyxDQUFDOztJQUNELE1BQU0sQ0FBQyxlQUFrQztRQUNyQyxJQUFJLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzdCLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxDQUFDO1FBQ25GLGNBQWM7UUFDZCxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQztRQUMvRCxXQUFXO1FBQ1gsZUFBZSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO2FBQ3ZDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDeEIsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDeEIsQ0FBQzs7QUFDTCxDQUFDO0FBckJZLGlCQUFTLFlBcUJyQixDQUFBO0FBQUEsQ0FBQyJ9

View File

@ -1,5 +1,6 @@
"use strict"; "use strict";
const plugins = require("./smartnginx.plugins"); const plugins = require("./smartnginx.plugins");
const paths = require("./smartnginx.paths");
exports.getBaseConfigString = () => { exports.getBaseConfigString = () => {
let baseConfig = plugins.smartstring.indent.normalize(` let baseConfig = plugins.smartstring.indent.normalize(`
user www-data; user www-data;
@ -63,7 +64,7 @@ exports.getBaseConfigString = () => {
# Virtual Host Configs # Virtual Host Configs
## ##
include /etc/nginx/conf.d/*.conf; include ${paths.nginxHostFileBase}/*.conf;
include /etc/nginx/sites-enabled/*; include /etc/nginx/sites-enabled/*;
} }
daemon off; daemon off;
@ -85,8 +86,8 @@ exports.getHostConfigString = (hostNameArg, destinationIpArg) => {
server { server {
listen *:443 ssl; listen *:443 ssl;
server_name ${hostNameArg}; server_name ${hostNameArg};
ssl_certificate /LE_CERTS/${hostNameArg}/fullchain.pem; ssl_certificate ${paths.nginxCertBase}/${hostNameArg}/fullchain.pem;
ssl_certificate_key /LE_CERTS/${hostNameArg}/privkey.pem; ssl_certificate_key ${paths.nginxCertBase}/${hostNameArg}/privkey.pem;
location / { location / {
proxy_pass http://${hostNameArg}; proxy_pass http://${hostNameArg};
@ -99,4 +100,4 @@ exports.getHostConfigString = (hostNameArg, destinationIpArg) => {
`); `);
return hostConfig; return hostConfig;
}; };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZ2lueC5zbmlwcGV0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0bmdpbnguc25pcHBldHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE1BQVksT0FBTyxXQUFNLHNCQUFzQixDQUFDLENBQUE7QUFDckMsMkJBQW1CLEdBQUc7SUFDaEMsSUFBSSxVQUFVLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUFrRXJELENBQUMsQ0FBQztJQUNILE1BQU0sQ0FBQyxVQUFVLENBQUM7QUFDbkIsQ0FBQyxDQUFBO0FBR1UsMkJBQW1CLEdBQUcsQ0FBQyxXQUFrQixFQUFDLGdCQUF1QjtJQUMzRSxJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUM7YUFDMUMsV0FBVztZQUNaLGdCQUFnQjs7Ozs7aUJBS1gsV0FBVzs4QkFDRSxXQUFXOzs7OztpQkFLeEIsV0FBVzsrQkFDRyxXQUFXO21DQUNQLFdBQVc7Ozt3QkFHdEIsV0FBVzs7Ozs7OztFQU9qQyxDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsVUFBVSxDQUFDO0FBQ25CLENBQUMsQ0FBQyJ9 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRuZ2lueC5zbmlwcGV0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3NtYXJ0bmdpbnguc25pcHBldHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE1BQVksT0FBTyxXQUFNLHNCQUFzQixDQUFDLENBQUE7QUFDaEQsTUFBWSxLQUFLLFdBQU0sb0JBQW9CLENBQUMsQ0FBQTtBQUNqQywyQkFBbUIsR0FBRztJQUNoQyxJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O2FBOEQxQyxLQUFLLENBQUMsaUJBQWlCOzs7O0VBSWxDLENBQUMsQ0FBQztJQUNILE1BQU0sQ0FBQyxVQUFVLENBQUM7QUFDbkIsQ0FBQyxDQUFBO0FBR1UsMkJBQW1CLEdBQUcsQ0FBQyxXQUFrQixFQUFDLGdCQUF1QjtJQUMzRSxJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUM7YUFDMUMsV0FBVztZQUNaLGdCQUFnQjs7Ozs7aUJBS1gsV0FBVzs4QkFDRSxXQUFXOzs7OztpQkFLeEIsV0FBVztxQkFDUCxLQUFLLENBQUMsYUFBYSxJQUFJLFdBQVc7eUJBQzlCLEtBQUssQ0FBQyxhQUFhLElBQUksV0FBVzs7O3dCQUduQyxXQUFXOzs7Ozs7O0VBT2pDLENBQUMsQ0FBQztJQUNILE1BQU0sQ0FBQyxVQUFVLENBQUM7QUFDbkIsQ0FBQyxDQUFDIn0=

8
npmextra.json Normal file
View File

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

1073
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,14 @@
{ {
"name": "smartnginx", "name": "@pushrocks/smartnginx",
"version": "1.0.1", "version": "2.0.5",
"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",
"scripts": { "scripts": {
"test": "(npmts)", "test": "tstest test/",
"cleanTest": "(rm -r nginxconfig)" "cleanTest": "(rm -r nginxconfig) && npm run test",
"build": "(tsbuild)"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -22,19 +24,17 @@
}, },
"homepage": "https://gitlab.com/pushrocks/smartnginx#README", "homepage": "https://gitlab.com/pushrocks/smartnginx#README",
"dependencies": { "dependencies": {
"@types/q": "^0.0.27", "@pushrocks/smartfile": "^6.0.6",
"@types/shelljs": "^0.3.27", "@pushrocks/smartlog": "^2.0.1",
"beautylog": "^5.0.18", "@pushrocks/smartpromise": "^2.0.5",
"cert": "1.0.6", "@pushrocks/smartshell": "^2.0.6",
"q": "^1.4.1", "@pushrocks/smartstring": "^3.0.0"
"shelljs": "^0.7.1",
"smartfile": "^4.0.12",
"smartstring": "^2.0.15"
}, },
"devDependencies": { "devDependencies": {
"npmts-g": "^5.2.6", "@gitzone/tsbuild": "^2.0.22",
"qenv": "^1.0.8", "@gitzone/tsrun": "^1.1.12",
"should": "^10.0.0", "@gitzone/tstest": "^1.0.13",
"typings-test": "^1.0.1" "@pushrocks/tapbundle": "^3.0.5",
"qenv": "^1.1.7"
} }
} }

View File

@ -1,3 +1 @@
vars: vars:
- CF_EMAIL
- CF_KEY

2
test/test.d.ts vendored
View File

@ -1,2 +0,0 @@
import "typings-test";
import "should";

View File

@ -1,61 +0,0 @@
"use strict";
require("typings-test");
const path = require("path");
require("should");
const qenv_1 = require("qenv");
const smartnginx = require("../dist/index");
// setup environment
let testQenv = new qenv_1.Qenv(process.cwd(), path.join(process.cwd(), ".nogit"));
describe("smartnginx", function () {
let testNginxConfig;
let testNginxZone01;
let testNginxZone02;
describe("NginxZone", function () {
it(`"new NginxZone()" should produce an instance of NginxConfig`, function () {
testNginxZone01 = new smartnginx.NginxHost({
hostName: "test100.bleu.de",
type: smartnginx.hostTypes.reverseProxy,
destination: "192.192.192.191"
});
testNginxZone02 = new smartnginx.NginxHost({
hostName: "test102.bleu.de",
type: smartnginx.hostTypes.reverseProxy,
destination: "192.192.192.192"
});
testNginxZone01.should.be.instanceof(smartnginx.NginxHost);
console.log(testNginxZone01.configString);
});
});
describe("NginxConfig", function () {
this.timeout(10000);
it(`"new NginxConfig()" should produce an instance of NginxConfig`, function () {
testNginxConfig = new smartnginx.NginxConfig({
cfEmail: process.env.CF_EMAIL,
cfKey: process.env.CF_KEY,
testMode: true
});
testNginxConfig.should.be.instanceof(smartnginx.NginxConfig);
});
describe(".addZone()", function () {
it("should add a zone to NginxConfig Object", function () {
testNginxConfig.addHost(testNginxZone01);
testNginxConfig.addHost(testNginxZone02);
});
});
describe(".deploy()", function () {
this.timeout(600000);
it("should deploy a config from an instance", function (done) {
testNginxConfig.deploy()
.then(() => {
done();
});
});
});
describe(".stop", function () {
it("should end the process", function () {
testNginxConfig.nginxProcess.stop();
});
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLFFBQU8sY0FBYyxDQUFDLENBQUE7QUFDdEIsTUFBTyxJQUFJLFdBQVcsTUFBTSxDQUFDLENBQUM7QUFDOUIsUUFBTyxRQUFRLENBQUMsQ0FBQTtBQUNoQix1QkFBbUIsTUFBTSxDQUFDLENBQUE7QUFDMUIsTUFBWSxVQUFVLFdBQU0sZUFBZSxDQUFDLENBQUE7QUFFNUMsb0JBQW9CO0FBQ3BCLElBQUksUUFBUSxHQUFHLElBQUksV0FBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsRUFBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO0FBQ3pFLFFBQVEsQ0FBQyxZQUFZLEVBQUM7SUFDbEIsSUFBSSxlQUFzQyxDQUFDO0lBQzNDLElBQUksZUFBb0MsQ0FBQztJQUN6QyxJQUFJLGVBQW9DLENBQUM7SUFDekMsUUFBUSxDQUFDLFdBQVcsRUFBQztRQUNqQixFQUFFLENBQUMsNkRBQTZELEVBQUM7WUFDN0QsZUFBZSxHQUFHLElBQUksVUFBVSxDQUFDLFNBQVMsQ0FBQztnQkFDdkMsUUFBUSxFQUFDLGlCQUFpQjtnQkFDMUIsSUFBSSxFQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsWUFBWTtnQkFDdEMsV0FBVyxFQUFDLGlCQUFpQjthQUNoQyxDQUFDLENBQUM7WUFDSCxlQUFlLEdBQUcsSUFBSSxVQUFVLENBQUMsU0FBUyxDQUFDO2dCQUN2QyxRQUFRLEVBQUMsaUJBQWlCO2dCQUMxQixJQUFJLEVBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxZQUFZO2dCQUN0QyxXQUFXLEVBQUMsaUJBQWlCO2FBQ2hDLENBQUMsQ0FBQztZQUNILGVBQWUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDM0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDOUMsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDLENBQUMsQ0FBQztJQUNILFFBQVEsQ0FBQyxhQUFhLEVBQUM7UUFDbkIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwQixFQUFFLENBQUMsK0RBQStELEVBQUM7WUFDL0QsZUFBZSxHQUFHLElBQUksVUFBVSxDQUFDLFdBQVcsQ0FBQztnQkFDekMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUTtnQkFDN0IsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTTtnQkFDekIsUUFBUSxFQUFDLElBQUk7YUFDaEIsQ0FBQyxDQUFDO1lBQ0gsZUFBZSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNqRSxDQUFDLENBQUMsQ0FBQztRQUNILFFBQVEsQ0FBQyxZQUFZLEVBQUM7WUFDbEIsRUFBRSxDQUFDLHlDQUF5QyxFQUFDO2dCQUN6QyxlQUFlLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUN6QyxlQUFlLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBQzdDLENBQUMsQ0FBQyxDQUFBO1FBQ04sQ0FBQyxDQUFDLENBQUM7UUFDSCxRQUFRLENBQUMsV0FBVyxFQUFDO1lBQ2pCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDckIsRUFBRSxDQUFDLHlDQUF5QyxFQUFDLFVBQVMsSUFBSTtnQkFDdEQsZUFBZSxDQUFDLE1BQU0sRUFBRTtxQkFDbkIsSUFBSSxDQUFDO29CQUNGLElBQUksRUFBRSxDQUFDO2dCQUNYLENBQUMsQ0FBQyxDQUFDO1lBQ1gsQ0FBQyxDQUFDLENBQUE7UUFDTixDQUFDLENBQUMsQ0FBQztRQUNILFFBQVEsQ0FBQyxPQUFPLEVBQUM7WUFDYixFQUFFLENBQUMsd0JBQXdCLEVBQUM7Z0JBQ3hCLGVBQWUsQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDeEMsQ0FBQyxDQUFDLENBQUE7UUFDTixDQUFDLENBQUMsQ0FBQTtJQUNOLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyxDQUFDLENBQUMifQ==

View File

@ -1,60 +1,45 @@
import "typings-test"; import { tap, expect } from '@pushrocks/tapbundle';
import path = require("path"); import path = require('path');
import "should";
import {Qenv} from "qenv";
import * as smartnginx from "../dist/index";
// setup environment import { Qenv } from 'qenv';
let testQenv = new Qenv(process.cwd(),path.join(process.cwd(),".nogit")); let testQenv = new Qenv(process.cwd(), path.join(process.cwd(), '.nogit'));
describe("smartnginx",function(){
let testNginxConfig:smartnginx.NginxConfig;
let testNginxZone01:smartnginx.NginxHost; import * as smartnginx from '../ts';
let testNginxZone02:smartnginx.NginxHost;
describe("NginxZone",function(){ let testSmartNginx: smartnginx.SmartNginx;
it(`"new NginxZone()" should produce an instance of NginxConfig`,function(){ let testNginxZone01: smartnginx.NginxHost;
testNginxZone01 = new smartnginx.NginxHost({ let testNginxZone02: smartnginx.NginxHost;
hostName:"test100.bleu.de",
type:smartnginx.hostTypes.reverseProxy, tap.test('should create a valid instance of SmartNginx', async () => {
destination:"192.192.192.191" testSmartNginx = new smartnginx.SmartNginx();
}); expect(testSmartNginx).to.be.instanceof(smartnginx.SmartNginx);
testNginxZone02 = new smartnginx.NginxHost({
hostName:"test102.bleu.de",
type:smartnginx.hostTypes.reverseProxy,
destination:"192.192.192.192"
});
testNginxZone01.should.be.instanceof(smartnginx.NginxHost);
console.log(testNginxZone01.configString);
});
});
describe("NginxConfig",function(){
this.timeout(10000);
it(`"new NginxConfig()" should produce an instance of NginxConfig`,function(){
testNginxConfig = new smartnginx.NginxConfig({
cfEmail: process.env.CF_EMAIL,
cfKey: process.env.CF_KEY,
testMode:true
});
testNginxConfig.should.be.instanceof(smartnginx.NginxConfig);
});
describe(".addZone()",function(){
it("should add a zone to NginxConfig Object",function(){
testNginxConfig.addHost(testNginxZone01);
testNginxConfig.addHost(testNginxZone02);
})
});
describe(".deploy()",function(){
this.timeout(600000);
it("should deploy a config from an instance",function(done){
testNginxConfig.deploy()
.then(() => {
done();
});
})
});
describe(".stop",function(){
it("should end the process",function(){
testNginxConfig.nginxProcess.stop();
})
})
});
}); });
tap.test(`should produce an instance of NginxConfig`, async () => {
testNginxZone01 = new smartnginx.NginxHost(testSmartNginx, {
hostName: 'test100.bleu.de',
destination: '192.192.192.191'
});
testNginxZone02 = new smartnginx.NginxHost(testSmartNginx, {
hostName: 'test102.bleu.de',
destination: '192.192.192.192'
});
expect(testNginxZone01).to.be.instanceof(smartnginx.NginxHost);
console.log(testNginxZone01.configString);
});
tap.test('.addZone() should add a zone to NginxConfig Object', async () => {
testSmartNginx.addHost('test200.bleu.de', '192.192.192.191');
testSmartNginx.addHost('test201.blue.de', '192.192.192.191');
});
tap.test('.deploy() should deploy a config from an instance', async () => {
await testSmartNginx.deploy();
});
tap.test('.stop() should end the process', async () => {
testSmartNginx.nginxProcess.stop();
});
tap.start();

View File

@ -1,6 +1,6 @@
import * as plugins from "./smartnginx.plugins"; import * as plugins from './smartnginx.plugins';
// classes // classes
export * from "./smartnginx.classes.nginxconfig"; export * from './smartnginx.classes.smartnginx';
export * from "./smartnginx.classes.nginxprocess"; export * from './smartnginx.classes.nginxprocess';
export * from "./smartnginx.classes.nginxhost"; export * from './smartnginx.classes.nginxhost';

View File

@ -0,0 +1,15 @@
import * as plugins from './smartnginx.plugins';
export class CertHandler {
private _readyDeferred = plugins.smartpromise.defer();
certHandlerReady = this._readyDeferred.promise;
constructor() {} // nothing to do here for now
/**
* ensure a cert is at the right location
* @param hostName
*/
async ensureCertForHost(hostName) {
}
}

View File

@ -1,71 +0,0 @@
import * as plugins from "./smartnginx.plugins";
import * as paths from "./smartnginx.paths";
import * as snippets from "./smartnginx.snippets";
import { NginxHost } from "./smartnginx.classes.nginxhost";
import { NginxProcess } from "./smartnginx.classes.nginxprocess";
let allConfigs: NginxConfig[] = [];
/**
* main class that manages a NginxInstance
*/
export class NginxConfig {
hosts: NginxHost[] = [];
cert: plugins.cert.Cert; // the Cert Instance from which the config gets its certificates
nginxProcess: NginxProcess = new NginxProcess(this);
isDeployed: boolean = false;
constructor(optionsArg: plugins.cert.ICertConstructorOptions) {
this.cert = new plugins.cert.Cert({
cfEmail: optionsArg.cfEmail,
cfKey: optionsArg.cfKey,
sslDir: paths.nginxCertBase,
gitOriginRepo: optionsArg.gitOriginRepo,
testMode: optionsArg.testMode
});
};
// interact with Hosts
addHost(nginxHostArg: NginxHost){
this.hosts.push(nginxHostArg);
}
listHosts(): NginxHost[]{
return this.hosts;
};
removeHost(nginxHostArg: NginxHost) {
}
clean() {
this.hosts = [];
}
// handle deployment of hosts
deploy() {
let done = plugins.q.defer();
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
plugins.smartfile.memory.toFsSync(
snippets.getBaseConfigString(),
paths.nginxConfFile
);
// deploy hosts
let promiseArray = [];
for (let host of this.hosts) {
let hostDeployedPromise = host.deploy(this.cert);
hostDeployedPromise.then(() => {
plugins.beautylog.info(`Host ${host.hostName} deployed!`);
this.nginxProcess.reloadConfig();
});
promiseArray.push(hostDeployedPromise);
};
plugins.q.all(promiseArray)
.then(() => {
done.resolve();
});
return done.promise;
};
};

View File

@ -1,43 +1,47 @@
import * as plugins from "./smartnginx.plugins"; import * as plugins from './smartnginx.plugins';
import * as paths from "./smartnginx.paths"; import * as paths from './smartnginx.paths';
import * as snippets from "./smartnginx.snippets" import * as snippets from './smartnginx.snippets';
import { SmartNginx } from './smartnginx.classes.smartnginx';
/** /**
* the host config data that NginxHost needs to create a valid instance * the host config data that NginxHost needs to create a valid instance
*/ */
export interface hostConfigData { export interface IHostConfigData {
hostName: string, hostName: string;
type: hostTypes, destination: string;
destination: string
} }
export enum hostTypes { export enum hostTypes {
reverseProxy, reverseProxy
static
} }
/** /**
* manages a single nginx host * manages a single nginx host
*/ */
export class NginxHost { export class NginxHost {
hostName: string; // the host name e.g. domain name /**
type: hostTypes; * smartnginxInstance this NginHost belongs to
destination: string; */
configString: string; // the actual host config file as string smartnginxInstance: SmartNginx
constructor(optionsArg:hostConfigData) {
this.hostName = optionsArg.hostName; hostName: string; // the host name e.g. domain name
this.type = optionsArg.type; destination: string;
this.destination = optionsArg.destination; configString: string; // the actual host config file as string
this.configString = snippets.getHostConfigString(optionsArg.hostName, optionsArg.destination); constructor(smartnginxInstanceArg: SmartNginx, optionsArg: IHostConfigData) {
}; this.smartnginxInstance = smartnginxInstanceArg;
deploy(certInstanceArg: plugins.cert.Cert) { this.hostName = optionsArg.hostName;
let done = plugins.q.defer(); this.destination = optionsArg.destination;
let filePath = plugins.path.join(paths.nginxHostFileBase, this.hostName + ".conf"); this.configString = snippets.getHostConfigString(optionsArg.hostName, optionsArg.destination);
// writeConfig }
plugins.smartfile.memory.toFsSync(this.configString, filePath);
// get cert /**
certInstanceArg.getDomainCert(this.hostName) *
.then(done.resolve); * @param certInstanceArg
return done.promise; */
}; async deploy() {
}; let filePath = plugins.path.join(paths.nginxHostFileBase, this.hostName + '.conf');
// writeConfig
plugins.smartfile.memory.toFsSync(this.configString, filePath);
}
}

View File

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

View File

@ -0,0 +1,86 @@
import * as plugins from './smartnginx.plugins';
import * as paths from './smartnginx.paths';
import * as snippets from './smartnginx.snippets';
import { NginxHost } from './smartnginx.classes.nginxhost';
import { NginxProcess } from './smartnginx.classes.nginxprocess';
import { CertHandler } from './smartnginx.classes.certhandler';
let allConfigs: SmartNginx[] = [];
/**
* main class that manages a NginxInstance
*/
export class SmartNginx {
certHandler = new CertHandler();
hosts: NginxHost[] = [];
nginxProcess: NginxProcess = new NginxProcess(this);
isDeployed: boolean = false;
constructor() {
};
// ===================
// interact with Hosts
// ===================
/**
* add a host
* @param nginxHostArg
*/
addHost(hostNameArg: string, destinationIp: string): NginxHost {
const nginxHost = new NginxHost(this, {
hostName: hostNameArg,
destination: destinationIp
})
this.hosts.push(nginxHost);
return nginxHost;
}
getNginxHostByHostName(hostNameArg: string): NginxHost {
return this.hosts.find(nginxHost => {
return nginxHost.hostName === hostNameArg;
})
}
/**
* listHosts
*/
listHosts(): NginxHost[] {
return this.hosts;
}
/**
* remove a Host
* @param nginxHostArg
*/
removeHost(nginxHostArg: NginxHost) {}
/**
* clean all hosts
*/
clean() {
this.hosts = [];
}
/**
* deploy the current stack and restart nginx
*/
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
plugins.smartfile.memory.toFsSync(snippets.getBaseConfigString(), paths.nginxConfFile);
// deploy hosts
let promiseArray = [];
for (let host of this.hosts) {
await host.deploy();
plugins.smartlog.defaultLogger.info(`Host ${host.hostName} deployed!`);
this.nginxProcess.reloadConfig();
};
}
}

View File

@ -1,10 +1,11 @@
import * as plugins from "./smartnginx.plugins" import * as plugins from './smartnginx.plugins';
// directories // directories
export let packageBase = plugins.path.join(__dirname,"../"); export let packageBase = plugins.path.join(__dirname, '../');
export let nginxConfigBase = plugins.path.join(packageBase,"nginxconfig"); export let nginxConfigBase = plugins.path.join(packageBase, 'nginxconfig');
export let nginxHostFileBase = plugins.path.join(nginxConfigBase,"hosts");
export let nginxCertBase = plugins.path.join(nginxConfigBase,"cert"); 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 let nginxConfFile = plugins.path.join(nginxConfigBase, 'nginx.conf');

View File

@ -1,9 +1,17 @@
import "typings-global"; import * as smartlog from '@pushrocks/smartlog';
export import beautylog = require("beautylog"); import * as childProcess from 'child_process';
export import cert = require("cert"); import * as path from 'path';
export import childProcess = require("child_process"); import * as smartpromise from '@pushrocks/smartpromise';
export import path = require("path"); import * as smartshell from '@pushrocks/smartshell';
export import q = require("q"); import * as smartfile from '@pushrocks/smartfile';
export import shelljs = require("shelljs"); import * as smartstring from '@pushrocks/smartstring';
export import smartfile = require("smartfile");
export import smartstring = require("smartstring"); export {
smartlog,
childProcess,
path,
smartpromise,
smartshell,
smartfile,
smartstring
}

View File

@ -1,6 +1,7 @@
import * as plugins from "./smartnginx.plugins"; import * as plugins from './smartnginx.plugins';
import * as paths from './smartnginx.paths';
export let getBaseConfigString = () => { export let getBaseConfigString = () => {
let baseConfig = plugins.smartstring.indent.normalize(` let baseConfig = plugins.smartstring.indent.normalize(`
user www-data; user www-data;
worker_processes auto; worker_processes auto;
pid /run/nginx.pid; pid /run/nginx.pid;
@ -62,17 +63,16 @@ export let getBaseConfigString = () => {
# Virtual Host Configs # Virtual Host Configs
## ##
include /etc/nginx/conf.d/*.conf; include ${paths.nginxHostFileBase}/*.conf;
include /etc/nginx/sites-enabled/*; include /etc/nginx/sites-enabled/*;
} }
daemon off; daemon off;
`); `);
return baseConfig; return baseConfig;
} };
export let getHostConfigString = (hostNameArg: string, destinationIpArg: string) => {
export let getHostConfigString = (hostNameArg:string,destinationIpArg:string) => { let hostConfig = plugins.smartstring.indent.normalize(`
let hostConfig = plugins.smartstring.indent.normalize(`
upstream ${hostNameArg} { upstream ${hostNameArg} {
server ${destinationIpArg}; server ${destinationIpArg};
} }
@ -86,8 +86,8 @@ export let getHostConfigString = (hostNameArg:string,destinationIpArg:string) =>
server { server {
listen *:443 ssl; listen *:443 ssl;
server_name ${hostNameArg}; server_name ${hostNameArg};
ssl_certificate /LE_CERTS/${hostNameArg}/fullchain.pem; ssl_certificate ${paths.nginxCertBase}/${hostNameArg}/fullchain.pem;
ssl_certificate_key /LE_CERTS/${hostNameArg}/privkey.pem; ssl_certificate_key ${paths.nginxCertBase}/${hostNameArg}/privkey.pem;
location / { location / {
proxy_pass http://${hostNameArg}; proxy_pass http://${hostNameArg};
@ -98,6 +98,5 @@ export let getHostConfigString = (hostNameArg:string,destinationIpArg:string) =>
} }
} }
`); `);
return hostConfig; return hostConfig;
}; };