updater

package
v0.20.0 Latest Latest
Warning

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

Go to latest
Published: Nov 7, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Overview

Package updater updates a server install: it unpacks a checked release, backs up the database and switches builds.

Index

Constants

View Source
const (
	// Current names the link to the build that runs.
	Current = "current"
	// Previous names the link to the build an update goes back to.
	Previous = "previous"
)
View Source
const ExitFailedCheck = 76

ExitFailedCheck is the exit code of a start whose build failed its start check after an update.

Variables

View Source
var ErrRefused = errors.New("updater: a check refused the update")

ErrRefused marks an update a check before its download refused, its message saying why.

View Source
var ErrUpdateRuns = errors.New("updater: another update runs, so wait for it to end and run update:apply again")

ErrUpdateRuns stops a job while another update holds the update lock.

Functions

func CheckPages

func CheckPages(ctx context.Context, fetch func(*http.Request) (*http.Response, error), address string) error

CheckPages asks the site at address for each checked page through fetch, refusing the first answer it does not take.

func DumpMajor

func DumpMajor(ctx context.Context, bin string) (int, error)

DumpMajor returns the PostgreSQL major of the pg_dump at bin, refusing one that cannot run or names no version.

func Lock

func Lock(ctx context.Context, db *sql.DB) (func(), error)

Lock takes the update lock on a connection of db it keeps, and returns what lets go of it and of the connection.

func MarkDatabaseReached

func MarkDatabaseReached(settings Settings, running string) error

MarkDatabaseReached writes under the state lock that running, the build an update switched to, reached the database.

func NewClient

func NewClient(timeout time.Duration) *http.Client

NewClient returns the client a download fetches with, giving up after timeout and following https redirects only.

func PointIn

func PointIn(tree *os.Root, link, name string) error

PointIn points the link called link of tree at the build called name, renaming a new link over the old one.

func Unpack

func Unpack(archive io.Reader, dir string) error

Unpack writes the known files of the release archive into dir, a folder it makes, deleting dir when any entry fails.

func UnpackIn

func UnpackIn(tree *os.Root, archive io.Reader, dir string) error

UnpackIn writes the known files of the release archive into dir, a folder it makes in tree, deleting it on a failure.

Types

type Backup

type Backup struct {
	PgDump      string
	DatabaseURL string
	Folder      string
	Name        string
	Held        string
	Keep        int
}

Backup is one pg_dump of the database into the backups folder, which keeps it, the one Held names and the newest.

func (Backup) Take

func (b Backup) Take(ctx context.Context) error

Take runs pg_dump into a partial file, renames it to the name of the backup, saves the name to disk, then prunes.

type BackupCount

type BackupCount struct {
	Kept   int        `json:"kept"`
	Limit  int        `json:"limit"`
	Newest *time.Time `json:"newest"`
}

BackupCount is how many backups the install root keeps, how many it may keep, and when the newest was taken.

type CheckError

type CheckError struct {
	// contains filtered or unexported fields
}

CheckError is the error of a start whose build failed its start check after an update, saying what happened next.

func (CheckError) Error

func (e CheckError) Error() string

Error says what failed and what the guard did about it.

func (CheckError) Unwrap

func (e CheckError) Unwrap() error

Unwrap returns what failed and what the guard did about it.

type Download

type Download struct {
	Artifact update.Artifact
	Signers  []ed25519.PublicKey
	Partial  string
	Cap      int64
	Client   *http.Client
}

Download is one archive to fetch: its record entry, the keys that may sign it, its partial file, cap and client.

func (Download) Fetch

func (d Download) Fetch(ctx context.Context) (*os.File, error)

Fetch downloads the archive into a new partial file and returns it checked and open at its start, deleted on failure.

type Failure

type Failure struct {
	ServiceResult string
}

Failure is what the service manager says about the start that failed, as it hands it to its rollback unit.

type Guard

type Guard struct {
	// contains filtered or unexported fields
}

Guard is the boot guard: the start check of a build the last update names, until that update is settled.

func Start

func Start(settings Settings, running string, logger *slog.Logger) (*Guard, error)

Start counts a start of running after a switch under the state lock, failing past the attempts or once refused.

func (*Guard) ReachedDatabase

func (g *Guard) ReachedDatabase() error

ReachedDatabase writes under the state lock that the build of a start the guard checks reached the database.

func (*Guard) Serve

func (g *Guard) Serve(
	ctx context.Context, srv *http.Server, inside func(context.Context) error, serve func(context.Context) error,
) error

Serve runs serve with the start check once srv listens, ending it when a switched build fails it, or alone with none.

type Job

type Job struct {
	Settings    Settings
	Check       update.Config
	Store       update.Settings
	DB          *sql.DB
	DatabaseURL string
	Stamp       string
	Kit         string
	ThemeError  error
	To          string
	Retry       bool
	SkipBackup  bool
}

Job is one update of a server install as update:apply runs it, with what a person asked of it.

func (Job) Apply

func (j Job) Apply(ctx context.Context) (State, error)

Apply locks, checks, plans, downloads, stages, backs up and switches, returning the state the job ends at.

func (Job) Plan

func (j Job) Plan(ctx context.Context) (*Planned, error)

Plan reads the database server, takes the update lock and runs every check that needs no download.

type JobFailure

type JobFailure struct {
	At    time.Time `json:"at"`
	From  string    `json:"from"`
	To    string    `json:"to"`
	Step  Step      `json:"step"`
	Error string    `json:"error"`
}

JobFailure is how a job failed after it wrote a step: when, from and to which versions, at which step and why.

type LastUpdate

type LastUpdate struct {
	Step    Step        `json:"step"`
	From    string      `json:"from"`
	To      string      `json:"to"`
	Failure *JobFailure `json:"failure"`
}

LastUpdate is the update the state file names: its step, the versions it went from and to, and the last failure.

type Layout

type Layout struct {
	Root string
	// Data names the folder that keeps the backups and the state in place of the install root.
	Data string
}

Layout is an install root: one folder per build side by side, and the links naming the current and previous builds.

func (Layout) Backups

func (l Layout) Backups() string

Backups returns the folder that keeps the backups of the database.

func (Layout) Binary

func (l Layout) Binary(name string) string

Binary returns the gophenberg binary of the build called name.

func (Layout) Build

func (l Layout) Build(name string) string

Build returns the folder of the build called name.

func (Layout) Download

func (l Layout) Download(release string) string

Download returns the partial file the archive of release downloads into.

func (Layout) Kept

func (l Layout) Kept() string

Kept returns the folder that keeps the backups and the state, the install root with no data folder.

func (Layout) MakeData

func (l Layout) MakeData() error

MakeData makes a data folder only its owner opens, leaving one that is already there as it stands.

func (Layout) Named

func (l Layout) Named(link string) (string, error)

Named returns the build the link called link names, like 0.20.0 for versions/0.20.0, refusing any other target.

func (Layout) Point

func (l Layout) Point(link, name string) error

Point points the link called link at the build called name, renaming a new link over the old one.

func (Layout) ReadState

func (l Layout) ReadState() (State, error)

ReadState returns the state the state file holds, an empty state before the first update.

func (Layout) StateFile

func (l Layout) StateFile() string

StateFile returns the file that holds the state of the last update.

func (Layout) WriteState

func (l Layout) WriteState(state State) error

WriteState writes state into a new file renamed over the state file, so a sudden stop leaves one or the other.

type Overview

type Overview struct {
	Refused []string    `json:"refused"`
	Job     *LastUpdate `json:"job"`
	Backups BackupCount `json:"backups"`
}

Overview is what the admin shows of an install root: the versions it refuses, its last update and its backups.

func ReadOverview

func ReadOverview(settings Settings) (Overview, error)

ReadOverview returns what the admin shows of the install root the settings name, read as update:status reads it.

type Planned

type Planned struct {
	// contains filtered or unexported fields
}

Planned is a job whose checks before the download passed, holding the update lock until the rest of it ends.

func (*Planned) Apply

func (p *Planned) Apply(ctx context.Context) (State, error)

Apply downloads, stages, backs up and switches, then lets go of the update lock, returning the state the job ends at.

type Reason

type Reason string

Reason names why an install cannot update itself from the admin.

const (
	// NoInstallRoot is an install with no install root, like the Docker image, which only a person updates.
	NoInstallRoot Reason = "no_install_root"
	// CustomBuild is a binary the release workflow did not build, which an official archive would replace.
	CustomBuild Reason = "custom_build"
)

func CannotUpdate

func CannotUpdate(settings Settings, stamp string) Reason

CannotUpdate returns why the install the settings name cannot update itself under stamp, empty when it can.

func ReasonOf

func ReasonOf(err error) Reason

ReasonOf returns why the install cannot update itself when err says so, empty for any other error and for none.

type Settings

type Settings struct {
	Root            string
	Data            string
	DownloadCap     int64
	DownloadTimeout time.Duration
	DiskMargin      int64
	BackupsKept     int
	PgDump          string
	Attempts        int
	VerifyTimeout   time.Duration
	VersionsKept    int
	// contains filtered or unexported fields
}

Settings is how a server install updates itself and checks each update at its first starts, as GOPHENBERG_ names it.

func SettingsFrom

func SettingsFrom(env gonsole.Env) (Settings, error)

SettingsFrom reads the update settings env holds, refusing a relative folder and any value out of range.

func (Settings) Layout

func (s Settings) Layout() Layout

Layout returns the install root and the data folder the settings name.

type State

type State struct {
	Step            Step        `json:"step"`
	From            string      `json:"from"`
	To              string      `json:"to"`
	Attempts        int         `json:"attempts"`
	DatabaseReached bool        `json:"database_reached"`
	LongJump        bool        `json:"long_jump"`
	Backup          string      `json:"backup"`
	Refused         []string    `json:"refused"`
	Failure         *JobFailure `json:"failure,omitempty"`
}

State is what the state file holds: the last update, the versions that failed their start check, the last failure.

func Rollback

func Rollback(settings Settings) (State, error)

Rollback takes back the last update that switched builds, pointing current at the build before it.

func RollbackAfterFailure

func RollbackAfterFailure(settings Settings, failure Failure) (State, error)

RollbackAfterFailure takes back an update whose new build failed to start, once, as the rollback unit runs it.

func (State) WithEmptyLists

func (s State) WithEmptyLists() State

WithEmptyLists returns the state with an empty list of refused versions in place of none, which JSON shows as [].

type Status

type Status struct {
	Root     string   `json:"root"`
	Data     string   `json:"data"`
	Current  string   `json:"current"`
	Previous string   `json:"previous"`
	Update   State    `json:"update"`
	Restore  string   `json:"restore"`
	Backups  []string `json:"backups"`
}

Status is what update:status shows of an install root: the builds its links name, the last update and the backups.

func ReadStatus

func ReadStatus(settings Settings) (Status, error)

ReadStatus returns the status of the install root the settings name, an empty one for an install with no root.

type Step

type Step string

Step names how far an update got, written to the state file before the step runs.

const (
	// StepDownload downloads the archive and checks its checksum and signature.
	StepDownload Step = "download"
	// StepStage unpacks the archive into its build folder and checks the build.
	StepStage Step = "stage"
	// StepBackup backs up the database before the switch.
	StepBackup Step = "backup"
	// StepSwitched points current at the new build, which then waits for a restart and its first start check.
	StepSwitched Step = "switched"
	// StepCommitted keeps an update whose new build passed its start check.
	StepCommitted Step = "committed"
	// StepFailed keeps the site down after a new build that raised the minimum version failed its start check.
	StepFailed Step = "failed"
	// StepRolledBack takes back an update, current naming the build before it again and the version after it refused.
	StepRolledBack Step = "rolled-back"
)

type SwitchedError

type SwitchedError struct {
	Release string
	Err     error
}

SwitchedError reports a job whose switch stands although a step after it failed, so its build waits for a restart.

func (SwitchedError) Error

func (e SwitchedError) Error() string

Error says that current names the release and that Gophenberg must restart to start it, with the failure.

func (SwitchedError) Unwrap

func (e SwitchedError) Unwrap() error

Unwrap returns the failure after the switch.

Jump to

Keyboard shortcuts

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