Compare commits

..

10 Commits
0.7 ... 0.8

Author SHA1 Message Date
cupcakearmy
2f0092befe Merge remote-tracking branch 'origin/master' 2019-12-04 23:50:07 +01:00
cupcakearmy
1026e68b68 version bump 2019-12-04 23:49:39 +01:00
2389c59aa9 Update README.md 2019-12-04 23:48:22 +01:00
087aeaf578 Update README.md 2019-12-04 23:43:01 +01:00
3b7062f733 Update README.md 2019-12-04 23:39:19 +01:00
cupcakearmy
96b63c744b switch to yarn & update typescript 2019-12-04 23:36:49 +01:00
cupcakearmy
9669b70e20 refactor forget and make compatible with new options api 2019-12-04 23:36:27 +01:00
cupcakearmy
bcb081234c formatting 2019-12-04 23:36:04 +01:00
cupcakearmy
336f44e9dc simplify for 2019-12-04 23:35:41 +01:00
cupcakearmy
d0cda7f1d5 always convert to string 2019-12-04 23:35:26 +01:00
7 changed files with 81 additions and 69 deletions

View File

@@ -54,13 +54,11 @@ backends:
Then we check if everything is correct by running the `check` command. We will pass the `-a` (or `--all`) to tell autorestic to check all the locations. Then we check if everything is correct by running the `check` command. We will pass the `-a` (or `--all`) to tell autorestic to check all the locations.
Lets see a more realistic example (from the config above) If we would check only one location we could run the following: `autorestic check -l home`. Otherwise simpply check all locations with `autorestic check -a`
``` ##### Note
autorestic check -l important
```
If we would check only one location we could run the following: `autorestic -l home check`. Note that the data is automatically encrypted on the server. The key will be generated and added to your config file. Every backend will have a separate key. You should keep a copy of the keys somewhere in case your server dies. Otherwise DATA IS LOST!
### Backup ### Backup
@@ -76,6 +74,7 @@ autorestic restore -a --to /path/where/to/restore
This will restore all the locations to the selected target. If for one location there are more than one backends specified autorestic will take the first one. This will restore all the locations to the selected target. If for one location there are more than one backends specified autorestic will take the first one.
Lets see a more realistic example (from the config above)
``` ```
autorestic restore -l home --from hdd --to /path/where/to/restore autorestic restore -l home --from hdd --to /path/where/to/restore
``` ```
@@ -132,7 +131,7 @@ backends:
B2_ACCOUNT_KEY: backblaze_account_key B2_ACCOUNT_KEY: backblaze_account_key
``` ```
## Pruning and snapshot policies ### Pruning and snapshot policies
Autorestic supports declaring snapshot policies for location to avoid keeping old snapshot around if you don't need them. Autorestic supports declaring snapshot policies for location to avoid keeping old snapshot around if you don't need them.
@@ -143,24 +142,20 @@ locations:
etc: etc:
from: /etc from: /etc
to: local to: local
keep: options:
# options matches the --keep-* options used in the restic forget CLI forget:
# cf https://restic.readthedocs.io/en/latest/060_forget.html#removing-snapshots-according-to-a-policy keep-last: 5 # always keep at least 5 snapshots
last: 5 # always keep at least 5 snapshots keep-hourly: 3 # keep 3 last hourly shapshots
hourly: 3 # keep 3 last hourly shapshots keep-daily: 4 # keep 4 last daily shapshots
daily: 4 # keep 4 last daily shapshots keep-weekly: 1 # keep 1 last weekly shapshots
weekly: 1 # keep 1 last weekly shapshots keep-monthly: 12 # keep 12 last monthly shapshots
monthly: 12 # keep 12 last monthly shapshots keep-yearly: 7 # keep 7 last yearly shapshots
yearly: 7 # keep 7 last yearly shapshots keep-within: "2w" # keep snapshots from the last 2 weeks
within: "2w" # keep snapshots from the last 2 weeks
``` ```
Pruning can be triggered using `autorestic forget -a`, for all locations, or selectively with `autorestic forget -l <location>`. **please note that contrary to the restic CLI, `restic forget` will call `restic prune` internally.** Pruning can be triggered using `autorestic forget -a`, for all locations, or selectively with `autorestic forget -l <location>`. **please note that contrary to the restic CLI, `restic forget` will call `restic prune` internally.**
Run with the `--dry-run` flag to only print information about the process without actually pruning the snapshots. This is especially useful for debugging or testing policies: Run with the `--dry-run` flag to only print information about the process without actually pruning the snapshots. This is especially useful for debugging or testing policies:
``` ```
$ autorestic forget -a --dry-run --verbose $ autorestic forget -a --dry-run --verbose
@@ -181,9 +176,30 @@ f8f8f976 2019-12-02 12:11:08 computer within 2w /etc
3 snapshots 3 snapshots
``` ```
##### Note ### Excluding files/folders
Note that the data is automatically encrypted on the server. The key will be generated and added to your config file. Every backend will have a separate key. You should keep a copy of the keys somewhere in case your server dies. Otherwise DATA IS LOST! If you want to exclude certain files or folders it done easily by specifiyng the right flags in the location you desire to filter. The flags are taken straight from the [restic cli exclude rules](https://restic.readthedocs.io/en/latest/040_backup.html#excluding-files).
```yaml
locations:
my-location:
from: /data
to:
- local
- remote
options:
backup:
exclude:
- '*.nope'
- '*.abc'
exclude-file: .gitignore
backends:
local:
...
remote:
...
```
## Contributors ## Contributors

View File

@@ -4,7 +4,7 @@
"build": "tsc", "build": "tsc",
"build:watch": "tsc -w", "build:watch": "tsc -w",
"dev": "tsnd --no-notify --respawn ./src/autorestic.ts", "dev": "tsnd --no-notify --respawn ./src/autorestic.ts",
"bin": "npm run build && pkg lib/autorestic.js --targets latest-macos-x64,latest-linux-x64 --out-path bin" "bin": "yarn run build && pkg lib/autorestic.js --targets latest-macos-x64,latest-linux-x64 --out-path bin"
}, },
"devDependencies": { "devDependencies": {
"@types/js-yaml": "^3.12.1", "@types/js-yaml": "^3.12.1",
@@ -12,7 +12,7 @@
"@types/node": "^12.11.7", "@types/node": "^12.11.7",
"pkg": "^4.4.0", "pkg": "^4.4.0",
"ts-node-dev": "^1.0.0-pre.40", "ts-node-dev": "^1.0.0-pre.40",
"typescript": "^3.5.1" "typescript": "^3.7"
}, },
"dependencies": { "dependencies": {
"axios": "^0.19.0", "axios": "^0.19.0",

View File

@@ -26,7 +26,7 @@ export const { _: commands, ...flags } = minimist(process.argv.slice(2), {
string: ['l', 'b'], string: ['l', 'b'],
}) })
export const VERSION = '0.7' export const VERSION = '0.8'
export const INSTALL_DIR = '/usr/local/bin' export const INSTALL_DIR = '/usr/local/bin'
export const VERBOSE = flags.verbose export const VERBOSE = flags.verbose

View File

@@ -10,8 +10,8 @@ import { exec, ConfigError, pathRelativeToConfigFile, getFlagsFromLocation } fro
export const backupSingle = (name: string, to: string, location: Location) => { export const backupSingle = (name: string, to: string, location: Location) => {
if (!config) throw ConfigError if (!config) throw ConfigError
const writer = new Writer(name + to.blue + ' : ' + 'Backing up... ⏳') const writer = new Writer(name + to.blue + ' : ' + 'Backing up... ⏳')
const backend = config.backends[to]
const backend = config.backends[to]
const path = pathRelativeToConfigFile(location.from) const path = pathRelativeToConfigFile(location.from)
const cmd = exec( const cmd = exec(
@@ -27,13 +27,12 @@ export const backupSingle = (name: string, to: string, location: Location) => {
export const backupLocation = (name: string, location: Location) => { export const backupLocation = (name: string, location: Location) => {
const display = name.yellow + ' ▶ ' const display = name.yellow + ' ▶ '
const filler = new Array(name.length + 3).fill(' ').join('') const filler = new Array(name.length + 3).fill(' ').join('')
if (Array.isArray(location.to)) {
let first = true let first = true
for (const t of location.to) {
for (const t of Array.isArray(location.to) ? location.to : [location.to]) {
backupSingle(first ? display : filler, t, location) backupSingle(first ? display : filler, t, location)
if (first) first = false if (first) first = false
} }
} else backupSingle(display, location.from, location)
} }
export const backupAll = (locations?: Locations) => { export const backupAll = (locations?: Locations) => {

View File

@@ -2,47 +2,47 @@ import { Writer } from 'clitastic'
import { config, VERBOSE } from './autorestic' import { config, VERBOSE } from './autorestic'
import { getEnvFromBackend } from './backend' import { getEnvFromBackend } from './backend'
import { Locations, Location, ForgetPolicy, Flags } from './types' import { Locations, Location, Flags } from './types'
import { exec, ConfigError } from './utils' import { exec, ConfigError, pathRelativeToConfigFile, getFlagsFromLocation } from './utils'
export const forgetSingle = (dryRun: boolean, name: string, from: string, to: string, policy: ForgetPolicy) => { export const forgetSingle = (name: string, to: string, location: Location, dryRun: boolean) => {
if (!config) throw ConfigError if (!config) throw ConfigError
const writer = new Writer(name + to.blue + ' : ' + 'Removing old spnapshots… ⏳') const base = name + to.blue + ' : '
const writer = new Writer(base + 'Removing old snapshots… ⏳')
const backend = config.backends[to] const backend = config.backends[to]
const flags = [] as any[] const path = pathRelativeToConfigFile(location.from)
for (const [name, value] of Object.entries(policy)) { const flags = getFlagsFromLocation(location, 'forget')
flags.push(`--keep-${name}`)
flags.push(value) if (flags.length == 0) {
writer.done(base + 'skipping, no policy declared')
return
} }
if (dryRun) { if (dryRun) flags.push('--dry-run')
flags.push('--dry-run')
} writer.replaceLn(base + 'Forgetting old snapshots… ⏳')
const env = getEnvFromBackend(backend) const cmd = exec(
writer.replaceLn(name + to.blue + ' : ' + 'Forgeting old snapshots… ⏳') 'restic',
const cmd = exec('restic', ['forget', '--path', from, '--prune', ...flags], { env }) ['forget', '--path', path, '--prune', ...flags],
{ env: getEnvFromBackend(backend) },
)
if (VERBOSE) console.log(cmd.out, cmd.err) if (VERBOSE) console.log(cmd.out, cmd.err)
writer.done(name + to.blue + ' : ' + 'Done ✓'.green) writer.done(base + 'Done ✓'.green)
} }
export const forgetLocation = (dryRun: boolean, name: string, backup: Location, policy?: ForgetPolicy) => { export const forgetLocation = (name: string, backup: Location, dryRun: boolean) => {
const display = name.yellow + ' ▶ ' const display = name.yellow + ' ▶ '
if (!policy) { const filler = new Array(name.length + 3).fill(' ').join('')
console.log(display + 'skipping, no policy declared')
} else {
if (Array.isArray(backup.to)) {
let first = true let first = true
for (const t of backup.to) {
const nameOrBlankSpaces: string = first for (const t of Array.isArray(backup.to) ? backup.to : [backup.to]) {
? display const nameOrBlankSpaces: string = first ? display : filler
: new Array(name.length + 3).fill(' ').join('') forgetSingle(nameOrBlankSpaces, t, backup, dryRun)
forgetSingle(dryRun, nameOrBlankSpaces, backup.from, t, policy)
if (first) first = false if (first) first = false
} }
} else forgetSingle(dryRun, display, backup.from, backup.to, policy)
}
} }
export const forgetAll = (backups?: Locations, flags?: Flags) => { export const forgetAll = (backups?: Locations, flags?: Flags) => {
@@ -51,12 +51,10 @@ export const forgetAll = (backups?: Locations, flags?: Flags) => {
backups = config.locations backups = config.locations
} }
console.log('\nRemoving old shapshots according to policy'.underline.grey) console.log('\nRemoving old snapshots according to policy'.underline.grey)
const dryRun = flags ? flags['dry-run'] : false const dryRun = flags ? flags['dry-run'] : false
if (dryRun) console.log('Running in dry-run mode, not touching data\n'.yellow) if (dryRun) console.log('Running in dry-run mode, not touching data\n'.yellow)
for (const [name, backup] of Object.entries(backups)) { for (const [name, backup] of Object.entries(backups))
const policy = config.locations[name].keep forgetLocation(name, backup, dryRun)
forgetLocation(dryRun, name, backup, policy)
}
} }

View File

@@ -215,8 +215,7 @@ const handlers: Handlers = {
darwin: 'macos', darwin: 'macos',
} }
const name = `autorestic_${platformMap[process.platform] || const name = `autorestic_${platformMap[process.platform] || process.platform}_${process.arch}`
process.platform}_${process.arch}`
const dl = json.assets.find((asset: any) => asset.name === name) const dl = json.assets.find((asset: any) => asset.name === name)
const to = INSTALL_DIR + '/autorestic' const to = INSTALL_DIR + '/autorestic'

View File

@@ -103,7 +103,7 @@ export const getFlagsFromLocation = (location: Location, command?: string): stri
values = [values] values = [values]
for (const value of values) for (const value of values)
flags = [...flags, `--${flag}`, value] flags = [...flags, `--${String(flag)}`, String(value)]
} }
return flags return flags
} }