backup/config.go

182 lines
3.8 KiB
Go
Raw Normal View History

2021-11-14 03:53:13 +01:00
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"regexp"
2021-11-14 05:21:22 +01:00
"time"
2021-11-14 03:53:13 +01:00
"golang.org/x/crypto/ssh"
)
type Config struct {
Zfsnap map[string]string `json:"zfsnap"`
Box map[string]*Box `json:"box"`
Apps []AppConfig `json:apps`
Timezone string `json:"timezone"`
2021-11-14 05:21:22 +01:00
Now time.Time `json:"-"`
2021-11-14 03:53:13 +01:00
}
//Load config from file
func (c *Config) Load() error {
if *debugFlag {
log.Printf("SSHConfig.Load : Start")
}
b, err := ioutil.ReadFile(*cfgFile)
if err != nil {
if *debugFlag {
log.Printf("Config.Load : ioutil.ReadFile(%s) : %s", *cfgFile, err)
}
return err
}
err = json.Unmarshal(b, &c)
if err != nil {
if *debugFlag {
log.Printf("Config.Load : json.Unmarshal : %s", err)
}
return err
}
2021-11-14 05:21:22 +01:00
l, err := time.LoadLocation(cfg.Timezone)
if err != nil {
if *debugFlag {
log.Printf("Config.Load : time.LoadLocation : %s", err)
}
return err
}
c.Now = time.Now().In(l)
2021-11-14 03:53:13 +01:00
for k, v := range c.Box {
2021-11-14 05:21:22 +01:00
v.Name = k
2021-11-14 03:53:13 +01:00
s := &SSHConfig{
logged: false,
name: k,
}
v.ssh = s
keyRaw, err := ioutil.ReadFile(v.Key)
if err != nil {
if *debugFlag {
log.Printf("Config.Load : ioutil.ReadFile(%s) : %s", k, err)
}
return err
}
key, err := ssh.ParseRawPrivateKey(keyRaw)
if err != nil {
if *debugFlag {
log.Printf("Config.Load : ssh.ParseRawPrivateKey(%s) : %s", k, err)
}
return err
}
s.signer, err = ssh.NewSignerFromKey(key)
if err != nil {
if *debugFlag {
log.Printf("Config.Load : ssh.NewSignerFromKey(%s) : %s", k, err)
}
return err
}
s.config = &ssh.ClientConfig{
User: v.User,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(s.signer),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
s.client, err = ssh.Dial("tcp", v.Addr, s.config)
if err != nil {
if *debugFlag {
log.Printf("Config.Load : ssh.Dial(%s) : %s", k, err)
}
return err
}
session, err := s.client.NewSession()
if err != nil {
if *debugFlag {
log.Printf("Config.Load : client.NewSession(%s) : %s", k, err)
}
return err
}
var b bytes.Buffer
session.Stdout = &b
err = session.Run("TZ=\"" + cfg.Timezone + "\" zfsnap --version")
if err != nil {
if *debugFlag {
log.Printf("Config.Load : client.NewSession(%s) : %s", k, err)
}
return err
}
if *debugFlag {
log.Printf("Config.Load : logged into %s : %s", k, b.String())
}
session.Close()
s.logged = true
}
for _, app := range c.Apps {
for _, src := range app.Sources {
if !src.Valid() {
return fmt.Errorf("Source not valid : %s", string(src))
}
if _, ok := cfg.Box[src.Box()]; !ok {
return fmt.Errorf("No box defined for source : %s", string(src))
}
}
for _, dest := range app.Destinations {
if !dest.Valid() {
return fmt.Errorf("Destination not valid : %s", string(dest))
}
if _, ok := cfg.Box[dest.Box()]; !ok {
return fmt.Errorf("No box defined for destination : %s", string(dest))
}
}
for val, before := range app.Before {
_, err = regexp.Compile(val)
if err != nil {
if *debugFlag {
log.Printf("Config.Load : invalid regex : %s", val)
}
return err
}
if !before.Valid() {
return fmt.Errorf("Before not valid : %s", string(before))
}
if _, ok := cfg.Box[before.Box()]; !ok {
return fmt.Errorf("No box defined for before : %s", string(before))
}
}
for val, after := range app.After {
_, err = regexp.Compile(val)
if err != nil {
if *debugFlag {
log.Printf("Config.Load : invalid regex : %s", val)
}
return err
}
if !after.Valid() {
return fmt.Errorf("After not valid : %s", string(after))
}
if _, ok := cfg.Box[after.Box()]; !ok {
return fmt.Errorf("No box defined for after : %s", string(after))
}
}
}
return nil
}
//Close config
func (c *Config) Close() error {
return nil
}