Documentation
¶
Overview ¶
Package core is the privileged half of Zelie. It runs as root, owns containerd, and accepts a small set of typed requests over a Unix socket. Nothing here listens on the network.
Index ¶
- Constants
- func LoadExternal(path string) (*External, []ExternalListener, error)
- type Backup
- type BackupMeta
- type Builder
- type Client
- func (c *Client) AddOldKey(ctx context.Context, recovery string) ([]string, error)
- func (c *Client) AppendUpload(ctx context.Context, id string, offset int64, piece io.Reader) (Upload, error)
- func (c *Client) BackUpVolumes(ctx context.Context, app string, vols []VolumeRef, live bool) (Backup, error)
- func (c *Client) Backups(ctx context.Context, app string) ([]Backup, error)
- func (c *Client) Build(ctx context.Context, app, version string, env, sealedEnv []string, ...) (build.Result, error)
- func (c *Client) CreateBackup(ctx context.Context, app, container, kind string) (Backup, error)
- func (c *Client) CreateVolume(ctx context.Context, name string) error
- func (c *Client) DataExport(ctx context.Context, app, container, engine string, q dataview.Query, ...) error
- func (c *Client) DataKey(ctx context.Context, app, container, key string) (dataview.Value, error)
- func (c *Client) DataKeys(ctx context.Context, app, container, pattern, cursor string) (dataview.KeyPage, error)
- func (c *Client) DataRows(ctx context.Context, app, container, engine string, q dataview.Query) (dataview.Page, error)
- func (c *Client) DataTables(ctx context.Context, app, container, engine string) ([]dataview.Table, error)
- func (c *Client) DownloadBackup(ctx context.Context, app, name string, w io.Writer) error
- func (c *Client) FetchBackup(ctx context.Context, app, name string) error
- func (c *Client) Host(ctx context.Context) (engine.Host, error)
- func (c *Client) ImportUpload(ctx context.Context, id, kind string) (Backup, error)
- func (c *Client) Links(ctx context.Context, app string) ([]engine.Link, error)
- func (c *Client) List(ctx context.Context) ([]engine.Status, error)
- func (c *Client) Logs(ctx context.Context, id string, follow bool, tail int64, w io.Writer) error
- func (c *Client) Offsite(ctx context.Context) (OffsiteInfo, error)
- func (c *Client) OffsiteBackups(ctx context.Context) (OffsiteList, error)
- func (c *Client) Pin(ctx context.Context, image string) (string, error)
- func (c *Client) RecoveryKey(ctx context.Context, host string, w io.Writer) error
- func (c *Client) Remove(ctx context.Context, id string) error
- func (c *Client) RemoveBackup(ctx context.Context, app, name string) error
- func (c *Client) RemoveBuildCache(ctx context.Context, app string) error
- func (c *Client) RemoveExternal(ctx context.Context, app, engine, container string) error
- func (c *Client) RemoveImage(ctx context.Context, name string) error
- func (c *Client) RemoveOffsite(ctx context.Context) error
- func (c *Client) RemoveOffsiteBackup(ctx context.Context, app, name string) error
- func (c *Client) RemoveUpload(ctx context.Context, id string) error
- func (c *Client) RemoveVolume(ctx context.Context, name string) error
- func (c *Client) RestoreBackup(ctx context.Context, app, name, kind, container, volume string) error
- func (c *Client) RestoreVolumes(ctx context.Context, app, name string, vols []VolumeRef, size int64) error
- func (c *Client) Run(ctx context.Context, s engine.Spec) error
- func (c *Client) RunApp(ctx context.Context, s engine.Spec, sealedEnv []string, linked ...LinkedVar) (string, error)
- func (c *Client) SecretKey(ctx context.Context) (secret.PublicKey, error)
- func (c *Client) SetExternal(ctx context.Context, app, engine, container string, port, target int, ...) error
- func (c *Client) SetLinks(ctx context.Context, app string, links []engine.Link) error
- func (c *Client) SetOffsite(ctx context.Context, cfg OffsiteConfig) (OffsiteInfo, error)
- func (c *Client) StartUpload(ctx context.Context, app string, size int64) (Upload, error)
- func (c *Client) Stop(ctx context.Context, id string, graceSeconds int) error
- func (c *Client) SweepImages(ctx context.Context, keep []string) ([]string, error)
- func (c *Client) SyncExternal(ctx context.Context, list []ExternalListener) error
- func (c *Client) Update(ctx context.Context, version string) error
- func (c *Client) UpdateStatus(ctx context.Context) (UpdateStatus, error)
- func (c *Client) Upload(ctx context.Context, id string) (Upload, error)
- func (c *Client) UploadBackup(ctx context.Context, app, name string, meta BackupMeta) error
- func (c *Client) Usage(ctx context.Context, id string) (engine.Usage, error)
- func (c *Client) Version(ctx context.Context) (string, error)
- func (c *Client) VolumeSizes(ctx context.Context) (map[string]int64, error)
- func (c *Client) Wait(ctx context.Context, id string) (int, error)
- type Engine
- type Error
- type External
- type ExternalListener
- type LinkedVar
- type Offsite
- type OffsiteBackup
- type OffsiteConfig
- type OffsiteInfo
- type OffsiteList
- type Server
- type UpdateStatus
- type Updater
- type Upload
- type VolumeRef
Constants ¶
const DefaultSocket = "/run/zelie/core.sock"
DefaultSocket is where the core listens.
const ExternalUser = "zelie_external"
ExternalUser is the database user desktop tools sign in as. It is not the apps' user, so its password can change or go without touching them.
const MaxUploadChunk = 32 << 20
MaxUploadChunk is the most one piece of an upload may carry.
Variables ¶
This section is empty.
Functions ¶
func LoadExternal ¶
func LoadExternal(path string) (*External, []ExternalListener, error)
LoadExternal reads the saved listeners. Start opens them.
Types ¶
type BackupMeta ¶
type BackupMeta struct {
// Engine is the database's; empty for a backup of an app's volumes.
Engine string `json:"engine"`
Volumes []string `json:"volumes,omitempty"`
Size int64 `json:"size,omitempty"`
}
BackupMeta is what a backup holds, sent along with it, encrypted, so another server can tell what to restore it into.
type Builder ¶
type Builder interface {
Build(ctx context.Context, req build.Request, out io.Writer) (build.Result, error)
RemoveCache(app string) error
}
Builder is what the core needs to build images.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client talks to the core over its socket. The panel and the CLI use it.
func (*Client) AddOldKey ¶
AddOldKey adds the keys of another recovery file, and returns the public halves of the new ones.
func (*Client) AppendUpload ¶
func (c *Client) AppendUpload(ctx context.Context, id string, offset int64, piece io.Reader) (Upload, error)
AppendUpload sends one piece of an upload, which starts at offset.
func (*Client) BackUpVolumes ¶
func (c *Client) BackUpVolumes(ctx context.Context, app string, vols []VolumeRef, live bool) (Backup, error)
BackUpVolumes backs up an app's volumes into one archive. Live copies them while the app runs; otherwise the app must be stopped.
func (*Client) Build ¶
func (c *Client) Build(ctx context.Context, app, version string, env, sealedEnv []string, source io.Reader, out io.Writer) (build.Result, error)
Build sends source, a gzipped tar with one top-level directory, to be built for app, with the app's variables: env as NAME=value, sealedEnv sealed for the core. The build's output is written to out as it happens.
func (*Client) CreateBackup ¶
CreateBackup backs up a database from its running container.
func (*Client) CreateVolume ¶
CreateVolume makes an empty volume.
func (*Client) DataExport ¶
func (c *Client) DataExport(ctx context.Context, app, container, engine string, q dataview.Query, w io.Writer) error
DataExport writes every row the query finds to w as CSV.
func (*Client) DataKeys ¶
func (c *Client) DataKeys(ctx context.Context, app, container, pattern, cursor string) (dataview.KeyPage, error)
DataKeys goes one step through a Redis database's keys.
func (*Client) DataRows ¶
func (c *Client) DataRows(ctx context.Context, app, container, engine string, q dataview.Query) (dataview.Page, error)
DataRows reads a page of a table.
func (*Client) DataTables ¶
func (c *Client) DataTables(ctx context.Context, app, container, engine string) ([]dataview.Table, error)
DataTables lists a database's tables and views, with their columns.
func (*Client) DownloadBackup ¶
DownloadBackup copies the encrypted file to w.
func (*Client) FetchBackup ¶
FetchBackup brings a backup back from the destination onto this server.
func (*Client) ImportUpload ¶
ImportUpload makes a backup of a whole upload, as a dump of kind.
func (*Client) Logs ¶
Logs writes a container's output to w. With tail above zero it starts at the first whole line within that many bytes of the end. With follow set it keeps streaming new output until ctx is cancelled.
func (*Client) Offsite ¶
func (c *Client) Offsite(ctx context.Context) (OffsiteInfo, error)
Offsite returns the destination backups are copied to.
func (*Client) OffsiteBackups ¶
func (c *Client) OffsiteBackups(ctx context.Context) (OffsiteList, error)
OffsiteBackups lists the backups in the destination, and what each holds.
func (*Client) RecoveryKey ¶
RecoveryKey returns the recovery file for the backups.
func (*Client) RemoveBackup ¶
func (*Client) RemoveBuildCache ¶
RemoveBuildCache deletes what builds of an app keep between them.
func (*Client) RemoveExternal ¶
RemoveExternal closes a database's loopback port and, if container is running, drops the external user.
func (*Client) RemoveImage ¶
RemoveImage deletes an image Zelie built.
func (*Client) RemoveOffsite ¶
RemoveOffsite forgets the destination; the bucket is left as it is.
func (*Client) RemoveOffsiteBackup ¶
RemoveOffsiteBackup deletes a backup's copy in the destination.
func (*Client) RemoveVolume ¶
RemoveVolume deletes a volume and its files. No container may use it.
func (*Client) RestoreBackup ¶
func (c *Client) RestoreBackup(ctx context.Context, app, name, kind, container, volume string) error
RestoreBackup puts a backup back: into the running container for kinds that load in place, into the stopped database's volume for the others.
func (*Client) RestoreVolumes ¶
func (c *Client) RestoreVolumes(ctx context.Context, app, name string, vols []VolumeRef, size int64) error
RestoreVolumes replaces the files of a stopped app's volumes with a backup's. size is how much the backup's files take, from when it was made.
func (*Client) RunApp ¶
func (c *Client) RunApp(ctx context.Context, s engine.Spec, sealedEnv []string, linked ...LinkedVar) (string, error)
RunApp runs a container of s.App with secret variables sealed for it, and variables made from the secrets of apps it is linked to. It returns the image that runs, pinned by digest (see engine.Pin).
func (*Client) SetExternal ¶
func (c *Client) SetExternal(ctx context.Context, app, engine, container string, port, target int, sealedPassword string) error
SetExternal opens a database's loopback port. With a sealed password it also makes the external user, or gives it the new password.
func (*Client) SetLinks ¶
SetLinks replaces the links of an app: which other apps it may reach, on which port, and by what name.
func (*Client) SetOffsite ¶
func (c *Client) SetOffsite(ctx context.Context, cfg OffsiteConfig) (OffsiteInfo, error)
SetOffsite checks a destination and saves it.
func (*Client) StartUpload ¶
StartUpload makes room for a file of size bytes for app.
func (*Client) SweepImages ¶
SweepImages tells the core which images are still needed. It deletes those that have not been for a week and returns their names.
func (*Client) SyncExternal ¶
func (c *Client) SyncExternal(ctx context.Context, list []ExternalListener) error
SyncExternal makes the core's loopback ports exactly these.
func (*Client) Update ¶ added in v0.2.0
Update starts an update to version. It returns once the release is downloaded and checked; the services restart after.
func (*Client) UpdateStatus ¶ added in v0.2.0
func (c *Client) UpdateStatus(ctx context.Context) (UpdateStatus, error)
func (*Client) UploadBackup ¶
UploadBackup copies a backup to the destination, with what it holds.
func (*Client) VolumeSizes ¶
VolumeSizes returns the disk each volume takes, by name.
type Engine ¶
type Engine interface {
Run(ctx context.Context, s engine.Spec) error
Stop(ctx context.Context, id string, grace time.Duration) error
Remove(ctx context.Context, id string) error
List(ctx context.Context) ([]engine.Status, error)
RemoveImage(ctx context.Context, name string) error
Images(ctx context.Context) ([]engine.Image, error)
SetUnused(ctx context.Context, name string, since time.Time) error
Pin(ctx context.Context, ref string) (string, error)
Wait(ctx context.Context, id string) (uint32, error)
Usage(id string) (engine.Usage, error)
CreateVolume(name string) error
RemoveVolume(ctx context.Context, name string) error
VolumeSizes() (map[string]int64, error)
Links(app string) ([]engine.Link, error)
SetLinks(ctx context.Context, app string, links []engine.Link) error
Exec(ctx context.Context, id string, args []string, stdin io.Reader, stdout, stderr io.Writer) (uint32, error)
OpenVolume(ctx context.Context, name string) (*os.Root, error)
ReadVolume(name string) (*os.Root, error)
VolumeSize(name string) (int64, error)
}
Engine is what the core needs from the container engine.
type Error ¶
type Error struct {
Status int
Message string
// Code and Params are set for a message meant for the user.
Code string
Params map[string]any
}
Error is a failure reported by the core.
type External ¶
type External struct {
// contains filtered or unexported fields
}
External keeps the loopback listeners, and saves them so they come back when the core restarts.
func (*External) Set ¶
func (x *External) Set(l ExternalListener) error
Set opens or moves an app's listener.
func (*External) Start ¶
func (x *External) Start(list []ExternalListener)
Start opens the saved listeners. One that cannot open is logged and left for the panel to set again.
func (*External) Sync ¶
func (x *External) Sync(list []ExternalListener) error
Sync makes the listeners exactly list, which the panel sends when it starts.
type ExternalListener ¶
type ExternalListener struct {
App string `json:"app"`
Port int `json:"port"` // on 127.0.0.1
Target int `json:"target"` // the database's port in its container
}
ExternalListener is one loopback port and where it leads.
type LinkedVar ¶
type LinkedVar struct {
Name string
// Template is the value, with {secret} where the secret goes.
Template string
// From is the app the secret belongs to, and Sealed the secret, sealed
// for it.
From, Sealed string
}
LinkedVar is a variable made from a secret of another app, such as a database URL with the database's password in it.
type Offsite ¶
type Offsite struct {
// contains filtered or unexported fields
}
Offsite holds the destination. Its keys stay in a file only root reads: the panel can set them but never read them back, so a panel taken over cannot hand them out. Pointing the backups at another bucket gains it nothing either, since they are encrypted.
func LoadOffsite ¶
LoadOffsite reads the destination saved at path, if there is one.
type OffsiteBackup ¶
type OffsiteBackup struct {
App string `json:"app"`
Name string `json:"name"`
Bytes int64 `json:"bytes"`
Created time.Time `json:"created"`
// Meta is what the backup holds, when it was asked for and could be
// read. Locked is set when it is there but no key here opens it.
Meta *BackupMeta `json:"meta,omitempty"`
Locked bool `json:"locked,omitempty"`
}
OffsiteBackup is a backup file found in the bucket.
type OffsiteConfig ¶
type OffsiteConfig struct {
Endpoint string `json:"endpoint"`
Region string `json:"region"`
Bucket string `json:"bucket"`
Prefix string `json:"prefix"`
AccessKey string `json:"access_key"`
// SecretKey may be left out when changing the folder or the region;
// the one already saved is kept.
SecretKey string `json:"secret_key,omitempty"`
}
OffsiteConfig is where backups are copied off this server: a folder in an S3 bucket, and the keys to it.
type OffsiteInfo ¶
type OffsiteInfo struct {
Set bool `json:"set"`
Endpoint string `json:"endpoint,omitempty"`
Region string `json:"region,omitempty"`
Bucket string `json:"bucket,omitempty"`
Prefix string `json:"prefix,omitempty"`
AccessKey string `json:"access_key,omitempty"`
}
OffsiteInfo is the destination as the panel may see it: everything but the secret key.
type OffsiteList ¶
type OffsiteList struct {
// Key is the public key the folder's backups were encrypted for, from
// the note beside them, and Opens whether a key here opens them.
Key string `json:"key,omitempty"`
Opens bool `json:"opens"`
Backups []OffsiteBackup `json:"backups"`
}
OffsiteList is what the destination's folder holds.
type Server ¶
type Server struct {
Engine Engine
Builder Builder
Secrets *secret.Keys
Backups *backup.Dir
Offsite *Offsite
// External holds the loopback ports of databases open to desktop tools.
External *External
// Updater updates Zelie itself; nil where it cannot.
Updater *Updater
Paths engine.Paths
Log *slog.Logger
Allowed peer.Policy
// Host describes the server; tests replace it.
Host func() (engine.Host, error)
// contains filtered or unexported fields
}
func (*Server) StartExternal ¶
func (s *Server) StartExternal(list []ExternalListener)
StartExternal opens the saved listeners once the server can find containers.
type UpdateStatus ¶ added in v0.2.0
type UpdateStatus struct {
Version string `json:"version"`
Last *update.Result `json:"last,omitempty"`
}
UpdateStatus is the running version and how the last update went.
type Updater ¶ added in v0.2.0
type Updater struct {
// Fetch downloads a release's binary and checks its signature.
Fetch func(ctx context.Context, version string) ([]byte, error)
// Place puts it where the services run from, keeping the old one.
Place func(bin []byte) error
// Start runs the unit that restarts the services and checks them.
Start func(ctx context.Context, from, to string) error
// Running reports whether that unit runs now.
Running func(ctx context.Context) bool
// Last is the outcome of the last update.
Last func() (update.Result, error)
// Installed reports whether the services run from the installed binary.
Installed func() bool
}
Updater does the parts of an update that touch the machine. Tests replace it.