diff --git a/defaults.yaml b/defaults.yaml index 85a55d6f..8999ccb7 100644 --- a/defaults.yaml +++ b/defaults.yaml @@ -136,6 +136,8 @@ images: command: memcached -u memcache mysql: command: 'mysqld_safe' + postgresql: + command: 'sudo -u postgres /usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main --config_file=/etc/postgresql/9.3/main/postgresql.conf' redis: command: 'redis-server' solr: @@ -155,6 +157,8 @@ images: command: memcached -u memcache mysql: command: 'mysqld_safe' + postgresql: + command: 'sudo -u postgres /usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main --config_file=/etc/postgresql/9.3/main/postgresql.conf' redis: command: 'redis-server' solr: @@ -171,6 +175,8 @@ images: command: memcached -u memcache mysql: command: 'mysqld_safe' + postgresql: + command: 'sudo -u postgres /usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main --config_file=/etc/postgresql/9.3/main/postgresql.conf' redis: command: 'redis-server' solr: @@ -190,6 +196,8 @@ images: command: memcached -u memcache mysql: command: 'mysqld_safe' + postgresql: + command: 'sudo -u postgres /usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main --config_file=/etc/postgresql/9.3/main/postgresql.conf' redis: command: 'redis-server' solr: @@ -209,6 +217,8 @@ images: command: memcached -u memcache mysql: command: 'mysqld_safe' + postgresql: + command: 'sudo -u postgres /usr/lib/postgresql/9.5/bin/postgres -D /var/lib/postgresql/9.5/main --config_file=/etc/postgresql/9.5/main/postgresql.conf' redis: command: 'redis-server' solr: @@ -228,6 +238,8 @@ images: command: memcached -u memcache mysql: command: 'mysqld_safe' + postgresql: + command: 'sudo -u postgres /usr/lib/postgresql/9.5/bin/postgres -D /var/lib/postgresql/9.5/main --config_file=/etc/postgresql/9.5/main/postgresql.conf' redis: command: 'redis-server' solr: @@ -247,6 +259,8 @@ images: command: memcached -u memcache mysql: command: 'mysqld_safe' + postgresql: + command: 'sudo -u postgres /usr/lib/postgresql/9.5/bin/postgres -D /var/lib/postgresql/9.5/main --config_file=/etc/postgresql/9.5/main/postgresql.conf' redis: command: 'redis-server' solr: diff --git a/lib/plugins/TaskRunner/Drupal.js b/lib/plugins/TaskRunner/Drupal.js index 2f031f37..5db1095f 100644 --- a/lib/plugins/TaskRunner/Drupal.js +++ b/lib/plugins/TaskRunner/Drupal.js @@ -81,7 +81,7 @@ class Drupal extends LAMPApp { this.addScriptSymlinks(); } this.addScriptApachePhp(); - this.addScriptMysql(); + this.addScriptDatabase(); this.addScriptCreateDatabase(); this.addScriptAppendSettingsPHPSettings(); this.addScriptPublicFilesDirectory(); @@ -228,11 +228,7 @@ class Drupal extends LAMPApp { ` 'password' => '$DATABASE_PASS',`, ` 'prefix' => '${this.options.databasePrefix}',`, ` 'host' => 'localhost',`, - ` 'driver' => 'mysql',`, - ` 'port' => '3306',`, - // This is pretty gross. We should find a better way to handle this. - ` 'namespace' => 'Drupal\\\\\\\\Core\\\\\\\\Database\\\\\\\\Driver\\\\\\\\mysql',`, - ` 'driver' => 'mysql',`, + ` 'driver' => '${this.options.databaseEngine}',`, ` ),`, ` ),`, `);`, @@ -268,11 +264,10 @@ class Drupal extends LAMPApp { ` 'password' => '$DATABASE_PASS',`, ` 'prefix' => '${this.options.databasePrefix}',`, ` 'host' => 'localhost',`, - ` 'driver' => 'mysql',`, + ` 'driver' => '${this.options.databaseEngine}',`, ` 'port' => '3306',`, // This is pretty gross. We should find a better way to handle this. - ` 'namespace' => 'Drupal\\\\\\\\Core\\\\\\\\Database\\\\\\\\Driver\\\\\\\\mysql',`, - ` 'driver' => 'mysql',`, + ` 'namespace' => 'Drupal\\\\\\\\Core\\\\\\\\Database\\\\\\\\Driver\\\\\\\\${this.options.databaseEngine}',`, ` ),`, ` ),`, `);`, diff --git a/lib/plugins/TaskRunner/LAMPApp.js b/lib/plugins/TaskRunner/LAMPApp.js index a1a01cd0..e8cdf377 100644 --- a/lib/plugins/TaskRunner/LAMPApp.js +++ b/lib/plugins/TaskRunner/LAMPApp.js @@ -10,6 +10,9 @@ class LAMPApp extends Script { * @param {object} container - An instantiated and configured Container object. * @param {object} options - A hash of configuration options specific to this task. * @param {string} [options.database] - The file name of the database to import if specified. Note that this database *must be added to the assets array separately*. + * @param {string} [options.database] - The file name of the database to import if specified. Note that this database *must be added to the assets array separately*. + * @param {string} [options.databaseEngine] - The name of the database engine to use. Must be either `mysql` or `pgsql`. Defaults to `mysql`. + * @param {string} [options.databaseUser] - The username of the database to use. * @param {string} [options.databaseName] - The name of the database to use. Defaults to 'lampdb'. * @param {string} [options.databaseUser] - The username of the database to use. Defaults to 'root'. * @param {string} [options.databasePass] - The password for the database username. Defaults to 'strongpassword'. @@ -36,13 +39,19 @@ class LAMPApp extends Script { * Options are {'enabled' (boolean, defaults to false) and 'pathToVcl' (string)}. * @param {boolean} [options.restartMysql] - Whether to restart MySQL. If mysqlCnfOptions is set, MySQL will be restarted automatically, * so you probably won't need to use this. + * @param {boolean} [options.restartPostgresql] - Whether to restart PostgreSQL. */ constructor(container, options) { super(container, options); this.databaseName = options.databaseName || 'lampdb'; + + this.options.databasePrefix = options.databasePrefix || ''; + this.options.databaseEngine = options.databaseEngine || 'mysql'; + this.databaseUser = options.databaseUser || 'root'; this.databasePass = options.databasePass || 'strongpassword'; + this.options.cliDefines = options.cliDefines || {}; this.options.mysqlCnfOptions = options.mysqlCnfOptions || {}; this.options.phpIniOptions = options.phpIniOptions || {}; @@ -54,6 +63,7 @@ class LAMPApp extends Script { this.options.restartApache = options.restartApache || false; this.options.varnish = options.varnish || {}; this.options.restartMysql = options.restartMysql || false; + this.options.restartPostgresql = options.restartPostgres || false; // TODO: Add some kind of validation. @@ -82,7 +92,7 @@ class LAMPApp extends Script { this.addScriptImportDatabase(); } this.addScriptApachePhp(); - this.addScriptMysql(); + this.addScriptDatabase(); } addScriptHeader() { @@ -112,20 +122,23 @@ class LAMPApp extends Script { ]); } - addScriptCreateDatabase() { - this.script = this.script.concat([ - "echo 'Creating MySQL Database, user and granting access.'", - 'DATABASE_NAME=' + this.databaseName, - 'DATABASE_USER=' + this.databaseUser, - 'DATABASE_PASS=' + this.databasePass, - // Set db credentials if found. - 'if [ -e $ASSET_DIR/credentials.sh ]; then source $ASSET_DIR/credentials.sh; fi', - 'mysql < /mysql-setup.sql', - "mysql -e 'create database '$DATABASE_NAME", - 'if [ "$DATABASE_USER" != "root" ]; then mysql -e \'create user "\'$DATABASE_USER\'"@"localhost" identified by "\'$DATABASE_PASS\'"\'; fi', - "mysql -e 'grant all on '$DATABASE_NAME'.* to \"'$DATABASE_USER'\"@\"localhost\"'", - "mysql -e 'flush privileges'", - ]); + addScriptCreateDatbase() { + switch (this.options.databaseEngine) { + case 'mysql': + this.script = this.script.concat([ + 'echo \'Creating MySQL Database, user and granting access.\'', + 'mysql -e \'create database ' + this.databaseName + '\'', + 'mysql -e \'grant all on ' + this.databaseName + '.* to "root"@"localhost"\'', + 'mysql -e \'flush privileges\'', + ]); + break; + case 'pgsql': + this.script = this.script.concat([ + 'echo \'Creating PostgreSQL Database, user and granting access.\'', + 'sudo -u postgres createdb --encoding=UTF8 --owner=root --template=template0 ' + this.databaseName, + ]); + break; + } } addScriptImportDatabase() { @@ -141,9 +154,21 @@ class LAMPApp extends Script { } else { databaseImportBase = 'pv $ASSET_DIR/' + this.options.database + ' | '; } - this.script.push( - `${databaseImportBase} $(mysql -u $DATABASE_USER --password=$DATABASE_PASS $DATABASE_NAME);` - ); + + else if (this.options.databaseBzipped) { + databaseImportBase = 'bunzip2 -c'; + } + else { + databaseImportBase = 'cat'; + } + switch (this.options.databaseEngine) { + case 'mysql': + this.script.push(`${databaseImportBase} $ASSET_DIR/${this.options.database} | $(mysql -u ${constants.DATABASE_USER} --password=${constants.DATABASE_PASSWORD} ${this.databaseName});`); + break; + case 'pgsql': + this.script.push(`sudo -u postgres ${databaseImportBase} $ASSET_DIR/${this.options.database} | $(psql ${this.databaseName});`); + break; + } this.script.push(`rm $ASSET_DIR/${this.options.database};`); } } @@ -171,9 +196,16 @@ class LAMPApp extends Script { } // a meta-script that installs all mysql related scripts. - addScriptMysql() { - this.addScriptMysqlCnfOptions(); - this.addScriptRestartMysql(); + addScriptDatabase() { + switch (this.options.databaseEngine) { + case 'mysql': + this.addScriptMysqlCnfOptions(); + this.addScriptRestartMysql(); + break; + case 'pgsql': + this.addScriptRestartPostgresql(); + break; + } } // a meta-script that runs all setup commands. @@ -372,6 +404,12 @@ class LAMPApp extends Script { } } + addScriptRestartPostgresql() { + if (this.options.restartMysql) { + this.script = this.script.concat('service postgresql restart'); + } + } + isEmptyObject(o) { return !Object.keys(o).length; } diff --git a/lib/plugins/TaskRunner/WordPressApp.js b/lib/plugins/TaskRunner/WordPressApp.js index 48cda4b5..f4999071 100644 --- a/lib/plugins/TaskRunner/WordPressApp.js +++ b/lib/plugins/TaskRunner/WordPressApp.js @@ -79,7 +79,7 @@ class WordPressApp extends LAMPApp { this.addScriptFlushCaches(); } this.addScriptApachePhp(); - this.addScriptMysql(); + this.addScriptDatabase(); } /** diff --git a/test/tasks/DrupalApp.js b/test/tasks/DrupalApp.js index 5b9eeb23..b93030cc 100644 --- a/test/tasks/DrupalApp.js +++ b/test/tasks/DrupalApp.js @@ -17,8 +17,10 @@ const mockContainer = { describe('Drupal App', function() { let options; let options2; + let options3; let app; let app2; + let app3; before(function(done) { options = { @@ -27,11 +29,18 @@ describe('Drupal App', function() { }; options2 = { database: 'my-cool-db.sql', + databaseEngine: 'mysql', databaseGzipped: true, clearCaches: false, databasePrefix: 'my_custom_prefix', varnish: {enable: true}, }; + options3 = { + database: 'my-cool-db.sql', + databaseEngine: 'pgsql', + databaseGzipped: true, + clearCaches: false, + }; done(); }); @@ -46,6 +55,11 @@ describe('Drupal App', function() { app2.should.have.property('id').which.is.a.String; app2.id.should.match(/[0-9a-z]{16}/g); + app3 = new DrupalApp(mockContainer, options3); + app3.should.be.ok; + app3.should.have.property('id').which.is.a.String; + app3.id.should.match(/[0-9a-z]{16}/g); + done(); }); @@ -74,11 +88,11 @@ describe('Drupal App', function() { let support = app.drupalVersionSupported(); support.should.be.ok; - const app3 = new DrupalApp(mockContainer, Object.assign({}, options, {drupalVersion: 1})); - app3.script = []; - app3.addScriptUnsupportedDrupalVersion(); - app3.script.should.have.length(2); - support = app3.drupalVersionSupported(); + const app4 = new DrupalApp(mockContainer, Object.assign({}, options, {drupalVersion: 1})); + app4.script = []; + app4.addScriptUnsupportedDrupalVersion(); + app4.script.should.have.length(2); + support = app4.drupalVersionSupported(); support.should.not.be.ok; done(); }); @@ -91,11 +105,11 @@ describe('Drupal App', function() { app.script.should.eql(['drush --root=/var/www/html cache-clear all']); // testing D8 - const app3 = new DrupalApp(mockContainer, Object.assign({}, options, {drupalVersion: 8})); - app3.script = []; - app3.addScriptClearCaches(); - app3.script.should.have.length(1); - app3.script.should.eql(['drush --root=/var/www/html cache-rebuild']); + const app4 = new DrupalApp(mockContainer, Object.assign({}, options, {drupalVersion: 8})); + app4.script = []; + app4.addScriptClearCaches(); + app4.script.should.have.length(1); + app4.script.should.eql(['drush --root=/var/www/html cache-rebuild']); done(); }); @@ -162,11 +176,11 @@ describe('Drupal App', function() { }); it('should append custom settings to script', function(done) { - const app3 = new DrupalApp(mockContainer, Object.assign({}, options, {settingsRequireFile: 'dummy.php', settingsAppend: 'dummy'})); - app3.script = []; - app3.appendCustomSettings(); - app3.script.should.have.length(2); - app3.script.should.eql([ + const app4 = new DrupalApp(mockContainer, Object.assign({}, options, {settingsRequireFile: 'dummy.php', settingsAppend: 'dummy'})); + app4.script = []; + app4.appendCustomSettings(); + app4.script.should.have.length(2); + app4.script.should.eql([ 'echo "require_once(\'dummy.php\');" >> /var/www/html/sites/default/settings.php', 'echo dummy >> /var/www/html/sites/default/settings.php', ]); @@ -176,7 +190,7 @@ describe('Drupal App', function() { it('should add D8 settings', function(done) { app.script = []; app.addD8PHPSettings(); - app.script.should.have.length(24); + app.script.should.have.length(23); done(); }); @@ -184,9 +198,17 @@ describe('Drupal App', function() { app.script = []; app.addD7PHPSettings(); app.script.should.have.length(19); + app.script.should.containEql(' \'driver\' => \'mysql\','); done(); }); + it('should add postgreSQL settings', function(done) { + app3.script = []; + app3.addD7PHPSettings(); + app3.script.should.have.length(19); + app3.script.should.containEql(' \'driver\' => \'pgsql\','); + done(); + }); it('should add Drupal settings and any custom settings', function(done) { // testing D7 (default) @@ -195,10 +217,10 @@ describe('Drupal App', function() { app.script.should.have.length(19); // testing D8 - const app3 = new DrupalApp(mockContainer, Object.assign({}, options, {drupalVersion: 8})); - app3.script = []; - app3.addScriptAppendSettingsPHPSettings(); - app3.script.should.have.length(24); + const app4 = new DrupalApp(mockContainer, Object.assign({}, options, {drupalVersion: 8})); + app4.script = []; + app4.addScriptAppendSettingsPHPSettings(); + app4.script.should.have.length(23); done(); }); diff --git a/test/tasks/LAMPApp.js b/test/tasks/LAMPApp.js index d5bc5e65..16e7adbd 100644 --- a/test/tasks/LAMPApp.js +++ b/test/tasks/LAMPApp.js @@ -63,7 +63,16 @@ describe('LAMP App', function() { }; var appGZ = new LAMPApp(mockContainer, optionsGZ); - it('builds proper LAMP script', function() { + var optionsPgsql = { + database: 'my-cool-db.sql', + databaseEngine: 'pgsql', + databaseName: 'my-cool-db', + databaseGzipped: false, + }; + var appPgsql = new LAMPApp(mockContainer, optionsPgsql); + + it('builds proper lamp script', function() { + app.script.should.containEql('mkdir -p $SRC_DIR; cd $SRC_DIR'); @@ -77,6 +86,10 @@ describe('LAMP App', function() { 'cat $ASSET_DIR/my-cool-db.sql | $(mysql -u $DATABASE_USER --password=$DATABASE_PASS $DATABASE_NAME)' ); + appPgsql.script.should.not.containEql('mysql -e \'create database my-cool-db\''); + appPgsql.script.should.containEql( + `sudo -u postgres cat $ASSET_DIR/my-cool-db.sql | $(psql my-cool-db);` + ); }); it('handles gzipped databases', function() {