Improve authelia-scripts to add suites with Docker-based Authelia server.
parent
38271e3335
commit
a1c9bb6302
|
@ -0,0 +1,3 @@
|
|||
Error: No such container: authelia-test
|
||||
Error: No such container: 2
|
||||
Error: No such container: dev/null
|
|
@ -231,6 +231,25 @@
|
|||
"integrity": "sha512-FhlMa34NHp9K5MY1Uz8yb+ZvuX0pnvn3jScRSNAb75KHGB8d3rEU6hqMs3Z2vjuytcMfRg6c5CHMc3wtYyD2/A==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/chokidar": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/chokidar/-/chokidar-1.7.5.tgz",
|
||||
"integrity": "sha512-PDkSRY7KltW3M60hSBlerxI8SFPXsO3AL/aRVsO4Kh9IHRW74Ih75gUuTd/aE4LSSFqypb10UIX3QzOJwBQMGQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/events": "1.2.0",
|
||||
"@types/node": "10.0.3"
|
||||
}
|
||||
},
|
||||
"@types/commander": {
|
||||
"version": "2.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/commander/-/commander-2.12.2.tgz",
|
||||
"integrity": "sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commander": "2.19.0"
|
||||
}
|
||||
},
|
||||
"@types/connect": {
|
||||
"version": "3.4.32",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz",
|
||||
|
@ -2586,23 +2605,21 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^2.0.6"
|
||||
"delegates": "1.0.0",
|
||||
"readable-stream": "2.3.6"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"balanced-match": "1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
|
@ -2615,20 +2632,17 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -2669,7 +2683,7 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minipass": "^2.2.1"
|
||||
"minipass": "2.2.4"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
|
@ -2684,14 +2698,14 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"aproba": "^1.0.3",
|
||||
"console-control-strings": "^1.0.0",
|
||||
"has-unicode": "^2.0.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"wide-align": "^1.1.0"
|
||||
"aproba": "1.2.0",
|
||||
"console-control-strings": "1.1.0",
|
||||
"has-unicode": "2.0.1",
|
||||
"object-assign": "4.1.1",
|
||||
"signal-exit": "3.0.2",
|
||||
"string-width": "1.0.2",
|
||||
"strip-ansi": "3.0.1",
|
||||
"wide-align": "1.1.2"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
|
@ -2700,12 +2714,12 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
"fs.realpath": "1.0.0",
|
||||
"inflight": "1.0.6",
|
||||
"inherits": "2.0.3",
|
||||
"minimatch": "3.0.4",
|
||||
"once": "1.4.0",
|
||||
"path-is-absolute": "1.0.1"
|
||||
}
|
||||
},
|
||||
"has-unicode": {
|
||||
|
@ -2720,7 +2734,7 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safer-buffer": "^2.1.0"
|
||||
"safer-buffer": "2.1.2"
|
||||
}
|
||||
},
|
||||
"ignore-walk": {
|
||||
|
@ -2729,7 +2743,7 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimatch": "^3.0.4"
|
||||
"minimatch": "3.0.4"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
|
@ -2738,15 +2752,14 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
"once": "1.4.0",
|
||||
"wrappy": "1.0.2"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -2758,9 +2771,8 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
"number-is-nan": "1.0.1"
|
||||
}
|
||||
},
|
||||
"isarray": {
|
||||
|
@ -2773,25 +2785,22 @@
|
|||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
"brace-expansion": "1.1.11"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.2.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.1",
|
||||
"yallist": "^3.0.0"
|
||||
"safe-buffer": "5.1.1",
|
||||
"yallist": "3.0.2"
|
||||
}
|
||||
},
|
||||
"minizlib": {
|
||||
|
@ -2800,14 +2809,13 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minipass": "^2.2.1"
|
||||
"minipass": "2.2.4"
|
||||
}
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -2824,9 +2832,9 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"debug": "^2.1.2",
|
||||
"iconv-lite": "^0.4.4",
|
||||
"sax": "^1.2.4"
|
||||
"debug": "2.6.9",
|
||||
"iconv-lite": "0.4.21",
|
||||
"sax": "1.2.4"
|
||||
}
|
||||
},
|
||||
"node-pre-gyp": {
|
||||
|
@ -2835,16 +2843,16 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"detect-libc": "^1.0.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"needle": "^2.2.0",
|
||||
"nopt": "^4.0.1",
|
||||
"npm-packlist": "^1.1.6",
|
||||
"npmlog": "^4.0.2",
|
||||
"rc": "^1.1.7",
|
||||
"rimraf": "^2.6.1",
|
||||
"semver": "^5.3.0",
|
||||
"tar": "^4"
|
||||
"detect-libc": "1.0.3",
|
||||
"mkdirp": "0.5.1",
|
||||
"needle": "2.2.0",
|
||||
"nopt": "4.0.1",
|
||||
"npm-packlist": "1.1.10",
|
||||
"npmlog": "4.1.2",
|
||||
"rc": "1.2.7",
|
||||
"rimraf": "2.6.2",
|
||||
"semver": "5.5.0",
|
||||
"tar": "4.4.1"
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
|
@ -2853,8 +2861,8 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"abbrev": "1",
|
||||
"osenv": "^0.1.4"
|
||||
"abbrev": "1.1.1",
|
||||
"osenv": "0.1.5"
|
||||
}
|
||||
},
|
||||
"npm-bundled": {
|
||||
|
@ -2869,8 +2877,8 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ignore-walk": "^3.0.1",
|
||||
"npm-bundled": "^1.0.1"
|
||||
"ignore-walk": "3.0.1",
|
||||
"npm-bundled": "1.0.3"
|
||||
}
|
||||
},
|
||||
"npmlog": {
|
||||
|
@ -2879,17 +2887,16 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"are-we-there-yet": "~1.1.2",
|
||||
"console-control-strings": "~1.1.0",
|
||||
"gauge": "~2.7.3",
|
||||
"set-blocking": "~2.0.0"
|
||||
"are-we-there-yet": "1.1.4",
|
||||
"console-control-strings": "1.1.0",
|
||||
"gauge": "2.7.4",
|
||||
"set-blocking": "2.0.0"
|
||||
}
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -2901,9 +2908,8 @@
|
|||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
"wrappy": "1.0.2"
|
||||
}
|
||||
},
|
||||
"os-homedir": {
|
||||
|
@ -2924,8 +2930,8 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"os-homedir": "^1.0.0",
|
||||
"os-tmpdir": "^1.0.0"
|
||||
"os-homedir": "1.0.2",
|
||||
"os-tmpdir": "1.0.2"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
|
@ -2946,10 +2952,10 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"deep-extend": "^0.5.1",
|
||||
"ini": "~1.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-json-comments": "~2.0.1"
|
||||
"deep-extend": "0.5.1",
|
||||
"ini": "1.3.5",
|
||||
"minimist": "1.2.0",
|
||||
"strip-json-comments": "2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
|
@ -2966,13 +2972,13 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
"core-util-is": "1.0.2",
|
||||
"inherits": "2.0.3",
|
||||
"isarray": "1.0.0",
|
||||
"process-nextick-args": "2.0.0",
|
||||
"safe-buffer": "5.1.1",
|
||||
"string_decoder": "1.1.1",
|
||||
"util-deprecate": "1.0.2"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
|
@ -2981,7 +2987,7 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"glob": "^7.0.5"
|
||||
"glob": "7.1.2"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
|
@ -3023,11 +3029,10 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
"code-point-at": "1.1.0",
|
||||
"is-fullwidth-code-point": "1.0.0",
|
||||
"strip-ansi": "3.0.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
|
@ -3036,7 +3041,7 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
|
@ -3044,7 +3049,7 @@
|
|||
"bundled": true,
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
"ansi-regex": "2.1.1"
|
||||
}
|
||||
},
|
||||
"strip-json-comments": {
|
||||
|
@ -3059,13 +3064,13 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chownr": "^1.0.1",
|
||||
"fs-minipass": "^1.2.5",
|
||||
"minipass": "^2.2.4",
|
||||
"minizlib": "^1.1.0",
|
||||
"mkdirp": "^0.5.0",
|
||||
"safe-buffer": "^5.1.1",
|
||||
"yallist": "^3.0.2"
|
||||
"chownr": "1.0.1",
|
||||
"fs-minipass": "1.2.5",
|
||||
"minipass": "2.2.4",
|
||||
"minizlib": "1.1.0",
|
||||
"mkdirp": "0.5.1",
|
||||
"safe-buffer": "5.1.1",
|
||||
"yallist": "3.0.2"
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
|
@ -3080,7 +3085,7 @@
|
|||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"string-width": "^1.0.2"
|
||||
"string-width": "1.0.2"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
|
|
|
@ -9,12 +9,13 @@
|
|||
"node": ">=8.0.0 <10.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "./scripts/authelia-scripts start",
|
||||
"start": "ts-node -P ./test/tsconfig.json ./scripts/authelia-scripts start",
|
||||
"build": "./scripts/authelia-scripts build",
|
||||
"unittest": "./scripts/authelia-scripts unittest",
|
||||
"test": "./scripts/authelia-scripts test",
|
||||
"travis": "./scripts/authelia-scripts travis",
|
||||
"cover": "NODE_ENV=test nyc npm t"
|
||||
"cover": "NODE_ENV=test nyc npm t",
|
||||
"scripts": "./scripts/authelia-scripts"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -60,6 +61,8 @@
|
|||
"devDependencies": {
|
||||
"@types/bluebird": "^3.5.4",
|
||||
"@types/body-parser": "^1.16.3",
|
||||
"@types/chokidar": "^1.7.5",
|
||||
"@types/commander": "^2.12.2",
|
||||
"@types/connect-redis": "0.0.7",
|
||||
"@types/ejs": "^2.3.33",
|
||||
"@types/express": "^4.0.35",
|
||||
|
|
|
@ -5,16 +5,13 @@ var program = require('commander');
|
|||
program
|
||||
.version('0.0.1')
|
||||
|
||||
.command('start', 'Start development environment.')
|
||||
.command('suites', 'Run Authelia in specific environments.')
|
||||
.command('serve', 'Run Authelia with a customized configuration.')
|
||||
.command('build', 'Build production version of Authelia from source.')
|
||||
.command('clean', 'Clean the production version of Authelia.')
|
||||
.command('serve', 'Serve production version of Authelia.')
|
||||
.command('test', 'Run Authelia integration tests.')
|
||||
.command('unittest', 'Run Authelia integration tests.')
|
||||
|
||||
.command('travis', 'Build and test Authelia on Travis.')
|
||||
.command('hash-password <password>', 'Hash a password with SSHA512.')
|
||||
.command('docker', 'Docker related commands.')
|
||||
.parse(process.argv);
|
||||
|
||||
|
||||
|
|
|
@ -3,8 +3,4 @@
|
|||
var { exec } = require('./utils/exec');
|
||||
var { IMAGE_NAME } = require('./utils/docker');
|
||||
|
||||
async function main() {
|
||||
await exec(`docker build -t ${IMAGE_NAME} .`);
|
||||
}
|
||||
|
||||
main();
|
||||
exec(`docker build -t ${IMAGE_NAME} .`);
|
|
@ -1,49 +1,27 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var program = require('commander');
|
||||
var execSync = require('child_process').execSync;
|
||||
var spawn = require('child_process').spawn;
|
||||
var fs = require('fs');
|
||||
|
||||
let config;
|
||||
|
||||
program
|
||||
.option('-c, --config <config>', 'Configuration file to run Authelia with.')
|
||||
.option('--no-watch', 'Disable hot reload.')
|
||||
.description('Run Authelia server with a custom configuration file. This is an alternative to suites in the case the environment is already set up.')
|
||||
.arguments('[config_file]', 'Configuration file to run Authelia with.')
|
||||
.action((configArg) => config = configArg)
|
||||
.parse(process.argv);
|
||||
|
||||
let config = 'config.yml'; // set default config file.
|
||||
|
||||
if (program.config) {
|
||||
config = program.config;
|
||||
if (!config) {
|
||||
config = 'config.yml'; // set default config file.;
|
||||
}
|
||||
|
||||
// Render the production version of the nginx portal configuration
|
||||
execSync('./example/compose/nginx/portal/render.js --production');
|
||||
|
||||
// Prepare the environment
|
||||
execSync('./scripts/utils/prepare-environment.sh');
|
||||
|
||||
var server;
|
||||
if (program.watch) {
|
||||
server = spawn('./node_modules/.bin/nodemon',
|
||||
['-e', 'yml', '--ignore', './users_database*.yml', '--exec', `node dist/server/src/index.js ${config}`]);
|
||||
}
|
||||
else {
|
||||
server = spawn('/usr/bin/env', ['node', 'dist/server/src/index.js', config]);
|
||||
}
|
||||
|
||||
var logStream = fs.createWriteStream('/tmp/authelia-server.log', {flags: 'a'});
|
||||
|
||||
server.stdout.on('data', (data) => {
|
||||
process.stdout.write(`${data}`);
|
||||
});
|
||||
server.stdout.pipe(logStream);
|
||||
|
||||
server.stderr.on('data', (data) => {
|
||||
process.stderr.write(`${data}`);
|
||||
});
|
||||
server.stderr.pipe(logStream);
|
||||
const server = spawn('/usr/bin/env', ['node', 'dist/server/src/index.js', config]);
|
||||
|
||||
server.stdout.pipe(process.stdout);
|
||||
server.stderr.pipe(process.stderr);
|
||||
|
||||
server.on('exit', function(statusCode) {
|
||||
process.exit(statusCode);
|
||||
})
|
||||
});
|
|
@ -1,162 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var program = require('commander');
|
||||
var spawn = require('child_process').spawn;
|
||||
var chokidar = require('chokidar');
|
||||
var fs = require('fs');
|
||||
var kill = require('tree-kill');
|
||||
|
||||
program
|
||||
.option('-s, --suite <suite>', 'The suite to run Authelia for. This suite represents a configuration for Authelia and a set of tests for that configuration.')
|
||||
.parse(process.argv)
|
||||
|
||||
if (!program.suite) {
|
||||
throw new Error('Please provide a suite.');
|
||||
}
|
||||
|
||||
const ENVIRONMENT_FILENAME = '.suite';
|
||||
const AUTHELIA_INTERRUPT_FILENAME = '.authelia-interrupt';
|
||||
const CONFIG_FILEPATH = `test/suites/${program.suite}/config.yml`;
|
||||
|
||||
|
||||
var tsWatcher = chokidar.watch(['server', 'shared/**/*.ts', 'node_modules', AUTHELIA_INTERRUPT_FILENAME, CONFIG_FILEPATH], {
|
||||
persistent: true,
|
||||
ignoreInitial: true,
|
||||
});
|
||||
|
||||
// Properly cleanup server and client if ctrl-c is hit
|
||||
process.on('SIGINT', function() {
|
||||
killServer();
|
||||
killClient();
|
||||
fs.unlinkSync(ENVIRONMENT_FILENAME);
|
||||
process.exit();
|
||||
});
|
||||
|
||||
|
||||
let serverProcess;
|
||||
function reloadServer() {
|
||||
killServer(() => {
|
||||
startServer();
|
||||
});
|
||||
}
|
||||
|
||||
function startServer() {
|
||||
if (fs.existsSync(AUTHELIA_INTERRUPT_FILENAME)) {
|
||||
console.log('Authelia is interrupted. Consider removing ' + AUTHELIA_INTERRUPT_FILENAME + ' if it\'s not expected.');
|
||||
return;
|
||||
}
|
||||
exec('./node_modules/.bin/tslint', ['-c', 'server/tslint.json', '-p', 'server/tsconfig.json'])
|
||||
.then(function() {
|
||||
serverProcess = spawn('./scripts/run-dev-server.sh', [CONFIG_FILEPATH]);
|
||||
serverProcess.stdout.pipe(process.stdout);
|
||||
serverProcess.stderr.pipe(process.stderr);
|
||||
});
|
||||
}
|
||||
|
||||
let clientProcess;
|
||||
function startClient() {
|
||||
clientProcess = spawn('npm', ['run', 'start'], {
|
||||
cwd: './client',
|
||||
env: {
|
||||
...process.env,
|
||||
'BROWSER': 'none'
|
||||
}
|
||||
});
|
||||
clientProcess.stdout.pipe(process.stdout);
|
||||
clientProcess.stderr.pipe(process.stderr);
|
||||
}
|
||||
|
||||
function killServer(onExit) {
|
||||
if (serverProcess) {
|
||||
serverProcess.on('exit', () => {
|
||||
serverProcess = undefined;
|
||||
if (onExit) onExit();
|
||||
});
|
||||
try {
|
||||
kill(serverProcess.pid, 'SIGKILL');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (onExit) onExit();
|
||||
}
|
||||
} else {
|
||||
if (onExit) onExit();
|
||||
}
|
||||
}
|
||||
|
||||
function killClient(onExit) {
|
||||
if (clientProcess) {
|
||||
clientProcess.on('exit', () => {
|
||||
clientProcess = undefined;
|
||||
if (onExit) onExit();
|
||||
});
|
||||
try {
|
||||
kill(clientProcess.pid, 'SIGKILL');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (onExit) onExit();
|
||||
}
|
||||
} else {
|
||||
if (onExit) onExit();
|
||||
}
|
||||
}
|
||||
|
||||
function generateConfigurationSchema() {
|
||||
return ixec('./node_modules/.bin/typescript-json-schema',
|
||||
['-o', 'server/src/lib/configuration/Configuration.schema.json', '--strictNullChecks', '--required', 'server/tsconfig.json', 'Configuration']);
|
||||
}
|
||||
|
||||
function reload(path) {
|
||||
console.log(`File ${path} has been changed, reloading...`);
|
||||
if (path.startsWith('server/src/lib/configuration/schema')) {
|
||||
console.log('Schema needs to be regenerated.');
|
||||
generateConfigurationSchema();
|
||||
}
|
||||
else if (path === AUTHELIA_INTERRUPT_FILENAME) {
|
||||
if (fs.existsSync(path)) {
|
||||
console.log('Authelia is being interrupted.');
|
||||
killServer();
|
||||
} else {
|
||||
console.log('Authelia is restarting.');
|
||||
startServer();
|
||||
}
|
||||
return;
|
||||
}
|
||||
reloadServer();
|
||||
}
|
||||
|
||||
function exec(command, args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const cmd = spawn(command, args);
|
||||
|
||||
cmd.stdout.pipe(process.stdout);
|
||||
cmd.stderr.pipe(process.stderr);
|
||||
cmd.on('close', (code) => {
|
||||
if (code == 0) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
reject(new Error('Status code ' + code));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log(`Create suite file ${ENVIRONMENT_FILENAME}.`);
|
||||
fs.writeFileSync(ENVIRONMENT_FILENAME, program.suite);
|
||||
|
||||
console.log(`Render nginx configuration...`);
|
||||
await exec('./example/compose/nginx/portal/render.js');
|
||||
|
||||
console.log(`Prepare environment with docker-compose...`);
|
||||
await exec('./scripts/utils/prepare-environment.sh');
|
||||
|
||||
console.log('Start watching...');
|
||||
tsWatcher.on('add', reload);
|
||||
tsWatcher.on('unlink', reload);
|
||||
tsWatcher.on('change', reload);
|
||||
|
||||
startServer();
|
||||
startClient();
|
||||
}
|
||||
|
||||
main()
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var program = require('commander');
|
||||
|
||||
program
|
||||
.command('start', 'Start a suite.')
|
||||
.command('list', 'List the available suites')
|
||||
.command('test', 'Test a suite.')
|
||||
.command('clean', 'Clean remaining environment artifacts (like docker-compose env).')
|
||||
.parse(process.argv);
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var program = require('commander');
|
||||
var spawn = require('child_process').spawn;
|
||||
|
||||
program
|
||||
.description(`Clean environment artifacts from previous suites.`)
|
||||
.parse(process.argv)
|
||||
|
||||
runEnvProcess = spawn('./node_modules/.bin/ts-node -P test/tsconfig.json -- ./scripts/clean-environment.ts', {
|
||||
shell: true
|
||||
});
|
||||
runEnvProcess.stdout.pipe(process.stdout);
|
||||
runEnvProcess.stderr.pipe(process.stderr);
|
||||
|
||||
runEnvProcess.on('exit', function(statusCode) {
|
||||
process.exit(statusCode);
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var program = require('commander');
|
||||
var ListSuites = require('./utils/ListSuites');
|
||||
|
||||
program
|
||||
.description(`List the available suites.`)
|
||||
.parse(process.argv)
|
||||
|
||||
console.log(ListSuites().join("\n"));
|
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var program = require('commander');
|
||||
var spawn = require('child_process').spawn;
|
||||
var fs = require('fs');
|
||||
|
||||
let suite;
|
||||
|
||||
program
|
||||
.description(`Start the suite provided as argument. You can list the suites with the 'list' command.`)
|
||||
.arguments('<suite>')
|
||||
.action((suiteArg) => suite = suiteArg)
|
||||
.parse(process.argv)
|
||||
|
||||
if (!suite) {
|
||||
program.help();
|
||||
}
|
||||
|
||||
const ENVIRONMENT_FILENAME = '.suite';
|
||||
|
||||
let runEnvProcess;
|
||||
|
||||
// Sometime SIGINT is received twice, we make sure with this variable that we cleanup
|
||||
// only once.
|
||||
var alreadyCleaningUp = false;
|
||||
|
||||
// Properly cleanup server and client if ctrl-c is hit
|
||||
process.on('SIGINT', function() {
|
||||
if (alreadyCleaningUp) return;
|
||||
alreadyCleaningUp = true;
|
||||
console.log('Cleanup procedure is running...');
|
||||
});
|
||||
|
||||
async function main() {
|
||||
fs.writeFileSync(ENVIRONMENT_FILENAME, suite);
|
||||
|
||||
// Start the environment from ts-node process.
|
||||
runEnvProcess = spawn('./node_modules/.bin/ts-node -P test/tsconfig.json -- ./scripts/run-environment.ts ' + suite, {
|
||||
shell: true
|
||||
});
|
||||
runEnvProcess.stdout.pipe(process.stdout);
|
||||
runEnvProcess.stderr.pipe(process.stderr);
|
||||
|
||||
runEnvProcess.on('exit', function(statusCode) {
|
||||
fs.unlinkSync(ENVIRONMENT_FILENAME);
|
||||
process.exit(statusCode);
|
||||
});
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1)
|
||||
});
|
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var program = require('commander');
|
||||
var spawn = require('child_process').spawn;
|
||||
var fs = require('fs');
|
||||
|
||||
let suite;
|
||||
|
||||
program
|
||||
.description('Run the tests for the current suite or the provided one.')
|
||||
.arguments('[suite]')
|
||||
.option('--headless', 'Run in headless mode.')
|
||||
.action((suiteArg) => suite = suiteArg)
|
||||
.parse(process.argv);
|
||||
|
||||
let args = [];
|
||||
const ENVIRONMENT_FILENAME = '.suite'; // This file is created by the start command.
|
||||
|
||||
if (suite) {
|
||||
if (fs.existsSync(ENVIRONMENT_FILENAME)) {
|
||||
console.error('You cannot test a suite while another one is running. If you want to test the current suite, ' +
|
||||
'do not provide the suite argument. Otherwise, stop the current suite and run the command again.');
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('Suite %s provided. Running test related to this suite against built version of Authelia.', suite);
|
||||
args.push('test/suites/' + suite + '/test.ts');
|
||||
}
|
||||
else if (fs.existsSync(ENVIRONMENT_FILENAME)) {
|
||||
suite = fs.readFileSync(ENVIRONMENT_FILENAME);
|
||||
console.log('Suite %s detected from dev env. Running test related to this suite.', suite);
|
||||
args.push('test/suites/' + suite + '/test.ts');
|
||||
}
|
||||
else {
|
||||
console.log('No suite provided therefore all suites will be tested.');
|
||||
args.push('test/suites/**/test.ts');
|
||||
}
|
||||
|
||||
mocha = spawn('./node_modules/.bin/mocha', ['--exit', '--colors', '--require', 'ts-node/register', ...args], {
|
||||
env: {
|
||||
...process.env,
|
||||
TS_NODE_PROJECT: 'test/tsconfig.json',
|
||||
HEADLESS: (program.headless) ? 'y' : 'n',
|
||||
}
|
||||
});
|
||||
|
||||
mocha.stdout.pipe(process.stdout);
|
||||
mocha.stderr.pipe(process.stderr);
|
||||
|
||||
mocha.on('exit', function(statusCode) {
|
||||
if (statusCode != 0) {
|
||||
console.error("The tests failed... Mocha exited with status code " + statusCode);
|
||||
fs.readFile('/tmp/authelia-server.log', function(err, data) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
console.log(data.toString('utf-8'));
|
||||
});
|
||||
}
|
||||
process.exit(statusCode);
|
||||
})
|
|
@ -1,65 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var program = require('commander');
|
||||
var spawn = require('child_process').spawn;
|
||||
var fs = require('fs');
|
||||
var execSync = require('child_process').execSync;
|
||||
|
||||
program
|
||||
.option('--headless', 'Run in headless mode.')
|
||||
.parse(process.argv);
|
||||
|
||||
let withServer = false;
|
||||
let args = [];
|
||||
const ENVIRONMENT_FILENAME = '.suite'; // This file is created by the start command.
|
||||
|
||||
if (fs.existsSync(ENVIRONMENT_FILENAME)) {
|
||||
const suite = fs.readFileSync(ENVIRONMENT_FILENAME);
|
||||
console.log('Suite %s detected (dev env running). Running test related to this suite.', suite);
|
||||
args.push('test/suites/' + suite + '/*.ts');
|
||||
}
|
||||
else if (program.args.length > 0) {
|
||||
console.log('No suite detected. Running selected tests against built server.');
|
||||
withServer = true;
|
||||
args = program.args;
|
||||
|
||||
// Render the production version of the nginx portal configuration
|
||||
execSync('./example/compose/nginx/portal/render.js --production');
|
||||
// Prepare the environment
|
||||
execSync('./scripts/utils/prepare-environment.sh');
|
||||
}
|
||||
else {
|
||||
console.log('No suite detected but no tests have been selected...');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
mocha = spawn('./node_modules/.bin/mocha', ['--exit', '--colors', '--require', 'ts-node/register', ...args], {
|
||||
env: {
|
||||
...process.env,
|
||||
TS_NODE_PROJECT: 'test/tsconfig.json',
|
||||
WITH_SERVER: (withServer) ? 'y' : 'n',
|
||||
HEADLESS: (program.headless) ? 'y' : 'n',
|
||||
}
|
||||
});
|
||||
|
||||
mocha.stdout.on('data', (data) => {
|
||||
process.stdout.write(`${data}`);
|
||||
});
|
||||
|
||||
mocha.stderr.on('data', (data) => {
|
||||
process.stderr.write(`${data}`);
|
||||
});
|
||||
|
||||
mocha.on('exit', function(statusCode) {
|
||||
if (statusCode != 0) {
|
||||
console.error("The tests failed... Mocha exited with status code " + statusCode);
|
||||
fs.readFile('/tmp/authelia-server.log', function(err, data) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
console.log(data.toString('utf-8'));
|
||||
});
|
||||
}
|
||||
process.exit(statusCode);
|
||||
})
|
|
@ -19,7 +19,7 @@ authelia-scripts unittest
|
|||
authelia-scripts docker build
|
||||
|
||||
# Run integration tests
|
||||
authelia-scripts test --headless test/suites/**/*.ts
|
||||
authelia-scripts suites test --headless
|
||||
|
||||
# Test npm deployment before actual deployment
|
||||
# ./scripts/npm-deployment-test.sh
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
var ListSuites = require('./utils/ListSuites');
|
||||
|
||||
const suites = ListSuites();
|
||||
|
||||
suites.forEach(async (suite: string) => {
|
||||
var { teardown } = require(`../test/suites/${suite}/environment`);;
|
||||
teardown().catch((err: Error) => console.error(err));
|
||||
});
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
docker-compose \
|
||||
-f docker-compose.yml \
|
||||
-f example/compose/mongo/docker-compose.yml \
|
||||
-f example/compose/redis/docker-compose.yml \
|
||||
-f example/compose/nginx/backend/docker-compose.yml \
|
||||
-f example/compose/nginx/portal/docker-compose.yml \
|
||||
-f example/compose/smtp/docker-compose.yml \
|
||||
-f example/compose/httpbin/docker-compose.yml \
|
||||
-f example/compose/ldap/docker-compose.admin.yml \
|
||||
-f example/compose/ldap/docker-compose.yml $*
|
|
@ -1,6 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Starts the server with the provided configuration in $1
|
||||
# This scripts is called from authelia-scripts.
|
||||
|
||||
./node_modules/.bin/ts-node -P ./server/tsconfig.json ./server/src/index.ts $*
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
const userSuite = process.argv[2];
|
||||
|
||||
var { setup, teardown } = require(`../test/suites/${userSuite}/environment`);
|
||||
|
||||
function sleep(ms: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
let teardownInProgress = false;
|
||||
|
||||
process.on('SIGINT', function() {
|
||||
if (teardownInProgress) return;
|
||||
teardownInProgress = true;
|
||||
console.log('Tearing down environment...');
|
||||
return teardown()
|
||||
.then(() => {
|
||||
process.exit(0)
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
});
|
||||
|
||||
function main() {
|
||||
console.log('Setting up environment...');
|
||||
return setup()
|
||||
.then(async () => {
|
||||
while (true) {
|
||||
await sleep(10000);
|
||||
}
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
|
@ -0,0 +1,13 @@
|
|||
const { lstatSync, readdirSync } = require('fs')
|
||||
const { join } = require('path')
|
||||
|
||||
const isDirectory = source => lstatSync(source).isDirectory()
|
||||
const getDirectories = source =>
|
||||
readdirSync(source)
|
||||
.map(name => join(source, name))
|
||||
.filter(isDirectory)
|
||||
.map(x => x.split('/').slice(-1)[0])
|
||||
|
||||
module.exports = function() {
|
||||
return getDirectories('test/suites/');
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
./scripts/dc-dev.sh up -d
|
||||
./scripts/dc-dev.sh kill -s SIGHUP nginx-portal
|
|
@ -0,0 +1,26 @@
|
|||
import fs from 'fs';
|
||||
import AutheliaServerWithHotReload from "./AutheliaServerWithHotReload";
|
||||
import AutheliaServerInterface from './AutheliaServerInterface';
|
||||
import AutheliaServerFromDist from './AutheliaServerFromDist';
|
||||
|
||||
class AutheliaServer implements AutheliaServerInterface {
|
||||
private runnerImpl: AutheliaServerInterface;
|
||||
|
||||
constructor(configPath: string) {
|
||||
if (fs.existsSync('.suite')) {
|
||||
this.runnerImpl = new AutheliaServerWithHotReload(configPath);
|
||||
} else {
|
||||
this.runnerImpl = new AutheliaServerFromDist(configPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
async start() {
|
||||
await this.runnerImpl.start();
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await this.runnerImpl.stop();
|
||||
}
|
||||
}
|
||||
|
||||
export default AutheliaServer;
|
|
@ -0,0 +1,39 @@
|
|||
import AutheliaServerInterface from './AutheliaServerInterface';
|
||||
import ChildProcess from 'child_process';
|
||||
import treeKill = require('tree-kill');
|
||||
import fs from 'fs';
|
||||
|
||||
class AutheliaServerFromDist implements AutheliaServerInterface {
|
||||
private configPath: string;
|
||||
private logInFile: boolean;
|
||||
private serverProcess: ChildProcess.ChildProcess | undefined;
|
||||
|
||||
constructor(configPath: string, logInFile: boolean = false) {
|
||||
this.configPath = configPath;
|
||||
this.logInFile = logInFile;
|
||||
}
|
||||
|
||||
async start() {
|
||||
this.serverProcess = ChildProcess.spawn('./scripts/authelia-scripts serve ' + this.configPath, {
|
||||
shell: true
|
||||
} as any);
|
||||
if (this.logInFile) {
|
||||
var logStream = fs.createWriteStream('/tmp/authelia-server.log', {flags: 'a'});
|
||||
this.serverProcess.stdout.pipe(logStream);
|
||||
this.serverProcess.stderr.pipe(logStream);
|
||||
} else {
|
||||
this.serverProcess.stdout.pipe(process.stdout);
|
||||
this.serverProcess.stderr.pipe(process.stderr);
|
||||
}
|
||||
this.serverProcess.on('exit', (statusCode) => {
|
||||
console.log('Authelia server exited with code ' + statusCode);
|
||||
})
|
||||
}
|
||||
|
||||
async stop() {
|
||||
if (!this.serverProcess) return;
|
||||
treeKill(this.serverProcess.pid, 'SIGKILL');
|
||||
}
|
||||
}
|
||||
|
||||
export default AutheliaServerFromDist;
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
interface AutheliaServerInterface {
|
||||
start(): Promise<void>;
|
||||
stop(): Promise<void>
|
||||
}
|
||||
|
||||
export default AutheliaServerInterface;
|
|
@ -0,0 +1,149 @@
|
|||
import Chokidar from 'chokidar';
|
||||
import fs from 'fs';
|
||||
import { exec } from '../utils/exec';
|
||||
import ChildProcess from 'child_process';
|
||||
import kill from 'tree-kill';
|
||||
import AutheliaServerInterface from './AutheliaServerInterface';
|
||||
|
||||
class AutheliaServerWithHotReload implements AutheliaServerInterface {
|
||||
private watcher: Chokidar.FSWatcher;
|
||||
private configPath: string;
|
||||
private AUTHELIA_INTERRUPT_FILENAME = '.authelia-interrupt';
|
||||
private serverProcess: ChildProcess.ChildProcess | undefined;
|
||||
private clientProcess: ChildProcess.ChildProcess | undefined;
|
||||
|
||||
constructor(configPath: string) {
|
||||
this.configPath = configPath;
|
||||
this.watcher = Chokidar.watch(['server', 'shared/**/*.ts', 'node_modules',
|
||||
this.AUTHELIA_INTERRUPT_FILENAME, configPath], {
|
||||
persistent: true,
|
||||
ignoreInitial: true,
|
||||
});
|
||||
}
|
||||
|
||||
private async startServer() {
|
||||
await exec('./node_modules/.bin/tslint -c server/tslint.json -p server/tsconfig.json')
|
||||
this.serverProcess = ChildProcess.spawn('./node_modules/.bin/ts-node',
|
||||
['-P', './server/tsconfig.json', './server/src/index.ts', this.configPath], {
|
||||
env: {...process.env},
|
||||
});
|
||||
this.serverProcess.stdout.pipe(process.stdout);
|
||||
this.serverProcess.stderr.pipe(process.stderr);
|
||||
this.serverProcess.on('exit', () => {
|
||||
console.log('Authelia server exited.');
|
||||
if (!this.serverProcess) return;
|
||||
this.serverProcess.removeAllListeners();
|
||||
this.serverProcess = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
private killServer() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.serverProcess) {
|
||||
try {
|
||||
const timeout = setTimeout(
|
||||
() => reject(new Error('Server not killed after timeout.')), 10000);
|
||||
this.serverProcess.on('exit', () => {
|
||||
clearTimeout(timeout);
|
||||
resolve();
|
||||
});
|
||||
kill(this.serverProcess.pid, 'SIGKILL');
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async startClient() {
|
||||
this.clientProcess = ChildProcess.spawn('npm', ['run', 'start'], {
|
||||
cwd: './client',
|
||||
env: {
|
||||
...process.env,
|
||||
'BROWSER': 'none'
|
||||
}
|
||||
});
|
||||
this.clientProcess.stdout.pipe(process.stdout);
|
||||
this.clientProcess.stderr.pipe(process.stderr);
|
||||
this.clientProcess.on('exit', () => {
|
||||
console.log('Authelia client exited.');
|
||||
if (!this.clientProcess) return;
|
||||
this.clientProcess.removeAllListeners();
|
||||
this.clientProcess = undefined;
|
||||
})
|
||||
}
|
||||
|
||||
private killClient() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.clientProcess) {
|
||||
try {
|
||||
const timeout = setTimeout(
|
||||
() => reject(new Error('Server not killed after timeout.')), 10000);
|
||||
this.clientProcess.on('exit', () => {
|
||||
clearTimeout(timeout);
|
||||
resolve();
|
||||
});
|
||||
kill(this.clientProcess.pid, 'SIGKILL');
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async generateConfigurationSchema() {
|
||||
await exec('./node_modules/.bin/typescript-json-schema -o ' +
|
||||
'server/src/lib/configuration/Configuration.schema.json ' +
|
||||
'--strictNullChecks --required server/tsconfig.json Configuration');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle file changes.
|
||||
* @param path The path of the file that has been changed.
|
||||
*/
|
||||
private async onFileChanged(path: string) {
|
||||
console.log(`File ${path} has been changed, reloading...`);
|
||||
if (path.startsWith('server/src/lib/configuration/schema')) {
|
||||
console.log('Schema needs to be regenerated.');
|
||||
await this.generateConfigurationSchema();
|
||||
}
|
||||
else if (path === this.AUTHELIA_INTERRUPT_FILENAME) {
|
||||
if (fs.existsSync(path)) {
|
||||
console.log('Authelia is being interrupted.');
|
||||
await this.killServer();
|
||||
} else {
|
||||
console.log('Authelia is restarting.');
|
||||
await this.startServer();
|
||||
}
|
||||
return;
|
||||
}
|
||||
await this.killServer();
|
||||
await this.startServer();
|
||||
}
|
||||
|
||||
async start() {
|
||||
if (fs.existsSync(this.AUTHELIA_INTERRUPT_FILENAME)) {
|
||||
console.log('Authelia is interrupted. Consider removing ' + this.AUTHELIA_INTERRUPT_FILENAME + ' if it\'s not expected.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Start watching file changes...');
|
||||
this.watcher.on('add', (p) => this.onFileChanged(p));
|
||||
this.watcher.on('unlink', (p) => this.onFileChanged(p));
|
||||
this.watcher.on('change', (p) => this.onFileChanged(p));
|
||||
|
||||
this.startClient();
|
||||
this.startServer();
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await this.killClient();
|
||||
await this.killServer();
|
||||
}
|
||||
}
|
||||
|
||||
export default AutheliaServerWithHotReload;
|
|
@ -1,16 +1,17 @@
|
|||
import WithAutheliaRunning from "./WithAutheliaRunning";
|
||||
import WithEnvironment from "./WithEnvironment";
|
||||
import fs from 'fs';
|
||||
|
||||
interface AutheliaSuiteType {
|
||||
(description: string, configPath: string, cb: (this: Mocha.ISuiteCallbackContext) => void): Mocha.ISuite;
|
||||
only: (description: string, configPath: string, cb: (this: Mocha.ISuiteCallbackContext) => void) => Mocha.ISuite;
|
||||
}
|
||||
|
||||
function AutheliaSuiteBase(description: string, configPath: string,
|
||||
function AutheliaSuiteBase(description: string, suite: string,
|
||||
cb: (this: Mocha.ISuiteCallbackContext) => void,
|
||||
context: (description: string, ctx: (this: Mocha.ISuiteCallbackContext) => void) => Mocha.ISuite) {
|
||||
return context('Suite: ' + description, function(this: Mocha.ISuiteCallbackContext) {
|
||||
if (process.env['WITH_SERVER'] == 'y') {
|
||||
WithAutheliaRunning(configPath);
|
||||
if (!fs.existsSync('.suite')) {
|
||||
WithEnvironment(suite);
|
||||
}
|
||||
|
||||
cb.call(this);
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
import { exec } from '../../helpers/utils/exec';
|
||||
|
||||
class DockerCompose {
|
||||
private commandPrefix: string;
|
||||
|
||||
constructor(composeFiles: string[]) {
|
||||
this.commandPrefix = 'docker-compose ' + composeFiles.map((f) => '-f ' + f).join(' ');
|
||||
}
|
||||
|
||||
async up() {
|
||||
await exec(this.commandPrefix + ' up -d');
|
||||
}
|
||||
|
||||
async down() {
|
||||
await exec(this.commandPrefix + ' down');
|
||||
}
|
||||
|
||||
async restart(service: string) {
|
||||
await exec(this.commandPrefix + ' restart ' + service);
|
||||
}
|
||||
}
|
||||
|
||||
export default DockerCompose;
|
|
@ -0,0 +1,19 @@
|
|||
import DockerCompose from "./DockerCompose";
|
||||
|
||||
class DockerEnvironment {
|
||||
private dockerCompose: DockerCompose;
|
||||
|
||||
constructor(composeFiles: string[]) {
|
||||
this.dockerCompose = new DockerCompose(composeFiles);
|
||||
}
|
||||
|
||||
async start() {
|
||||
await this.dockerCompose.up();
|
||||
}
|
||||
|
||||
async stop() {
|
||||
await this.dockerCompose.down();
|
||||
}
|
||||
}
|
||||
|
||||
export default DockerEnvironment;
|
|
@ -1,44 +0,0 @@
|
|||
|
||||
import ChildProcess from 'child_process';
|
||||
import fs from 'fs';
|
||||
|
||||
export default function WithAutheliaRunning(configPath: string, waitTimeout: number = 5000) {
|
||||
before(function() {
|
||||
this.timeout(10000);
|
||||
|
||||
console.log('Spawning Authelia server with configuration %s.', configPath);
|
||||
const authelia = ChildProcess.spawn(
|
||||
'./scripts/authelia-scripts',
|
||||
['serve', '--no-watch', '--config', configPath],
|
||||
{detached: true});
|
||||
|
||||
authelia.on('exit', function(statusCode) {
|
||||
console.log('Server terminated with status ' + statusCode);
|
||||
if (statusCode != 0) {
|
||||
fs.readFile('/tmp/authelia-server.log', function(err, data) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
console.log(data.toString('utf-8'));
|
||||
})
|
||||
}
|
||||
});
|
||||
this.authelia = authelia;
|
||||
|
||||
const waitPromise = new Promise((resolve, reject) => setTimeout(() => resolve(), waitTimeout));
|
||||
return waitPromise;
|
||||
});
|
||||
|
||||
after(function() {
|
||||
this.timeout(10000);
|
||||
|
||||
console.log('Killing Authelia server.');
|
||||
// Kill the group of processes.
|
||||
process.kill(-this.authelia.pid);
|
||||
|
||||
// Leave 5 seconds for the process to terminate.
|
||||
const waitPromise = new Promise((resolve, reject) => setTimeout(() => resolve(), 5000));
|
||||
return waitPromise;
|
||||
});
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import sleep from '../utils/sleep';
|
||||
|
||||
export default function WithAutheliaRunning(suitePath: string, waitTimeout: number = 5000) {
|
||||
const suite = suitePath.split('/').slice(-1)[0];
|
||||
var { setup, teardown } = require(`../../suites/${suite}/environment`);
|
||||
|
||||
before(async function() {
|
||||
this.timeout(10000);
|
||||
|
||||
console.log('Preparing environment...');
|
||||
await setup();
|
||||
await sleep(waitTimeout);
|
||||
});
|
||||
|
||||
after(async function() {
|
||||
this.timeout(10000);
|
||||
|
||||
console.log('Stopping environment...');
|
||||
await teardown();
|
||||
|
||||
await sleep(waitTimeout);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
var spawn = require('child_process').spawn;
|
||||
|
||||
|
||||
export function exec(command: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const cmd = spawn(command, {
|
||||
shell: true,
|
||||
});
|
||||
|
||||
cmd.stdout.pipe(process.stdout);
|
||||
cmd.stderr.pipe(process.stderr);
|
||||
cmd.on('exit', (statusCode: number) => {
|
||||
if (statusCode == 0) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
reject(new Error('Exited with status code ' + statusCode));
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
|
||||
export default function sleep(ms: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
import DockerEnvironment from "../../helpers/context/DockerEnvironment";
|
||||
import AutheliaServer from "../../helpers/context/AutheliaServer";
|
||||
import { exec } from "../../helpers/utils/exec";
|
||||
import fs from 'fs';
|
||||
|
||||
const composeFiles = [
|
||||
'docker-compose.yml',
|
||||
'example/compose/mongo/docker-compose.yml',
|
||||
'example/compose/redis/docker-compose.yml',
|
||||
'example/compose/nginx/backend/docker-compose.yml',
|
||||
'example/compose/nginx/portal/docker-compose.yml',
|
||||
'example/compose/smtp/docker-compose.yml',
|
||||
'example/compose/httpbin/docker-compose.yml',
|
||||
'example/compose/ldap/docker-compose.admin.yml', // This is just used for administration, not for testing.
|
||||
'example/compose/ldap/docker-compose.yml'
|
||||
]
|
||||
|
||||
const dockerEnv = new DockerEnvironment(composeFiles);
|
||||
const autheliaServer = new AutheliaServer(__dirname + '/config.yml');
|
||||
|
||||
async function setup() {
|
||||
// In dev mode Authelia has the server served on one port and the frontend on another port.
|
||||
await exec('./example/compose/nginx/portal/render.js ' + (fs.existsSync('.suite') ? '': '--production'));
|
||||
|
||||
console.log(`Prepare environment with docker-compose...`);
|
||||
await dockerEnv.start();
|
||||
|
||||
console.log('Start Authelia server.');
|
||||
await autheliaServer.start();
|
||||
}
|
||||
|
||||
async function teardown() {
|
||||
console.log('Stop Authelia server.');
|
||||
await autheliaServer.stop();
|
||||
|
||||
console.log(`Cleanup environment with docker-compose...`);
|
||||
await dockerEnv.stop();
|
||||
}
|
||||
|
||||
export { setup, teardown, composeFiles };
|
|
@ -3,6 +3,8 @@ import FullLogin from "../../../helpers/FullLogin";
|
|||
import child_process from 'child_process';
|
||||
import WithDriver from "../../../helpers/context/WithDriver";
|
||||
import Logout from "../../../helpers/Logout";
|
||||
import { composeFiles } from '../environment';
|
||||
import DockerCompose from "../../../helpers/context/DockerCompose";
|
||||
|
||||
export default function() {
|
||||
after(async function() {
|
||||
|
@ -15,7 +17,8 @@ export default function() {
|
|||
this.timeout(30000);
|
||||
|
||||
const secret = await LoginAndRegisterTotp(this.driver, "john", "password", true);
|
||||
child_process.execSync("./scripts/dc-dev.sh restart mongo");
|
||||
const dockerCompose = new DockerCompose(composeFiles);
|
||||
await dockerCompose.restart('mongo');
|
||||
await FullLogin(this.driver, "john", secret, "https://admin.example.com:8080/secret.html");
|
||||
});
|
||||
}
|
|
@ -8,11 +8,7 @@ import BasicAuthentication from "./scenarii/BasicAuthentication";
|
|||
import AutheliaRestart from "./scenarii/AutheliaRestart";
|
||||
import AuthenticationRegulation from "./scenarii/AuthenticationRegulation";
|
||||
|
||||
before(function() {
|
||||
|
||||
});
|
||||
|
||||
AutheliaSuite('Complete configuration', __dirname + '/config.yml', function() {
|
||||
AutheliaSuite('Complete configuration', __dirname, function() {
|
||||
this.timeout(10000);
|
||||
|
||||
describe('Custom headers forwarded to backend', CustomHeadersForwarded);
|
|
@ -0,0 +1,18 @@
|
|||
import { exec } from '../../helpers/utils/exec';
|
||||
import ChildProcess from 'child_process';
|
||||
|
||||
async function setup() {
|
||||
await exec('docker run -d -v $(pwd)/config.yml:/etc/authelia/config.yml --name authelia-test clems4ever/authelia > /dev/null');
|
||||
console.log('Container has been spawned.');
|
||||
}
|
||||
|
||||
async function teardown() {
|
||||
try {
|
||||
ChildProcess.execSync('docker ps | grep "authelia-test"');
|
||||
await exec('docker rm -f authelia-test > /dev/null');
|
||||
} catch (e) {
|
||||
// If grep does not find anything, execSync throws an exception since the command returns 1.
|
||||
}
|
||||
}
|
||||
|
||||
export { setup, teardown };
|
|
@ -1,27 +0,0 @@
|
|||
import ChildProcess from 'child_process';
|
||||
import Bluebird from 'bluebird';
|
||||
import Assert from 'assert';
|
||||
|
||||
const execAsync = Bluebird.promisify<string, string>(ChildProcess.exec);
|
||||
|
||||
function sleep(ms: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
describe('Test docker container can run', function() {
|
||||
this.timeout(15000);
|
||||
|
||||
before(async function() {
|
||||
await execAsync('docker run -d -v $(pwd)/config.yml:/etc/authelia/config.yml --name authelia-test clems4ever/authelia');
|
||||
});
|
||||
|
||||
after(async function() {
|
||||
await execAsync('docker rm -f authelia-test');
|
||||
});
|
||||
|
||||
it('should be running', async function() {
|
||||
await sleep(5000);
|
||||
const output: string = await execAsync('docker ps -a | grep "authelia-test"');
|
||||
Assert(output.match(new RegExp('Up [0-9] seconds')));
|
||||
});
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
import ChildProcess from 'child_process';
|
||||
import Bluebird from 'bluebird';
|
||||
import Assert from 'assert';
|
||||
import sleep from '../../helpers/utils/sleep';
|
||||
import AutheliaSuite from '../../helpers/context/AutheliaSuite';
|
||||
|
||||
const execAsync = Bluebird.promisify<string, string>(ChildProcess.exec);
|
||||
|
||||
AutheliaSuite('Test docker container runs as expected', __dirname, function() {
|
||||
this.timeout(15000);
|
||||
|
||||
it('should be running', async function() {
|
||||
await sleep(5000);
|
||||
const output: string = await execAsync('docker ps -a | grep "authelia-test"');
|
||||
Assert(output.match(new RegExp('Up [0-9]+ seconds')));
|
||||
});
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
import fs from 'fs';
|
||||
import { exec } from "../../helpers/utils/exec";
|
||||
import AutheliaServer from "../../helpers/context/AutheliaServer";
|
||||
import DockerEnvironment from "../../helpers/context/DockerEnvironment";
|
||||
|
||||
const autheliaServer = new AutheliaServer(__dirname + '/config.yml');
|
||||
const dockerEnv = new DockerEnvironment([
|
||||
'docker-compose.yml',
|
||||
'example/compose/nginx/backend/docker-compose.yml',
|
||||
'example/compose/nginx/portal/docker-compose.yml',
|
||||
'example/compose/smtp/docker-compose.yml',
|
||||
])
|
||||
|
||||
async function setup() {
|
||||
await exec('mkdir -p /tmp/authelia/db');
|
||||
await exec('./example/compose/nginx/portal/render.js ' + (fs.existsSync('.suite') ? '': '--production'));
|
||||
await dockerEnv.start();
|
||||
await autheliaServer.start();
|
||||
}
|
||||
|
||||
async function teardown() {
|
||||
await dockerEnv.stop();
|
||||
await autheliaServer.stop();
|
||||
await exec('mkdir -p /tmp/authelia/db');
|
||||
}
|
||||
|
||||
export { setup, teardown };
|
|
@ -1,6 +1,3 @@
|
|||
import ChildProcess from 'child_process';
|
||||
import Bluebird from "bluebird";
|
||||
|
||||
import AutheliaSuite from "../../helpers/context/AutheliaSuite";
|
||||
import BadPassword from "./scenarii/BadPassword";
|
||||
import RegisterTotp from './scenarii/RegisterTotp';
|
||||
|
@ -12,21 +9,12 @@ import VerifyEndpoint from './scenarii/VerifyEndpoint';
|
|||
import RequiredTwoFactor from './scenarii/RequiredTwoFactor';
|
||||
import LogoutRedirectToAlreadyLoggedIn from './scenarii/LogoutRedirectToAlreadyLoggedIn';
|
||||
import SimpleAuthentication from './scenarii/SimpleAuthentication';
|
||||
import { exec } from '../../helpers/utils/exec';
|
||||
|
||||
const execAsync = Bluebird.promisify(ChildProcess.exec);
|
||||
|
||||
before(async function() {
|
||||
await execAsync('mkdir -p /tmp/authelia/db');
|
||||
});
|
||||
|
||||
after(async function() {
|
||||
await execAsync('rm -r /tmp/authelia/db');
|
||||
});
|
||||
|
||||
AutheliaSuite('Minimal configuration', __dirname + '/config.yml', function() {
|
||||
AutheliaSuite('Minimal configuration', __dirname, function() {
|
||||
this.timeout(10000);
|
||||
beforeEach(async function() {
|
||||
await execAsync('cp users_database.example.yml users_database.yml');
|
||||
await exec('cp users_database.example.yml users_database.yml');
|
||||
});
|
||||
|
||||
describe('Simple authentication', SimpleAuthentication);
|
|
@ -10,7 +10,7 @@
|
|||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"isolatedModules": false,
|
||||
"noEmit": true,
|
||||
"lib": [
|
||||
"esnext"
|
||||
|
|
Loading…
Reference in New Issue