21277: Keep fleet desktop running when host is offline (#30493)

For #21277 

Show offline message on Fleet Desktop if host is offline.
This commit is contained in:
Juan Fernandez 2025-07-07 10:35:15 -04:00 committed by GitHub
parent c854509821
commit 685d4226c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 48 additions and 14 deletions

View file

@ -0,0 +1 @@
* Added feature for showing an informational message on fleet desktop if host becomes offline.

View file

@ -175,6 +175,14 @@ func main() {
myDeviceItem := systray.AddMenuItem("Connecting...", "")
myDeviceItem.Disable()
myDeviceItem.Hide()
hostOfflineItem := systray.AddMenuItem(
`🛜🚫 Your computer is offline.
It might take up to 5 minutes to reconnect to Fleet.`,
"")
hostOfflineItem.Disable()
selfServiceItem := systray.AddMenuItem("Self-service", "")
selfServiceItem.Disable()
@ -220,12 +228,17 @@ func main() {
disableTray := func() {
log.Debug().Msg("disabling tray items")
myDeviceItem.SetTitle("Connecting...")
myDeviceItem.Show()
myDeviceItem.Disable()
transparencyItem.Disable()
selfServiceItem.Disable()
selfServiceItem.Hide()
migrateMDMItem.Disable()
migrateMDMItem.Hide()
hostOfflineItem.Hide()
}
reportError := func(err error, info map[string]any) {
@ -283,8 +296,13 @@ func main() {
if err == nil || errors.Is(err, service.ErrMissingLicense) {
log.Debug().Msg("enabling tray items")
myDeviceItem.SetTitle("My device")
myDeviceItem.Show()
myDeviceItem.Enable()
transparencyItem.Enable()
transparencyItem.Show()
hostOfflineItem.Hide()
// Hide Self-Service for Free tier
if errors.Is(err, service.ErrMissingLicense) || (summary.SelfService != nil && !*summary.SelfService) {
@ -345,21 +363,28 @@ func main() {
sum, err := client.DesktopSummary(tokenReader.GetCached())
switch {
case err == nil:
// OK
hostOfflineItem.Hide()
case errors.Is(err, service.ErrMissingLicense):
myDeviceItem.SetTitle("My device")
myDeviceItem.Show()
hostOfflineItem.Hide()
continue
case errors.Is(err, service.ErrUnauthenticated):
disableTray()
hostOfflineItem.Hide()
<-checkToken()
continue
default:
myDeviceItem.Hide()
transparencyItem.Disable()
hostOfflineItem.Show()
log.Error().Err(err).Msg("get desktop summary")
continue
}
refreshMenuItems(sum.DesktopSummary, selfServiceItem, myDeviceItem)
myDeviceItem.Enable()
myDeviceItem.Show()
// Check our file to see if we should migrate
var migrationType string

View file

@ -955,6 +955,10 @@ func main() {
return fmt.Errorf("error new orbit client: %w", err)
}
// If the server can't be reached, we want to fail quickly on any blocking network calls
// so that desktop can be launched as soon as possible.
serverIsReachable := orbitClient.Ping() == nil
// create the notifications middleware that wraps the orbit client
// (must be shared by all runners that use a ConfigFetcher).
const (
@ -1043,18 +1047,20 @@ func main() {
orbitClient.RegisterConfigReceiver(extRunner)
}
// Run a early check of fleetd configuration to check if orbit needs to
// restart before proceeding to start the sub-systems.
// Run an early check of fleetd configuration (iff server can be reached)
// to check if orbit needs to restart before proceeding to start the sub-systems.
//
// E.g. the administrator has updated the following agent options for this device:
// - `update_channels`
// - `extensions` were removed/unset
// - `command_line_flags` (osquery startup flags)
if err := orbitClient.RunConfigReceivers(); err != nil {
log.Error().Msgf("failed initial config fetch: %s", err)
} else if orbitClient.RestartTriggered() {
log.Info().Msg("exiting after early config fetch")
return nil
if serverIsReachable {
if err := orbitClient.RunConfigReceivers(); err != nil {
log.Error().Msgf("failed initial config fetch: %s", err)
} else if orbitClient.RestartTriggered() {
log.Info().Msg("exiting after early config fetch")
return nil
}
}
addSubsystem(&g, "config receivers", &wrapSubsystem{
@ -1094,12 +1100,14 @@ func main() {
return fmt.Errorf("initializing client: %w", err)
}
// Check if token is not expired and still good.
// If not, rotate the token.
expired, _ := trw.HasExpired()
if expired || deviceClient.CheckToken(trw.GetCached()) != nil {
if err := trw.Rotate(); err != nil {
return fmt.Errorf("rotating token: %w", err)
// Check if the token is not expired and still good.
// If not, rotate the token iff the server is reachable.
if serverIsReachable {
expired, _ := trw.HasExpired()
if expired || deviceClient.CheckToken(trw.GetCached()) != nil {
if err := trw.Rotate(); err != nil {
return fmt.Errorf("rotating token: %w", err)
}
}
}