Commit 1723e6aa authored by ale's avatar ale

Allow restoring backups from a specific time in the past

parent be64a239
Pipeline #5438 passed with stages
in 5 minutes and 19 seconds
......@@ -17,10 +17,34 @@ import (
var rpcTimeout = 300 * time.Second
type timeFlag time.Time
func (f timeFlag) String() string {
return time.Time(f).Format(time.RFC3339)
}
func (f *timeFlag) Set(value string) error {
for _, fmt := range []string{
time.RFC3339,
time.Stamp,
time.Kitchen,
"2006/01/02",
"2006-01-02",
} {
if t, err := time.Parse(fmt, value); err == nil {
log.Printf("parsed %s as %v", value, t)
*f = timeFlag(t)
return nil
}
}
return errors.New("could not parse time value")
}
type queryCommand struct {
configPath string
host string
numVersions int
olderThan timeFlag
}
func (c *queryCommand) Name() string { return "query" }
......@@ -36,6 +60,7 @@ func (c *queryCommand) SetFlags(f *flag.FlagSet) {
f.StringVar(&c.configPath, "config", "/etc/tabacco/agent.yml", "configuration `file`")
f.StringVar(&c.host, "host", "", "filter by host")
f.IntVar(&c.numVersions, "num-versions", 1, "return the most recent `N` versions")
f.Var(&c.olderThan, "older-than", "return a backup older than `TIME`")
}
func (c *queryCommand) buildRequest(f *flag.FlagSet) (*tabacco.FindRequest, error) {
......@@ -46,6 +71,7 @@ func (c *queryCommand) buildRequest(f *flag.FlagSet) (*tabacco.FindRequest, erro
Pattern: f.Arg(0),
Host: c.host,
NumVersions: c.numVersions,
OlderThan: time.Time(c.olderThan),
}, nil
}
......
......@@ -4,6 +4,7 @@ import (
"context"
"flag"
"log"
"time"
"github.com/google/subcommands"
......@@ -16,6 +17,7 @@ type restoreCommand struct {
configPath string
httpAddr string
targetDir string
olderThan timeFlag
}
func (c *restoreCommand) Name() string { return "restore" }
......@@ -32,6 +34,7 @@ func (c *restoreCommand) SetFlags(f *flag.FlagSet) {
f.StringVar(&c.configPath, "config", "/etc/tabacco/agent.yml", "configuration `file`")
f.StringVar(&c.httpAddr, "http-addr", ":5330", "listen `address` for the HTTP server exporting metrics and debugging")
f.StringVar(&c.targetDir, "target", ".", "target `path` for restore")
f.Var(&c.olderThan, "older-than", "pick the first backup older than `TIME`")
}
func (c *restoreCommand) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
......@@ -79,7 +82,8 @@ func (c *restoreCommand) buildRestoreJob(ctx context.Context, mgr tabacco.Manage
func (c *restoreCommand) newFindRequest(s string) *tabacco.FindRequest {
return &tabacco.FindRequest{
Pattern: s,
Pattern: s,
OlderThan: time.Time(c.olderThan),
}
}
......
......@@ -222,6 +222,10 @@ func (s *Service) FindAtoms(ctx context.Context, req *tabacco.FindRequest) ([]*t
where = append(where, "atom_full_path LIKE ?")
args = append(args, strings.Replace(req.Pattern, "*", "%", -1))
}
if !req.OlderThan.IsZero() {
where = append(where, "backup_timestamp < ?")
args = append(args, req.OlderThan)
}
// Build the final query and execute it.
q := fmt.Sprintf(
......
......@@ -94,8 +94,9 @@ type FindRequest struct {
Pattern string `json:"pattern"`
patternRx *regexp.Regexp
Host string `json:"host"`
NumVersions int `json:"num_versions"`
Host string `json:"host"`
NumVersions int `json:"num_versions"`
OlderThan time.Time `json:"older_than,omitempty"`
}
func (req *FindRequest) matchPattern(s string) bool {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment