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 ¶
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
// 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 ¶
NewLinuxSystem returns a System wired against the live Linux host.
func NewSystem ¶
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.