GPLv3's "How to Apply These Terms" asks for a notice in each source file; this is the modern two-line SPDX form of it rather than the full paragraph. 82 files, including tests. The blank line after the header is load-bearing. In Go a comment block immediately preceding `package X` becomes the package doc comment, so without the separator the SPDX lines would be absorbed into the doc for the eleven packages whose doc.go (or main.go) opens with one, and `go doc` would print them. Verified it doesn't.
67 lines
2.2 KiB
Go
67 lines
2.2 KiB
Go
// SPDX-FileCopyrightText: 2026 LINUXexpert-org
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package backup
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os/exec"
|
|
)
|
|
|
|
// FDBOptions configures a FoundationDB backup via fdbbackup, FDB's own
|
|
// backup CLI (not something Stalwart-specific) - see ARCHITECTURE.md §4.2.
|
|
type FDBOptions struct {
|
|
ClusterFile string // -C; empty uses fdbbackup's own default cluster file
|
|
Destination string // -d, a backup URL e.g. "file:///var/backups/stalwart-fdb"
|
|
Tag string // -t; defaults to "default" if empty
|
|
}
|
|
|
|
func (o FDBOptions) tag() string {
|
|
if o.Tag == "" {
|
|
return "default"
|
|
}
|
|
return o.Tag
|
|
}
|
|
|
|
// BuildFDBBackupStartArgs returns the fdbbackup argv for starting a backup,
|
|
// without the leading "fdbbackup".
|
|
func BuildFDBBackupStartArgs(o FDBOptions) []string {
|
|
args := []string{"start"}
|
|
if o.ClusterFile != "" {
|
|
args = append(args, "-C", o.ClusterFile)
|
|
}
|
|
args = append(args, "-d", o.Destination, "-t", o.tag())
|
|
return args
|
|
}
|
|
|
|
// StartFDBBackup kicks off an fdbbackup run. fdbbackup start returns as soon
|
|
// as the backup job is registered, not when it finishes - callers that need
|
|
// to know it's done should poll FDBBackupStatus and look for their own
|
|
// definition of "complete" in its output, since this wrapper doesn't parse
|
|
// fdbbackup's status text (that format isn't stable enough here to depend
|
|
// on without verifying it against the fdbbackup version actually in use).
|
|
func StartFDBBackup(ctx context.Context, o FDBOptions) error {
|
|
cmd := exec.CommandContext(ctx, "fdbbackup", BuildFDBBackupStartArgs(o)...)
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return fmt.Errorf("backup: fdbbackup start failed: %w (output: %s)", err, out)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// FDBBackupStatus returns fdbbackup's raw status output for the given tag,
|
|
// for a human or a caller-supplied parser to interpret.
|
|
func FDBBackupStatus(ctx context.Context, o FDBOptions) (string, error) {
|
|
args := []string{"status", "-t", o.tag()}
|
|
if o.ClusterFile != "" {
|
|
args = append(args, "-C", o.ClusterFile)
|
|
}
|
|
cmd := exec.CommandContext(ctx, "fdbbackup", args...)
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return string(out), fmt.Errorf("backup: fdbbackup status failed: %w (output: %s)", err, out)
|
|
}
|
|
return string(out), nil
|
|
}
|