'wdcli backup': Move to separate package

This commit is contained in:
Tom Wiesing 2022-09-17 18:17:37 +02:00
parent 5cd5ae9be2
commit 822c70cd69
No known key found for this signature in database
11 changed files with 493 additions and 380 deletions

View file

@ -0,0 +1,43 @@
package component
import (
"io"
"github.com/tkw1536/goprogram/stream"
)
// Backupable represents a component with a Backup method
type Backupable interface {
Component
// BackupName returns a new name to be used as an argument for path.
BackupName() string
// Backup backs up this component into the destination path path
Backup(context BackupContext) error
}
// BackupContext is the context for backups
type BackupContext interface {
// IO returns the input output stream belonging to this backup file
IO() stream.IOStream
// Name creates a new directory inside the destination.
// Passing the empty path creates the destination as a directory.
//
// It then allows op to fill the file.
AddDirectory(path string, op func() error) error
// CopyFile copies a file from source to dst.
CopyFile(dest, src string) error
// AddFile creates a new file at the provided path inside the destination.
// Passing the empty path creates the destination as a file.
//
// It then allows op to write to the file.
//
// The op function must not retain file.
// The underlying file does not need to be closed.
// AddFile will not return before op has returned.
AddFile(path string, op func(file io.Writer) error) error
}

View file

@ -3,7 +3,6 @@ package component
import (
"github.com/FAU-CDI/wisski-distillery/internal/config"
"github.com/tkw1536/goprogram/stream"
)
// Component represents a logical subsystem of the distillery.
@ -46,20 +45,6 @@ type Installable interface {
Context(parent InstallationContext) InstallationContext
}
// Backupable represents a component with a Backup method
type Backupable interface {
Component
// BackupName returns a new name to be used as an argument for path.
BackupName() string
// Backup backs up this component into the destination path path.
//
// The destination path may be a folder or directory, depending on the component.
// The destination path does not need to exist.
Backup(io stream.IOStream, path string) error
}
// ComponentBase implements base functionality for a component
type ComponentBase struct {
Dir string // Dir is the directory this component lives in

View file

@ -1,12 +1,9 @@
package control
import (
"io/fs"
"os"
"path/filepath"
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
"github.com/tkw1536/goprogram/stream"
"github.com/FAU-CDI/wisski-distillery/internal/component"
)
func (*Control) BackupName() string {
@ -14,27 +11,18 @@ func (*Control) BackupName() string {
}
// Backup backups all control plane configuration files into dest
func (control *Control) Backup(io stream.IOStream, dest string) error {
// create the destination directory, TODO: outsource this
if err := os.Mkdir(dest, fs.ModeDir); err != nil {
return err
}
func (control *Control) Backup(context component.BackupContext) error {
files := control.backupFiles()
for _, src := range files {
dst := filepath.Join(dest, filepath.Base(src)) // destination path
// if the src file does not exist, don't copy it!
if !fsx.IsFile(src) { // TODO: log this somewhere
continue
return context.AddDirectory("", func() error {
for _, src := range files {
name := filepath.Base(src)
if err := context.CopyFile(name, src); err != nil {
return err
}
}
if err := fsx.CopyFile(dst, src); err != nil {
return err
}
}
return nil
return nil
})
}
// backupfiles lists the files to be backed up.

View file

@ -2,9 +2,9 @@ package sql
import (
"errors"
"os"
"io"
"github.com/tkw1536/goprogram/stream"
"github.com/FAU-CDI/wisski-distillery/internal/component"
)
var errSQLBackup = errors.New("SQLBackup: Mysqldump returned non-zero exit code")
@ -14,22 +14,17 @@ func (*SQL) BackupName() string {
}
// Backup makes a backup of all SQL databases into the path dest.
func (sql *SQL) Backup(io stream.IOStream, dest string) error {
// open the file, TODO: Outsource this to context
writer, err := os.Create(dest)
if err != nil {
return err
}
defer writer.Close()
func (sql *SQL) Backup(context component.BackupContext) error {
return context.AddFile("", func(file io.Writer) error {
io := context.IO().Streams(file, nil, nil, 0).NonInteractive()
code, err := sql.Stack().Exec(io, "sql", "mysqldump", "--all-databases")
if err != nil {
return err
}
if code != 0 {
return errSQLBackup
}
return nil
})
// run sqldump
io = io.Streams(writer, nil, nil, 0).NonInteractive()
code, err := sql.Stack().Exec(io, "sql", "mysqldump", "--all-databases")
if err != nil {
return err
}
if code != 0 {
return errSQLBackup
}
return nil
}

View file

@ -2,48 +2,34 @@ package triplestore
import (
"encoding/json"
"io/fs"
"os"
"path/filepath"
"io"
"github.com/tkw1536/goprogram/stream"
"github.com/FAU-CDI/wisski-distillery/internal/component"
)
func (ts *Triplestore) BackupName() string { return "triplestore" }
// Backup makes a backup of all Triplestore repositories databases into the path dest.
func (ts *Triplestore) Backup(io stream.IOStream, dest string) error {
func (ts *Triplestore) Backup(context component.BackupContext) error {
// list all the repositories
// list all the directories
repos, err := ts.listRepositories()
if err != nil {
return err
}
// create the base directory, todo: outsource this
if err := os.Mkdir(dest, fs.ModeDir); err != nil {
return err
}
// iterate over all the repositories
for _, repo := range repos {
if rErr := (func(repo Repository) error {
name := filepath.Join(dest, repo.ID+".nq")
// todo: outsource this
dest, err := os.Create(name)
if err != nil {
// then backup each file separatly
return context.AddDirectory("", func() error {
for _, repo := range repos {
if err := context.AddFile(repo.ID+".nq", func(file io.Writer) error {
_, err := ts.Snapshot(file, repo.ID)
return err
}); err != nil {
return err
}
defer dest.Close()
_, err = ts.Snapshot(dest, repo.ID)
return err
}(repo)); err == nil && rErr != nil {
err = rErr
}
}
return err
return nil
})
}
func (ts Triplestore) listRepositories() (repos []Repository, err error) {