@bluecadet/bcdb
Advanced tools
Comparing version 1.0.7 to 1.1.0
@@ -7,3 +7,5 @@ const chalk = require('chalk'); | ||
console.log(''); | ||
console.log(chalk.green('bcdb pull --exclude=[path/to/exclude] ') + ' seperate multiple paths with a comma (,)'); | ||
console.log(chalk.green('bcdb pull --exclude=[path/to/exclude] --force -f')); | ||
console.log(chalk.blue('--force') + ' or ' + chalk.blue('-f') + ': force a new database backup to be created'); | ||
console.log(chalk.blue('--exclude=[path/to/exclude]') + ': seperate multiple paths with a comma (,)'); | ||
console.log(''); | ||
@@ -10,0 +12,0 @@ console.log(chalk.green('bcdb init ') + ' initialize a project'); |
@@ -12,2 +12,3 @@ const fs = require('fs'); | ||
let db_host = response.db_host ? response.db_host : 'localhost'; | ||
let bac_exp = response.bac_exp ? response.bac_exp : '60'; | ||
@@ -24,2 +25,3 @@ let data = `module.exports = { | ||
file_path: '${filepath}', | ||
backup_expires: '${bac_exp}', | ||
}`; | ||
@@ -62,3 +64,3 @@ | ||
type: 'input', | ||
query: `${chalk.cyan('Local database user ')} (root):`, | ||
query: `${chalk.cyan('Local database user ')} [root]:`, | ||
handle: 'db_user' | ||
@@ -68,3 +70,3 @@ }, | ||
type: 'input', | ||
query: `${chalk.cyan('Local database password')} (root):`, | ||
query: `${chalk.cyan('Local database password')} [root]:`, | ||
handle: 'db_pass' | ||
@@ -74,3 +76,3 @@ }, | ||
type: 'input', | ||
query: `${chalk.cyan('Local database hostname')} (localhost):`, | ||
query: `${chalk.cyan('Local database hostname')} [localhost]:`, | ||
handle: 'db_host' | ||
@@ -85,2 +87,7 @@ }, | ||
}, | ||
{ | ||
type: 'input', | ||
query: `${chalk.cyan('Number (in minutes) that an existing backup is valid for (if backup is older, a new one will be created)')} [60]:`, | ||
handle: 'bac_exp' | ||
}, | ||
]; | ||
@@ -91,3 +98,2 @@ | ||
let filepath = false; | ||
@@ -94,0 +100,0 @@ |
250
lib/pull.js
@@ -16,3 +16,118 @@ const utils = require('./utils.js'); | ||
/** | ||
* Ping terminus to create a new backup, and then return the url | ||
* of the backup | ||
* | ||
* @param {object} site | ||
*/ | ||
function createPantheonBackup(site) { | ||
return new Promise((resolve, reject) => { | ||
exec(`terminus backup:create --element=db ${site}`, (err, stdout, stderr) => { | ||
if (err) { | ||
reject(); | ||
console.log(chalk.red(`ERROR @ terminus backup:create --element=db ${site}`)); | ||
throw Error(err); | ||
} | ||
// Get the newly created backup | ||
exec(`terminus backup:get --element=db ${site}`, (err, stdout, stderr) => { | ||
if (err) { | ||
reject(); | ||
console.log(chalk.red(`ERROR @ terminus backup:get --element=db ${site}`)); | ||
throw Error(err); | ||
} | ||
resolve(stdout); | ||
}); | ||
}); | ||
}); | ||
} | ||
/** | ||
* | ||
* @param {object} site | ||
* @param {number} bac_exp * Number of minutes that | ||
*/ | ||
function getPantheonDatabaseBackupURL(site, bac_exp) { | ||
return new Promise((resolve, reject) => { | ||
if (bac_exp === 'override') { | ||
// Force flag, create new DB backup | ||
console.log(chalk.yellow(`...force flag - Creating a new database backup...`)); | ||
createPantheonBackup(site) | ||
.catch(err => { | ||
throw Error(err); | ||
}) | ||
.then(url => { | ||
resolve(url); | ||
}); | ||
} else { | ||
exec(`terminus backup:info --field=date ${site}`, (err, stdout, stderr) => { | ||
if (err) { | ||
// A database backup hasn't been created yet, so create a new one | ||
console.log(chalk.blue(`...Creating a new database backup...`)); | ||
createPantheonBackup(site) | ||
.catch(err => { | ||
throw Error(err); | ||
}) | ||
.then(url => { | ||
resolve(url); | ||
}); | ||
} else { | ||
const BAC_TIME = parseInt(stdout.trim(), 10); | ||
const NOW = Math.floor(Date.now() / 1000); | ||
const MINUTES_DIFF = Math.floor((NOW - BAC_TIME) / 60); | ||
const IS_BAC_EXPIRED = bac_exp < MINUTES_DIFF; | ||
// console.log('last backup time: ' + BAC_TIME); | ||
// console.log('now: ' + NOW); | ||
// console.log('MINUTES_DIFF: ' + MINUTES_DIFF); | ||
// console.log('IS_BAC_EXPIRED: ' + IS_BAC_EXPIRED); | ||
if ( IS_BAC_EXPIRED ) { | ||
// Database is older than desired setting | ||
console.log(chalk.blue(`...Creating a new database backup...`)); | ||
createPantheonBackup(site) | ||
.catch(err => { | ||
throw Error(err); | ||
}) | ||
.then(url => { | ||
resolve(url); | ||
}); | ||
} else { | ||
// Database is newer than desired setting | ||
console.log(chalk.blue('...Using latest backup (created ') + chalk.cyan(MINUTES_DIFF + ' minutes') + chalk.blue(' ago)...')); | ||
exec(`terminus backup:get --element=db ${site}`, (err, stdout, stderr) => { | ||
if (err) { | ||
reject(); | ||
console.log(chalk.red(`ERROR @ terminus backup:get --element=db ${site}`)); | ||
throw Error(err); | ||
} | ||
resolve(stdout); | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
/** | ||
* Make a Pantheon DB backup, download it, load it into MAMP | ||
@@ -29,82 +144,90 @@ * | ||
const DB_FILE_PATH = SITE_PATH + '/db.sql'; | ||
// ------ | ||
const DB_FRESHNESS = PROJECT_CONFIG.backup_expires; | ||
console.log(chalk.blue(`Creating database backup for ${site}...`)); | ||
console.log(chalk.blue(`Checking for database backups for ${site}...`)); | ||
exec(`terminus backup:create --element=db ${site}`, (err, stdout, stderr) => { | ||
if (err) { | ||
console.log(chalk.red(`ERROR @ terminus backup:create --element=db ${site}`)); | ||
throw Error(err); | ||
} | ||
let BAC_EXP = PROJECT_CONFIG.backup_expires; | ||
exec(`terminus backup:get --element=db ${site}`, (err, stdout, stderr) => { | ||
if (err) { | ||
console.log(chalk.red(`ERROR @ terminus backup:get --element=db ${site}`)); | ||
throw Error(err); | ||
} | ||
if (!BAC_EXP) { | ||
BAC_EXP = '60'; | ||
console.log('='.repeat(process.stdout.columns)); | ||
console.log(chalk.white("A value for '") + | ||
chalk.white.underline('backup_expires') + | ||
chalk.white("' has not been set in your `.bcdb.js` file. Either set a value manually in `.bcdb.js` or run ") + | ||
chalk.white.underline('bcdb init') + | ||
chalk.white(' to be prompted for a value.') | ||
); | ||
console.log(chalk.red('A default expiration value of ') + | ||
chalk.red.underline(BAC_EXP) + | ||
chalk.red(' (minutes) will be used until a value is set.') | ||
); | ||
console.log('='.repeat(process.stdout.columns)); | ||
} | ||
console.log(chalk.blue(`...Downloading database backup...`)); | ||
getPantheonDatabaseBackupURL(site, BAC_EXP).then(backup_url => { | ||
const requestStream = request(stdout) | ||
.pipe(zlib.createGunzip()) | ||
.pipe(fs.createWriteStream(DB_FILE_PATH)); | ||
console.log(chalk.blue(`...Downloading database backup...`)); | ||
requestStream.on('finish', function () { | ||
const requestStream = request(backup_url) | ||
.pipe(zlib.createGunzip()) | ||
.pipe(fs.createWriteStream(DB_FILE_PATH)); | ||
console.log(chalk.blue(`...Importing database...`)); | ||
requestStream.on('finish', function () { | ||
// Connect to mysql, prep DB by dropping and creating | ||
const CONNECTION = mysql.createConnection(CONNECTION_OPTS); | ||
CONNECTION.connect(); | ||
console.log(chalk.blue(`...Importing database...`)); | ||
// Drop the DB | ||
CONNECTION.query('DROP DATABASE IF EXISTS `' + PROJECT_CONFIG.localDatabase.name + '`', function (err, results, fields) { | ||
if (err) { | ||
console.log(chalk.red(`ERROR @ CONNECTION.query('DROP DATABASE IF EXISTS...`)); | ||
throw err; | ||
} | ||
}); | ||
// Connect to mysql, prep DB by dropping and creating | ||
const CONNECTION = mysql.createConnection(CONNECTION_OPTS); | ||
CONNECTION.connect(); | ||
// Create the DB | ||
CONNECTION.query('CREATE DATABASE `' + PROJECT_CONFIG.localDatabase.name + '`', function (err, results, fields) { | ||
if (err) { | ||
console.log(chalk.red(`ERROR @ CONNECTION.query('CREATE DATABASE...`)); | ||
throw Error(err); | ||
} | ||
}); | ||
// Drop the DB | ||
CONNECTION.query('DROP DATABASE IF EXISTS `' + PROJECT_CONFIG.localDatabase.name + '`', function (err, results, fields) { | ||
if (err) { | ||
console.log(chalk.red(`ERROR @ CONNECTION.query('DROP DATABASE IF EXISTS...`)); | ||
throw err; | ||
} | ||
}); | ||
// When complete, import the DB | ||
CONNECTION.end(function(err) { | ||
if (err) { | ||
console.log(chalk.red(`ERROR @ CONNECTION.end`)); | ||
throw Error(err); | ||
} | ||
// Create the DB | ||
CONNECTION.query('CREATE DATABASE `' + PROJECT_CONFIG.localDatabase.name + '`', function (err, results, fields) { | ||
if (err) { | ||
console.log(chalk.red(`ERROR @ CONNECTION.query('CREATE DATABASE...`)); | ||
throw Error(err); | ||
} | ||
}); | ||
// Import the DB once the connection has ended | ||
let command = '{executable} -u{username} -p{password} {database} < {file}'; | ||
// When complete, import the DB | ||
CONNECTION.end(function(err) { | ||
if (err) { | ||
console.log(chalk.red(`ERROR @ CONNECTION.end`)); | ||
throw Error(err); | ||
} | ||
command = command.replace('{executable}', '/Applications/MAMP/Library/bin/mysql'); | ||
command = command.replace('{username}', PROJECT_CONFIG.localDatabase.user); | ||
command = command.replace('{password}', PROJECT_CONFIG.localDatabase.pass); | ||
command = command.replace('{database}', PROJECT_CONFIG.localDatabase.name); | ||
command = command.replace('{file}', DB_FILE_PATH); | ||
// Import the DB once the connection has ended | ||
let command = '{executable} -u{username} -p{password} {database} < {file}'; | ||
exec(command, (err) => { | ||
if (err) { | ||
console.log(`Error @ /Applications/MAMP/Library/bin/mysql --user=${PROJECT_CONFIG.localDatabase.user} --password=${PROJECT_CONFIG.localDatabase.pass} ${PROJECT_CONFIG.localDatabase.name} < ${DB_FILE_PATH} > /dev/null 2>&1`) | ||
throw Error(err); | ||
} else { | ||
console.log(chalk.green('✨ Database import complete!')); | ||
command = command.replace('{executable}', '/Applications/MAMP/Library/bin/mysql'); | ||
command = command.replace('{username}', PROJECT_CONFIG.localDatabase.user); | ||
command = command.replace('{password}', PROJECT_CONFIG.localDatabase.pass); | ||
command = command.replace('{database}', PROJECT_CONFIG.localDatabase.name); | ||
command = command.replace('{file}', DB_FILE_PATH); | ||
// Callback | ||
cb(); | ||
} | ||
}); | ||
exec(command, (err) => { | ||
if (err) { | ||
console.log(`Error @ /Applications/MAMP/Library/bin/mysql --user=${PROJECT_CONFIG.localDatabase.user} --password=${PROJECT_CONFIG.localDatabase.pass} ${PROJECT_CONFIG.localDatabase.name} < ${DB_FILE_PATH} > /dev/null 2>&1`) | ||
throw Error(err); | ||
} else { | ||
console.log(chalk.green('✨ Database import complete!')); | ||
}); // end CONNECTION.end... | ||
// Callback | ||
cb(); | ||
} | ||
}); | ||
}); // end requestStream.on('finish'... | ||
}); // end CONNECTION.end... | ||
}); // end exec(`terminus backup:get... | ||
}); // end requestStream.on('finish'... | ||
}); // end exec(`terminus backup:create... | ||
}); | ||
} | ||
@@ -188,2 +311,7 @@ | ||
// Allow `--force` or `-f` flags to force a new DB download. | ||
if ( argv.force || argv.f ) { | ||
PROJECT_CONFIG.backup_expires = 'override'; | ||
} | ||
// Callback for listing Pantheon Envs | ||
@@ -190,0 +318,0 @@ const PULL_CONFIG = (ENV_LIST) => { |
{ | ||
"name": "@bluecadet/bcdb", | ||
"version": "1.0.7", | ||
"version": "1.1.0", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "bugs": { |
@@ -32,3 +32,5 @@ # BCDB | ||
`npm install -g @bluecadet/bcdb` | ||
``` | ||
$ npm install -g @bluecadet/bcdb | ||
``` | ||
@@ -47,9 +49,18 @@ | ||
### pull [--exclude=file/path] | ||
### pull [--force] [-f] [--exclude=file/path] | ||
Run `bcdb pull` to pull a database or files from a specfic Pantheon enviornment | ||
To override the backup expiration and force a new database backup to be created, use the | ||
`--force` or `-f` flag: | ||
``` | ||
$ bcdb pull -f | ||
``` | ||
You can optionally pass directories or other rsync `exclude` parameters with the `--exclude=` argument. Seperate excludes with a comma: | ||
`bcdb pull --exclude=files/path` | ||
`bcdb pull --exclude=files/path,another/path` | ||
``` | ||
$ bcdb pull --exclude=files/path | ||
$ bcdb pull --exclude=files/path,another/path | ||
``` |
21243
554
64