mirror of
https://github.com/cupcakearmy/autorestic.git
synced 2025-09-06 10:30:39 +00:00
Compare commits
38 Commits
Author | SHA1 | Date | |
---|---|---|---|
12adeb2b06 | |||
37b26dfc31 | |||
c1795b2acc | |||
b8d12e518c | |||
50060cf539 | |||
c33aac42dc | |||
c359053e0e | |||
c16340ab26 | |||
edc85c4ac3 | |||
68682777f2 | |||
|
b6c7922df5 | ||
|
991b8bec22 | ||
bbc32568ad | |||
f3c038c716 | |||
59612a97b6 | |||
33319a00ef | |||
8eb14ea14f | |||
70eb9e441f | |||
be25af2d76 | |||
1c436369f0 | |||
6efcce07b7 | |||
|
dc6dd2e712 | ||
|
68628d3776 | ||
40988ef3b4 | |||
fad33fcdaa | |||
|
8cf8a77558 | ||
36998cfd3b | |||
cf03562ea2 | |||
188560395d | |||
bacbd0f806 | |||
93bf0388a4 | |||
ec8fdbd135 | |||
420934489c | |||
|
2ba767c8c3 | ||
b489c662c7 | |||
6862529a89 | |||
aa96a95600 | |||
89e32c298c |
40
CHANGELOG.md
40
CHANGELOG.md
@@ -5,6 +5,46 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.0.8] - 2021-04-28
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `--lean` flag to cron command for less output about skipping backups.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- consistent lower casing in usage descriptions.
|
||||||
|
|
||||||
|
## [1.0.7] - 2021-04-26
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Support for `darwin/arm64` aka Apple Silicon.
|
||||||
|
- Added support for `arm64` and `aarch64` in install scripts.
|
||||||
|
|
||||||
|
## [1.0.6] - 2021-04-24
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Support for rclone
|
||||||
|
|
||||||
|
## [1.0.5] - 2021-04-24
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Correct exit code on backup failure and better logging/output/feedback.
|
||||||
|
- Check if `from` key is an actual directory.
|
||||||
|
|
||||||
|
## [1.0.4] - 2021-04-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Options to add rest username and password in config
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Don't add empty strings when saving config
|
||||||
|
|
||||||
## [1.0.3] - 2021-04-20
|
## [1.0.3] - 2021-04-20
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
23
DEVELOPMENT.md
Normal file
23
DEVELOPMENT.md
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Development
|
||||||
|
|
||||||
|
## Coding
|
||||||
|
|
||||||
|
The easiest way (imo) is to run [`gowatch`](https://github.com/silenceper/gowatch) in a separate terminal and the simply run `./autorestic ...`. `gowatch` will watch the code and automatically rebuild the binary when changes are saved to disk.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go run build/build.go
|
||||||
|
```
|
||||||
|
|
||||||
|
This will build and compress binaries for multiple platforms. The output will be put in the `dist` folder.
|
||||||
|
|
||||||
|
## Releasing
|
||||||
|
|
||||||
|
Releases are automatically built by the github workflow and uploaded to the release.
|
||||||
|
|
||||||
|
1. Bump `VERSION` in `internal/config.go`.
|
||||||
|
2. Update `CHANGELOG.md`
|
||||||
|
3. Commit to master
|
||||||
|
4. Create a new release with the `v1.2.3` tag and mark as draft.
|
||||||
|
5. The Github action will build the binaries, upload and mark the release as ready when done.
|
@@ -36,3 +36,8 @@ Autorestic is a wrapper around the amazing [restic](https://restic.net/). While
|
|||||||
### ❓ Questions / Support
|
### ❓ Questions / Support
|
||||||
|
|
||||||
Check the [discussions page](https://github.com/cupcakearmy/autorestic/discussions)
|
Check the [discussions page](https://github.com/cupcakearmy/autorestic/discussions)
|
||||||
|
|
||||||
|
## Contributing / Developing
|
||||||
|
|
||||||
|
PRs, feature requests, etc. are welcomed :)
|
||||||
|
Have a look at [the dev docs](./DEVELOPMENT.md)
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
# Releasing
|
|
||||||
|
|
||||||
Releases are automatically built by the github workflow and uploaded to the release.
|
|
||||||
|
|
||||||
1. Bump `VERSION` in `internal/config.go`.
|
|
||||||
2. Update `CHANGELOG.md`
|
|
||||||
3. Commit to master
|
|
||||||
4. Create a new release with the `v1.2.3` tag and mark as draft.
|
|
||||||
5. The Github action will build the binaries, upload and mark the release as ready when done.
|
|
@@ -9,6 +9,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/cupcakearmy/autorestic/internal"
|
"github.com/cupcakearmy/autorestic/internal"
|
||||||
)
|
)
|
||||||
@@ -16,7 +17,7 @@ import (
|
|||||||
var DIR, _ = filepath.Abs("./dist")
|
var DIR, _ = filepath.Abs("./dist")
|
||||||
|
|
||||||
var targets = map[string][]string{
|
var targets = map[string][]string{
|
||||||
"darwin": {"amd64"},
|
"darwin": {"amd64", "arm64"},
|
||||||
"freebsd": {"386", "amd64", "arm"},
|
"freebsd": {"386", "amd64", "arm"},
|
||||||
"linux": {"386", "amd64", "arm", "arm64"},
|
"linux": {"386", "amd64", "arm", "arm64"},
|
||||||
"netbsd": {"386", "amd64"},
|
"netbsd": {"386", "amd64"},
|
||||||
@@ -27,7 +28,7 @@ type buildOptions struct {
|
|||||||
Target, Arch, Version string
|
Target, Arch, Version string
|
||||||
}
|
}
|
||||||
|
|
||||||
func build(options buildOptions) error {
|
func build(options buildOptions, wg *sync.WaitGroup) {
|
||||||
fmt.Printf("Building %s %s\n", options.Target, options.Arch)
|
fmt.Printf("Building %s %s\n", options.Target, options.Arch)
|
||||||
out := fmt.Sprintf("autorestic_%s_%s_%s", options.Version, options.Target, options.Arch)
|
out := fmt.Sprintf("autorestic_%s_%s_%s", options.Version, options.Target, options.Arch)
|
||||||
out = path.Join(DIR, out)
|
out = path.Join(DIR, out)
|
||||||
@@ -46,7 +47,7 @@ func build(options buildOptions) error {
|
|||||||
)
|
)
|
||||||
err := c.Run()
|
err := c.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,26 +59,25 @@ func build(options buildOptions) error {
|
|||||||
c.Stderr = os.Stderr
|
c.Stderr = os.Stderr
|
||||||
err := c.Run()
|
err := c.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
wg.Done()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
os.RemoveAll(DIR)
|
os.RemoveAll(DIR)
|
||||||
v := internal.VERSION
|
v := internal.VERSION
|
||||||
|
var wg sync.WaitGroup
|
||||||
for target, archs := range targets {
|
for target, archs := range targets {
|
||||||
for _, arch := range archs {
|
for _, arch := range archs {
|
||||||
err := build(buildOptions{
|
wg.Add(1)
|
||||||
|
build(buildOptions{
|
||||||
Target: target,
|
Target: target,
|
||||||
Arch: arch,
|
Arch: arch,
|
||||||
Version: v,
|
Version: v,
|
||||||
})
|
}, &wg)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/cupcakearmy/autorestic/internal"
|
"github.com/cupcakearmy/autorestic/internal"
|
||||||
|
"github.com/cupcakearmy/autorestic/internal/colors"
|
||||||
"github.com/cupcakearmy/autorestic/internal/lock"
|
"github.com/cupcakearmy/autorestic/internal/lock"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@@ -18,9 +21,17 @@ var backupCmd = &cobra.Command{
|
|||||||
|
|
||||||
selected, err := internal.GetAllOrSelected(cmd, false)
|
selected, err := internal.GetAllOrSelected(cmd, false)
|
||||||
CheckErr(err)
|
CheckErr(err)
|
||||||
|
errors := 0
|
||||||
for _, name := range selected {
|
for _, name := range selected {
|
||||||
location, _ := internal.GetLocation(name)
|
location, _ := internal.GetLocation(name)
|
||||||
location.Backup(false)
|
err := location.Backup(false)
|
||||||
|
if err != nil {
|
||||||
|
colors.Error.Println(err)
|
||||||
|
errors++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if errors > 0 {
|
||||||
|
CheckErr(fmt.Errorf("%d errors were found", errors))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -17,7 +17,7 @@ var checkCmd = &cobra.Command{
|
|||||||
|
|
||||||
CheckErr(internal.CheckConfig())
|
CheckErr(internal.CheckConfig())
|
||||||
|
|
||||||
colors.Success.Println("Everyting is fine.")
|
colors.Success.Println("Everything is fine.")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@ var cronCmd = &cobra.Command{
|
|||||||
Short: "Run cron job for automated backups",
|
Short: "Run cron job for automated backups",
|
||||||
Long: `Intended to be mainly triggered by an automated system like systemd or crontab. For each location checks if a cron backup is due and runs it.`,
|
Long: `Intended to be mainly triggered by an automated system like systemd or crontab. For each location checks if a cron backup is due and runs it.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
internal.CRON_LEAN, _ = cmd.Flags().GetBool("lean")
|
||||||
err := lock.Lock()
|
err := lock.Lock()
|
||||||
CheckErr(err)
|
CheckErr(err)
|
||||||
defer lock.Unlock()
|
defer lock.Unlock()
|
||||||
@@ -22,4 +23,5 @@ var cronCmd = &cobra.Command{
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(cronCmd)
|
rootCmd.AddCommand(cronCmd)
|
||||||
|
cronCmd.Flags().Bool("lean", false, "only output information about actual backups")
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,6 @@ var forgetCmd = &cobra.Command{
|
|||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(forgetCmd)
|
rootCmd.AddCommand(forgetCmd)
|
||||||
internal.AddFlagsToCommand(forgetCmd, false)
|
internal.AddFlagsToCommand(forgetCmd, false)
|
||||||
forgetCmd.Flags().Bool("prune", false, "Also prune repository")
|
forgetCmd.Flags().Bool("prune", false, "also prune repository")
|
||||||
forgetCmd.Flags().Bool("dry-run", false, "Do not write changes, show what would be affected")
|
forgetCmd.Flags().Bool("dry-run", false, "do not write changes, show what would be affected")
|
||||||
}
|
}
|
||||||
|
@@ -57,5 +57,4 @@ func initConfig() {
|
|||||||
viper.SetConfigName(".autorestic")
|
viper.SetConfigName(".autorestic")
|
||||||
}
|
}
|
||||||
viper.AutomaticEnv()
|
viper.AutomaticEnv()
|
||||||
internal.GetConfig()
|
|
||||||
}
|
}
|
||||||
|
@@ -16,5 +16,5 @@ var uninstallCmd = &cobra.Command{
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(uninstallCmd)
|
rootCmd.AddCommand(uninstallCmd)
|
||||||
uninstallCmd.Flags().Bool("no-restic", false, "Do not uninstall restic.")
|
uninstallCmd.Flags().Bool("no-restic", false, "do not uninstall restic.")
|
||||||
}
|
}
|
||||||
|
@@ -17,5 +17,5 @@ var upgradeCmd = &cobra.Command{
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(upgradeCmd)
|
rootCmd.AddCommand(upgradeCmd)
|
||||||
upgradeCmd.Flags().Bool("no-restic", false, "Also update restic. Default: true")
|
upgradeCmd.Flags().Bool("no-restic", false, "also update restic")
|
||||||
}
|
}
|
||||||
|
3209
docs/.codedoc/package-lock.json
generated
3209
docs/.codedoc/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codedoc/core": "^0.2.15"
|
"@codedoc/core": "^0.2.23"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
> [General](/cli/general)
|
> [General](/cli/general)
|
||||||
> [Info](/cli/info)
|
> [Info](/cli/info)
|
||||||
> [Check](/cli/check)
|
> [Check](/cli/check)
|
||||||
|
> [Completion](/cli/completion)
|
||||||
> [Backup](/cli/backup)
|
> [Backup](/cli/backup)
|
||||||
> [Restore](/cli/restore)
|
> [Restore](/cli/restore)
|
||||||
> [Forget](/cli/forget)
|
> [Forget](/cli/forget)
|
||||||
|
@@ -19,11 +19,18 @@ backends:
|
|||||||
backends:
|
backends:
|
||||||
name-of-backend:
|
name-of-backend:
|
||||||
type: b2
|
type: b2
|
||||||
path: 'myAccount:myBucket/my/path'
|
path: 'backblaze_bucketID'
|
||||||
B2_ACCOUNT_ID: backblaze_account_id
|
# Or With a path
|
||||||
B2_ACCOUNT_KEY: backblaze_account_key
|
# path: 'backblaze_bucketID:/some/path'
|
||||||
|
env:
|
||||||
|
B2_ACCOUNT_ID: 'backblaze_keyID'
|
||||||
|
B2_ACCOUNT_KEY: 'backblaze_applicationKey'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### API Keys gotcha
|
||||||
|
|
||||||
|
If you use a _File name prefix_ when making the application key, do not include a leading slash. Make sure to include this prefix in the path (e.g. `path: 'backblaze_bucketID:my/path'`).
|
||||||
|
|
||||||
## S3 / Minio
|
## S3 / Minio
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -33,8 +40,9 @@ backends:
|
|||||||
path: s3.amazonaws.com/bucket_name
|
path: s3.amazonaws.com/bucket_name
|
||||||
# Minio
|
# Minio
|
||||||
# path: http://localhost:9000/bucket_name
|
# path: http://localhost:9000/bucket_name
|
||||||
AWS_ACCESS_KEY_ID: my_key
|
env:
|
||||||
AWS_SECRET_ACCESS_KEY: my_secret
|
AWS_ACCESS_KEY_ID: my_key
|
||||||
|
AWS_SECRET_ACCESS_KEY: my_secret
|
||||||
```
|
```
|
||||||
|
|
||||||
## SFTP
|
## SFTP
|
||||||
@@ -57,6 +65,21 @@ backends:
|
|||||||
name-of-backend:
|
name-of-backend:
|
||||||
type: rest
|
type: rest
|
||||||
path: http://localhost:8000/repo_name
|
path: http://localhost:8000/repo_name
|
||||||
|
# Or authenticated
|
||||||
|
path: https://user:pass@host:6969/path
|
||||||
|
```
|
||||||
|
|
||||||
|
Optionally you can set user and password separately
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
backends:
|
||||||
|
rest:
|
||||||
|
type: rest
|
||||||
|
path: http://localhost:6969/path
|
||||||
|
key: ...
|
||||||
|
rest:
|
||||||
|
user: user
|
||||||
|
password: pass
|
||||||
```
|
```
|
||||||
|
|
||||||
> :ToCPrevNext
|
> :ToCPrevNext
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
# 💽 Backends
|
# 💽 Backends
|
||||||
|
|
||||||
Backends are the ouputs of the backup process. Each location needs at least one.
|
Backends are the outputs of the backup process. Each location needs at least one.
|
||||||
|
|
||||||
```yaml | .autorestic.yml
|
```yaml | .autorestic.yml
|
||||||
backends:
|
backends:
|
||||||
|
17
docs/markdown/cli/completion.md
Normal file
17
docs/markdown/cli/completion.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Completion
|
||||||
|
|
||||||
|
```bash
|
||||||
|
autorestic completion [bash|zsh|fish|powershell]
|
||||||
|
```
|
||||||
|
|
||||||
|
Autorestic can generate shell completions automatically to make the experience even easier.
|
||||||
|
Supported shells are
|
||||||
|
|
||||||
|
- bash
|
||||||
|
- zsh
|
||||||
|
- fish
|
||||||
|
- powershell
|
||||||
|
|
||||||
|
To see how to install run `autorestic help completion` and follow the instructions for your specific shell
|
||||||
|
|
||||||
|
> :ToCPrevNext
|
@@ -1,11 +1,13 @@
|
|||||||
# Cron
|
# Cron
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
autorestic cron
|
autorestic cron [--lean]
|
||||||
```
|
```
|
||||||
|
|
||||||
This command is mostly intended to be triggered by an automated system like systemd or crontab.
|
This command is mostly intended to be triggered by an automated system like systemd or crontab.
|
||||||
|
|
||||||
It will run cron jobs es [specified in the cron section](/locations/cron) of a specific location.
|
It will run cron jobs as [specified in the cron section](/location/cron) of a specific location.
|
||||||
|
|
||||||
|
The `--lean` flag will omit output like _skipping location x: not due yet_. This can be useful if you are dumping the output of the cron job to a log file and don't want to be overwhelmed by the output log.
|
||||||
|
|
||||||
> :ToCPrevNext
|
> :ToCPrevNext
|
||||||
|
@@ -4,10 +4,10 @@
|
|||||||
autorestic exec [-b, --backend] [-a, --all] <command> -- [native options]
|
autorestic exec [-b, --backend] [-a, --all] <command> -- [native options]
|
||||||
```
|
```
|
||||||
|
|
||||||
This is avery handy command which enables you to run any native restic command on desired backends. An example would be listing all the snapshots of all your backends:
|
This is avery handy command which enables you to run any native restic command on desired backends. Generally will want to include the verbose flag `-v, --verbose` to see the output. An example would be listing all the snapshots of all your backends:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
autorestic exec -a -- snapshots
|
autorestic exec -av -- snapshots
|
||||||
```
|
```
|
||||||
|
|
||||||
With `exec` you can basically run every cli command that you would be able to run with the restic cli. It only pre-fills path, key, etc.
|
With `exec` you can basically run every cli command that you would be able to run with the restic cli. It only pre-fills path, key, etc.
|
||||||
|
@@ -26,3 +26,5 @@ Verbose mode will show the output of the native restic commands that are otherwi
|
|||||||
```bash
|
```bash
|
||||||
autorestic --verbose backup -a
|
autorestic --verbose backup -a
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> :ToCPrevNext
|
||||||
|
@@ -1,11 +1,13 @@
|
|||||||
# Restore
|
# Restore
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
autorestic restore [-l, --location] [--from backend] [--to <out dir>]
|
autorestic restore [-l, --location] [--from backend] [--to <out dir>] [-f, --force]
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
The `--to` path das to be empty as no data will be overwritten by default. If you are sure you can pass the `-f, --force` flag and the data will be overwritten in the destination. However note that this will overwrite all the data existent in the backup, not only the 1 file that is missing e.g.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@@ -2,7 +2,12 @@
|
|||||||
|
|
||||||
This amazing people helped the project!
|
This amazing people helped the project!
|
||||||
|
|
||||||
- @ChanceM [Docs]
|
- @agateblue - Docs, Pruning, S3
|
||||||
- @EliotBerriot [Docs, Pruning, S3]
|
- @david-boles - Docs
|
||||||
|
- @jin-park-dev - Typos
|
||||||
|
- @sumnerboy12 - Typos
|
||||||
|
- @FuzzyMistborn - Typos
|
||||||
|
- @ChanceM - Typos
|
||||||
|
- @TheForcer - Typos
|
||||||
|
|
||||||
> :ToCPrevNext
|
> :ToCPrevNext
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
## List all the snapshots for all the backends
|
## List all the snapshots for all the backends
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
autorestic exec -a -- snapshots
|
autorestic exec -av -- snapshots
|
||||||
```
|
```
|
||||||
|
|
||||||
## Unlock a locked repository
|
## Unlock a locked repository
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
# Cron
|
# Cron
|
||||||
|
|
||||||
Often it is usefull to trigger backups autmatically. For this we can specify a `cron` attribute to each location.
|
Often it is usefully to trigger backups automatically. For this we can specify a `cron` attribute to each location.
|
||||||
|
|
||||||
```yaml | .autorestic.yml
|
```yaml | .autorestic.yml
|
||||||
locations:
|
locations:
|
||||||
@@ -14,11 +14,11 @@ Here is a awesome website with [some examples](https://crontab.guru/examples.htm
|
|||||||
|
|
||||||
## Installing the cron
|
## Installing the cron
|
||||||
|
|
||||||
**This has to be done only once, regadless of now many cros you have in your config file.**
|
**This has to be done only once, regardless of now many cron jobs you have in your config file.**
|
||||||
|
|
||||||
To actually enable cron jobs you need something to call `autorestic cron` on a timed shedule.
|
To actually enable cron jobs you need something to call `autorestic cron` on a timed schedule.
|
||||||
Note that the shedule has nothing to do with the `cron` attribute in each location.
|
Note that the schedule has nothing to do with the `cron` attribute in each location.
|
||||||
My advise would be to trigger the command every 5min, but if you have a cronjob that runs only once a week, it's probably enough to shedule it once a day.
|
My advise would be to trigger the command every 5min, but if you have a cronjob that runs only once a week, it's probably enough to schedule it once a day.
|
||||||
|
|
||||||
### Crontab
|
### Crontab
|
||||||
|
|
||||||
@@ -30,14 +30,14 @@ First, open your crontab in edit mode
|
|||||||
crontab -e
|
crontab -e
|
||||||
```
|
```
|
||||||
|
|
||||||
Then paste this at the bottom of the file and save it. Note that in this specific example the `.autorestic.yml` is located in `/srv/`. You need to modify that part of course to fit your config file.
|
Then paste this at the bottom of the file and save it. Note that in this specific example the config file is located at one of the default locations (e.g. `~/.autorestic.yml`). If your config is somewhere else you'll need to specify it using the `-c` option.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# This is required, as it otherwise cannot find restic as a command.
|
# This is required, as it otherwise cannot find restic as a command.
|
||||||
PATH="/usr/local/bin:/usr/bin:/bin"
|
PATH="/usr/local/bin:/usr/bin:/bin"
|
||||||
|
|
||||||
# Example running every 5 minutes
|
# Example running every 5 minutes
|
||||||
*/5 * * * * autorestic -c /srv/.autorestic.yml --ci cron
|
*/5 * * * * autorestic --ci cron
|
||||||
```
|
```
|
||||||
|
|
||||||
> The `--ci` option is not required, but recommended
|
> The `--ci` option is not required, but recommended
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
# Excluding files
|
# Excluding files
|
||||||
|
|
||||||
If you want to exclude certain files or folders it done easily by specifiyng the right flags in the location you desire to filter.
|
If you want to exclude certain files or folders it done easily by specifying 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) so you can use any flag used there.
|
The flags are taken straight from the [restic cli exclude rules](https://restic.readthedocs.io/en/latest/040_backup.html#excluding-files) so you can use any flag used there.
|
||||||
|
|
||||||
|
@@ -14,11 +14,11 @@ locations:
|
|||||||
options:
|
options:
|
||||||
forget:
|
forget:
|
||||||
keep-last: 5 # always keep at least 5 snapshots
|
keep-last: 5 # always keep at least 5 snapshots
|
||||||
keep-hourly: 3 # keep 3 last hourly shapshots
|
keep-hourly: 3 # keep 3 last hourly snapshots
|
||||||
keep-daily: 4 # keep 4 last daily shapshots
|
keep-daily: 4 # keep 4 last daily snapshots
|
||||||
keep-weekly: 1 # keep 1 last weekly shapshots
|
keep-weekly: 1 # keep 1 last weekly snapshots
|
||||||
keep-monthly: 12 # keep 12 last monthly shapshots
|
keep-monthly: 12 # keep 12 last monthly snapshots
|
||||||
keep-yearly: 7 # keep 7 last yearly shapshots
|
keep-yearly: 7 # keep 7 last yearly snapshots
|
||||||
keep-within: '2w' # keep snapshots from the last 2 weeks
|
keep-within: '2w' # keep snapshots from the last 2 weeks
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -22,6 +22,6 @@ Paths can be absolute or relative. If relative they are resolved relative to the
|
|||||||
|
|
||||||
## `to`
|
## `to`
|
||||||
|
|
||||||
This is einther a single backend or an array of backends. The backends have to be configured in the same config file.
|
This is either a single backend or an array of backends. The backends have to be configured in the same config file.
|
||||||
|
|
||||||
> :ToCPrevNext
|
> :ToCPrevNext
|
||||||
|
@@ -9,13 +9,13 @@ curl -s https://raw.githubusercontent.com/CupCakeArmy/autorestic/master/install.
|
|||||||
## Write a simple config file
|
## Write a simple config file
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
vim .autorestic.yml
|
vim ~/.autorestic.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
For a quick overview:
|
For a quick overview:
|
||||||
|
|
||||||
- `locations` can be seen as the inputs and `backends` the output where the data is stored and backed up.
|
- `locations` can be seen as the inputs and `backends` the output where the data is stored and backed up.
|
||||||
- One `location` can have one or multiple `backends` for redudancy.
|
- One `location` can have one or multiple `backends` for redundancy.
|
||||||
- One `backend` can also be the target for multiple `locations`.
|
- One `backend` can also be the target for multiple `locations`.
|
||||||
|
|
||||||
> **⚠️ WARNING ⚠️**
|
> **⚠️ WARNING ⚠️**
|
||||||
@@ -24,25 +24,26 @@ For a quick overview:
|
|||||||
|
|
||||||
```yaml | .autorestic.yml
|
```yaml | .autorestic.yml
|
||||||
locations:
|
locations:
|
||||||
- name: home
|
home:
|
||||||
from: /home/me
|
from: /home/me
|
||||||
to: remote
|
to: remote
|
||||||
|
|
||||||
- name: important
|
important:
|
||||||
from: /path/to/important/stuff
|
from: /path/to/important/stuff
|
||||||
to:
|
to:
|
||||||
- remote
|
- remote
|
||||||
- hdd
|
- hdd
|
||||||
|
|
||||||
backends:
|
backends:
|
||||||
- name: remote
|
remote:
|
||||||
type: s3
|
type: s3
|
||||||
path: 's3.amazonaws.com/bucket_name'
|
path: 's3.amazonaws.com/bucket_name'
|
||||||
key: some-random-password-198rc79r8y1029c8yfewj8f1u0ef87yh198uoieufy
|
key: some-random-password-198rc79r8y1029c8yfewj8f1u0ef87yh198uoieufy
|
||||||
AWS_ACCESS_KEY_ID: account_id
|
env:
|
||||||
AWS_SECRET_ACCESS_KEY: account_key
|
AWS_ACCESS_KEY_ID: account_id
|
||||||
|
AWS_SECRET_ACCESS_KEY: account_key
|
||||||
|
|
||||||
- name: hdd
|
hdd:
|
||||||
type: local
|
type: local
|
||||||
path: /mnt/my_external_storage
|
path: /mnt/my_external_storage
|
||||||
key: 'if not key is set it will be generated for you'
|
key: 'if not key is set it will be generated for you'
|
||||||
@@ -51,7 +52,7 @@ backends:
|
|||||||
## Check
|
## Check
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
autorestic check -a
|
autorestic check
|
||||||
```
|
```
|
||||||
|
|
||||||
This checks if the config file has any issues. If this is the first time this can take longer as autorestic will setup the backends.
|
This checks if the config file has any issues. If this is the first time this can take longer as autorestic will setup the backends.
|
||||||
|
12
docs/package-lock.json
generated
12
docs/package-lock.json
generated
@@ -131,9 +131,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/chalk": {
|
"node_modules/chalk": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": "^4.1.0",
|
"ansi-styles": "^4.1.0",
|
||||||
"supports-color": "^7.1.0"
|
"supports-color": "^7.1.0"
|
||||||
@@ -1153,9 +1153,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-styles": "^4.1.0",
|
"ansi-styles": "^4.1.0",
|
||||||
"supports-color": "^7.1.0"
|
"supports-color": "^7.1.0"
|
||||||
|
@@ -16,9 +16,11 @@ else
|
|||||||
fi
|
fi
|
||||||
echo $OS
|
echo $OS
|
||||||
|
|
||||||
NATIVE_ARCH=$(uname -m)
|
NATIVE_ARCH=$(uname -m | tr '[:upper:]' '[:lower:]')
|
||||||
if [[ $NATIVE_ARCH == *"x86_64"* ]]; then
|
if [[ $NATIVE_ARCH == *"x86_64"* ]]; then
|
||||||
ARCH=amd64
|
ARCH=amd64
|
||||||
|
elif [[ $NATIVE_ARCH == *"arm64"* || $NATIVE_ARCH == *"aarch64"* ]]; then
|
||||||
|
ARCH=arm64
|
||||||
elif [[ $NATIVE_ARCH == *"x86"* ]]; then
|
elif [[ $NATIVE_ARCH == *"x86"* ]]; then
|
||||||
ARCH=386
|
ARCH=386
|
||||||
else
|
else
|
||||||
@@ -36,4 +38,4 @@ bzip2 -fd "${OUT_FILE}.bz2"
|
|||||||
chmod +x ${OUT_FILE}
|
chmod +x ${OUT_FILE}
|
||||||
|
|
||||||
autorestic install
|
autorestic install
|
||||||
echo "Succefsully installed autorestic"
|
echo "Successfully installed autorestic"
|
||||||
|
@@ -4,19 +4,25 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/cupcakearmy/autorestic/internal/colors"
|
"github.com/cupcakearmy/autorestic/internal/colors"
|
||||||
"github.com/spf13/viper"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type BackendRest struct {
|
||||||
|
User string `yaml:"user,omitempty"`
|
||||||
|
Password string `yaml:"password,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type Backend struct {
|
type Backend struct {
|
||||||
name string
|
name string
|
||||||
Type string `mapstructure:"type,omitempty"`
|
Type string `yaml:"type,omitempty"`
|
||||||
Path string `mapstructure:"path,omitempty"`
|
Path string `yaml:"path,omitempty"`
|
||||||
Key string `mapstructure:"key,omitempty"`
|
Key string `yaml:"key,omitempty"`
|
||||||
Env map[string]string `mapstructure:"env,omitempty"`
|
Env map[string]string `yaml:"env,omitempty"`
|
||||||
|
Rest BackendRest `yaml:"rest,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetBackend(name string) (Backend, bool) {
|
func GetBackend(name string) (Backend, bool) {
|
||||||
@@ -29,7 +35,20 @@ func (b Backend) generateRepo() (string, error) {
|
|||||||
switch b.Type {
|
switch b.Type {
|
||||||
case "local":
|
case "local":
|
||||||
return GetPathRelativeToConfig(b.Path)
|
return GetPathRelativeToConfig(b.Path)
|
||||||
case "b2", "azure", "gs", "s3", "sftp", "rest":
|
case "rest":
|
||||||
|
parsed, err := url.Parse(b.Path)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if b.Rest.User != "" {
|
||||||
|
if b.Rest.Password == "" {
|
||||||
|
parsed.User = url.User(b.Rest.User)
|
||||||
|
} else {
|
||||||
|
parsed.User = url.UserPassword(b.Rest.User, b.Rest.Password)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s:%s", b.Type, parsed.String()), nil
|
||||||
|
case "b2", "azure", "gs", "s3", "sftp", "rclone":
|
||||||
return fmt.Sprintf("%s:%s", b.Type, b.Path), nil
|
return fmt.Sprintf("%s:%s", b.Type, b.Path), nil
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("backend type \"%s\" is invalid", b.Type)
|
return "", fmt.Errorf("backend type \"%s\" is invalid", b.Type)
|
||||||
@@ -70,15 +89,10 @@ func (b Backend) validate() error {
|
|||||||
c := GetConfig()
|
c := GetConfig()
|
||||||
tmp := c.Backends[b.name]
|
tmp := c.Backends[b.name]
|
||||||
tmp.Key = key
|
tmp.Key = key
|
||||||
tmp.name = ""
|
|
||||||
c.Backends[b.name] = tmp
|
c.Backends[b.name] = tmp
|
||||||
file := viper.ConfigFileUsed()
|
if err := c.SaveConfig(); err != nil {
|
||||||
if err := CopyFile(file, file+".old"); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
colors.Secondary.Println("Saved a backup copy of your file next the the original.")
|
|
||||||
viper.Set("backends", c.Backends)
|
|
||||||
viper.WriteConfig()
|
|
||||||
}
|
}
|
||||||
env, err := b.getEnv()
|
env, err := b.getEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -107,16 +121,20 @@ func (b Backend) Exec(args []string) error {
|
|||||||
}
|
}
|
||||||
options := ExecuteOptions{Envs: env}
|
options := ExecuteOptions{Envs: env}
|
||||||
out, err := ExecuteResticCommand(options, args...)
|
out, err := ExecuteResticCommand(options, args...)
|
||||||
|
if err != nil {
|
||||||
|
colors.Error.Println(out)
|
||||||
|
return err
|
||||||
|
}
|
||||||
if VERBOSE {
|
if VERBOSE {
|
||||||
colors.Faint.Println(out)
|
colors.Faint.Println(out)
|
||||||
}
|
}
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Backend) ExecDocker(l Location, args []string) error {
|
func (b Backend) ExecDocker(l Location, args []string) (string, error) {
|
||||||
env, err := b.getEnv()
|
env, err := b.getEnv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
volume := l.getVolumeName()
|
volume := l.getVolumeName()
|
||||||
path, _ := l.getPath()
|
path, _ := l.getPath()
|
||||||
@@ -143,8 +161,5 @@ func (b Backend) ExecDocker(l Location, args []string) error {
|
|||||||
}
|
}
|
||||||
docker = append(docker, "restic/restic", "-c", "restic "+strings.Join(args, " "))
|
docker = append(docker, "restic/restic", "-c", "restic "+strings.Join(args, " "))
|
||||||
out, err := ExecuteCommand(options, docker...)
|
out, err := ExecuteCommand(options, docker...)
|
||||||
if VERBOSE {
|
return out, err
|
||||||
colors.Faint.Println(out)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
@@ -120,7 +120,9 @@ func upgradeRestic() error {
|
|||||||
func Upgrade(restic bool) error {
|
func Upgrade(restic bool) error {
|
||||||
// Upgrade restic
|
// Upgrade restic
|
||||||
if restic {
|
if restic {
|
||||||
InstallRestic()
|
if err := InstallRestic(); err != nil {
|
||||||
|
colors.Error.Println(err)
|
||||||
|
}
|
||||||
upgradeRestic()
|
upgradeRestic()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,14 +12,15 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "1.0.3"
|
const VERSION = "1.0.8"
|
||||||
|
|
||||||
var CI bool = false
|
var CI bool = false
|
||||||
var VERBOSE bool = false
|
var VERBOSE bool = false
|
||||||
|
var CRON_LEAN bool = false
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Locations map[string]Location `mapstructure:"locations"`
|
Locations map[string]Location `yaml:"locations"`
|
||||||
Backends map[string]Backend `mapstructure:"backends"`
|
Backends map[string]Backend `yaml:"backends"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
@@ -29,7 +30,9 @@ func GetConfig() *Config {
|
|||||||
if config == nil {
|
if config == nil {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
if err := viper.ReadInConfig(); err == nil {
|
if err := viper.ReadInConfig(); err == nil {
|
||||||
colors.Faint.Println("Using config file:", viper.ConfigFileUsed())
|
if !CRON_LEAN {
|
||||||
|
colors.Faint.Println("Using config file:", viper.ConfigFileUsed())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -190,10 +193,29 @@ func GetAllOrSelected(cmd *cobra.Command, backends bool) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AddFlagsToCommand(cmd *cobra.Command, backend bool) {
|
func AddFlagsToCommand(cmd *cobra.Command, backend bool) {
|
||||||
cmd.PersistentFlags().BoolP("all", "a", false, "Backup all locations")
|
var usage string
|
||||||
if backend {
|
if backend {
|
||||||
cmd.PersistentFlags().StringSliceP("backend", "b", []string{}, "backends")
|
usage = "all backends"
|
||||||
} else {
|
} else {
|
||||||
cmd.PersistentFlags().StringSliceP("location", "l", []string{}, "Locations")
|
usage = "all locations"
|
||||||
|
}
|
||||||
|
cmd.PersistentFlags().BoolP("all", "a", false, usage)
|
||||||
|
if backend {
|
||||||
|
cmd.PersistentFlags().StringSliceP("backend", "b", []string{}, "select backends")
|
||||||
|
} else {
|
||||||
|
cmd.PersistentFlags().StringSliceP("location", "l", []string{}, "select locations")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) SaveConfig() error {
|
||||||
|
file := viper.ConfigFileUsed()
|
||||||
|
if err := CopyFile(file, file+".old"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
colors.Secondary.Println("Saved a backup copy of your file next the the original.")
|
||||||
|
|
||||||
|
viper.Set("backends", c.Backends)
|
||||||
|
viper.Set("locations", c.Locations)
|
||||||
|
|
||||||
|
return viper.WriteConfig()
|
||||||
|
}
|
||||||
|
@@ -24,19 +24,19 @@ const (
|
|||||||
type HookArray = []string
|
type HookArray = []string
|
||||||
|
|
||||||
type Hooks struct {
|
type Hooks struct {
|
||||||
Before HookArray `mapstructure:"before"`
|
Before HookArray `yaml:"before"`
|
||||||
After HookArray `mapstructure:"after"`
|
After HookArray `yaml:"after"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Options map[string]map[string][]string
|
type Options map[string]map[string][]string
|
||||||
|
|
||||||
type Location struct {
|
type Location struct {
|
||||||
name string `mapstructure:",omitempty"`
|
name string `yaml:",omitempty"`
|
||||||
From string `mapstructure:"from,omitempty"`
|
From string `yaml:"from,omitempty"`
|
||||||
To []string `mapstructure:"to,omitempty"`
|
To []string `yaml:"to,omitempty"`
|
||||||
Hooks Hooks `mapstructure:"hooks,omitempty"`
|
Hooks Hooks `yaml:"hooks,omitempty"`
|
||||||
Cron string `mapstructure:"cron,omitempty"`
|
Cron string `yaml:"cron,omitempty"`
|
||||||
Options Options `mapstructure:"options,omitempty"`
|
Options Options `yaml:"options,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetLocation(name string) (Location, bool) {
|
func GetLocation(name string) (Location, bool) {
|
||||||
@@ -49,6 +49,18 @@ func (l Location) validate(c *Config) error {
|
|||||||
if l.From == "" {
|
if l.From == "" {
|
||||||
return fmt.Errorf(`Location "%s" is missing "from" key`, l.name)
|
return fmt.Errorf(`Location "%s" is missing "from" key`, l.name)
|
||||||
}
|
}
|
||||||
|
if from, err := GetPathRelativeToConfig(l.From); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
if stat, err := os.Stat(from); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
if !stat.IsDir() {
|
||||||
|
return fmt.Errorf("\"%s\" is not valid directory for location \"%s\"", from, l.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(l.To) == 0 {
|
if len(l.To) == 0 {
|
||||||
return fmt.Errorf(`Location "%s" has no "to" targets`, l.name)
|
return fmt.Errorf(`Location "%s" has no "to" targets`, l.name)
|
||||||
}
|
}
|
||||||
@@ -81,12 +93,13 @@ func ExecuteHooks(commands []string, options ExecuteOptions) error {
|
|||||||
for _, command := range commands {
|
for _, command := range commands {
|
||||||
colors.Body.Println("> " + command)
|
colors.Body.Println("> " + command)
|
||||||
out, err := ExecuteCommand(options, "-c", command)
|
out, err := ExecuteCommand(options, "-c", command)
|
||||||
|
if err != nil {
|
||||||
|
colors.Error.Println(out)
|
||||||
|
return err
|
||||||
|
}
|
||||||
if VERBOSE {
|
if VERBOSE {
|
||||||
colors.Faint.Println(out)
|
colors.Faint.Println(out)
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
colors.Body.Println("")
|
colors.Body.Println("")
|
||||||
return nil
|
return nil
|
||||||
@@ -161,16 +174,16 @@ func (l Location) Backup(cron bool) error {
|
|||||||
switch t {
|
switch t {
|
||||||
case TypeLocal:
|
case TypeLocal:
|
||||||
out, err = ExecuteResticCommand(backupOptions, cmd...)
|
out, err = ExecuteResticCommand(backupOptions, cmd...)
|
||||||
if VERBOSE {
|
|
||||||
colors.Faint.Println(out)
|
|
||||||
}
|
|
||||||
case TypeVolume:
|
case TypeVolume:
|
||||||
err = backend.ExecDocker(l, cmd)
|
out, err = backend.ExecDocker(l, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
colors.Error.Println(out)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if VERBOSE {
|
||||||
|
colors.Faint.Println(out)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// After hooks
|
// After hooks
|
||||||
@@ -271,7 +284,7 @@ func (l Location) Restore(to, from string, force bool) error {
|
|||||||
}
|
}
|
||||||
err = backend.Exec([]string{"restore", "--target", to, "--path", path, "latest"})
|
err = backend.Exec([]string{"restore", "--target", to, "--path", path, "latest"})
|
||||||
case TypeVolume:
|
case TypeVolume:
|
||||||
err = backend.ExecDocker(l, []string{"restore", "--target", ".", "--path", path, "latest"})
|
_, err = backend.ExecDocker(l, []string{"restore", "--target", ".", "--path", path, "latest"})
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -296,7 +309,9 @@ func (l Location) RunCron() error {
|
|||||||
lock.SetCron(l.name, now.Unix())
|
lock.SetCron(l.name, now.Unix())
|
||||||
l.Backup(true)
|
l.Backup(true)
|
||||||
} else {
|
} else {
|
||||||
colors.Body.Printf("Skipping \"%s\", not due yet.\n", l.name)
|
if !CRON_LEAN {
|
||||||
|
colors.Body.Printf("Skipping \"%s\", not due yet.\n", l.name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user