db

package
v0.11.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 20, 2026 License: AGPL-3.0 Imports: 25 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AgentTypeFilesystem = config.AgentTypeFilesystem
	AgentTypeDatabase   = config.AgentTypeDatabase
	AgentTypeKubernetes = config.AgentTypeKubernetes
	JobTypeFilesystem   = config.AgentTypeFilesystem
	JobTypeDatabase     = config.AgentTypeDatabase
	JobTypeKubernetes   = config.AgentTypeKubernetes
	// JobTypePVE backs up a Proxmox VE host's configuration; it runs on the
	// filesystem agent installed on the node
	JobTypePVE = "pve"
	// JobTypeDocker backs up a Docker host (definitions, compose files, volumes); it
	// runs on the filesystem agent installed on the host
	JobTypeDocker = "docker"
)

Agent / job types: each agent binary handles one kind of job

View Source
const (
	PxarFormatV1 = "v1" // single stream + catalog; browsable everywhere
	PxarFormatV2 = "v2" // split metadata/payload streams; PBS 3.2+
)

pxar archive formats a target accepts

Variables

View Source
var (
	ErrNotFound = errors.New("record not found")
)

Functions

func CleanDBEngines added in v0.11.3

func CleanDBEngines(in []string) []string

CleanDBEngines keeps the known engine names, canonical and without duplicates

func JobAllowedOnAgent added in v0.9.5

func JobAllowedOnAgent(jobType, agentType string) bool

JobAllowedOnAgent reports whether an agent of agentType may run a job of jobType. Job types normally match the agent type; the exceptions are database jobs on a kubernetes agent (dumped from a pod inside the cluster) or on a filesystem agent (the combined agent, when it reports database client tools), and Proxmox VE / Docker host jobs, which run on the filesystem agent installed on the host.

func NormalizeAgentType added in v0.6.0

func NormalizeAgentType(t string) (string, bool)

NormalizeAgentType maps "" to filesystem and reports unknown values

func NormalizeJobType added in v0.9.5

func NormalizeJobType(t string) (string, bool)

NormalizeJobType maps "" to filesystem and accepts the job-only types pve and docker

func SetScheduleLocation added in v0.7.2

func SetScheduleLocation(loc *time.Location)

SetScheduleLocation installs the timezone used for next-run display

func ValidateBackupPaths added in v0.6.0

func ValidateBackupPaths(paths []string) ([]string, error)

ValidateBackupPaths normalises a job's backup paths and rejects combinations that cannot form one archive: every path must be absolute, exact duplicates are dropped and no path may lie inside another (its data would be archived twice). Paths sharing a basename are fine; the agent names them after their full path in the archive. The rules are those of a Unix agent regardless of the host the server runs on, so the slash-only path package is used rather than path/filepath.

func ValidateBackupPathsFor added in v0.9.5

func ValidateBackupPathsFor(agentOS string, paths []string) ([]string, error)

ValidateBackupPathsFor validates paths with the rules of the agent's operating system ("windows" or anything else): the server runs on Linux but stores jobs for Windows agents, whose paths use drive letters and backslashes.

func ValidateCron added in v0.6.2

func ValidateCron(expr string) error

ValidateCron rejects schedule expressions the scheduler cannot run; empty = manual

func ValidateExcludePatterns added in v0.6.0

func ValidateExcludePatterns(patterns []string) error

ValidateExcludePatterns checks exclude patterns against the pxar pattern syntax (proxmox-backup-client --exclude); invalid patterns would otherwise fail the backup only at run time on the agent.

func ValidateLocalBackupPaths added in v0.9.6

func ValidateLocalBackupPaths(paths []string) ([]string, error)

ValidateLocalBackupPaths validates paths with the rules of the operating system the caller runs on; the agent uses it for the paths it is about to read.

Types

type APIKey

type APIKey struct {
	ID         uuid.UUID  `json:"id"`
	Name       string     `json:"name"`
	KeyHash    string     `json:"-"`
	CreatedBy  string     `json:"created_by"`
	CreatedAt  time.Time  `json:"created_at"`
	LastUsedAt *time.Time `json:"last_used_at"`
	ExpiresAt  *time.Time `json:"expires_at"`
	RevokedAt  *time.Time `json:"revoked_at"`
}

APIKey is an admin credential for fallbck-ctl and scripts. The raw key is never stored.

type Agent

type Agent struct {
	ID        uuid.UUID `json:"id" db:"id"`
	Hostname  string    `json:"hostname" db:"hostname"`
	IPAddress string    `json:"ip_address" db:"ip_address"`
	OS        string    `json:"os" db:"os"`
	Arch      string    `json:"arch" db:"arch"`
	Version   string    `json:"version" db:"version"`
	AgentType string    `json:"agent_type" db:"agent_type"`
	TaskQueue string    `json:"task_queue" db:"task_queue"`
	// DebugLogging raises the agent's log level to debug (applied via heartbeats)
	DebugLogging bool `json:"debug_logging" db:"debug_logging"`
	// PVEHost is reported by the agent when it runs on a Proxmox VE node
	PVEHost bool `json:"pve_host" db:"pve_host"`
	// DockerHost is reported by the agent when a Docker daemon answers on its host
	DockerHost bool `json:"docker_host" db:"docker_host"`
	// DBTools is reported by a filesystem agent that found database client tools
	// (pg_dump, mysqldump/mariadb-dump, mongodump) and can therefore run database jobs
	DBTools bool `json:"db_tools" db:"db_tools"`
	// DBEngines are the database engines the agent reported (see CanRunDBEngine)
	DBEngines  []string    `json:"db_engines" db:"db_engines"`
	Status     AgentStatus `json:"status" db:"status"`
	LastSeenAt *time.Time  `json:"last_seen_at" db:"last_seen_at"`
	CreatedAt  time.Time   `json:"created_at" db:"created_at"`
	UpdatedAt  time.Time   `json:"updated_at" db:"updated_at"`
}

Agent represents a registered backup agent host

func (*Agent) CanRunDBEngine added in v0.11.3

func (a *Agent) CanRunDBEngine(engine string) bool

CanRunDBEngine reports whether this agent can back up the engine. Filesystem agents go by the engines they report; one that only sent the older db_tools flag predates the mssql engine and is assumed to have the client tools of the other three. Kubernetes agents dump from a pod and the retired database agent predates mssql, so both handle everything except SQL Server.

func (*Agent) CanRunJob added in v0.10.1

func (a *Agent) CanRunJob(jobType string) bool

CanRunJob reports whether this agent may run a job of jobType, including the capability flags a filesystem agent reports (Proxmox VE node, Docker daemon, database client tools)

type AgentAuthState

type AgentAuthState struct {
	ID           uuid.UUID
	TaskQueue    string
	TokenVersion int
	Revoked      bool
}

AgentAuthState is the subset of agent state needed to validate an agent bearer token

type AgentCapabilities added in v0.10.1

type AgentCapabilities struct {
	PVEHost    bool
	DockerHost bool
	DBTools    bool
	DBEngines  []string
}

AgentCapabilities are the host facts a filesystem agent reports with every heartbeat

type AgentStatus

type AgentStatus string

AgentStatus represents the lifecycle state of an agent

const (
	AgentStatusOnline  AgentStatus = "online"
	AgentStatusOffline AgentStatus = "offline"
	AgentStatusBusy    AgentStatus = "busy"
	AgentStatusError   AgentStatus = "error"
)

type BackupJob

type BackupJob struct {
	ID           uuid.UUID `json:"id" db:"id"`
	Name         string    `json:"name" db:"name"`
	AgentID      uuid.UUID `json:"agent_id" db:"agent_id"`
	TargetID     uuid.UUID `json:"target_id" db:"target_id"`
	ScheduleCron string    `json:"schedule_cron" db:"schedule_cron"`
	BackupPaths  []string  `json:"backup_paths" db:"backup_paths"`
	ExcludePaths []string  `json:"exclude_paths" db:"exclude_paths"`
	Enabled      bool      `json:"enabled" db:"enabled"`
	// DirectPBS makes the agent talk to PBS itself (credentials handed out per run)
	// instead of through the server-side tunnel. Server-side setting only.
	DirectPBS bool `json:"direct_pbs" db:"direct_pbs"`
	// JobType is filesystem (BackupPaths) or database (DBConfig)
	JobType string `json:"job_type" db:"job_type"`
	// DBConfig is the database job specification; the password is stored but never
	// returned by the API (see Sanitize)
	DBConfig *dbbackup.Spec `json:"db_config,omitempty" db:"db_config"`
	// K8sConfig is the kubernetes job specification
	K8sConfig *k8sbackup.Spec `json:"k8s_config,omitempty" db:"k8s_config"`
	// PVEConfig is the Proxmox VE host job specification
	PVEConfig *pvebackup.Spec `json:"pve_config,omitempty" db:"pve_config"`
	// DockerConfig is the Docker host job specification
	DockerConfig *dockerbackup.Spec `json:"docker_config,omitempty" db:"docker_config"`
	CreatedAt    time.Time          `json:"created_at" db:"created_at"`
	UpdatedAt    time.Time          `json:"updated_at" db:"updated_at"`

	// Joined fields for display
	AgentName  string `json:"agent_name,omitempty"`
	TargetName string `json:"target_name,omitempty"`
	// LastRun is the job's newest run (filled by the Jobs page; nil = never ran)
	LastRun *JobLastRun `json:"last_run,omitempty" db:"-"`
}

BackupJob defines what, when, and where an agent backs up

func (*BackupJob) IsDatabase added in v0.6.0

func (j *BackupJob) IsDatabase() bool

IsDatabase reports whether the job is a database backup

func (*BackupJob) IsDocker added in v0.9.11

func (j *BackupJob) IsDocker() bool

IsDocker reports whether the job is a Docker host backup

func (*BackupJob) IsKubernetes added in v0.7.2

func (j *BackupJob) IsKubernetes() bool

IsKubernetes reports whether the job is a kubernetes backup

func (*BackupJob) IsPVE added in v0.9.5

func (j *BackupJob) IsPVE() bool

IsPVE reports whether the job is a Proxmox VE host backup

func (*BackupJob) NextRunString added in v0.6.2

func (j *BackupJob) NextRunString() string

NextRunString reports when the schedule fires next, in the schedule timezone with its abbreviation; empty when the job is manual, disabled, or the expression does not parse.

func (*BackupJob) Sanitize added in v0.6.0

func (j *BackupJob) Sanitize() *BackupJob

Sanitize redacts the stored database password (HasPassword tells whether one exists)

func (*BackupJob) Summary added in v0.6.0

func (j *BackupJob) Summary() string

Summary describes what the job backs up (paths, database target or cluster scope)

type BackupRun

type BackupRun struct {
	ID            uuid.UUID  `json:"id" db:"id"`
	JobID         uuid.UUID  `json:"job_id" db:"job_id"`
	AgentID       uuid.UUID  `json:"agent_id" db:"agent_id"`
	TargetID      uuid.UUID  `json:"target_id" db:"target_id"`
	WorkflowID    string     `json:"workflow_id" db:"workflow_id"`
	RunID         string     `json:"run_id" db:"run_id"`
	Status        RunStatus  `json:"status" db:"status"`
	StartTime     *time.Time `json:"start_time" db:"start_time"`
	EndTime       *time.Time `json:"end_time" db:"end_time"`
	BytesScanned  int64      `json:"bytes_scanned" db:"bytes_scanned"`
	BytesUploaded int64      `json:"bytes_uploaded" db:"bytes_uploaded"`
	DedupRatio    float64    `json:"dedup_ratio" db:"dedup_ratio"`
	ChunkCount    int        `json:"chunk_count" db:"chunk_count"`
	ErrorMessage  string     `json:"error_message" db:"error_message"`
	PBSSnapshotID string     `json:"pbs_snapshot_id" db:"pbs_snapshot_id"`
	// LogTail is the agent's recent log output captured when the run failed
	LogTail string `json:"log_tail,omitempty" db:"log_tail"`
	// Details is a type-specific JSON blob (archives / databases / PVCs) for the run
	// detail page; carries a top-level "type" discriminator. Empty for older runs.
	Details json.RawMessage `json:"details,omitempty" db:"details"`
	// Progress is the live state of a running backup (phase + per-item statuses),
	// updated mid-run and polled by the detail page.
	Progress  json.RawMessage `json:"progress,omitempty" db:"progress"`
	CreatedAt time.Time       `json:"created_at" db:"created_at"`

	// Joined fields
	JobName   string `json:"job_name,omitempty"`
	AgentName string `json:"agent_name,omitempty"`
}

BackupRun records a single execution of a backup job

func (*BackupRun) DurationString added in v0.6.0

func (r *BackupRun) DurationString() string

DurationString renders how long the run took (or has been running); "-" before start

type BackupTarget

type BackupTarget struct {
	ID                 uuid.UUID `json:"id" db:"id"`
	Name               string    `json:"name" db:"name"`
	TargetType         string    `json:"target_type" db:"target_type"` // "pbs"
	Endpoint           string    `json:"endpoint" db:"endpoint"`
	Datastore          string    `json:"datastore" db:"datastore"`
	Namespace          string    `json:"namespace" db:"namespace"`
	AuthTokenEncrypted string    `json:"-" db:"auth_token_encrypted"`
	Fingerprint        string    `json:"fingerprint" db:"fingerprint"`
	TLSVerify          bool      `json:"tls_verify" db:"tls_verify"`
	PxarFormat         string    `json:"pxar_format" db:"pxar_format"`
	CreatedAt          time.Time `json:"created_at" db:"created_at"`
	UpdatedAt          time.Time `json:"updated_at" db:"updated_at"`

	// HasToken reports whether an API token is stored (the token itself is never returned)
	HasToken bool `json:"has_token" db:"-"`
}

BackupTarget represents a remote backup repository such as Proxmox Backup Server

func (*BackupTarget) Sanitize added in v0.6.0

func (t *BackupTarget) Sanitize() *BackupTarget

Sanitize fills derived, API-safe fields

type DB

type DB struct {
	Pool *pgxpool.Pool
}

DB wraps the pgx connection pool and exposes repository operations

func New

func New(ctx context.Context, cfg config.DatabaseConfig) (*DB, error)

New creates a new database connection pool and applies migrations if enabled

func (*DB) BindTokenAgent added in v0.11.0

func (d *DB) BindTokenAgent(ctx context.Context, tokenID, agentID uuid.UUID) error

BindTokenAgent records the agent that enrolled with the token

func (*DB) BumpAgentTokenVersion

func (d *DB) BumpAgentTokenVersion(ctx context.Context, id uuid.UUID) (int, error)

BumpAgentTokenVersion invalidates every previously issued token for the agent and returns the new version that must be embedded in freshly issued tokens.

func (*DB) CloneTarget added in v0.11.0

func (d *DB) CloneTarget(ctx context.Context, sourceID uuid.UUID, name, namespace, pxarFormat string) (*BackupTarget, error)

CloneTarget creates a new target from an existing one: same PBS endpoint, datastore, API token (copied encrypted, it never leaves the server), fingerprint, TLS setting and (unless overridden) pxar format, with a new name and namespace.

func (*DB) Close

func (d *DB) Close()

Close closes the underlying pool

func (*DB) CreateAPIKey

func (d *DB) CreateAPIKey(ctx context.Context, key *APIKey) error

func (*DB) CreateAgent

func (d *DB) CreateAgent(ctx context.Context, agent *Agent) error

func (*DB) CreateEnrollmentToken

func (d *DB) CreateEnrollmentToken(ctx context.Context, token *EnrollmentToken) error

func (*DB) CreateJob

func (d *DB) CreateJob(ctx context.Context, job *BackupJob) error

func (*DB) CreateRun

func (d *DB) CreateRun(ctx context.Context, run *BackupRun) error

func (*DB) CreateTarget

func (d *DB) CreateTarget(ctx context.Context, target *BackupTarget) error

func (*DB) DeleteAgent

func (d *DB) DeleteAgent(ctx context.Context, id uuid.UUID) error

func (*DB) DeleteEnrollmentToken added in v0.6.0

func (d *DB) DeleteEnrollmentToken(ctx context.Context, id uuid.UUID) error

DeleteEnrollmentToken invalidates a token immediately (enrollment looks tokens up by hash, so a deleted row can never be consumed again)

func (*DB) DeleteJob

func (d *DB) DeleteJob(ctx context.Context, id uuid.UUID) error

func (*DB) DeleteTarget

func (d *DB) DeleteTarget(ctx context.Context, id uuid.UUID) error

func (*DB) GetAPIKeyByHash

func (d *DB) GetAPIKeyByHash(ctx context.Context, hash string) (*APIKey, error)

func (*DB) GetAgentAuthState

func (d *DB) GetAgentAuthState(ctx context.Context, id uuid.UUID) (*AgentAuthState, error)

GetAgentAuthState returns the token version and revocation state of an agent. Returns ErrNotFound if the agent does not exist (e.g. it was deleted).

func (*DB) GetAgentByID

func (d *DB) GetAgentByID(ctx context.Context, id uuid.UUID) (*Agent, error)

func (*DB) GetEnrollmentToken added in v0.11.0

func (d *DB) GetEnrollmentToken(ctx context.Context, id uuid.UUID) (*EnrollmentToken, error)

GetEnrollmentToken loads one token (with the hostname of the agent that used it)

func (*DB) GetJobByID

func (d *DB) GetJobByID(ctx context.Context, id uuid.UUID) (*BackupJob, error)

func (*DB) GetRunByID added in v0.3.1

func (d *DB) GetRunByID(ctx context.Context, id uuid.UUID) (*BackupRun, error)

GetRunByID returns a single run

func (*DB) GetRunByWorkflowID added in v0.3.1

func (d *DB) GetRunByWorkflowID(ctx context.Context, workflowID string) (*BackupRun, error)

GetRunByWorkflowID returns the run record created for a Temporal workflow execution

func (*DB) GetTargetByID

func (d *DB) GetTargetByID(ctx context.Context, id uuid.UUID) (*BackupTarget, error)

func (*DB) LatestRunByJob added in v0.11.2

func (d *DB) LatestRunByJob(ctx context.Context) (map[uuid.UUID]*JobLastRun, error)

LatestRunByJob returns the newest run of every job that has one

func (*DB) ListAPIKeys

func (d *DB) ListAPIKeys(ctx context.Context) ([]*APIKey, error)

func (*DB) ListAgents

func (d *DB) ListAgents(ctx context.Context) ([]*Agent, error)

func (*DB) ListEnrollmentTokens

func (d *DB) ListEnrollmentTokens(ctx context.Context) ([]*EnrollmentToken, error)

func (*DB) ListJobs

func (d *DB) ListJobs(ctx context.Context) ([]*BackupJob, error)

func (*DB) ListRuns

func (d *DB) ListRuns(ctx context.Context, limit int) ([]*BackupRun, error)

func (*DB) ListTargets

func (d *DB) ListTargets(ctx context.Context) ([]*BackupTarget, error)

func (*DB) MarkRunStarted added in v0.3.1

func (d *DB) MarkRunStarted(ctx context.Context, id uuid.UUID, temporalRunID string, startedAt time.Time) error

MarkRunStarted moves a pending run to running once the workflow has prepared the session

func (*DB) MergeAgents added in v0.10.1

func (d *DB) MergeAgents(ctx context.Context, from, into uuid.UUID) (int64, int64, error)

MergeAgents moves every job and run of the agent from onto the agent into and deletes from, in one transaction. Deleting an agent cascades to its jobs and runs, so the move must come first. It returns the number of jobs and runs moved.

func (*DB) Migrate

func (d *DB) Migrate(ctx context.Context) error

Migrate applies all pending schema migrations to PostgreSQL. Each migration runs in its own transaction and is recorded in schema_migrations so it is applied exactly once.

func (*DB) RevokeAPIKey

func (d *DB) RevokeAPIKey(ctx context.Context, id uuid.UUID) error

func (*DB) RevokeAgent

func (d *DB) RevokeAgent(ctx context.Context, id uuid.UUID) error

RevokeAgent marks the agent as revoked; its tokens stop validating immediately

func (*DB) SetAgentDebugLogging added in v0.6.2

func (d *DB) SetAgentDebugLogging(ctx context.Context, id uuid.UUID, enabled bool) error

SetAgentDebugLogging flips the per-agent debug toggle (delivered on the next heartbeat)

func (*DB) SetRunItems added in v0.9.0

func (d *DB) SetRunItems(ctx context.Context, runID uuid.UUID, updatedAt string, items map[string][]byte) error

SetRunItems merges per-item statuses into an active run's progress. Each item is written at progress.items.<key> so concurrent per-item updates never clobber.

func (*DB) SetRunPhase added in v0.9.0

func (d *DB) SetRunPhase(ctx context.Context, runID uuid.UUID, phase, updatedAt string) error

SetRunPhase records the current phase of an active run (jsonb_set: no read-modify-write)

func (*DB) SetRunStatus added in v0.3.1

func (d *DB) SetRunStatus(ctx context.Context, id uuid.UUID, status RunStatus, message string, endTime *time.Time) error

SetRunStatus updates the status (and optionally end time / message) of a run

func (*DB) TouchAPIKey

func (d *DB) TouchAPIKey(ctx context.Context, id uuid.UUID) error

TouchAPIKey records the last use of a key (best-effort, called on successful auth)

func (*DB) UpdateAgentHeartbeat

func (d *DB) UpdateAgentHeartbeat(ctx context.Context, id uuid.UUID, status AgentStatus, caps AgentCapabilities) (bool, error)

UpdateAgentHeartbeat records the heartbeat and returns the agent's remote debug-logging setting for the response.

func (*DB) UpdateJob added in v0.6.0

func (d *DB) UpdateJob(ctx context.Context, job *BackupJob) error

UpdateJob replaces the editable fields of a job

func (*DB) UpdateRun

func (d *DB) UpdateRun(ctx context.Context, run *BackupRun) error

func (*DB) UpdateTarget added in v0.9.0

func (d *DB) UpdateTarget(ctx context.Context, target *BackupTarget) error

UpdateTarget replaces a target's editable fields (name, endpoint, datastore, namespace, token, fingerprint, TLS, format). The caller supplies the final values, including AuthTokenEncrypted (kept unchanged by loading the existing row first when the operator leaves the token field blank).

func (*DB) UpsertAgent

func (d *DB) UpsertAgent(ctx context.Context, agent *Agent) error

func (*DB) ValidateAndConsumeToken

func (d *DB) ValidateAndConsumeToken(ctx context.Context, tokenHash string) (*EnrollmentToken, error)

type EnrollmentToken

type EnrollmentToken struct {
	ID        uuid.UUID `json:"id" db:"id"`
	TokenHash string    `json:"-" db:"token_hash"`
	Name      string    `json:"name" db:"name"`
	MaxUses   int       `json:"max_uses" db:"max_uses"`
	UsesCount int       `json:"uses_count" db:"uses_count"`
	ExpiresAt time.Time `json:"expires_at" db:"expires_at"`
	CreatedAt time.Time `json:"created_at" db:"created_at"`
	// AgentID is the agent that last enrolled with this token (onboarding waits for it)
	AgentID *uuid.UUID `json:"agent_id,omitempty" db:"agent_id"`
	// AgentHostname is joined for display; empty when no agent used the token
	AgentHostname string `json:"agent_hostname,omitempty" db:"-"`
}

EnrollmentToken represents a one-time or multi-use token for agent onboarding

func (*EnrollmentToken) Status added in v0.6.0

func (t *EnrollmentToken) Status() string

Status describes whether the token can still be used

type JobLastRun added in v0.11.2

type JobLastRun struct {
	RunID  uuid.UUID `json:"run_id"`
	Status RunStatus `json:"status"`
	At     time.Time `json:"at"`
}

JobLastRun is the newest run of a job, for list views

type Migration

type Migration struct {
	Version int
	Name    string
	SQL     string
}

Migration is a single embedded SQL migration file

func LoadMigrations

func LoadMigrations() ([]Migration, error)

LoadMigrations returns the embedded migrations ordered by version. Files are named NNN_description.sql; the numeric prefix is the version.

type RunStatus

type RunStatus string

RunStatus represents the state of a backup run

const (
	RunStatusPending   RunStatus = "pending"
	RunStatusRunning   RunStatus = "running"
	RunStatusCompleted RunStatus = "completed"
	RunStatusFailed    RunStatus = "failed"
	// RunStatusCancelling: cancellation requested, waiting for the agent to stop
	RunStatusCancelling RunStatus = "cancelling"
	RunStatusCancelled  RunStatus = "cancelled"
)

func (RunStatus) IsActive added in v0.3.1

func (s RunStatus) IsActive() bool

IsActive reports whether a run can still be cancelled

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL