mirror of
https://github.com/cupcakearmy/autorestic.git
synced 2025-09-06 02:20:39 +00:00
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
86ae70672a | |||
5c0788900f | |||
20334a7e83 | |||
7bebd04482 | |||
b9b8857bf4 | |||
dd6e618161 | |||
a4b54f9f64 | |||
c2e88193cd | |||
a2ef69d96d | |||
|
d45949b028 | ||
77d47cc697 | |||
a3239c0f3b | |||
90cd3171e5 | |||
61673bd88b | |||
41736ea3c4 | |||
a7779e04bd | |||
|
1326e7e53c |
24
CHANGELOG.md
24
CHANGELOG.md
@@ -5,6 +5,30 @@ 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/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.2.0] - 2021-08-05
|
||||
|
||||
### Added
|
||||
|
||||
- Community page
|
||||
- Support for yaml references and aliases
|
||||
|
||||
### Fixed
|
||||
|
||||
- Better verbose output for hooks
|
||||
- Better error message for bad formatted configs
|
||||
|
||||
## [1.1.2] - 2021-07-11
|
||||
|
||||
### Fixes
|
||||
|
||||
Don't check all backend when running `forget` or `exec` commands.
|
||||
|
||||
## [1.1.1] - 2021-05-17
|
||||
|
||||
### Added
|
||||
|
||||
- Options for backends
|
||||
|
||||
## [1.1.0] - 2021-05-06
|
||||
|
||||
### Added
|
||||
|
@@ -19,7 +19,7 @@ Releases are automatically built by the github workflow and uploaded to the rele
|
||||
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.
|
||||
4. Create a new release with the `v1.2.3` tag and mark as pre-release.
|
||||
5. The Github action will build the binaries, upload and mark the release as ready when done.
|
||||
|
||||
### Brew
|
||||
|
@@ -13,12 +13,11 @@ var backupCmd = &cobra.Command{
|
||||
Use: "backup",
|
||||
Short: "Create backups for given locations",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
internal.GetConfig()
|
||||
err := lock.Lock()
|
||||
CheckErr(err)
|
||||
defer lock.Unlock()
|
||||
|
||||
internal.GetConfig()
|
||||
|
||||
selected, err := internal.GetAllOrSelected(cmd, false)
|
||||
CheckErr(err)
|
||||
errors := 0
|
||||
|
@@ -11,12 +11,11 @@ var execCmd = &cobra.Command{
|
||||
Use: "exec",
|
||||
Short: "Execute arbitrary native restic commands for given backends",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
internal.GetConfig()
|
||||
err := lock.Lock()
|
||||
CheckErr(err)
|
||||
defer lock.Unlock()
|
||||
|
||||
CheckErr(internal.CheckConfig())
|
||||
|
||||
selected, err := internal.GetAllOrSelected(cmd, true)
|
||||
CheckErr(err)
|
||||
for _, name := range selected {
|
||||
|
@@ -10,12 +10,11 @@ var forgetCmd = &cobra.Command{
|
||||
Use: "forget",
|
||||
Short: "Forget and optionally prune snapshots according the specified policies",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
internal.GetConfig()
|
||||
err := lock.Lock()
|
||||
CheckErr(err)
|
||||
defer lock.Unlock()
|
||||
|
||||
CheckErr(internal.CheckConfig())
|
||||
|
||||
selected, err := internal.GetAllOrSelected(cmd, false)
|
||||
CheckErr(err)
|
||||
prune, _ := cmd.Flags().GetBool("prune")
|
||||
|
@@ -22,6 +22,7 @@
|
||||
>
|
||||
> [Overview](/backend/overview)
|
||||
> [Available Backends](/backend/available)
|
||||
> [Options](/backend/options)
|
||||
|
||||
> :Collapse label=CLI
|
||||
>
|
||||
@@ -36,10 +37,10 @@
|
||||
> [Exec](/cli/exec)
|
||||
> [Install](/cli/install)
|
||||
> [Uninstall](/cli/uninstall)
|
||||
> [Update](/cli/update)
|
||||
> [Upgrade](/cli/upgrade)
|
||||
|
||||
[Examples](/examples)
|
||||
|
||||
[QA](/qa)
|
||||
|
||||
[Community](/community)
|
||||
[Contributors](/contrib)
|
||||
|
||||
|
23
docs/markdown/backend/options.md
Normal file
23
docs/markdown/backend/options.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Options
|
||||
|
||||
For the `backup` and `forget` commands you can pass any native flags to `restic`.
|
||||
|
||||
> It is also possible to set options for an [a specific location](/location/options).
|
||||
|
||||
```yaml
|
||||
backend:
|
||||
foo:
|
||||
type: ...
|
||||
path: ...
|
||||
options:
|
||||
backup:
|
||||
tag:
|
||||
- foo
|
||||
- bar
|
||||
```
|
||||
|
||||
In this example, whenever `autorestic` runs `restic backup` it will append a `--tag abc --tag` to the native command.
|
||||
|
||||
For more detail see the [location docs](/location/options) for options, as they are the same
|
||||
|
||||
> :ToCPrevNext
|
@@ -4,7 +4,7 @@
|
||||
autorestic forget [-l, --location] [-a, --all] [--dry-run] [--prune]
|
||||
```
|
||||
|
||||
This will prune and remove old data form the backends according to the [keep policy you have specified for the location](/location/forget)
|
||||
This will prune and remove old data form the backends according to the [keep policy you have specified for the location](/location/forget).
|
||||
|
||||
The `--dry-run` flag will do a dry run showing what would have been deleted, but won't touch the actual data.
|
||||
|
||||
|
@@ -1,11 +0,0 @@
|
||||
# Update
|
||||
|
||||
Autorestic can update itself! Super handy right? Simply run autorestic update and we will check for you if there are updates for restic and autorestic and install them if necessary.
|
||||
|
||||
```bash
|
||||
autorestic update
|
||||
```
|
||||
|
||||
Updates both restic and autorestic automagically.
|
||||
|
||||
> :ToCPrevNext
|
11
docs/markdown/cli/upgrade.md
Normal file
11
docs/markdown/cli/upgrade.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Upgrade
|
||||
|
||||
Autorestic can upgrade itself! Super handy right? Simply run autorestic upgrade and we will check for you if there are updates for restic and autorestic and install them if necessary.
|
||||
|
||||
```bash
|
||||
autorestic upgrade
|
||||
```
|
||||
|
||||
Updates both restic and autorestic automagically.
|
||||
|
||||
> :ToCPrevNext
|
9
docs/markdown/community.md
Normal file
9
docs/markdown/community.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# 🏘 Community
|
||||
|
||||
A list of community driven projects. (No official affiliation)
|
||||
|
||||
- Docker image: https://github.com/pascaliske/docker-autorestic
|
||||
- Ansible Role: https://github.com/adsanz/ansible-restic-role
|
||||
- Ansible Role: https://github.com/ItsNotGoodName/ansible-role-autorestic
|
||||
|
||||
> :ToCPrevNext
|
@@ -31,12 +31,53 @@ backends:
|
||||
remote:
|
||||
type: b2
|
||||
path: 'myBucket:backup/home'
|
||||
B2_ACCOUNT_ID: account_id
|
||||
B2_ACCOUNT_KEY: account_key
|
||||
env:
|
||||
B2_ACCOUNT_ID: account_id
|
||||
B2_ACCOUNT_KEY: account_key
|
||||
|
||||
hdd:
|
||||
type: local
|
||||
path: /mnt/my_external_storage
|
||||
```
|
||||
|
||||
## Aliases
|
||||
|
||||
A handy tool for more advanced configurations is to use yaml aliases.
|
||||
These must be specified under the global `extras` key in the `.autorestic.yml` config file.
|
||||
Aliases allow to reuse snippets of config throughout the same file.
|
||||
|
||||
The following example shows how the locations `a` and `b` share the same hooks and forget policies.
|
||||
|
||||
```yaml | .autorestic.yml
|
||||
extras:
|
||||
hooks: &foo
|
||||
before:
|
||||
- echo "Hello"
|
||||
after:
|
||||
- echo "kthxbye"
|
||||
policies: &bar
|
||||
keep-daily: 14
|
||||
keep-weekly: 52
|
||||
|
||||
backends:
|
||||
# ...
|
||||
locations:
|
||||
a:
|
||||
from: /data/a
|
||||
to: some
|
||||
hooks:
|
||||
<<: *foo
|
||||
options:
|
||||
forget:
|
||||
<<: *bar
|
||||
b:
|
||||
from: data/b
|
||||
to: some
|
||||
hooks:
|
||||
<<: *foo
|
||||
options:
|
||||
forget:
|
||||
<<: *bar
|
||||
```
|
||||
|
||||
> :ToCPrevNext
|
||||
|
@@ -12,5 +12,6 @@ This amazing people helped the project!
|
||||
- @ChanceM - Typos
|
||||
- @TheForcer - Typos
|
||||
- @themorlan - Typos
|
||||
- @somebox - Typos
|
||||
|
||||
> :ToCPrevNext
|
||||
|
@@ -2,6 +2,8 @@
|
||||
|
||||
For the `backup` and `forget` commands you can pass any native flags to `restic`.
|
||||
|
||||
> It is also possible to set options for an [entire backend](/backend/options).
|
||||
|
||||
```yaml
|
||||
locations:
|
||||
foo:
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# Update
|
||||
# Upgrade
|
||||
|
||||
## From `0.x` to `1.0`
|
||||
|
||||
|
854
docs/package-lock.json
generated
854
docs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,8 @@ elif [[ $NATIVE_ARCH == *"arm64"* || $NATIVE_ARCH == *"aarch64"* ]]; then
|
||||
ARCH=arm64
|
||||
elif [[ $NATIVE_ARCH == *"x86"* ]]; then
|
||||
ARCH=386
|
||||
elif [[ $NATIVE_ARCH == *"armv7"* ]]; then
|
||||
ARCH=arm
|
||||
else
|
||||
echo "Could not determine Architecure automatically, please check the release page manually: https://github.com/cupcakearmy/autorestic/releases"
|
||||
exit 1
|
||||
|
@@ -17,12 +17,13 @@ type BackendRest struct {
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
name string
|
||||
Type string `yaml:"type,omitempty"`
|
||||
Path string `yaml:"path,omitempty"`
|
||||
Key string `yaml:"key,omitempty"`
|
||||
Env map[string]string `yaml:"env,omitempty"`
|
||||
Rest BackendRest `yaml:"rest,omitempty"`
|
||||
name string
|
||||
Type string `yaml:"type,omitempty"`
|
||||
Path string `yaml:"path,omitempty"`
|
||||
Key string `yaml:"key,omitempty"`
|
||||
Env map[string]string `yaml:"env,omitempty"`
|
||||
Rest BackendRest `yaml:"rest,omitempty"`
|
||||
Options Options `yaml:"options,omitempty"`
|
||||
}
|
||||
|
||||
func GetBackend(name string) (Backend, bool) {
|
||||
|
@@ -2,23 +2,27 @@ package internal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/cupcakearmy/autorestic/internal/colors"
|
||||
"github.com/cupcakearmy/autorestic/internal/lock"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const VERSION = "1.1.0"
|
||||
const VERSION = "1.2.0"
|
||||
|
||||
var CI bool = false
|
||||
var VERBOSE bool = false
|
||||
var CRON_LEAN bool = false
|
||||
|
||||
type Config struct {
|
||||
Extras interface{} `yaml:"extras"`
|
||||
Locations map[string]Location `yaml:"locations"`
|
||||
Backends map[string]Backend `yaml:"backends"`
|
||||
}
|
||||
@@ -31,7 +35,8 @@ func GetConfig() *Config {
|
||||
once.Do(func() {
|
||||
if err := viper.ReadInConfig(); err == nil {
|
||||
if !CRON_LEAN {
|
||||
colors.Faint.Println("Using config file:", viper.ConfigFileUsed())
|
||||
absConfig, _ := filepath.Abs(viper.ConfigFileUsed())
|
||||
colors.Faint.Println("Using config file:", absConfig)
|
||||
}
|
||||
} else {
|
||||
return
|
||||
@@ -39,7 +44,9 @@ func GetConfig() *Config {
|
||||
|
||||
config = &Config{}
|
||||
if err := viper.UnmarshalExact(config); err != nil {
|
||||
panic(err)
|
||||
colors.Error.Println("Could not parse config file!")
|
||||
lock.Unlock()
|
||||
os.Exit(1)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -140,7 +147,7 @@ func CheckConfig() error {
|
||||
}
|
||||
for name, location := range c.Locations {
|
||||
location.name = name
|
||||
if err := location.validate(c); err != nil {
|
||||
if err := location.validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -220,3 +227,13 @@ func (c *Config) SaveConfig() error {
|
||||
|
||||
return viper.WriteConfig()
|
||||
}
|
||||
|
||||
func getOptions(options Options, key string) []string {
|
||||
var selected []string
|
||||
for k, values := range options[key] {
|
||||
for _, value := range values {
|
||||
selected = append(selected, fmt.Sprintf("--%s", k), value)
|
||||
}
|
||||
}
|
||||
return selected
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@ func GetLocation(name string) (Location, bool) {
|
||||
return l, ok
|
||||
}
|
||||
|
||||
func (l Location) validate(c *Config) error {
|
||||
func (l Location) validate() error {
|
||||
if l.From == "" {
|
||||
return fmt.Errorf(`Location "%s" is missing "from" key`, l.name)
|
||||
}
|
||||
@@ -78,17 +78,6 @@ func (l Location) validate(c *Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l Location) getOptions(key string) []string {
|
||||
var options []string
|
||||
saved := l.Options[key]
|
||||
for k, values := range saved {
|
||||
for _, value := range values {
|
||||
options = append(options, fmt.Sprintf("--%s", k), value)
|
||||
}
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
func ExecuteHooks(commands []string, options ExecuteOptions) error {
|
||||
if len(commands) == 0 {
|
||||
return nil
|
||||
@@ -143,8 +132,15 @@ func (l Location) Backup(cron bool) []error {
|
||||
Command: "bash",
|
||||
}
|
||||
|
||||
if err := l.validate(); err != nil {
|
||||
errors = append(errors, err)
|
||||
colors.Error.Print(err)
|
||||
goto after
|
||||
}
|
||||
|
||||
if t == TypeLocal {
|
||||
dir, _ := GetPathRelativeToConfig(l.From)
|
||||
colors.Faint.Printf("Executing under: \"%s\"\n", dir)
|
||||
options.Dir = dir
|
||||
}
|
||||
|
||||
@@ -164,9 +160,11 @@ func (l Location) Backup(cron bool) []error {
|
||||
continue
|
||||
}
|
||||
|
||||
flags := l.getOptions("backup")
|
||||
lFlags := getOptions(l.Options, "backup")
|
||||
bFlags := getOptions(backend.Options, "backup")
|
||||
cmd := []string{"backup"}
|
||||
cmd = append(cmd, flags...)
|
||||
cmd = append(cmd, lFlags...)
|
||||
cmd = append(cmd, bFlags...)
|
||||
if cron {
|
||||
cmd = append(cmd, "--tag", "cron")
|
||||
}
|
||||
@@ -232,7 +230,8 @@ func (l Location) Forget(prune bool, dry bool) error {
|
||||
options := ExecuteOptions{
|
||||
Envs: env,
|
||||
}
|
||||
flags := l.getOptions("forget")
|
||||
lFlags := getOptions(l.Options, "forget")
|
||||
bFlags := getOptions(backend.Options, "forget")
|
||||
cmd := []string{"forget", "--path", path}
|
||||
if prune {
|
||||
cmd = append(cmd, "--prune")
|
||||
@@ -240,7 +239,8 @@ func (l Location) Forget(prune bool, dry bool) error {
|
||||
if dry {
|
||||
cmd = append(cmd, "--dry-run")
|
||||
}
|
||||
cmd = append(cmd, flags...)
|
||||
cmd = append(cmd, lFlags...)
|
||||
cmd = append(cmd, bFlags...)
|
||||
out, err := ExecuteResticCommand(options, cmd...)
|
||||
if VERBOSE {
|
||||
colors.Faint.Println(out)
|
||||
|
Reference in New Issue
Block a user