Documentation
¶
Overview ¶
Package autoupdate decides which devices in the fleet should be rolled forward, and when (Task 20331).
The decision is separated from the doing, and kept free of I/O, because the interesting part of an auto-updater is not the upgrade — pkg/executor/remote and pkg/executor/install already do that — but the restraint. An updater that simply asks every stale device to upgrade the moment it notices is not a feature, it is a scheduled outage: the fleet is what runs the work, and every device is unavailable for the minute it takes to restart.
So Plan enforces four rules, and each of them exists because the naive version of this feature breaks something real:
Never interrupt running work. An upgrade restarts the agent, which kills whatever it is executing. A task that has been running for forty minutes is worth more than being current by an hour.
Never take the whole fleet down at once. Upgrades are rolled out a few devices at a time, so a release that turns out to be bad strands a bounded number of machines — and so the fleet retains capacity to keep scheduling while the rest roll.
Never act on a device the operator has taken out of service by hand. A cordon is a statement that a human is dealing with this machine, and rebooting it underneath them is exactly the wrong response.
Never "upgrade" a device to something that is not an upgrade. Already current, newer than the target, or running an unparseable build: all three are left alone rather than forced, because forcing is how an automatic system turns one bad assumption into a fleet-wide rollback.
Everything here is a pure function of its inputs, so the rules can be tested exhaustively without a device, a network or a clock.
Index ¶
Constants ¶
const DefaultMaxInFlight = 1
DefaultMaxInFlight is how many devices are upgraded at once when a policy does not say.
One. The conservative choice is right for the common fleet, which is small enough that "a few at a time" and "all of them" are the same thing — and an operator with three hundred edge devices who needs this to go faster is in a much better position to choose the number than this default is.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Device ¶
type Device struct {
ID string
Name string
// Version is the build the device reports. Empty or the legacy placeholder
// means it has not told us, which Plan treats as "leave alone".
Version string
// ProtocolVersion is the negotiated session version, used to tell a device
// that can be upgraded remotely from one that must be done by hand.
ProtocolVersion int
// Online is whether there is a live session to send the request on.
Online bool
// Busy is whether the device is running work right now.
Busy bool
// AdminHeld is whether an operator has cordoned or drained it.
AdminHeld bool
// Upgrading is whether this device has already been asked and has not yet
// come back. It is what keeps MaxInFlight meaningful across sweeps.
Upgrading bool
}
Device is what the planner needs to know about one executor. It is a flat snapshot rather than a live handle so that planning cannot race the fleet it is planning over.
type Policy ¶
type Policy struct {
// Enabled turns automatic upgrades on. Off by default, and deliberately:
// a hub that silently reboots edge devices because it was installed with a
// helpful default is a hub nobody trusts with hardware.
Enabled bool `json:"enabled"`
// TargetVersion is the release every device should converge on. Empty
// means the control plane's own build, which is the sane default — the
// hub and its agents are two halves of one protocol, and "match the hub"
// is the invariant an operator actually wants.
//
// A pinned tag is honoured as written, including when it is older than the
// hub: staged rollouts and rollbacks both need the fleet to sit on a
// version the control plane is not running.
TargetVersion string `json:"target_version,omitempty"`
// MaxInFlight bounds concurrent upgrades. Zero uses DefaultMaxInFlight.
MaxInFlight int `json:"max_in_flight,omitempty"`
}
Policy is the operator's standing instruction for the fleet.
type Verdict ¶
type Verdict struct {
Device Device
// Upgrade is whether to send the request now.
Upgrade bool
// Reason explains the decision either way, in the operator's terms. It is
// shown in the UI beside the device, so a fleet that is not converging can
// be understood without reading logs.
Reason string
}
Verdict is what the planner decided about one device.