浏览代码

Sqlite Tweaks

- Added cypress testing in CI for sqlite
- Cleaned up promises in setup
- Ensure check for settings is strict
Jamie Curnow 5 年之前
父节点
当前提交
492d450d26
共有 5 个文件被更改,包括 175 次插入100 次删除
  1. 0 0
      .jenkins/config-mysql.json
  2. 21 0
      .jenkins/config-sqlite.json
  3. 32 4
      Jenkinsfile
  4. 107 94
      backend/setup.js
  5. 15 2
      docker/docker-compose.ci.yml

+ 0 - 0
.jenkins/config.json → .jenkins/config-mysql.json


+ 21 - 0
.jenkins/config-sqlite.json

@@ -0,0 +1,21 @@
+{
+	"database": {
+		"engine": "knex-native",
+		"knex": {
+			"client": "sqlite3",
+			"connection": {
+				"filename": "/data/database.sqlite"
+			},
+			"pool": {
+				"min": 0,
+				"max": 1,
+				"createTimeoutMillis": 3000,
+				"acquireTimeoutMillis": 30000,
+				"idleTimeoutMillis": 30000,
+				"reapIntervalMillis": 1000,
+				"createRetryIntervalMillis": 100,
+				"propagateCreateError": false
+			}
+		}
+	}
+}

+ 32 - 4
Jenkinsfile

@@ -83,11 +83,11 @@ pipeline {
 				'''
 			}
 		}
-		stage('Test') {
+		stage('Integration Tests Sqlite') {
 			steps {
 				// Bring up a stack
-				sh 'docker-compose up -d fullstack'
-				sh './scripts/wait-healthy $(docker-compose ps -q fullstack) 120'
+				sh 'docker-compose up -d fullstack-sqlite'
+				sh './scripts/wait-healthy $(docker-compose ps -q fullstack-sqlite) 120'
 
 				// Run tests
 				sh 'rm -rf test/results'
@@ -99,8 +99,36 @@ pipeline {
 				always {
 					// Dumps to analyze later
 					sh 'mkdir -p debug'
-					sh 'docker-compose logs fullstack | gzip > debug/docker_fullstack.log.gz'
+					sh 'docker-compose logs fullstack-sqlite | gzip > debug/docker_fullstack_sqlite.log.gz'
 					sh 'docker-compose logs db | gzip > debug/docker_db.log.gz'
+					sh 'docker-compose down'
+					// Cypress videos and screenshot artifacts
+					dir(path: 'test/results') {
+						archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
+					}
+					junit 'test/results/junit/*'
+				}
+			}
+		}
+		stage('Integration Tests Mysql') {
+			steps {
+				// Bring up a stack
+				sh 'docker-compose up -d fullstack-mysql'
+				sh './scripts/wait-healthy $(docker-compose ps -q fullstack-mysql) 120'
+
+				// Run tests
+				sh 'rm -rf test/results'
+				sh 'docker-compose up cypress'
+				// Get results
+				sh 'docker cp -L "$(docker-compose ps -q cypress):/results" test/'
+			}
+			post {
+				always {
+					// Dumps to analyze later
+					sh 'mkdir -p debug'
+					sh 'docker-compose logs fullstack-mysql | gzip > debug/docker_fullstack_mysql.log.gz'
+					sh 'docker-compose logs db | gzip > debug/docker_db.log.gz'
+					sh 'docker-compose down'
 					// Cypress videos and screenshot artifacts
 					dir(path: 'test/results') {
 						archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'

+ 107 - 94
backend/setup.js

@@ -8,92 +8,101 @@ const authModel           = require('./models/auth');
 const settingModel        = require('./models/setting');
 const debug_mode          = process.env.NODE_ENV !== 'production' || !!process.env.DEBUG;
 
-function setupJwt(resolve, reject) {
-	// Now go and check if the jwt gpg keys have been created and if not, create them
-	if (!config.has('jwt') || !config.has('jwt.key') || !config.has('jwt.pub')) {
-		logger.info('Creating a new JWT key pair...');
+/**
+ * Creates a new JWT RSA Keypair if not alread set on the config
+ *
+ * @returns {Promise}
+ */
+const setupJwt = () => {
+	return new Promise((resolve, reject) => {
+		// Now go and check if the jwt gpg keys have been created and if not, create them
+		if (!config.has('jwt') || !config.has('jwt.key') || !config.has('jwt.pub')) {
+			logger.info('Creating a new JWT key pair...');
 
-		// jwt keys are not configured properly
-		const filename  = config.util.getEnv('NODE_CONFIG_DIR') + '/' + (config.util.getEnv('NODE_ENV') || 'default') + '.json';
-		let config_data = {};
+			// jwt keys are not configured properly
+			const filename  = config.util.getEnv('NODE_CONFIG_DIR') + '/' + (config.util.getEnv('NODE_ENV') || 'default') + '.json';
+			let config_data = {};
 
-		try {
-			config_data = require(filename);
-		} catch (err) {
-			// do nothing
-			if (debug_mode) {
-				logger.debug(filename + ' config file could not be required');
+			try {
+				config_data = require(filename);
+			} catch (err) {
+				// do nothing
+				if (debug_mode) {
+					logger.debug(filename + ' config file could not be required');
+				}
 			}
-		}
 
-		// Now create the keys and save them in the config.
-		let key = new NodeRSA({b: 2048});
-		key.generateKeyPair();
+			// Now create the keys and save them in the config.
+			let key = new NodeRSA({ b: 2048 });
+			key.generateKeyPair();
 
-		config_data.jwt = {
-			key: key.exportKey('private').toString(),
-			pub: key.exportKey('public').toString()
-		};
+			config_data.jwt = {
+				key: key.exportKey('private').toString(),
+				pub: key.exportKey('public').toString(),
+			};
 
-		// Write config
-		fs.writeFile(filename, JSON.stringify(config_data, null, 2), (err) => {
-			if (err) {
-				logger.error('Could not write JWT key pair to config file: ' + filename);
-				reject(err);
-			} else {
-				logger.info('Wrote JWT key pair to config file: ' + filename);
+			// Write config
+			fs.writeFile(filename, JSON.stringify(config_data, null, 2), (err) => {
+				if (err) {
+					logger.error('Could not write JWT key pair to config file: ' + filename);
+					reject(err);
+				} else {
+					logger.info('Wrote JWT key pair to config file: ' + filename);
 
-				logger.warn('Restarting interface to apply new configuration');
-				process.exit(0);
+					logger.warn('Restarting interface to apply new configuration');
+					process.exit(0);
+				}
+			});
+		} else {
+			// JWT key pair exists
+			if (debug_mode) {
+				logger.debug('JWT Keypair already exists');
 			}
-		});
 
-	} else {
-		// JWT key pair exists
-		if (debug_mode) {
-			logger.debug('JWT Keypair already exists');
+			resolve();
 		}
+	});
+};
 
-		resolve();
-	}
-}
-
-function setupDefaultUser() {
-	(userModel
+/**
+ * Creates a default admin users if one doesn't already exist in the database
+ *
+ * @returns {Promise}
+ */
+const setupDefaultUser = () => {
+	return userModel
 		.query()
 		.select(userModel.raw('COUNT(`id`) as `count`'))
 		.where('is_deleted', 0)
 		.first()
-	).then( (row) => {
-		if (!row.count) {
-			// Create a new user and set password
-			logger.info('Creating a new user: [email protected] with password: changeme');
+		.then((row) => {
+			if (!row.count) {
+				// Create a new user and set password
+				logger.info('Creating a new user: [email protected] with password: changeme');
 
-			let data = {
-				is_deleted: 0,
-				email:      '[email protected]',
-				name:       'Administrator',
-				nickname:   'Admin',
-				avatar:     '',
-				roles:      ['admin']
-			};
+				let data = {
+					is_deleted: 0,
+					email:      '[email protected]',
+					name:       'Administrator',
+					nickname:   'Admin',
+					avatar:     '',
+					roles:      ['admin'],
+				};
 
-			return userModel
-				.query()
-				.insertAndFetch(data)
-				.then( (user) => {
-					return authModel
-						.query()
-						.insert({
-							user_id: user.id,
-							type:    'password',
-							secret:  'changeme',
-							meta:    {}
-						})
-						.then(() => {
-							return userPermissionModel
-								.query()
-								.insert({
+				return userModel
+					.query()
+					.insertAndFetch(data)
+					.then((user) => {
+						return authModel
+							.query()
+							.insert({
+								user_id: user.id,
+								type:    'password',
+								secret:  'changeme',
+								meta:    {},
+							})
+							.then(() => {
+								return userPermissionModel.query().insert({
 									user_id:           user.id,
 									visibility:        'all',
 									proxy_hosts:       'manage',
@@ -101,25 +110,31 @@ function setupDefaultUser() {
 									dead_hosts:        'manage',
 									streams:           'manage',
 									access_lists:      'manage',
-									certificates:      'manage'
+									certificates:      'manage',
 								});
-						});
-				})
-				.then(() => {
-					logger.info('Initial admin setup completed');
-				});
-		} else if (debug_mode) {
-			logger.debug('Admin user setup not required');
-		}
-	});
-}
+							});
+					})
+					.then(() => {
+						logger.info('Initial admin setup completed');
+					});
+			} else if (debug_mode) {
+				logger.debug('Admin user setup not required');
+			}
+		});
+};
 
-function setupDefaultSettings() {
+/**
+ * Creates default settings if they don't already exist in the database
+ *
+ * @returns {Promise}
+ */
+const setupDefaultSettings = () => {
 	return settingModel
 		.query()
-		.select(userModel.raw('COUNT(`id`) as `count`'))
+		.select(settingModel.raw('COUNT(`id`) as `count`'))
+		.where({id: 'default-site'})
 		.first()
-		.then( (row) => {
+		.then((row) => {
 			if (!row.count) {
 				settingModel
 					.query()
@@ -128,22 +143,20 @@ function setupDefaultSettings() {
 						name:        'Default Site',
 						description: 'What to show when Nginx is hit with an unknown Host',
 						value:       'congratulations',
-						meta:        {}
-					}).then(() => {
+						meta:        {},
+					})
+					.then(() => {
 						logger.info('Default settings added');
 					});
-			} if (debug_mode) {
+			}
+			if (debug_mode) {
 				logger.debug('Default setting setup not required');
 			}
 		});
-}
+};
 
 module.exports = function () {
-	return new Promise((resolve, reject) => {
-		return setupJwt(resolve, reject);
-	}).then(() => {
-		return setupDefaultUser();
-	}).then(() => {
-		return setupDefaultSettings();
-	});
+	return setupJwt()
+		.then(setupDefaultUser)
+		.then(setupDefaultSettings);
 };

+ 15 - 2
docker/docker-compose.ci.yml

@@ -2,14 +2,14 @@
 version: "3"
 services:
 
-  fullstack:
+  fullstack-mysql:
     image: ${IMAGE}:ci-${BUILD_NUMBER}
     environment:
       - NODE_ENV=development
       - FORCE_COLOR=1
     volumes:
       - npm_data:/data
-      - ../.jenkins/config.json:/app/config/production.json
+      - ../.jenkins/config-mysql.json:/app/config/production.json
     expose:
       - 81
       - 80
@@ -17,6 +17,19 @@ services:
     depends_on:
       - db
 
+  fullstack-sqlite:
+    image: ${IMAGE}:ci-${BUILD_NUMBER}
+    environment:
+      - NODE_ENV=development
+      - FORCE_COLOR=1
+    volumes:
+      - npm_data:/data
+      - ../.jenkins/config-sqlite.json:/app/config/production.json
+    expose:
+      - 81
+      - 80
+      - 443
+
   db:
     image: jc21/mariadb-aria
     environment: