db

package
v0.9.13 Latest Latest
Warning

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

Go to latest
Published: Sep 17, 2026 License: AGPL-3.0 Imports: 24 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 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) 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"`
	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

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 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"`
	RetentionPolicy RetentionPolicy `json:"retention_policy" db:"retention_policy"`
	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"`
}

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) 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) 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) 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) 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) 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, pveHost, dockerHost bool) (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"`
}

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 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 RetentionPolicy

type RetentionPolicy struct {
	KeepLast    int `json:"keep_last"`
	KeepDaily   int `json:"keep_daily"`
	KeepWeekly  int `json:"keep_weekly"`
	KeepMonthly int `json:"keep_monthly"`
	KeepYearly  int `json:"keep_yearly"`
}

RetentionPolicy defines backup retention counts

func (RetentionPolicy) ToJSON

func (r RetentionPolicy) ToJSON() []byte

Helper to serialize RetentionPolicy to JSON bytes

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