Documentation
¶
Overview ¶
Package installstate owns the agent's installation ownership record and the lock that guards it. The record is internal bookkeeping, not a configuration input.
It answers three questions nothing else on the host can answer:
- Is there an installation here, and is it the one we are being asked to perform? The record carries the machine name and a fingerprint of the identity-defining configuration, so a retry can tell its own interrupted attempt from a different installation. Without it, bootstrap can only demand a pristine host and abort otherwise.
- How far did the last attempt get? It does not say, deliberately. Every stage reapplies on every attempt and decides from the host what it still has to do, so there is nothing here that could disagree with the host. The phase records only whether an installation is under way, finished, or being torn down, which is a thing the host cannot be asked.
- Is anything else mutating this host? The lock serializes bootstrap, reset, repave, NodeReboot, host agent activation and AgentUpgrade, which all touch the same files and services.
It is separate from the bootstrap coordinator because the daemon's repave, NodeReboot, AgentUpgrade and AgentReset paths, reset, and host agent activation all need the record or the lock without running a bootstrap.
Index ¶
Constants ¶
const (
DefaultDirectory = "/var/lib/unbounded/agent"
)
Variables ¶
var ErrInstallationInProgress = errors.New("installation has not finished")
ErrInstallationInProgress reports that an installation owns this host and has not finished. It is distinct from ErrLockHeld, which says another process is working right now: this one says the host is mid-installation whether or not anyone is currently acting on it.
Callers that run because systemd started them, rather than because a person asked, must not treat this as a failure. An installation in progress is an ordinary state, and reporting it as a crash is how a service ends up being restarted, rate-limited, and recovered for a problem it does not have.
var ErrLockHeld = errors.New("another host lifecycle operation holds the installation lock")
var ErrNotFound = errors.New("installation record not found")
Functions ¶
func Admit ¶
func Admit(store *Store, machine, fingerprint string) (Record, Disposition, error)
Admit reads ownership and classifies a bootstrap attempt. Callers that mutate the host must hold the installation lock around this call.
func Fingerprint ¶
Fingerprint hashes canonical JSON supplied before ephemeral credentials are resolved.
The caller decides what canonical means, and the hash is over exactly the bytes it is given. A release that adds a field to the fingerprinted struct changes the hash of every host that did not have it, and each of those reads as a different installation demanding an explicit reset. An optional field therefore has to carry omitempty and be absent at its default, so records written before it existed keep hashing the same way.
TestBootstrapV1CompatibilityFixtures enforces this: its fixtures carry a literal fingerprint, so any change to what is hashed fails there rather than on upgraded hosts.
Types ¶
type Phase ¶
type Phase string
Phase is what an installation is currently doing, not how far it has got.
It deliberately records no progress. A record that claimed a stage was finished would be a statement about the host that could stop being true without anyone noticing, and a retry that trusted it would skip work the host no longer has. The stages instead decide what to do by looking at the host, so the only thing worth persisting is which mode we are in.
const ( // Installing means an installation is under way. It says nothing about what // has been done, so there is nothing in it that can go stale. Installing Phase = "installing" // Complete means the installation finished. A later start verifies and // repairs from the applied config rather than reapplying bootstrap inputs, // which after an ordinary repave describe a retired slot. Complete Phase = "complete" // Resetting means a teardown started and may not have finished. This is the // one thing the host cannot be asked: a half-removed installation and a // half-built one look the same, because direction of travel is not visible. Resetting Phase = "resetting" )
type Record ¶
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
func DefaultStore ¶
func DefaultStore() *Store
func (*Store) AcquireLock ¶
func (*Store) AcquireMutationLock ¶
AcquireMutationLock serializes ordinary lifecycle work with bootstrap and reset. Legacy hosts without a record remain supported. When both locks are needed, acquire installation ownership before the binary activation lock.
func (*Store) MarkComplete ¶
MarkComplete commits completion. The durable record is the only completion signal; no separate marker file is maintained.
func (*Store) Remove ¶
Remove is called only after teardown's filesystem barriers succeed.
Dropping ownership is itself a durable step. If the unlink cannot be flushed, the record is put back, because a reset that reports failure must leave the host visibly owned. Otherwise the removal survives in page cache only, the error sends the operator away, and the next start is admitted as a fresh install onto a half-torn-down host.