-
-
Save themightychris/66465878ae4bab5138317ae637de3943 to your computer and use it in GitHub Desktop.
tbz -> restic migration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# install restic CLI | |
hab pkg install --binlink core/restic | |
# configure restic repository access | |
export RESTIC_REPOSITORY=/src/restic-local | |
export RESTIC_PASSWORD=abc123 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
const path = require('path'); | |
const fs = require('mz/fs'); | |
const shellExec = require('shell-exec'); | |
run(); | |
async function run() { | |
const cwd = process.cwd(); | |
const extractPath = `${cwd}/home/chris`; | |
const canonicalPath = '/home/chris'; | |
const studioPath = `/hab/studios/${cwd.substr(1).replace(/\//g, '--')}`; | |
const snapshotMatchPaths = [ | |
canonicalPath, | |
path.dirname(extractPath) | |
]; | |
// check that studio works and has mount at canonical path | |
const { stdout: mountOutput } = await shellExec(`hab studio -q run mount | grep "on /home "`); | |
if (!mountOutput.match(/^\/dev\S+ on \/home type /)) { | |
console.log(`/src/home mount not found, run: mount --bind ${cwd}/home ${studioPath}/home`); | |
return; | |
} | |
// verify inode id matches for extract/canonical directory | |
const { stdout: extractPathIdOutput } = await shellExec(`ls -id "${path.dirname(extractPath)}"`); | |
const extractPathId = extractPathIdOutput.match(/(^\d+) \S+$/m)[1]; | |
const { stdout: canonicalPathIdOutput } = await shellExec(`hab studio -q run ls -id "${path.dirname(canonicalPath)}"`); | |
const canonicalPathId = canonicalPathIdOutput.match(/(^\d+) \S+$/m)[1]; | |
if (!extractPathId || extractPathId != canonicalPathId) { | |
console.log('containing directory for extract path does not match by inode id inside and outside the studio, check mount'); | |
return; | |
} | |
// get list of old backup .tbzs | |
const backupRe = /^home\.\d{4}-\d{2}-\d{2}\.tbz$/; | |
const backups = new Map(); | |
for (const name of await fs.readdir(`${cwd}/chris-desktop`)) { | |
if (backupRe.test(name)) { | |
backups.set(name.substr(5, 10), `${cwd}/chris-desktop/${name}`); | |
} | |
} | |
console.log('found %s backups', backups.size); | |
// get list of existing restic snapshots | |
const { stdout: snapshotsJson } = await shellExec(`sudo -E restic snapshots --json`); | |
const snapshots = new Map(); | |
for (const snapshot of JSON.parse(snapshotsJson)) { | |
if (snapshotMatchPaths.indexOf(snapshot.paths[0]) >= 0) { | |
snapshots.set(snapshot.time.substr(0, 10), snapshot); | |
} | |
} | |
console.log('found %s snapshots', snapshots.size); | |
// process each backup tbz (in order) | |
for (const [date, path] of backups) { | |
if (snapshots.has(date)) { | |
console.log('%s\tfound snapshot %s', date, snapshots.get(date).id); | |
continue; | |
} | |
console.log('%s\tsnapshotting...', date); | |
console.log('\t\tcleaning %s', extractPath); | |
await shellExec(`rm -rf "${extractPath}" && mkdir "${extractPath}"`); | |
console.log('\t\textracting %s', path); | |
await shellExec(`tar --directory="${extractPath}" -xjf "${path}"`); | |
const previousSnapshotDate = [...snapshots.keys()].filter(snapshotDate => snapshotDate < date).pop(); | |
const previousSnapshot = previousSnapshotDate && snapshots.get(previousSnapshotDate); | |
console.log('\t\tusing parent %s', previousSnapshot ? `${previousSnapshotDate}#${previousSnapshot.id}` : '[none]'); | |
const backupCommand = `hab studio -q run 'source .studiorc && restic backup "${canonicalPath}" --exclude-file=.restic-exclude --time "${date} 00:00:00" --parent ${previousSnapshot.id}'`; | |
console.log('\t\t%s', backupCommand); | |
const backupResult = await shellExec(backupCommand); | |
console.log(`\t\t\t${backupResult.stdout.replace(/\n/g, '\n\t\t\t')}`); | |
// break; // just one! | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment