autorestic/internal/config.go

223 lines
4.8 KiB
Go
Raw Permalink Normal View History

2021-04-08 23:55:10 +00:00
package internal
import (
"fmt"
"path"
"strings"
"sync"
2021-04-12 14:15:17 +00:00
"github.com/cupcakearmy/autorestic/internal/colors"
2021-04-08 23:55:10 +00:00
"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
2021-05-06 14:17:45 +00:00
const VERSION = "1.1.0"
2021-04-11 11:04:11 +00:00
2021-04-12 14:15:17 +00:00
var CI bool = false
var VERBOSE bool = false
2021-04-28 08:54:07 +00:00
var CRON_LEAN bool = false
2021-04-12 14:15:17 +00:00
2021-04-08 23:55:10 +00:00
type Config struct {
Locations map[string]Location `yaml:"locations"`
Backends map[string]Backend `yaml:"backends"`
2021-04-08 23:55:10 +00:00
}
var once sync.Once
var config *Config
func GetConfig() *Config {
if config == nil {
once.Do(func() {
2021-04-12 14:15:17 +00:00
if err := viper.ReadInConfig(); err == nil {
2021-04-28 08:54:07 +00:00
if !CRON_LEAN {
colors.Faint.Println("Using config file:", viper.ConfigFileUsed())
}
2021-04-12 14:15:17 +00:00
} else {
return
}
2021-04-08 23:55:10 +00:00
config = &Config{}
if err := viper.UnmarshalExact(config); err != nil {
2021-04-11 22:02:35 +00:00
panic(err)
2021-04-08 23:55:10 +00:00
}
})
}
return config
}
2021-04-11 16:17:21 +00:00
func GetPathRelativeToConfig(p string) (string, error) {
2021-04-08 23:55:10 +00:00
if path.IsAbs(p) {
2021-04-11 16:17:21 +00:00
return p, nil
2021-04-08 23:55:10 +00:00
} else if strings.HasPrefix(p, "~") {
home, err := homedir.Dir()
2021-04-11 16:17:21 +00:00
return path.Join(home, strings.TrimPrefix(p, "~")), err
2021-04-08 23:55:10 +00:00
} else {
2021-04-11 16:17:21 +00:00
return path.Join(path.Dir(viper.ConfigFileUsed()), p), nil
2021-04-08 23:55:10 +00:00
}
}
2021-04-16 20:37:15 +00:00
func (c *Config) Describe() {
2021-04-17 10:02:00 +00:00
// Locations
2021-04-16 20:37:15 +00:00
for name, l := range c.Locations {
var tmp string
colors.PrimaryPrint(`Location: "%s"`, name)
2021-04-17 10:02:00 +00:00
colors.PrintDescription("From", l.From)
2021-04-16 20:37:15 +00:00
tmp = ""
for _, to := range l.To {
2021-04-17 10:02:00 +00:00
tmp += fmt.Sprintf("\t%s %s\n", colors.Success.Sprint("→"), to)
2021-04-16 20:37:15 +00:00
}
2021-04-17 10:02:00 +00:00
colors.PrintDescription("To", tmp)
2021-04-16 20:37:15 +00:00
if l.Cron != "" {
2021-04-17 10:02:00 +00:00
colors.PrintDescription("Cron", l.Cron)
2021-04-16 20:37:15 +00:00
}
2021-05-06 13:55:32 +00:00
tmp = ""
hooks := map[string][]string{
"Before": l.Hooks.Before,
"After": l.Hooks.After,
"Failure": l.Hooks.Failure,
"Success": l.Hooks.Success,
}
for hook, commands := range hooks {
if len(commands) > 0 {
tmp += "\n\t" + hook
for _, cmd := range commands {
2021-04-17 10:02:00 +00:00
tmp += colors.Faint.Sprintf("\n\t ▶ %s", cmd)
2021-04-16 20:37:15 +00:00
}
}
2021-05-06 13:55:32 +00:00
}
if tmp != "" {
2021-04-17 10:02:00 +00:00
colors.PrintDescription("Hooks", tmp)
2021-04-16 20:37:15 +00:00
}
if len(l.Options) > 0 {
tmp = ""
for t, options := range l.Options {
2021-04-17 10:02:00 +00:00
tmp += "\n\t" + t
2021-04-16 20:37:15 +00:00
for option, values := range options {
for _, value := range values {
2021-04-17 10:02:00 +00:00
tmp += colors.Faint.Sprintf("\n\t ✧ --%s=%s", option, value)
2021-04-16 20:37:15 +00:00
}
}
}
2021-04-17 10:02:00 +00:00
colors.PrintDescription("Options", tmp)
}
}
// Backends
for name, b := range c.Backends {
colors.PrimaryPrint("Backend: \"%s\"", name)
colors.PrintDescription("Type", b.Type)
colors.PrintDescription("Path", b.Path)
if len(b.Env) > 0 {
tmp := ""
for option, value := range b.Env {
2021-04-17 11:04:40 +00:00
tmp += fmt.Sprintf("\n\t%s %s %s", colors.Success.Sprint("✧"), strings.ToUpper(option), colors.Faint.Sprint(value))
2021-04-17 10:02:00 +00:00
}
colors.PrintDescription("Env", tmp)
2021-04-16 20:37:15 +00:00
}
}
}
2021-04-16 20:02:25 +00:00
func CheckConfig() error {
c := GetConfig()
2021-04-12 14:15:17 +00:00
if c == nil {
return fmt.Errorf("config could not be loaded/found")
}
2021-04-12 08:55:57 +00:00
if !CheckIfResticIsCallable() {
2021-05-06 13:04:35 +00:00
return fmt.Errorf(`%s was not found. Install either with "autorestic install" or manually`, RESTIC_BIN)
2021-04-12 08:55:57 +00:00
}
2021-04-16 20:02:25 +00:00
for name, backend := range c.Backends {
backend.name = name
2021-04-08 23:55:10 +00:00
if err := backend.validate(); err != nil {
2021-04-11 22:02:35 +00:00
return err
}
2021-04-08 23:55:10 +00:00
}
2021-04-16 20:02:25 +00:00
for name, location := range c.Locations {
location.name = name
2021-04-08 23:55:10 +00:00
if err := location.validate(c); err != nil {
2021-04-11 22:02:35 +00:00
return err
}
2021-04-08 23:55:10 +00:00
}
return nil
}
2021-04-11 11:04:11 +00:00
func GetAllOrSelected(cmd *cobra.Command, backends bool) ([]string, error) {
2021-04-08 23:55:10 +00:00
var list []string
if backends {
2021-04-16 20:02:25 +00:00
for name := range config.Backends {
list = append(list, name)
2021-04-08 23:55:10 +00:00
}
} else {
2021-04-16 20:02:25 +00:00
for name := range config.Locations {
list = append(list, name)
2021-04-08 23:55:10 +00:00
}
}
2021-04-16 20:02:25 +00:00
2021-04-08 23:55:10 +00:00
all, _ := cmd.Flags().GetBool("all")
if all {
2021-04-11 11:04:11 +00:00
return list, nil
2021-04-16 20:02:25 +00:00
}
var selected []string
if backends {
selected, _ = cmd.Flags().GetStringSlice("backend")
2021-04-08 23:55:10 +00:00
} else {
2021-04-16 20:02:25 +00:00
selected, _ = cmd.Flags().GetStringSlice("location")
}
for _, s := range selected {
found := false
for _, l := range list {
if l == s {
found = true
break
2021-04-08 23:55:10 +00:00
}
}
2021-04-16 20:02:25 +00:00
if !found {
if backends {
return nil, fmt.Errorf("invalid backend \"%s\"", s)
} else {
return nil, fmt.Errorf("invalid location \"%s\"", s)
}
2021-04-11 12:22:46 +00:00
}
2021-04-11 11:04:11 +00:00
}
2021-04-16 20:02:25 +00:00
if len(selected) == 0 {
return selected, fmt.Errorf("nothing selected, aborting")
}
return selected, nil
2021-04-11 11:04:11 +00:00
}
func AddFlagsToCommand(cmd *cobra.Command, backend bool) {
2021-04-28 08:54:07 +00:00
var usage string
if backend {
usage = "all backends"
} else {
usage = "all locations"
}
cmd.PersistentFlags().BoolP("all", "a", false, usage)
2021-04-11 11:04:11 +00:00
if backend {
2021-04-28 08:54:07 +00:00
cmd.PersistentFlags().StringSliceP("backend", "b", []string{}, "select backends")
2021-04-11 11:04:11 +00:00
} else {
2021-04-28 08:54:07 +00:00
cmd.PersistentFlags().StringSliceP("location", "l", []string{}, "select locations")
2021-04-08 23:55:10 +00:00
}
}
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()
}