Files
mrhid6 f552006318
Agent Release / build (push) Successful in 3m36s
Agent Release / msi (push) Successful in 2m30s
feat: flag Ubuntu phased updates and leave them out of pending counts
apt lists phased updates as upgradable, but an upgrade defers them until the
host is selected. A simulated upgrade names them; they are reported with the
phased flag (vantage-shared v0.6.0) and not counted in pending_after.
2026-09-15 14:55:33 +00:00

72 lines
2.6 KiB
Go

package updates
import (
"errors"
"sync"
"time"
)
// PackageUpdate is one pending update. On Linux it is a package with a version
// on each side. On Windows CurrentVersion is empty and NewVersion carries the
// KB article ID: a Windows update is not a version bump of a named package,
// and inventing a current version would put a wrong string in front of an
// operator.
type PackageUpdate struct {
Name string
CurrentVersion string
NewVersion string
Phased bool // Ubuntu phased update this host is not yet selected for
}
// CheckAvailable lists pending OS updates.
func CheckAvailable() ([]PackageUpdate, error) { return checkAvailable() }
// ApplyOptions selects what an Apply run installs and when it must stop.
type ApplyOptions struct {
// SecurityOnly installs security fixes only. A host with no security
// metadata reports Unsupported and installs nothing: it never falls back
// to installing everything.
SecurityOnly bool
// Deadline is the end of the maintenance window. It only gates the start
// of each phase (index refresh, upgrade, Windows install): a phase that
// has not started by then is not started, and one already running is
// allowed to finish, bounded by defaultApplyCap from its own start. Zero
// means a manual run with no window.
Deadline time.Time
}
// Result is what one Apply run did. Output is the tail of the package
// manager's combined output, for the operator to read when something failed.
type Result struct {
Output string
Unsupported bool
Reason string // why Unsupported, in words for the run page
}
// ErrBusy means another Apply is already running on this host.
var ErrBusy = errors.New("an update run is already in progress on this host")
// defaultApplyCap is the backstop for one started upgrade command, counted
// from that command's own start. It exists for a package manager that hangs,
// not to enforce the window.
const defaultApplyCap = 2 * time.Hour
var applyMu sync.Mutex
// Apply installs pending updates. It never reboots: ScheduleReboot is a
// separate decision taken by the caller, and only when the command asked.
func Apply(opts ApplyOptions) (Result, error) {
if !applyMu.TryLock() {
return Result{}, ErrBusy
}
defer applyMu.Unlock()
return apply(opts.SecurityOnly, opts.Deadline)
}
// ScheduleReboot restarts the host after a short grace period, so a result
// sent just before it has time to leave.
func ScheduleReboot() error { return scheduleReboot() }
// RebootRequired reports whether this host is waiting on a restart.
func RebootRequired() bool { return rebootRequired() }