diff --git a/app.go b/app.go index d98da03..104584b 100644 --- a/app.go +++ b/app.go @@ -18,10 +18,10 @@ type AppConfig struct { func (a AppConfig) getTime() time.Time { for _, v := range a.Sources { - return cfg.Box[v.Box()].ssh.now + return cfg.Box[v.Box()].GetTime() } for _, v := range a.Destinations { - return cfg.Box[v.Box()].ssh.now + return cfg.Box[v.Box()].GetTime() } return time.Now() } @@ -37,10 +37,10 @@ func (a AppConfig) getSchedule() (string, error) { refreshSnapshot[v.Box()] = true } for k, _ := range refreshSnapshot { - err := cfg.Box[k].ssh.getSnapshotList() + err := cfg.Box[k].ZFSUpdateSnapshotList() if err != nil { if *debugFlag { - log.Printf("AppConfig.getSchedule : %s : getSnapshotList(%s) : %s", a.Name, k, err) + log.Printf("AppConfig.getSchedule : %s : ZFSUpdateSnapshotList(%s) : %s", a.Name, k, err) } return "", err } @@ -95,7 +95,7 @@ func (a AppConfig) needYearlySnapshot() bool { re := regexp.MustCompile(`^yearly-(?P[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`) for _, src := range a.Sources { timeSource[string(src)] = make(map[time.Time]struct{}) - for _, snap := range cfg.Box[src.Box()].ssh.snapshot { + for _, snap := range cfg.Box[src.Box()].ZFSGetSnapshotList() { if src.Path() == snap.Path() { if re.MatchString(snap.Name()) { dateString := re.ReplaceAllString(snap.Name(), "${Date}") @@ -157,7 +157,7 @@ func (a AppConfig) needMonthlySnapshot() bool { re := regexp.MustCompile(`^(yearly|monthly)-(?P[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`) for _, src := range a.Sources { timeSource[string(src)] = make(map[time.Time]struct{}) - for _, snap := range cfg.Box[src.Box()].ssh.snapshot { + for _, snap := range cfg.Box[src.Box()].ZFSGetSnapshotList() { if src.Path() == snap.Path() { if re.MatchString(snap.Name()) { dateString := re.ReplaceAllString(snap.Name(), "${Date}") @@ -219,7 +219,7 @@ func (a AppConfig) needWeeklySnapshot() bool { re := regexp.MustCompile(`^(yearly|monthly|weekly)-(?P[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`) for _, src := range a.Sources { timeSource[string(src)] = make(map[time.Time]struct{}) - for _, snap := range cfg.Box[src.Box()].ssh.snapshot { + for _, snap := range cfg.Box[src.Box()].ZFSGetSnapshotList() { if src.Path() == snap.Path() { if re.MatchString(snap.Name()) { dateString := re.ReplaceAllString(snap.Name(), "${Date}") @@ -283,7 +283,7 @@ func (a AppConfig) needDailySnapshot() bool { re := regexp.MustCompile(`^(yearly|monthly|weekly|daily)-(?P[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`) for _, src := range a.Sources { timeSource[string(src)] = make(map[time.Time]struct{}) - for _, snap := range cfg.Box[src.Box()].ssh.snapshot { + for _, snap := range cfg.Box[src.Box()].ZFSGetSnapshotList() { if src.Path() == snap.Path() { if re.MatchString(snap.Name()) { dateString := re.ReplaceAllString(snap.Name(), "${Date}") @@ -345,7 +345,7 @@ func (a AppConfig) needHourlySnapshot() bool { re := regexp.MustCompile(`^(yearly|monthly|weekly|daily|hourly)-(?P[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}.[0-9]{2}.[0-9]{2})--([0-9]+[ymwdhMs]{1}|forever)$`) for _, src := range a.Sources { timeSource[string(src)] = make(map[time.Time]struct{}) - for _, snap := range cfg.Box[src.Box()].ssh.snapshot { + for _, snap := range cfg.Box[src.Box()].ZFSGetSnapshotList() { if src.Path() == snap.Path() { if re.MatchString(snap.Name()) { dateString := re.ReplaceAllString(snap.Name(), "${Date}") @@ -391,12 +391,12 @@ func (a AppConfig) CheckZFS() error { } for _, src := range a.Sources { - if !cfg.Box[src.Box()].ssh.isZFS(src.Path()) { + if !cfg.Box[src.Box()].ZFSIsZFS(src.Path()) { return fmt.Errorf("No path %s on source", string(src)) } for _, dest := range a.Destinations { - if !cfg.Box[dest.Box()].ssh.isZFS(dest.Path() + "/" + src.Box() + "/" + src.Path()) { - err := cfg.Box[dest.Box()].ssh.createZFS(dest.Path() + "/" + src.Box() + "/" + src.Path()) + if !cfg.Box[dest.Box()].ZFSIsZFS(dest.Path() + "/" + src.Box() + "/" + src.Path()) { + err := cfg.Box[dest.Box()].ZFSCreateZFS(dest.Path() + "/" + src.Box() + "/" + src.Path()) if err != nil { if *debugFlag { log.Printf("AppConfig.CheckZFS : %s : Error creating %s on %s", a.Name, dest.Path()+"/"+src.Box()+"/"+src.Path(), dest.Box()) @@ -417,7 +417,7 @@ func (a AppConfig) ExecBefore(schedule string) error { for k, v := range a.Before { re := regexp.MustCompile(k) if re.MatchString(schedule) { - err := cfg.Box[v.Box()].ssh.exec(v.Path()) + err := cfg.Box[v.Box()].SSHExec(v.Path()) if err != nil { if *debugFlag { log.Printf("AppConfig.ExecBefore : %s : Error executing %s", a.Name, string(v)) @@ -437,7 +437,7 @@ func (a AppConfig) ExecAfter(schedule string) error { for k, v := range a.After { re := regexp.MustCompile(k) if re.MatchString(schedule) { - err := cfg.Box[v.Box()].ssh.exec(v.Path()) + err := cfg.Box[v.Box()].SSHExec(v.Path()) if err != nil { if *debugFlag { log.Printf("AppConfig.ExecAfter : %s : Error executing %s on %s", a.Name, v.Path(), v.Box()) @@ -463,7 +463,7 @@ func (a AppConfig) TakeSnapshot(schedule string) error { if *debugFlag { log.Printf("AppConfig.TakeSnapshot : %s : taking snapshot on %s for %s", a.Name, k, v) } - err := cfg.Box[k].ssh.exec("zfsnap snapshot -p " + schedule + "- -a " + cfg.Zfsnap[schedule] + v) + err := cfg.Box[k].SSHExec("zfsnap snapshot -p " + schedule + "- -a " + cfg.Zfsnap[schedule] + v) if err != nil { if *debugFlag { log.Printf("AppConfig.TakeSnapshot : %s : Error executing zfsnap on %s", a.Name, k) @@ -491,7 +491,7 @@ func (a AppConfig) RefreshSnapshot() error { if *debugFlag { log.Printf("AppConfig.RefreshSnapshot : %s : refreshing snapshots for source %s", a.Name, k) } - err := cfg.Box[k].ssh.getSnapshotList() + err := cfg.Box[k].ZFSUpdateSnapshotList() if err != nil { if *debugFlag { log.Printf("AppConfig.RefreshSnapshot : %s : Error getting snapshots on %s", a.Name, k) @@ -512,12 +512,12 @@ func (a AppConfig) SendSnapshots() error { if *debugFlag { log.Printf("AppConfig.SendSnapshots : %s : Sending snapshots from %s to %s", a.Name, string(src), string(dest)) } - dLastSnapshot, err := cfg.Box[dest.Box()].ssh.getLastSnapshot(dest.Path() + "/" + src.Box() + "/" + src.Path()) + dLastSnapshot, err := cfg.Box[dest.Box()].ZFSGetLastSnapshot(dest.Path() + "/" + src.Box() + "/" + src.Path()) if err != nil { if *debugFlag { log.Printf("AppConfig.SendSnapshots : %s : No snapshot for %s on %s", a.Name, string(src), dest.Box()) } - sFirstSnapshot, err := cfg.Box[src.Box()].ssh.getFirstSnapshot(src.Path()) + sFirstSnapshot, err := cfg.Box[src.Box()].ZFSGetFirstSnapshot(src.Path()) if err != nil { if *debugFlag { log.Printf("AppConfig.SendSnapshots : %s : No snapshot for %s", a.Name, string(src)) @@ -527,7 +527,7 @@ func (a AppConfig) SendSnapshots() error { if *debugFlag { log.Printf("AppConfig.SendSnapshots : %s : Initializing snapshot on %s from %s", a.Name, dest.Box(), string(sFirstSnapshot)) } - err = cfg.Box[dest.Box()].ssh.exec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send " + string(sFirstSnapshot) + " | zfs recv -F " + dest.Path() + "/" + src.Box() + "/" + src.Path()) + err = cfg.Box[dest.Box()].SSHExec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send " + string(sFirstSnapshot) + " | zfs recv -F " + dest.Path() + "/" + src.Box() + "/" + src.Path()) if err != nil { if *debugFlag { log.Printf("AppConfig.SendSnapshots : %s : Initializing snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sFirstSnapshot), err) @@ -536,13 +536,13 @@ func (a AppConfig) SendSnapshots() error { } var sCurrSnapshot Snapshot sNextSnapshot := sFirstSnapshot - for !cfg.Box[src.Box()].ssh.isLastSnapshot(sNextSnapshot) { + for !cfg.Box[src.Box()].ZFSIsLastSnapshot(sNextSnapshot) { sCurrSnapshot = sNextSnapshot - sNextSnapshot, err = cfg.Box[src.Box()].ssh.getNextSnapshot(sNextSnapshot) + sNextSnapshot, err = cfg.Box[src.Box()].ZFSGetNextSnapshot(sNextSnapshot) if *debugFlag { log.Printf("AppConfig.SendSnapshots : %s : Sending incrementally %s to %s", a.Name, string(sNextSnapshot), dest.Box()) } - err = cfg.Box[dest.Box()].ssh.exec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path()) + err = cfg.Box[dest.Box()].SSHExec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path()) if err != nil { if *debugFlag { log.Printf("AppConfig.SendSnapshots : %s : Sending snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sNextSnapshot), err) @@ -560,13 +560,13 @@ func (a AppConfig) SendSnapshots() error { } var sCurrSnapshot Snapshot sNextSnapshot := Snapshot(string(dLastSnapshot)[len(dest.Path())+len(src.Box())+2:]) - for !cfg.Box[src.Box()].ssh.isLastSnapshot(sNextSnapshot) { + for !cfg.Box[src.Box()].ZFSIsLastSnapshot(sNextSnapshot) { sCurrSnapshot = sNextSnapshot - sNextSnapshot, err = cfg.Box[src.Box()].ssh.getNextSnapshot(sNextSnapshot) + sNextSnapshot, err = cfg.Box[src.Box()].ZFSGetNextSnapshot(sNextSnapshot) if *debugFlag { log.Printf("AppConfig.SendSnapshots : %s : Sending incrementally %s to %s", a.Name, string(sNextSnapshot), dest.Box()) } - err = cfg.Box[dest.Box()].ssh.exec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path()) + err = cfg.Box[dest.Box()].SSHExec("ssh " + cfg.Box[src.Box()].User + "@" + src.Box() + " zfs send -I " + string(sCurrSnapshot) + " " + string(sNextSnapshot) + " | zfs recv " + dest.Path() + "/" + src.Box() + "/" + src.Path()) if err != nil { if *debugFlag { log.Printf("AppConfig.SendSnapshots : %s : Sending snapshot on %s from %s failed (%s)", a.Name, dest.Box(), string(sNextSnapshot), err) @@ -598,7 +598,7 @@ func (a AppConfig) CleanupSnapshot() error { if *debugFlag { log.Printf("AppConfig.CleanupSnapshot : %s : cleaning snapshots on %s for%s", a.Name, k, v) } - err := cfg.Box[k].ssh.exec("zfsnap destroy -p hourly- -p daily- -p weekly- -p monthly- -p yearly-" + v) + err := cfg.Box[k].SSHExec("zfsnap destroy -p hourly- -p daily- -p weekly- -p monthly- -p yearly-" + v) if err != nil { if *debugFlag { log.Printf("AppConfig.CleanupSnapshot : %s : Error executing zfsnap on %s", a.Name, k) diff --git a/backup.go b/backup.go index c54c845..32589bd 100644 --- a/backup.go +++ b/backup.go @@ -1,32 +1,11 @@ package main import ( - "bytes" - "encoding/json" "flag" - "fmt" - "io/ioutil" "log" "os" - "regexp" - - "golang.org/x/crypto/ssh" ) -type Config struct { - Zfsnap map[string]string `json:"zfsnap"` - Box map[string]*BoxConfig `json:"box"` - Apps []AppConfig `json:apps` - Timezone string `json:"timezone"` -} - -type BoxConfig struct { - Addr string `json:"addr"` - User string `json:"user"` - Key string `json:"key"` - ssh *SSHConfig -} - var ( appFlag = flag.String("app", "", "run specific app") cfgFile = flag.String("config", "config.json", "config file") @@ -37,165 +16,6 @@ var ( cfg Config ) -//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 - } - - for k, v := range c.Box { - 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 _, box := range c.Box { - err = box.ssh.getTime() - if err != nil { - if *debugFlag { - log.Printf("Config.Load : ssh.getTime() : %s", err) - } - return err - } - } - - 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 -} - func main() { flag.Parse() diff --git a/box.go b/box.go new file mode 100644 index 0000000..f784598 --- /dev/null +++ b/box.go @@ -0,0 +1,58 @@ +package main + +import "time" + +type Box struct { + Addr string `json:"addr"` + User string `json:"user"` + Key string `json:"key"` + ssh *SSHConfig +} + +func (b *Box) ZFSGetLastSnapshot(path string) (s Snapshot, err error) { + return b.ssh.getLastSnapshot(path) +} + +func (b *Box) ZFSIsLastSnapshot(s Snapshot) bool { + return b.ssh.isLastSnapshot(s) +} + +func (b *Box) ZFSGetFirstSnapshot(path string) (s Snapshot, err error) { + return b.ssh.getFirstSnapshot(path) +} + +func (b *Box) ZFSGetNextSnapshot(src Snapshot) (next Snapshot, err error) { + return b.ssh.getNextSnapshot(src) +} + +func (b *Box) ZFSUpdateSnapshotList() (err error) { + return b.ssh.getSnapshotList() +} + +func (b *Box) ZFSGetSnapshotList() []Snapshot { + return b.ssh.snapshot +} + +func (b *Box) ZFSUpdateList() (err error) { + return b.ssh.getZFSList() +} + +func (b *Box) ZFSIsZFS(path string) bool { + return b.ssh.isZFS(path) +} + +func (b *Box) ZFSCreateZFS(path string) (err error) { + return b.ssh.createZFS(path) +} + +func (b *Box) GetTime() time.Time { + return b.ssh.now +} + +func (b *Box) UpdateTime() (err error) { + return b.ssh.getTime() +} + +func (b *Box) SSHExec(cmd string) (err error) { + return b.ssh.exec(cmd) +} diff --git a/config.go b/config.go new file mode 100644 index 0000000..1bbfa13 --- /dev/null +++ b/config.go @@ -0,0 +1,178 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "regexp" + + "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"` +} + +//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 + } + + for k, v := range c.Box { + 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 _, box := range c.Box { + err = box.ssh.getTime() + if err != nil { + if *debugFlag { + log.Printf("Config.Load : ssh.getTime() : %s", err) + } + return err + } + } + + 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 +} diff --git a/generate.go b/generate.go new file mode 100644 index 0000000..8b92de7 --- /dev/null +++ b/generate.go @@ -0,0 +1,3 @@ +package main + +//go:generate bash ./version.sh diff --git a/version.go b/version.go new file mode 100644 index 0000000..ac92a2b --- /dev/null +++ b/version.go @@ -0,0 +1,6 @@ +// Code generated by version.sh (@generated) DO NOT EDIT. +package main +var githash = "0f4fca3" +var buildstamp = "2021-11-14_02:51:24" +var commits = "17" +var version = "0f4fca3-b17 - 2021-11-14_02:51:24" diff --git a/version.sh b/version.sh new file mode 100644 index 0000000..a436a5c --- /dev/null +++ b/version.sh @@ -0,0 +1,13 @@ +# Get the version. +githash=`git rev-parse --short HEAD` +buildstamp=`date -u '+%Y-%m-%d_%H:%M:%S'` +commits=`git rev-list --count master` +# Write out the package. +cat << EOF > version.go +// Code generated by version.sh (@generated) DO NOT EDIT. +package main +var githash = "$githash" +var buildstamp = "$buildstamp" +var commits = "$commits" +var version = "$githash-b$commits - $buildstamp" +EOF \ No newline at end of file diff --git a/zfs.go b/zfs.go new file mode 100644 index 0000000..06ab7d0 --- /dev/null +++ b/zfs.go @@ -0,0 +1 @@ +package main