From a05bf575a8d1270bccac4e11ec29aa6191a7359a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Christian=20Gr=C3=BCnhage?= Date: Wed, 31 May 2017 00:03:10 +0200 Subject: [PATCH] Replaced JSON with YAML, added run commands. TODO: Add documentation for run commands. --- generate/authorized_keys/example.json | 14 ----- generate/authorized_keys/example.yaml | 9 +++ .../generate_authorized_keys.go | 14 ++--- generate/folders/create_repo_folders.go | 4 +- main.go | 9 +++ run/config/structs.go | 25 ++++++++ run/create/create.go | 59 +++++++++++++++++++ run/example.yaml | 21 +++++++ run/prune/prune.go | 34 +++++++++++ run/run.go | 27 +++++++++ 10 files changed, 193 insertions(+), 23 deletions(-) delete mode 100644 generate/authorized_keys/example.json create mode 100644 generate/authorized_keys/example.yaml create mode 100644 run/config/structs.go create mode 100644 run/create/create.go create mode 100644 run/example.yaml create mode 100644 run/prune/prune.go create mode 100644 run/run.go diff --git a/generate/authorized_keys/example.json b/generate/authorized_keys/example.json deleted file mode 100644 index c4bd2d1..0000000 --- a/generate/authorized_keys/example.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "Folder": "/mnt/backupmount", - "Hosts":[ - { - "Name": "host1", - "SSHKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC7ZvLoWZgh5eMDQXLEdWobkt/B8mnM2osEynF0boorifRNwztQHY3bKXTHjUlMnnWH+UvZ3aXH16M1QmyuNi4kLUTSMu4GSVsXMfknHRjgJ927Y/j5TCGXfOcfB0B4pcgHS3fVi1VMXXiZ1S/X8cbt1llXHfEC5eKutDeJkRer3w== SSH_KEY" - }, - { - "Name": "host2", - "AppendOnly": true, - "SSHKey": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDIgm31x6ETn4HwxBthe3m14s1Bp9p8sT5kC/XSijN6uPpUmuF2ciRGc5QLzsBJR6MAD45zg6Q9nLBZGBnSIZDNfSGA5sqAeoZVHm4vjQWxenqG7dlNFXlC1DIHzMxxDsDUPneyXGBemAvVwL9h4HEC4xhMQIAJfaZqSWuNzzqYWw== SSH_KEY" - } - ] -} \ No newline at end of file diff --git a/generate/authorized_keys/example.yaml b/generate/authorized_keys/example.yaml new file mode 100644 index 0000000..af03584 --- /dev/null +++ b/generate/authorized_keys/example.yaml @@ -0,0 +1,9 @@ +--- +folder: "/mnt/backupmount" +hosts: +- name: host1 + sshkey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC7ZvLoWZgh5eMDQXLEdWobkt/B8mnM2osEynF0boorifRNwztQHY3bKXTHjUlMnnWH+UvZ3aXH16M1QmyuNi4kLUTSMu4GSVsXMfknHRjgJ927Y/j5TCGXfOcfB0B4pcgHS3fVi1VMXXiZ1S/X8cbt1llXHfEC5eKutDeJkRer3w== SSH_KEY + +- name: host2 + appendonly: true + sshkey: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDIgm31x6ETn4HwxBthe3m14s1Bp9p8sT5kC/XSijN6uPpUmuF2ciRGc5QLzsBJR6MAD45zg6Q9nLBZGBnSIZDNfSGA5sqAeoZVHm4vjQWxenqG7dlNFXlC1DIHzMxxDsDUPneyXGBemAvVwL9h4HEC4xhMQIAJfaZqSWuNzzqYWw== SSH_KEY diff --git a/generate/authorized_keys/generate_authorized_keys.go b/generate/authorized_keys/generate_authorized_keys.go index 885058a..df3c4c6 100644 --- a/generate/authorized_keys/generate_authorized_keys.go +++ b/generate/authorized_keys/generate_authorized_keys.go @@ -1,29 +1,29 @@ package authorized_keys import ( - "encoding/json" "fmt" + "gopkg.in/yaml.v2" ) type Host struct { - Name string - SSHKey string + Name string + SSHKey string AppendOnly bool } type HostList struct { Folder string - Hosts []Host + Hosts []Host } func Run(data []byte) { var hosts HostList - err := json.Unmarshal(data, &hosts) + err := yaml.Unmarshal(data, &hosts) check(err) for i := 0; i < len(hosts.Hosts); i++ { fmt.Print("command=\"borg serve --restrict-to-path ") fmt.Print(hosts.TotalPath(i)) - if (hosts.Hosts[i].AppendOnly) { + if hosts.Hosts[i].AppendOnly { fmt.Print(" --append only") } fmt.Print("\",no-pty,no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-user-rc ") @@ -39,4 +39,4 @@ func check(e error) { if e != nil { panic(e) } -} \ No newline at end of file +} diff --git a/generate/folders/create_repo_folders.go b/generate/folders/create_repo_folders.go index a73dc69..9999bab 100644 --- a/generate/folders/create_repo_folders.go +++ b/generate/folders/create_repo_folders.go @@ -2,14 +2,14 @@ package folders import ( "git.jcg.re/jcgruenhage/borgocli/generate/authorized_keys" - "encoding/json" + "gopkg.in/yaml.v2" "os" "fmt" ) func Run(data []byte) { var hosts authorized_keys.HostList - err := json.Unmarshal(data, &hosts) + err := yaml.Unmarshal(data, &hosts) check(err) fmt.Println("Backup Paths:") for i := 0; i < len(hosts.Hosts); i++ { diff --git a/main.go b/main.go index 006ec9a..6d2a7ef 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "git.jcg.re/jcgruenhage/borgocli/generate/authorized_keys" "io/ioutil" "git.jcg.re/jcgruenhage/borgocli/generate/folders" + "git.jcg.re/jcgruenhage/borgocli/run" ) func main() { @@ -16,6 +17,14 @@ func main() { case "folders": folders.Run(readFile(os.Args[3])) } + case "run": + var filename string + if len(os.Args) == 4 { + filename = os.Args[3] + } else { + filename = "/etc/borgocli.config" + } + run.Run(os.Args[2], readFile(filename)) } } diff --git a/run/config/structs.go b/run/config/structs.go new file mode 100644 index 0000000..ae213dc --- /dev/null +++ b/run/config/structs.go @@ -0,0 +1,25 @@ +package config + +type Config struct { + Data Data + Retention Retention +} + +type Data struct { + SourceDirectories []string + Excludes []string + Repository string + Compression string + ChunkerParameters string + Hostname string + Passphrase string +} + +type Retention struct { + Within string + Hourly int + Daily int + Weekly int + Monthly int + Yearly int +} diff --git a/run/create/create.go b/run/create/create.go new file mode 100644 index 0000000..2c7e671 --- /dev/null +++ b/run/create/create.go @@ -0,0 +1,59 @@ +package create + +import ( + "fmt" + "os/exec" + "regexp" + "errors" + "os" + "git.jcg.re/jcgruenhage/borgocli/run/config" +) + +func Run(config config.Config) { + var parameters []string + parameters = append(parameters, "create") + + match, err := regexp.MatchString("[0-9]+,[0-9]+,[0-9]+,[0-9]+", config.Data.ChunkerParameters) + check(err) + + if match { + parameters = append(parameters, fmt.Sprintf("--chunker-params %s", config.Data.ChunkerParameters)) + } else if len(config.Data.ChunkerParameters) != 0 { + panic(errors.New("The chunker parameters are malformed.")) + } + + match, err = regexp.MatchString("(none)|(lz4)|(zlib(,[0-9])?)|(lzma(,[0-9])?)", config.Data.Compression) + check(err) + + if match { + parameters = append(parameters, fmt.Sprintf("--compression %s", config.Data.Compression)) + } else if len(config.Data.ChunkerParameters) != 0 { + panic(errors.New("The compression parameter is malformed")) + } + + if len(config.Data.Excludes) != 0 { + for i := 0; i < len(config.Data.Excludes); i++ { + parameters = append(parameters, fmt.Sprintf("--exclude %s", config.Data.Excludes[i])) + } + } + + parameters = append(parameters, fmt.Sprintf("%s::%s-{now}", config.Data.Repository, config.Data.Hostname)) + parameters = append(parameters, config.Data.SourceDirectories...) + + if len(config.Data.Passphrase) != 0 { + os.Setenv("BORG_PASSPHRASE", config.Data.Passphrase) + } + + cmd := exec.Command("borg", parameters...) + + fmt.Print(cmd.Path, cmd.Args) + + if err := cmd.Run(); err != nil { + panic(err) + } +} +func check(err error) { + if err != nil { + panic(err) + } +} diff --git a/run/example.yaml b/run/example.yaml new file mode 100644 index 0000000..797f950 --- /dev/null +++ b/run/example.yaml @@ -0,0 +1,21 @@ +data: + sourcedirectories: + - "/home/user" + - "/etc" + - "/var/lib" + excludes: + - "*pyc" + - "*.javac" + - "/home/*/.cache" + repository: "ssh://borg@backuphost:port/repository/path" + compression: "zlib,9" + chunkerparameters: "19,24,21,4095" + hostname: "remarkableDeviceName" + passphrase: "super secret ultra strong passphrase" +retention: + within: "6h" + hourly: 48 + daily: 31 + weekly: 52 + monthly: 36 + yearly: -1 \ No newline at end of file diff --git a/run/prune/prune.go b/run/prune/prune.go new file mode 100644 index 0000000..8452709 --- /dev/null +++ b/run/prune/prune.go @@ -0,0 +1,34 @@ +package prune + +import ( + "os/exec" + "fmt" + "git.jcg.re/jcgruenhage/borgocli/run/config" +) + +func Run(config config.Config) { + var parameters []string + + parameters = append(parameters, "prune") + + if len(config.Retention.Within) != 0 { + parameters = append(parameters, fmt.Sprintf("--keep-within %s", config.Retention.Within)) + } + + parameters = append(parameters, fmt.Sprintf("--keep-hourly %d", config.Retention.Hourly)) + parameters = append(parameters, fmt.Sprintf("--keep-daily %d", config.Retention.Daily)) + parameters = append(parameters, fmt.Sprintf("--keep-weekly %d", config.Retention.Weekly)) + parameters = append(parameters, fmt.Sprintf("--keep-monthly %d", config.Retention.Monthly)) + parameters = append(parameters, fmt.Sprintf("--keep-yearly %d", config.Retention.Yearly)) + + parameters = append(parameters, fmt.Sprintf("-P %s", config.Data.Hostname), config.Data.Repository) + + cmd := exec.Command("borg", parameters...) + + + fmt.Print(cmd.Path, parameters) + + if err := cmd.Run(); err != nil { + panic(err) + } +} diff --git a/run/run.go b/run/run.go new file mode 100644 index 0000000..b42f632 --- /dev/null +++ b/run/run.go @@ -0,0 +1,27 @@ +package run + +import ( + "gopkg.in/yaml.v2" + "git.jcg.re/jcgruenhage/borgocli/run/prune" + "git.jcg.re/jcgruenhage/borgocli/run/create" + "git.jcg.re/jcgruenhage/borgocli/run/config" +) + +func Run(command string, data []byte) { + var config config.Config + err := yaml.Unmarshal(data, &config) + check(err) + switch command { + case "create": + create.Run(config) + case "prune": + prune.Run(config) + } + +} + +func check(e error) { + if e != nil { + panic(e) + } +}