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.
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`
```
autorestic check -l important
```
##### Note
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
@@ -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.
Lets see a more realistic example (from the config above)
```
autorestic restore -l home --from hdd --to /path/where/to/restore
```
@@ -132,7 +131,7 @@ backends:
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.
@@ -143,24 +142,20 @@ locations:
etc:
from: /etc
to: local
keep:
# options matches the --keep-* options used in the restic forget CLI
# cf https://restic.readthedocs.io/en/latest/060_forget.html#removing-snapshots-according-to-a-policy
last: 5 # always keep at least 5 snapshots
hourly: 3 # keep 3 last hourly shapshots
daily: 4 # keep 4 last daily shapshots
weekly: 1 # keep 1 last weekly shapshots
monthly: 12 # keep 12 last monthly shapshots
yearly: 7 # keep 7 last yearly shapshots
within: "2w" # keep snapshots from the last 2 weeks
options:
forget:
keep-last: 5 # always keep at least 5 snapshots
keep-hourly: 3 # keep 3 last hourly shapshots
keep-daily: 4 # keep 4 last daily shapshots
keep-weekly: 1 # keep 1 last weekly shapshots
keep-monthly: 12 # keep 12 last monthly shapshots
keep-yearly: 7 # keep 7 last yearly shapshots
keep-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.**
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
@@ -181,9 +176,30 @@ f8f8f976 2019-12-02 12:11:08 computer within 2w /etc
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

View File

@@ -4,7 +4,7 @@
"build": "tsc",
"build:watch": "tsc -w",
"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": {
"@types/js-yaml": "^3.12.1",
@@ -12,7 +12,7 @@
"@types/node": "^12.11.7",
"pkg": "^4.4.0",
"ts-node-dev": "^1.0.0-pre.40",
"typescript": "^3.5.1"
"typescript": "^3.7"
},
"dependencies": {
"axios": "^0.19.0",

View File

@@ -26,7 +26,7 @@ export const { _: commands, ...flags } = minimist(process.argv.slice(2), {
string: ['l', 'b'],
})
export const VERSION = '0.7'
export const VERSION = '0.8'
export const INSTALL_DIR = '/usr/local/bin'
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) => {
if (!config) throw ConfigError
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 cmd = exec(
@@ -27,13 +27,12 @@ export const backupSingle = (name: string, to: string, location: Location) => {
export const backupLocation = (name: string, location: Location) => {
const display = name.yellow + ' ▶ '
const filler = new Array(name.length + 3).fill(' ').join('')
if (Array.isArray(location.to)) {
let first = true
for (const t of location.to) {
backupSingle(first ? display : filler, t, location)
if (first) first = false
}
} else backupSingle(display, location.from, location)
let first = true
for (const t of Array.isArray(location.to) ? location.to : [location.to]) {
backupSingle(first ? display : filler, t, location)
if (first) first = false
}
}
export const backupAll = (locations?: Locations) => {

View File

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

View File

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

View File

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