Files
stalwart-migrator/internal/backup/fdbbackup.go
T
jcoffey-dev 4b0bec8956 Add SPDX headers to every Go file
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.
2026-08-23 18:03:15 -07:00

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
}