addons

package
v1.0.0 Latest Latest
Warning

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

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

Documentation

Overview

Package addons manages Postgres and Redis addon containers for apps (E2.3): hardened containers on the owning app's network, generated credentials stored age-encrypted and injected into the app as ordinary write-only secrets, and encrypted backups to S3-compatible storage (see backup.go). Everything reaching Docker is a typed struct — no addon name, password or option ever touches a shell (kills the CVE-2025-66209/66210/66211 class).

Index

Constants

View Source
const (
	BackupQueued  = "queued"
	BackupRunning = "running"
	BackupDone    = "done"
	BackupFailed  = "failed"
)

Backup states.

View Source
const (
	KindPostgres = "postgres"
	KindRedis    = "redis"
)

Kinds of addons.

View Source
const (
	PostgresImage = "postgres:17-alpine"
	RedisImage    = "redis:7-alpine"
)

Pinned images.

View Source
const (
	StateRunning = "running"
	StateStopped = "stopped"
	StateFailed  = "failed"
)

States.

View Source
const (
	PermAppsManage  = deploy.PermAppsManage
	PermAppsView    = deploy.PermAppsView
	PermDestructive = "destructive"
)

Permissions (mirrors internal/auth by name).

Variables

View Source
var (

	// ErrInvalid wraps validation failures (HTTP 400).
	ErrInvalid = deploy.ErrInvalid
	// ErrNotFound wraps unknown apps/addons/backups (HTTP 404).
	ErrNotFound = deploy.ErrNotFound
	// ErrForbidden is returned when the actor lacks a permission (HTTP 403).
	ErrForbidden = deploy.ErrForbidden
)

Functions

func ContainerName

func ContainerName(app, name string) string

ContainerName / VolumeName / SecretName derive the fixed names for an addon.

func SecretName

func SecretName(kind string) string

func VolumeName

func VolumeName(app, name string) string

Types

type BackupView

type BackupView struct {
	ID         string `json:"id"`
	AddonID    string `json:"addon_id"`
	State      string `json:"state"`
	ObjectKey  string `json:"object_key,omitempty"`
	SizeBytes  int64  `json:"size_bytes"`
	Error      string `json:"error,omitempty"`
	StartedAt  string `json:"started_at"`
	FinishedAt string `json:"finished_at,omitempty"`
}

BackupView is the API representation of a backup.

type Service

type Service struct {
	Store    *store.Store
	Docker   *docker.Client
	Keeper   *secrets.Keeper
	Redactor *secrets.Redactor
	Audit    audit.Sink
	Cfg      config.Config
	Queue    *queue.Client
	// S3 is the backup target; nil keeps encrypted backups on the local disk only.
	S3 *backup.S3
	// S3Prefix namespaces object keys (default "redoubt").
	S3Prefix string
	Logger   *slog.Logger
	Now      func() time.Time
	// TestContainers labels containers redoubt.test=1 (test-suite only).
	TestContainers bool
	HealthTimeout  time.Duration
}

Service is the addon service layer (shared by API, UI and CLI).

func (*Service) Backup

func (s *Service) Backup(ctx context.Context, actor deploy.Actor, appName, name string) (BackupView, error)

Backup records a backup and enqueues the job (transactionally).

func (*Service) Create

func (s *Service) Create(ctx context.Context, actor deploy.Actor, appName, kind, name string) (View, error)

Create provisions an addon: generates a password, stores it encrypted, starts the hardened container on the app's network, and injects the connection URL as an app secret.

func (*Service) Delete

func (s *Service) Delete(ctx context.Context, actor deploy.Actor, appName, name string, removeData bool) error

Delete removes the addon container (and its data volume only when removeData, which requires the destructive permission) and the injected secret.

func (*Service) Get

func (s *Service) Get(ctx context.Context, actor deploy.Actor, appName, name string) (View, error)

Get returns one addon.

func (*Service) List

func (s *Service) List(ctx context.Context, actor deploy.Actor, appName string) ([]View, error)

List returns an app's addons.

func (*Service) ListBackups

func (s *Service) ListBackups(ctx context.Context, actor deploy.Actor, appName, name string, limit int64) ([]BackupView, error)

ListBackups lists an addon's backups, newest first.

func (*Service) Restore

func (s *Service) Restore(ctx context.Context, actor deploy.Actor, appName, backupID, targetAddon string) (err error)

Restore loads a backup into targetAddon (same kind), replacing its contents.

func (*Service) RunBackup

func (s *Service) RunBackup(ctx context.Context, backupID string) (err error)

RunBackup executes a queued backup: dump inside a hardened job container, age-encrypt, upload (or keep locally when no S3 is configured), record.

func (*Service) RunScheduler

func (s *Service) RunScheduler(ctx context.Context, interval, tick time.Duration)

RunScheduler enqueues a backup for every addon whose last successful backup is older than interval, checking every tick. It blocks until ctx is done.

func (*Service) ScheduleDue

func (s *Service) ScheduleDue(ctx context.Context, interval time.Duration) int

ScheduleDue enqueues backups for addons whose latest successful backup is older than interval.

type View

type View struct {
	ID            string   `json:"id"`
	App           string   `json:"app"`
	Kind          string   `json:"kind"`
	Name          string   `json:"name"`
	ContainerName string   `json:"container_name"`
	VolumeName    string   `json:"volume_name"`
	Version       string   `json:"version"`
	State         string   `json:"state"`
	Hardened      bool     `json:"hardened"`
	Problems      []string `json:"problems,omitempty"`
	// SecretName is the app secret that carries the connection URL (write-only).
	SecretName string `json:"secret_name"`
	CreatedAt  string `json:"created_at"`
}

View is the API representation of an addon (never includes the password).

type Worker

type Worker struct {
	river.WorkerDefaults[queue.BackupArgs]
	S *Service
}

Worker is the River worker for BackupArgs.

func (*Worker) Timeout

func (w *Worker) Timeout(*river.Job[queue.BackupArgs]) time.Duration

Timeout bounds one backup.

func (*Worker) Work

func (w *Worker) Work(ctx context.Context, job *river.Job[queue.BackupArgs]) error

Work runs one backup job.

Jump to

Keyboard shortcuts

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