diff --git a/backive.puml b/backive.puml new file mode 100644 index 0000000..a6b79b2 --- /dev/null +++ b/backive.puml @@ -0,0 +1,121 @@ +@startuml +namespace backive { + class Backup << (S,Aquamarine) >> { + - logger *log.Logger + + + Name string + + TargetDevice string + + TargetPath string + + SourcePath string + + ScriptPath interface{} + + Frequency int + + ExeUser string + + Label string + + + CanRun() error + + PrepareRun() error + + Run() error + + ShouldRun() bool + + } + class Backups << (S,Aquamarine) >> { + + FindBackupsForDevice(d Device) ([]*Backup, bool) + + } + class Configuration << (S,Aquamarine) >> { + + Settings Settings + + Devices Devices + + Backups Backups + + Vconfig *viper.Viper + + + CreateViper() + + Load() + + } + class Database << (S,Aquamarine) >> { + - data map[string]interface{} + + + Save() + + Load() + + } + class Device << (S,Aquamarine) >> { + - isMounted bool + + + Name string + + UUID string + + OwnerUser string + + + Mount() error + + Unmount() error + + IsMounted() bool + + } + class EventHandler << (S,Aquamarine) >> { + - ls net.Listener + - callbacks []func(map[string]string) + + - process() + + + Init(socketPath string) error + + Listen() + + RegisterCallback(cb func(map[string]string) ) + + } + class MsgLvls << (S,Aquamarine) >> { + + Error MsgLevel + + Finish MsgLevel + + Remind MsgLevel + + Info MsgLevel + + Debug MsgLevel + + } + class Runs << (S,Aquamarine) >> { + - data map[string][]time.Time + + + Load(db Database) + + Save(db Database) + + RegisterRun(b *Backup) + + LastRun(b *Backup) (time.Time, error) + + } + class Settings << (S,Aquamarine) >> { + + SystemMountPoint string + + UserMountPoint string + + UnixSocketLocation string + + UIUnixSocketLocation string + + LogLocation string + + DbLocation string + + } + class UIHandler << (S,Aquamarine) >> { + - ls net.Listener + - client net.Conn + + + Init(socketPath string) error + + Listen() + + DisplayMessage(header string, message string, level MsgLevel) error + + } + class backive.Backups << (T, #FF7700) >> { + } + class backive.Devices << (T, #FF7700) >> { + } + class backive.MsgLevel << (T, #FF7700) >> { + } +} + + +namespace ui { + class uiSettings << (S,Aquamarine) >> { + - hideUntil time.Time + - globalLevel int + + } +} + + +"__builtin__.int" #.. "backive.MsgLevel" +"backive.map[string]*Backup" #.. "backive.Backups" +"backive.map[string]*Device" #.. "backive.Devices" +@enduml diff --git a/backup.go b/backup.go index 4eee154..12fb3b0 100644 --- a/backup.go +++ b/backup.go @@ -110,9 +110,7 @@ func (b *Backup) Run() error { scriptWArgs = append(scriptWArgs, v.(string)) } case []string: - for _, v := range slice { - scriptWArgs = append(scriptWArgs, v) - } + scriptWArgs = append(scriptWArgs, slice...) case string: scriptWArgs = append(scriptWArgs, slice) default: @@ -173,24 +171,53 @@ type Runs struct { // Load loads the data from the json database func (r *Runs) Load(db Database) { data := db.data["runs"] - if data != "" { - runerr := json.Unmarshal([]byte(db.data["runs"]), &r.data) - if runerr != nil { - panic(runerr) + if data != nil { + log.Println("Loading runs db") + switch d := data.(type) { + case string: + // be able to read the old version + log.Println("Loading legacy data") + runerr := json.Unmarshal([]byte(data.(string)), &r.data) + if runerr != nil { + panic(runerr) + } + case map[string]interface{}: + log.Println("Loading data") + if r.data == nil { + r.data = make(map[string][]time.Time) + } + raw := data.(map[string]interface{}) + for k, v := range raw { + r.data[k] = make([]time.Time, 0) + for _, i := range v.([]interface{}) { + t, _ := time.Parse(time.RFC3339Nano, i.(string)) + r.data[k] = append(r.data[k], t) + } + } + LogToJson(data) + default: + log.Printf("got data type: %s", d) } } + log.Println("Data loaded:") + LogToJson(r.data) } // Save saves the data into the json database func (r *Runs) Save(db Database) { if db.data == nil { - db.data = map[string]string{} + db.data = map[string]interface{}{} } - str, err := json.Marshal(r.data) + db.data["runs"] = r.data + LogToJson(db.data) +} + +func LogToJson(data interface{}) { + str, err := json.Marshal(data) if err != nil { panic(err) } - db.data["runs"] = string(str) + log.Printf("Data: %s", str) } // ShouldRun Takes a backup key and returns a bool if a backup should run now. @@ -208,17 +235,21 @@ func (b *Backup) ShouldRun() bool { if freq == 0 { return true } + if ok != nil && lr.Equal(time.Unix(0, 0)) { + return true + } return false } // RegisterRun saves a date of a backup run into the internal storage func (r *Runs) RegisterRun(b *Backup) { if r.data == nil { - r.data = map[string][]time.Time{} + x := map[string][]time.Time{} + r.data = x } nbl, ok := r.data[b.Name] if !ok { - nbl = make([]time.Time, 1) + nbl = make([]time.Time, 0) } nbl = append([]time.Time{time.Now()}, nbl...) r.data[b.Name] = nbl diff --git a/backup_test.go b/backup_test.go index 2dc5516..6d1e180 100644 --- a/backup_test.go +++ b/backup_test.go @@ -170,3 +170,5 @@ func TestRun(t *testing.T) { return nil } } + +// TODO: write a test for the lastRun method! diff --git a/cmd/backive/main.go b/cmd/backive/main.go index 0f89352..7ec5065 100644 --- a/cmd/backive/main.go +++ b/cmd/backive/main.go @@ -55,14 +55,19 @@ func defaultCallback(envMap map[string]string) { log.Printf("Device: Name: %s, UUID: %s", dev.Name, dev.UUID) backups, found := config.Backups.FindBackupsForDevice(*dev) log.Println("Searching configured backups...") + bnames := make([]string, 0) + for _, v := range backups { + bnames = append(bnames, v.Name) + } + log.Printf("Found backups: %s", bnames) if found { + // only mount device if we really have to do a backup! + dev.Mount() + log.Println("Device mounted.") for _, backup := range backups { - log.Printf("Backup found: %s", backup.Name) + log.Printf("Backup running: %s", backup.Name) err := backup.CanRun() if err == nil { - // only mount device if we really have to do a backup! - dev.Mount() - log.Println("Device mounted.") log.Println("Backup is able to run (config check passed).") prepErr := backup.PrepareRun() log.Println("Prepared run.") diff --git a/config.go b/config.go index 3da1755..223db3a 100644 --- a/config.go +++ b/config.go @@ -70,12 +70,12 @@ func (c *Configuration) Load() { panic("No configuration available!") } for k, v := range c.Backups { - log.Printf("Initializing backup '%s'\n", k) + //log.Printf("Initializing backup '%s'\n", k) v.Name = k log.Printf("Initialized backup '%s'\n", v.Name) } for k, v := range c.Devices { - log.Printf("Initializing device '%s'\n", k) + //log.Printf("Initializing device '%s'\n", k) v.Name = k log.Printf("Initialized device '%s'\n", v.Name) } diff --git a/database.go b/database.go index 31c2099..833a852 100644 --- a/database.go +++ b/database.go @@ -12,7 +12,7 @@ var mockOsReadFile = os.ReadFile // Database is a simple string to string mapping, where arbitrary strings can be stored and safed to disk or loaded type Database struct { - data map[string]string + data map[string]interface{} } var dbPath = "/var/lib/backive/data.json" @@ -40,7 +40,8 @@ func (d *Database) Load() { panic(rferr) } json.Unmarshal(data, &d.data) - } /*else if os.IsNotExist(err) { - // no data - }*/ + } else if os.IsNotExist(err) { + // initialize db + d.data = make(map[string]interface{}) + } } diff --git a/go.mod b/go.mod index 4b6c4d6..c6cfe03 100644 --- a/go.mod +++ b/go.mod @@ -48,5 +48,3 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect honnef.co/go/js/dom v0.0.0-20210725211120-f030747120f2 // indirect ) - -replace github.com/qwc/backive => ./ diff --git a/go.work b/go.work new file mode 100644 index 0000000..52a3b7c --- /dev/null +++ b/go.work @@ -0,0 +1,3 @@ +go 1.19 + +use . diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 0000000..806de33 --- /dev/null +++ b/go.work.sum @@ -0,0 +1 @@ +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0=