mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Export backup prior to migration
Closes #847 - Added logic to export database to the `core\server\data\` folder prior to beginning a migration. - Factored out versioning logic from migration to prevent circular references
This commit is contained in:
parent
664048be4e
commit
07df9911ce
5 changed files with 99 additions and 71 deletions
|
@ -1,8 +1,8 @@
|
|||
var when = require('when'),
|
||||
_ = require('lodash'),
|
||||
migration = require('../migration'),
|
||||
knex = require('../../models/base').knex,
|
||||
schema = require('../schema').tables,
|
||||
var _ = require('lodash'),
|
||||
when = require('when'),
|
||||
versioning = require('../versioning'),
|
||||
knex = require('../../models/base').knex,
|
||||
schema = require('../schema').tables,
|
||||
|
||||
excludedTables = ['sessions'],
|
||||
exporter;
|
||||
|
@ -10,7 +10,7 @@ var when = require('when'),
|
|||
exporter = function () {
|
||||
var tablesToExport = _.keys(schema);
|
||||
|
||||
return when.join(migration.getDatabaseVersion(), tablesToExport).then(function (results) {
|
||||
return when.join(versioning.getDatabaseVersion(), tablesToExport).then(function (results) {
|
||||
var version = results[0],
|
||||
tables = results[1],
|
||||
selectOps = _.map(tables, function (name) {
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
var _ = require('lodash'),
|
||||
when = require('when'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
nodefn = require('when/node/function'),
|
||||
errors = require('../../errors'),
|
||||
client = require('../../models/base').client,
|
||||
knex = require('../../models/base').knex,
|
||||
sequence = require('when/sequence'),
|
||||
|
||||
defaultSettings = require('../default-settings'),
|
||||
versioning = require('../versioning'),
|
||||
Settings = require('../../models/settings').Settings,
|
||||
fixtures = require('../fixtures'),
|
||||
schema = require('../schema').tables,
|
||||
dataExport = require('../export'),
|
||||
|
||||
initialVersion = '000',
|
||||
schemaTables = _.keys(schema),
|
||||
defaultDatabaseVersion,
|
||||
|
||||
init,
|
||||
reset,
|
||||
|
@ -20,58 +22,6 @@ var _ = require('lodash'),
|
|||
migrateUpFreshDb,
|
||||
getTables;
|
||||
|
||||
// Default Database Version
|
||||
// The migration version number according to the hardcoded default settings
|
||||
// This is the version the database should be at or migrated to
|
||||
function getDefaultDatabaseVersion() {
|
||||
if (!defaultDatabaseVersion) {
|
||||
// This be the current version according to the software
|
||||
defaultDatabaseVersion = _.find(defaultSettings.core, function (setting) {
|
||||
return setting.key === 'databaseVersion';
|
||||
}).defaultValue;
|
||||
}
|
||||
|
||||
return defaultDatabaseVersion;
|
||||
}
|
||||
|
||||
// Database Current Version
|
||||
// The migration version number according to the database
|
||||
// This is what the database is currently at and may need to be updated
|
||||
function getDatabaseVersion() {
|
||||
return knex.schema.hasTable('settings').then(function (exists) {
|
||||
// Check for the current version from the settings table
|
||||
if (exists) {
|
||||
// Temporary code to deal with old databases with currentVersion settings
|
||||
return knex('settings')
|
||||
.where('key', 'databaseVersion')
|
||||
.orWhere('key', 'currentVersion')
|
||||
.select('value')
|
||||
.then(function (versions) {
|
||||
var databaseVersion = _.reduce(versions, function (memo, version) {
|
||||
if (isNaN(version.value)) {
|
||||
errors.throwError('Database version is not recognised');
|
||||
}
|
||||
return parseInt(version.value, 10) > parseInt(memo, 10) ? version.value : memo;
|
||||
}, initialVersion);
|
||||
|
||||
if (!databaseVersion || databaseVersion.length === 0) {
|
||||
// we didn't get a response we understood, assume initialVersion
|
||||
databaseVersion = initialVersion;
|
||||
}
|
||||
|
||||
return databaseVersion;
|
||||
});
|
||||
}
|
||||
throw new Error('Settings table does not exist');
|
||||
});
|
||||
}
|
||||
|
||||
function setDatabaseVersion() {
|
||||
return knex('settings')
|
||||
.where('key', 'databaseVersion')
|
||||
.update({ 'value': defaultDatabaseVersion });
|
||||
}
|
||||
|
||||
function createTable(table) {
|
||||
return knex.schema.createTable(table, function (t) {
|
||||
var column,
|
||||
|
@ -168,8 +118,8 @@ init = function () {
|
|||
// 2. The database exists but is out of date
|
||||
// 3. The database exists but the currentVersion setting does not or cannot be understood
|
||||
// 4. The database has not yet been created
|
||||
return getDatabaseVersion().then(function (databaseVersion) {
|
||||
var defaultVersion = getDefaultDatabaseVersion();
|
||||
return versioning.getDatabaseVersion().then(function (databaseVersion) {
|
||||
var defaultVersion = versioning.getDefaultDatabaseVersion();
|
||||
if (databaseVersion === defaultVersion) {
|
||||
// 1. The database exists and is up-to-date
|
||||
return when.resolve();
|
||||
|
@ -179,7 +129,7 @@ init = function () {
|
|||
// Migrate to latest version
|
||||
return self.migrateUp().then(function () {
|
||||
// Finally update the databases current version
|
||||
return setDatabaseVersion();
|
||||
return versioning.setDatabaseVersion();
|
||||
});
|
||||
}
|
||||
if (databaseVersion > defaultVersion) {
|
||||
|
@ -249,9 +199,20 @@ function checkMySQLPostTable() {
|
|||
});
|
||||
}
|
||||
|
||||
function backupDatabase() {
|
||||
return dataExport().then(function (exportedData) {
|
||||
// Save the exported data to the file system for download
|
||||
var fileName = path.resolve(__dirname + '/../exported-' + (new Date().getTime()) + '.json');
|
||||
|
||||
return nodefn.call(fs.writeFile, fileName, JSON.stringify(exportedData));
|
||||
});
|
||||
}
|
||||
|
||||
// Migrate from a specific version to the latest
|
||||
migrateUp = function () {
|
||||
return getTables().then(function (oldTables) {
|
||||
return backupDatabase().then(function () {
|
||||
return getTables();
|
||||
}).then(function (oldTables) {
|
||||
// if tables exist and client is mysqls check if posts table is okay
|
||||
if (!_.isEmpty(oldTables) && client === 'mysql') {
|
||||
return checkMySQLPostTable().then(function () {
|
||||
|
@ -293,7 +254,6 @@ getTables = function () {
|
|||
};
|
||||
|
||||
module.exports = {
|
||||
getDatabaseVersion: getDatabaseVersion,
|
||||
init: init,
|
||||
reset: reset,
|
||||
migrateUp: migrateUp,
|
||||
|
|
66
core/server/data/versioning/index.js
Normal file
66
core/server/data/versioning/index.js
Normal file
|
@ -0,0 +1,66 @@
|
|||
var _ = require('lodash'),
|
||||
errors = require('../../errors'),
|
||||
knex = require('../../models/base').knex,
|
||||
|
||||
defaultSettings = require('../default-settings'),
|
||||
|
||||
initialVersion = '000',
|
||||
defaultDatabaseVersion;
|
||||
|
||||
// Default Database Version
|
||||
// The migration version number according to the hardcoded default settings
|
||||
// This is the version the database should be at or migrated to
|
||||
function getDefaultDatabaseVersion() {
|
||||
if (!defaultDatabaseVersion) {
|
||||
// This be the current version according to the software
|
||||
defaultDatabaseVersion = _.find(defaultSettings.core, function (setting) {
|
||||
return setting.key === 'databaseVersion';
|
||||
}).defaultValue;
|
||||
}
|
||||
|
||||
return defaultDatabaseVersion;
|
||||
}
|
||||
|
||||
// Database Current Version
|
||||
// The migration version number according to the database
|
||||
// This is what the database is currently at and may need to be updated
|
||||
function getDatabaseVersion() {
|
||||
return knex.schema.hasTable('settings').then(function (exists) {
|
||||
// Check for the current version from the settings table
|
||||
if (exists) {
|
||||
// Temporary code to deal with old databases with currentVersion settings
|
||||
return knex('settings')
|
||||
.where('key', 'databaseVersion')
|
||||
.orWhere('key', 'currentVersion')
|
||||
.select('value')
|
||||
.then(function (versions) {
|
||||
var databaseVersion = _.reduce(versions, function (memo, version) {
|
||||
if (isNaN(version.value)) {
|
||||
errors.throwError('Database version is not recognised');
|
||||
}
|
||||
return parseInt(version.value, 10) > parseInt(memo, 10) ? version.value : memo;
|
||||
}, initialVersion);
|
||||
|
||||
if (!databaseVersion || databaseVersion.length === 0) {
|
||||
// we didn't get a response we understood, assume initialVersion
|
||||
databaseVersion = initialVersion;
|
||||
}
|
||||
|
||||
return databaseVersion;
|
||||
});
|
||||
}
|
||||
throw new Error('Settings table does not exist');
|
||||
});
|
||||
}
|
||||
|
||||
function setDatabaseVersion() {
|
||||
return knex('settings')
|
||||
.where('key', 'databaseVersion')
|
||||
.update({ 'value': defaultDatabaseVersion });
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getDefaultDatabaseVersion: getDefaultDatabaseVersion,
|
||||
getDatabaseVersion: getDatabaseVersion,
|
||||
setDatabaseVersion: setDatabaseVersion
|
||||
};
|
|
@ -8,6 +8,7 @@ var testUtils = require('../utils'),
|
|||
|
||||
// Stuff we are testing
|
||||
migration = require('../../server/data/migration'),
|
||||
versioning = require('../../server/data/versioning'),
|
||||
exporter = require('../../server/data/export'),
|
||||
Settings = require('../../server/models/settings').Settings;
|
||||
|
||||
|
@ -39,7 +40,7 @@ describe("Exporter", function () {
|
|||
|
||||
it("exports data", function (done) {
|
||||
// Stub migrations to return 000 as the current database version
|
||||
var migrationStub = sandbox.stub(migration, "getDatabaseVersion", function () {
|
||||
var versioningStub = sandbox.stub(versioning, "getDatabaseVersion", function () {
|
||||
return when.resolve("003");
|
||||
});
|
||||
|
||||
|
@ -61,7 +62,7 @@ describe("Exporter", function () {
|
|||
// should not export sqlite data
|
||||
should.not.exist(exportData.data.sqlite_sequence);
|
||||
|
||||
migrationStub.restore();
|
||||
versioningStub.restore();
|
||||
done();
|
||||
}).catch(done);
|
||||
});
|
||||
|
|
|
@ -8,8 +8,9 @@ var testUtils = require('../utils'),
|
|||
errors = require('../../server/errors'),
|
||||
|
||||
// Stuff we are testing
|
||||
knex = require("../../server/models/base").knex,
|
||||
knex = require('../../server/models/base').knex,
|
||||
migration = require('../../server/data/migration'),
|
||||
versioning = require('../../server/data/versioning'),
|
||||
exporter = require('../../server/data/export'),
|
||||
importer = require('../../server/data/import'),
|
||||
Importer000 = require('../../server/data/import/000'),
|
||||
|
@ -113,7 +114,7 @@ describe("Import", function () {
|
|||
|
||||
it("imports data from 000", function (done) {
|
||||
var exportData,
|
||||
migrationStub = sandbox.stub(migration, "getDatabaseVersion", function () {
|
||||
versioningStub = sandbox.stub(versioning, "getDatabaseVersion", function () {
|
||||
return when.resolve("000");
|
||||
});
|
||||
|
||||
|
@ -151,7 +152,7 @@ describe("Import", function () {
|
|||
// test tags
|
||||
tags.length.should.equal(exportData.data.tags.length, 'no new tags');
|
||||
|
||||
migrationStub.restore();
|
||||
versioningStub.restore();
|
||||
|
||||
done();
|
||||
}).catch(done);
|
||||
|
|
Loading…
Add table
Reference in a new issue