Documentation
¶
Overview ¶
Package instancebackup is a whole-AppTown backup and restore (stock/docs/guides/apptown-backups.md): one archive, encrypted with a passphrase, holding the built-in database's dump, the data directory (without pgdata and cache, with the deployment backups kept on disk) and a manifest; and its restore onto a fresh host, where each built-in deployment is filled from its own newest whole set.
It composes owners and owns no table: data protection names each deployment's newest whole set, keeps the backup-file lock, moves the records of sets kept on disk, records the fills and copies an archive to the backup store; deployment lists the built-in host's deployments and holds those a restore must not act on; secret says whether an external store keeps values; the composition root makes the built-in database and dumps the database AppTown runs on, in a pg_dump container of the server's major (BuiltinDatabase, databaseDump).
The running AppTown takes a backup, asked through its control socket by `apptownd backup` (control.go), because only it can hold its own new work (Hold). No app is stopped for it. A restore runs before the restored AppTown first starts (restore.go).
Index ¶
- Constants
- Variables
- func CompleteRestore(dataDir string, pending *PendingRestore) error
- func ControlSocketPath(dataDir string) string
- type AfterRestoreReport
- type BuiltinDatabase
- type ControlReply
- type ControlRequest
- type Database
- type DatabaseProvenance
- type Dependencies
- type Hold
- type Manifest
- type PendingRestore
- type Report
- type Request
- type RestoreRequest
- type Service
Constants ¶
const ( ArchiveFormat = "apptown-backup" ArchiveVersion = 1 )
ArchiveFormat names a whole-AppTown archive's manifest.
Variables ¶
var ErrBackupUnderWay = errors.New("a backup of AppTown is already under way")
ErrBackupUnderWay refuses a second backup while one runs.
Functions ¶
func CompleteRestore ¶
func CompleteRestore(dataDir string, pending *PendingRestore) error
CompleteRestore requires the caller's exclusive daemon/data ownership lock and successful layout repair plus AfterRestore. The digest detects changed evidence; it is not a lock-free compare-and-delete primitive.
func ControlSocketPath ¶
ControlSocketPath is where a data directory's control socket is.
Types ¶
type AfterRestoreReport ¶
type AfterRestoreReport struct {
Relocated int64 `json:"relocated"` // sets kept on disk whose records moved to this data directory
Held []string `json:"held"` // App Platform and Portainer deployments to be checked
Filling []string `json:"filling"` // built-in deployments rebuilt with their newest set on disk
NotFilled []string `json:"notFilled"` // built-in deployments whose data needs a person, with why
NoBackup []string `json:"noBackup"` // built-in deployments with no whole set: not held, so a rebuild has no restored data
}
AfterRestoreReport is what a restore left for the restored AppTown's first start.
type BuiltinDatabase ¶
type BuiltinDatabase interface {
Names() (container, database string, ok bool)
Ensure(ctx context.Context) (url string, err error)
}
BuiltinDatabase is AppTown's built-in database, which the composition root makes, names and dumps (dbboot.go), and which a restore always loads into: Names is what db.env says its container and database are (false: there is none), Ensure starts or makes it and answers its URL once it answers.
type ControlReply ¶
type ControlReply struct {
Say string `json:"say,omitempty"`
Report *Report `json:"report,omitempty"`
Error string `json:"error,omitempty"`
}
ControlReply is one line of the reply.
type ControlRequest ¶
type ControlRequest struct {
Op string `json:"op"` // "backup"
Archive string `json:"archive"`
Passphrase string `json:"passphrase"`
Store bool `json:"store"`
User string `json:"user"` // the operating-system user the command runs as, self-reported
}
ControlRequest is what `apptownd backup` asks.
type Database ¶
type Database interface {
Dump(ctx context.Context, path string) error
DumpClientVersion(ctx context.Context) (string, error)
}
Database is the database a backup dumps, the built-in one or the -db-url one (the composition root's databaseDump): Dump writes a whole gzipped plain dump at path, without owners or privileges so it loads into the built-in database, or nothing; DumpClientVersion is the pg_dump that does it.
type DatabaseProvenance ¶
type DatabaseProvenance struct {
Engine string `json:"engine"`
ServerVersionNum int `json:"serverVersionNum"`
DumpClientVersion string `json:"dumpClientVersion"`
}
DatabaseProvenance records observed engine and dump-client versions. It is absent in legacy archives; it does not certify cross-major compatibility.
type Dependencies ¶
type Dependencies struct {
DB *database.DB
DataDir string
// Database is the database AppTown runs on, which a backup dumps.
Database Database
Protection *dataprotection.Service
Deployment *deployment.Service
Deployments *deployment.Deployments
Targets *deployment.Targets
// BuiltInTarget names AppTown's own Docker host.
BuiltInTarget string
Secrets *secret.Service
// NewWork is AppTown's hold of new jobs and steps.
NewWork *Hold
Now func() time.Time
}
Dependencies are what a backup and the record of a restore run on.
type Hold ¶
type Hold struct {
// contains filtered or unexported fields
}
Hold is AppTown holding new work for a moment: while it is held, a job waits before its work starts and the workflow dispatcher waits before it starts a step. Work already running goes on. It lives in memory only, so nothing of it is in a database dump and a stop releases it. A whole-AppTown backup holds it across the database dump and the copy of the data directory (backup.go). The zero value holds nothing.
type Manifest ¶
type Manifest struct {
Database *DatabaseProvenance `json:"database,omitempty"`
Format string `json:"format"`
Version int `json:"version"`
// Build is the apptownd that took it; Schema its database's version.
Build string `json:"build"`
Schema int `json:"schema"`
AppTown ids.ID `json:"apptown"` // AppTown's own id (forge.id)
TakenAt string `json:"takenAt"`
Host string `json:"host"`
// DataDir is where the data directory was: a restore elsewhere moves the
// records of the sets kept in it.
DataDir string `json:"dataDir"`
Dump backuparchive.Digest `json:"dump"`
KeyFiles map[string]backuparchive.Digest `json:"keyFiles"`
// ExternalSecrets says where values AppTown reads but does not hold
// are kept; "" when there is no such store.
ExternalSecrets string `json:"externalSecrets,omitempty"`
// NotIncluded says what the archive does not carry.
NotIncluded []string `json:"notIncluded"`
// Left are files of the data directory no archive can carry (sockets).
Left []string `json:"left,omitempty"`
}
Manifest says what a whole-AppTown archive holds.
type PendingRestore ¶
type PendingRestore struct {
Manifest *Manifest
// contains filtered or unexported fields
}
PendingRestore is a completely loaded archive whose offline relocation and AfterRestore bookkeeping must finish before ordinary startup.
func ReadPendingRestore ¶
func ReadPendingRestore(dataDir string) (*PendingRestore, error)
ReadPendingRestore is read-only and belongs before database/schema effects. An interrupted extraction or load is not a normal installed database.
type Report ¶
type Report struct {
Archive string `json:"archive"`
Bytes int64 `json:"bytes"`
SHA256 string `json:"sha256"`
StoreKey string `json:"storeKey,omitempty"`
Manifest Manifest `json:"manifest"`
Held time.Duration `json:"held"` // how long new work was held
Problems []string `json:"problems,omitempty"`
}
Report is what a backup did.
func AskControl ¶
func AskControl(ctx context.Context, dataDir string, req ControlRequest, say func(string)) (*Report, error)
AskControl sends one request to the AppTown whose data directory is dataDir and calls say for each step; it returns the report, or the error AppTown answered, or that AppTown could not be reached.
type Request ¶
type Request struct {
Archive string
Passphrase string
ToStore bool
// Actor is who asked, as the host's administrator names themselves.
Actor string
// Say is told each step as it starts; nil says nothing.
Say func(string)
}
Request is what a backup is asked to do: write the archive at an absolute path outside the data directory, encrypted with Passphrase, and copy it to the backup store when ToStore.
type RestoreRequest ¶
type RestoreRequest struct {
DataDir string
// LayoutVersion is the daemon's data layout, the only one it restores,
// checked before DB effects.
LayoutVersion int
Archive string
Passphrase string
Say func(string) // each step as it starts; nil says nothing
Docker docker.Scope
Database BuiltinDatabase
}
RestoreRequest is a restore of an archive into an empty data directory, on Docker (the host's own), making the built-in database Database names once the archive's db.env is in place.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service takes whole-AppTown backups and records what a restored AppTown does when it first starts.
func (*Service) AfterRestore ¶
AfterRestore records, in the restored database, what the restored AppTown must do when it first starts: the sets kept on disk found where the data directory now is, App Platform and Portainer deployments held until their providers are read, and each built-in deployment held until its rebuild puts its data back; and the receipt.