types.go 3.58 KB
Newer Older
ale's avatar
ale committed
1 2 3 4 5 6 7 8 9
package tabacco

import (
	"context"
	"fmt"
	"io"
	"regexp"
	"strings"
	"time"
10 11

	"git.autistici.org/ale/tabacco/jobs"
ale's avatar
ale committed
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
)

// Backup is the over-arching entity describing a high level backup
// operation. Backups are initiated autonomously by individual hosts,
// so each Backup belongs to a single Host.
type Backup struct {
	// Backup ID (globally unique identifier).
	ID string `json:"id"`

	// Timestamp (backup start).
	Timestamp time.Time `json:"timestamp"`

	// Host.
	Host string `json:"host"`
}

// An Atom is a bit of data that can be restored independently as part
// of a Dataset.
type Atom struct {
	// Name (path-like, not rooted).
	Name string `json:"name"`

	// Relative path with respect to the Dataset.
	RelativePath string `json:"rel_path"`

	// Source path (used for restore).
	SourcePath string `json:"source_path,omitempty"`
}

// A Dataset describes a data set as a high level structure containing
// one or more atoms. The 1-to-many scenario is justified by the
// following use case: imagine a sql database server, we may want to
// back it up as a single operation, but it contains multiple
// databases (the atom we're interested in), which we might want to
// restore independently.
type Dataset struct {
	// Name of the dataset. Will be prepended to target storage
	// paths.
	Name string `json:"name"`

	// Handler specifies the dataset type (which handler to use to
	// backup/restore it).
	Handler string `json:"handler"`

	// Atoms that are part of this dataset.
	Atoms []Atom `json:"atoms"`
}

// FindRequest specifies search criteria for atoms.
type FindRequest struct {
	Pattern   string `json:"pattern"`
	patternRx *regexp.Regexp

	Host        string `json:"host"`
	NumVersions int    `json:"num_versions"`
}

func (req *FindRequest) matchPattern(s string) bool {
	if req.patternRx == nil {
		req.patternRx = regexp.MustCompile(
			fmt.Sprintf("^%s$", strings.Replace(req.Pattern, "*", ".*", -1)))
	}
	return req.patternRx.MatchString(s)
}

// A Version ties together a Dataset and a Backup.
type Version struct {
	Dataset Dataset `json:"dataset"`
	Backup  Backup  `json:"backup"`
}

// MetadataStore is the client interface to the global metadata store.
type MetadataStore interface {
	// Find the datasets that match a specific criteria. Only
	// atoms matching the criteria will be included in the Dataset
	// objects in the response.
	FindAtoms(context.Context, FindRequest) ([][]Version, error)

	// Add a dataset entry (the Backup might already exist).
	AddDataset(context.Context, Backup, Dataset) error
}

// Handler can backup and restore a specific class of datasets.
type Handler interface {
ale's avatar
ale committed
96 97 98 99
	DatasetsForBackup(Dataset) []Dataset
	DatasetsForRestore(Dataset) []Dataset
	BackupJob(Repository, Backup, Dataset) jobs.Job
	RestoreJob(Repository, Backup, Dataset, string) jobs.Job
100
	Spec() HandlerSpec
ale's avatar
ale committed
101 102 103 104 105 106 107 108 109 110 111 112
}

// Repository is the interface to a remote repository.
type Repository interface {
	Init(context.Context) error
	Prepare(context.Context, Backup) error
	Backup(context.Context, Backup, Dataset, string) error
	Restore(context.Context, Backup, Dataset, string) error
	BackupStream(context.Context, Backup, Dataset, io.Reader) error
	RestoreStream(context.Context, Backup, Dataset, string, io.Writer) error
	Close() error
}
113 114 115

// Manager for backups and restores.
type Manager interface {
116
	BackupJob(context.Context, []SourceSpec) (Backup, jobs.Job, error)
117
	Backup(context.Context, []SourceSpec) (Backup, error)
118
	RestoreJob(context.Context, FindRequest, string) (jobs.Job, error)
119 120
	Restore(context.Context, FindRequest, string) error
	Close() error
121 122 123

	// Debug interface.
	GetStatus() ([]jobs.Status, []jobs.Status, []jobs.Status)
124
}