From 0a1d7d9cd8ad1ac01c8fcd4d3b4fef57cffd4cb0 Mon Sep 17 00:00:00 2001 From: Tom Fawssett Date: Sat, 24 Jun 2017 16:01:41 +0100 Subject: [PATCH] Add Backup function to search --- system/admin/handlers.go | 9 +++++++ system/search/backup.go | 57 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 system/search/backup.go diff --git a/system/admin/handlers.go b/system/admin/handlers.go index 3933d3d4..aac9ec26 100644 --- a/system/admin/handlers.go +++ b/system/admin/handlers.go @@ -23,6 +23,7 @@ import ( "github.com/ponzu-cms/ponzu/system/api/analytics" "github.com/ponzu-cms/ponzu/system/db" "github.com/ponzu-cms/ponzu/system/item" + "github.com/ponzu-cms/ponzu/system/search" "github.com/gorilla/schema" emailer "github.com/nilslice/email" @@ -224,6 +225,14 @@ func backupHandler(res http.ResponseWriter, req *http.Request) { return } + case "search": + err := search.Backup(ctx, res) + if err != nil { + log.Println("Failed to run backup on search:", err) + res.WriteHeader(http.StatusInternalServerError) + return + } + default: res.WriteHeader(http.StatusBadRequest) } diff --git a/system/search/backup.go b/system/search/backup.go new file mode 100644 index 00000000..9223636f --- /dev/null +++ b/system/search/backup.go @@ -0,0 +1,57 @@ +package search + +import ( + "context" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "time" + + "github.com/ponzu-cms/ponzu/system/backup" +) + +// Backup creates an archive of a project's search index and writes it +// to the response as a download +func Backup(ctx context.Context, res http.ResponseWriter) error { + ts := time.Now().Unix() + filename := fmt.Sprintf("search-%d.bak.tar.gz", ts) + tmp := os.TempDir() + bk := filepath.Join(tmp, filename) + + // create search-{stamp}.bak.tar.gz + f, err := os.Create(bk) + if err != nil { + return err + } + + backup.ArchiveFS(ctx, "search", f) + + err = f.Close() + if err != nil { + return err + } + + // write data to response + data, err := os.Open(bk) + if err != nil { + return err + } + defer data.Close() + defer os.Remove(bk) + + disposition := `attachment; filename=%s` + info, err := data.Stat() + if err != nil { + return err + } + + res.Header().Set("Content-Type", "application/octet-stream") + res.Header().Set("Content-Disposition", fmt.Sprintf(disposition, ts)) + res.Header().Set("Content-Length", fmt.Sprintf("%d", info.Size())) + + _, err = io.Copy(res, data) + + return err +}