feat: updates.Apply with security scope, window deadline, busy guard and captured output
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
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,
|
||||
@@ -14,11 +20,49 @@ type PackageUpdate struct {
|
||||
// CheckAvailable lists pending OS updates.
|
||||
func CheckAvailable() ([]PackageUpdate, error) { return checkAvailable() }
|
||||
|
||||
// ApplyAll installs every pending update. It never reboots: a control plane
|
||||
// silently restarting a production server is unrecoverable from the UI, so the
|
||||
// reboot stays a decision a person or a workflow makes. RebootRequired reports
|
||||
// when one is owed.
|
||||
func ApplyAll() error { return applyAll() }
|
||||
// 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 when the upgrade must be finished, normally the end of the
|
||||
// maintenance window. Zero means defaultApplyCap from now.
|
||||
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")
|
||||
|
||||
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()
|
||||
deadline := opts.Deadline
|
||||
if deadline.IsZero() {
|
||||
deadline = time.Now().Add(defaultApplyCap)
|
||||
}
|
||||
return apply(opts.SecurityOnly, 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() }
|
||||
|
||||
Reference in New Issue
Block a user