summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Manuel <nilslice@gmail.com>2017-06-26 16:33:41 -0700
committerGitHub <noreply@github.com>2017-06-26 16:33:41 -0700
commit08bab226d6b998eb5cf87e4be1db45e89fb9f772 (patch)
treeaba0be8dbd8c0ed630439a302fffcf5c078eeb21
parentcd6be5ebe16f3ee815e12d3022dfb79e4163d867 (diff)
parent0a1d7d9cd8ad1ac01c8fcd4d3b4fef57cffd4cb0 (diff)
Merge pull request #168 from tom-f/ponzu-dev
Add backup routine to search
-rw-r--r--system/admin/handlers.go9
-rw-r--r--system/admin/upload/backup.go91
-rw-r--r--system/backup/archive.go95
-rw-r--r--system/search/backup.go57
4 files changed, 168 insertions, 84 deletions
diff --git a/system/admin/handlers.go b/system/admin/handlers.go
index 0700003..c70dd86 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/admin/upload/backup.go b/system/admin/upload/backup.go
index b4f6393..9dc9e31 100644
--- a/system/admin/upload/backup.go
+++ b/system/admin/upload/backup.go
@@ -1,8 +1,6 @@
package upload
import (
- "archive/tar"
- "compress/gzip"
"context"
"fmt"
"io"
@@ -10,6 +8,8 @@ import (
"os"
"path/filepath"
"time"
+
+ "github.com/ponzu-cms/ponzu/system/backup"
)
// Backup creates an archive of a project's uploads and writes it
@@ -18,105 +18,28 @@ func Backup(ctx context.Context, res http.ResponseWriter) error {
ts := time.Now().Unix()
filename := fmt.Sprintf("uploads-%d.bak.tar.gz", ts)
tmp := os.TempDir()
- backup := filepath.Join(tmp, filename)
+ bk := filepath.Join(tmp, filename)
// create uploads-{stamp}.bak.tar.gz
- f, err := os.Create(backup)
+ f, err := os.Create(bk)
if err != nil {
return err
}
- // loop through directory and gzip files
- // add all to uploads.bak.tar.gz tarball
- gz := gzip.NewWriter(f)
- tarball := tar.NewWriter(gz)
-
- errChan := make(chan error, 1)
- walkFn := func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
-
- hdr, err := tar.FileInfoHeader(info, "")
- if err != nil {
- return err
- }
-
- hdr.Name = path
-
- err = tarball.WriteHeader(hdr)
- if err != nil {
- return err
- }
-
- if !info.IsDir() {
- src, err := os.Open(path)
- if err != nil {
- return err
- }
- defer src.Close()
-
- _, err = io.Copy(tarball, src)
- if err != nil {
- return err
- }
-
- err = tarball.Flush()
- if err != nil {
- return err
- }
-
- err = gz.Flush()
- if err != nil {
- return err
- }
- }
-
- return nil
- }
-
- // stop processing if we get a cancellation signal
- err = filepath.Walk("uploads", func(path string, info os.FileInfo, err error) error {
- go func() { errChan <- walkFn(path, info, err) }()
+ err = backup.ArchiveFS(ctx, "uploads", f)
- select {
- case <-ctx.Done():
- if err := ctx.Err(); err != nil {
- return err
- }
- case err := <-errChan:
- if err != nil {
- return err
- }
- }
-
- return nil
- })
- if err != nil {
- fmt.Println(err)
- return err
- }
-
- err = gz.Close()
- if err != nil {
- return err
- }
- err = tarball.Close()
- if err != nil {
- return err
- }
err = f.Close()
if err != nil {
return err
}
// write data to response
- data, err := os.Open(backup)
+ data, err := os.Open(bk)
if err != nil {
return err
}
defer data.Close()
- defer os.Remove(backup)
+ defer os.Remove(bk)
disposition := `attachment; filename=%s`
info, err := data.Stat()
diff --git a/system/backup/archive.go b/system/backup/archive.go
new file mode 100644
index 0000000..0a8b964
--- /dev/null
+++ b/system/backup/archive.go
@@ -0,0 +1,95 @@
+package backup
+
+import (
+ "archive/tar"
+ "compress/gzip"
+ "context"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+)
+
+// ArchiveFS walks the filesystem starting from basedir writing files encountered
+// tarred and gzipped to the provided writer
+func ArchiveFS(ctx context.Context, basedir string, w io.Writer) error {
+ gz := gzip.NewWriter(w)
+ tarball := tar.NewWriter(gz)
+
+ errChan := make(chan error, 1)
+ walkFn := func(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+
+ hdr, err := tar.FileInfoHeader(info, "")
+ if err != nil {
+ return err
+ }
+
+ hdr.Name = path
+
+ err = tarball.WriteHeader(hdr)
+ if err != nil {
+ return err
+ }
+
+ if !info.IsDir() {
+ src, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer src.Close()
+
+ _, err = io.Copy(tarball, src)
+ if err != nil {
+ return err
+ }
+
+ err = tarball.Flush()
+ if err != nil {
+ return err
+ }
+
+ err = gz.Flush()
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+ }
+
+ // stop processing if we get a cancellation signal
+ err := filepath.Walk(basedir, func(path string, info os.FileInfo, err error) error {
+ go func() { errChan <- walkFn(path, info, err) }()
+
+ select {
+ case <-ctx.Done():
+ if err := ctx.Err(); err != nil {
+ return err
+ }
+ case err := <-errChan:
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+ })
+ if err != nil {
+ fmt.Println(err)
+ return err
+ }
+
+ err = gz.Close()
+ if err != nil {
+ return err
+ }
+ err = tarball.Close()
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/system/search/backup.go b/system/search/backup.go
new file mode 100644
index 0000000..9223636
--- /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
+}