Documentation
¶
Index ¶
- func InstalledRVersions() []string
- func ResolveRBinary(version, fallback string) (string, bool)
- func RunBwrapExec(args []string) error
- func RunPreflight(cfg *config.ProcessConfig, fullCfg *config.Config, cgroups *cgroupManager) *preflight.Report
- type ProcessBackend
- func (b *ProcessBackend) Addr(_ context.Context, id string) (string, error)
- func (b *ProcessBackend) Build(ctx context.Context, spec backend.BuildSpec) (backend.BuildResult, error)
- func (b *ProcessBackend) CheckRVersion(version string) error
- func (b *ProcessBackend) CleanupOrphanResources(ctx context.Context) error
- func (b *ProcessBackend) HealthCheck(ctx context.Context, id string) bool
- func (b *ProcessBackend) ListManaged(_ context.Context) ([]backend.ManagedResource, error)
- func (b *ProcessBackend) Logs(_ context.Context, id string) (backend.LogStream, error)
- func (b *ProcessBackend) Preflight(_ context.Context) (*preflight.Report, error)
- func (b *ProcessBackend) RemoveResource(_ context.Context, r backend.ManagedResource) error
- func (b *ProcessBackend) Spawn(_ context.Context, spec backend.WorkerSpec) error
- func (b *ProcessBackend) Stop(_ context.Context, id string) error
- func (b *ProcessBackend) UpdateResources(_ context.Context, _ string, _ int64, _ int64) error
- func (b *ProcessBackend) WorkerResourceUsage(_ context.Context, id string) (*backend.WorkerResourceUsageResult, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func InstalledRVersions ¶
func InstalledRVersions() []string
InstalledRVersions returns the R versions installed under rigBase. Each entry is the directory name (e.g. "4.5.0", "4.4.3").
func ResolveRBinary ¶
ResolveRBinary maps a requested R version (e.g. "4.5.0") to the full path of a rig-managed R binary. Resolution order:
- Exact match: /opt/R/<version>/bin/R
- Minor match: highest /opt/R/<major>.<minor>.*/bin/R
- Fallback: the configured default R path
Returns the resolved path and whether the fallback was used. When version is empty the fallback is returned directly (not considered a miss).
func RunBwrapExec ¶ added in v0.0.4
RunBwrapExec is the `blockyard bwrap-exec --uid W --gid G -- <bwrap> <bwrap-args>` subcommand the process backend invokes instead of calling bwrap directly. It drops into the worker's (uid, gid), restores the dumpable flag that the kernel clears on suid transitions, and execs bwrap.
Why this isn't `SysProcAttr.Credential`: Go's fork+exec does setgroups+setgid+setuid but never calls `prctl(PR_SET_DUMPABLE, 1)` afterward. The kernel marks the process non-dumpable after any credential transition (even root→user), and a non-dumpable process sees /proc/self/uid_map as owned by root (not the current ruid). bwrap's unprivileged uid_map write then fails with EPERM — "bwrap: setting up uid map: Permission denied". Restoring dumpable between setuid and exec makes /proc/self/uid_map owned by the worker UID again, so bwrap can write the identity uid_map that makes worker traffic host-identifiable for iptables owner-match rules.
Exported because both cmd/blockyard/main.go and the process package's TestMain dispatch to it: in tests, os.Executable() returns the test binary rather than the blockyard binary, so the test binary must also recognise the "bwrap-exec" first arg and execute the shim itself — otherwise exec.Command(testbin, "bwrap-exec", ...) re-enters the test runner and the whole suite recurses.
Returns an error for any misuse; on success it never returns (execve replaces the process).
func RunPreflight ¶
func RunPreflight(cfg *config.ProcessConfig, fullCfg *config.Config, cgroups *cgroupManager) *preflight.Report
RunPreflight verifies the process backend prerequisites. Called by (*ProcessBackend).Preflight() with the full config so the egress probe can read Redis/vault/database addresses and the resource- limit check can read server-level defaults.
Check ordering matters: bwrap/R/userns are prerequisites for checkBwrapHostUIDMapping (it spawns bwrap), and that check is a prerequisite for checkWorkerEgress (which also spawns bwrap and whose results are meaningful only if the host UID mapping is effective). If a prerequisite fails we still run the later checks — they'll fail too, and emitting all failures at once is more useful than bailing at the first.
cgroups is the optional cgroup-v2 delegation manager; nil is safe and tests pass nil directly. The manager feeds checkCgroupDelegation and the worker-egress probe's cgroup enrollment.
Types ¶
type ProcessBackend ¶
type ProcessBackend struct {
// contains filtered or unexported fields
}
ProcessBackend implements backend.Backend using bubblewrap.
func New ¶
func New(fullCfg *config.Config, rc *redisstate.Client, db *sqlx.DB) (*ProcessBackend, error)
New creates a ProcessBackend. Verifies that bwrap exists at the configured path and that the worker mount point can be reached from inside the bwrap sandbox. The full config is stored so Preflight() can read the addresses of Redis/vault/database for the egress probe and the server-level resource-limit fields for the warning check.
rc and db are the shared connection pools opened by main.go before the backend factory runs. The allocator implementation is picked by config.ResolveSessionStoreMode(cfg) — the same selector that drives session, registry, and worker-map storage — so a deployment that asks for Postgres-primary sessions also gets Postgres-primary allocators. The allocator path is the only place this backend touches rc/db; both can be nil in test/single-process configurations and the memory allocators take over.
func (*ProcessBackend) Build ¶
func (b *ProcessBackend) Build(ctx context.Context, spec backend.BuildSpec) (backend.BuildResult, error)
func (*ProcessBackend) CheckRVersion ¶
func (b *ProcessBackend) CheckRVersion(version string) error
func (*ProcessBackend) CleanupOrphanResources ¶
func (b *ProcessBackend) CleanupOrphanResources(ctx context.Context) error
CleanupOrphanResources implements backend.Backend. Workers from a previous run are already dead (Pdeathsig killed them with the server), so the in-memory variants have nothing to clean up. The Redis variants, however, carry owned claims across server restarts and need a scan-and-delete at startup to return crashed-session ports and UIDs to the pool.
func (*ProcessBackend) HealthCheck ¶
func (b *ProcessBackend) HealthCheck(ctx context.Context, id string) bool
func (*ProcessBackend) ListManaged ¶
func (b *ProcessBackend) ListManaged(_ context.Context) ([]backend.ManagedResource, error)
func (*ProcessBackend) Preflight ¶
Preflight implements backend.Backend by delegating to RunPreflight.
func (*ProcessBackend) RemoveResource ¶
func (b *ProcessBackend) RemoveResource(_ context.Context, r backend.ManagedResource) error
func (*ProcessBackend) Spawn ¶
func (b *ProcessBackend) Spawn(_ context.Context, spec backend.WorkerSpec) error
func (*ProcessBackend) UpdateResources ¶
UpdateResources is not supported by the process backend: we do not enforce per-worker cgroup limits (decision #6), so there is nothing to update. Returning ErrNotSupported lets callers distinguish "cannot do this" from "ran into a real error"; api/apps.go checks for ErrNotSupported and skips its warning log so app-update requests do not spam one noisy warning per worker.
func (*ProcessBackend) WorkerResourceUsage ¶
func (b *ProcessBackend) WorkerResourceUsage(_ context.Context, id string) (*backend.WorkerResourceUsageResult, error)