apply

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2026 License: BSD-3-Clause Imports: 14 Imported by: 0

Documentation

Overview

Package apply turns a parsed Config into actual host mutations. The System interface abstracts the OS primitives ; per-OS implementations live in apply_<os>.go behind build tags.

All System calls must be idempotent. A first-boot agent is allowed to crash and resume ; on resume, replaying the same Config against the same host must be a no-op rather than an error or a duplicate effect.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Apply

func Apply(cfg config.Config, sys System, log *slog.Logger) error

Apply walks cfg in the documented order and invokes the matching System primitive for each entry. Halts on the first error.

log is non-nil and used for per-step trace ("set hostname", "write_file /etc/doas.conf", "user openbsd created", "runcmd #3 ok").

Types

type System

type System interface {
	// Hostname returns the live hostname (post any previous SetHostname).
	Hostname() (string, error)
	// SetHostname commits the new name to durable config (/etc/hostname,
	// /etc/myname, /etc/rc.conf depending on OS) AND applies it to the
	// running kernel via the native command.
	SetHostname(name string) error

	// UserExists reports whether name appears in the passwd database.
	UserExists(name string) (bool, error)
	// CreateUser provisions a new user with the given primary shell ;
	// the user's primary group is left to OS defaults (per-OS useradd
	// behaviour). Groups in extraGroups are appended (created if
	// missing). passwordHash, when non-empty, becomes the crypt(3)
	// hash ; empty hash locks the password.
	CreateUser(name, shell, passwordHash string, extraGroups []string) error
	// AddUserToGroups appends extraGroups to an EXISTING user's
	// supplementary groups. Used on the reconcile path so re-runs
	// against an already-provisioned host catch up new group adds.
	AddUserToGroups(name string, extraGroups []string) error
	// AddAuthorizedKey appends key to user's ~/.ssh/authorized_keys
	// (creating the directory + file with the right perms+owner).
	// Re-adding an already-present key is a no-op.
	AddAuthorizedKey(user, key string) error

	// WriteFile lands content at path with the given mode + ownership.
	// Existing files are diffed ; only on differing content/mode/owner
	// is the file overwritten (atomic rename via tempfile).
	WriteFile(path, content, mode, owner, group string) error

	// PackageInstall installs every name in pkgs via the OS-native
	// package manager (apt-get on debian-family, dnf on fedora-family,
	// pkg_add on OpenBSD, pkg on FreeBSD, pkgin on NetBSD). Empty list
	// is a no-op (the impl must NOT exec the package manager just to
	// have it churn). Idempotent : re-installing already-present
	// packages is the OS pkg manager's job (apt-get / pkg_add / pkg /
	// pkgin all skip already-installed packages by default).
	PackageInstall(pkgs []string) error

	// RunShell executes cmd via the OS sh, returning stdout/stderr
	// blended on a non-zero exit. The implementation logs the command
	// + outcome at debug level.
	RunShell(cmd string) error
}

System is the OS abstraction the apply layer talks to. Every method is idempotent : SetHostname on a host already named X is a no-op, CreateUser on an existing user only reconciles authorized_keys / shell / group membership, WriteFile compares content + mode + owner and only re-writes on diff.

func NewLinuxSystem

func NewLinuxSystem(log *slog.Logger) System

NewLinuxSystem returns a System wired against the live Linux host.

func NewSystem

func NewSystem(log *slog.Logger) (System, error)

NewSystem returns the System impl for the running OS. The actual implementations live behind build tags in apply_<os>.go ; each defines osNewSystem(*slog.Logger) System and this factory dispatches via runtime.GOOS as a defensive check (the build tag above already guarantees the right impl is linked in).

On unsupported platforms (darwin / windows / illumos / dragonflybsd / solaris), the binary doesn't link factory.go at all — see factory_unsupported.go which surfaces the error path. Tests on those platforms exercise memSystem directly.

Jump to

Keyboard shortcuts

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