mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 13:05:46 +00:00
b7c3cfe049
Updates tailscale/tailscale#4136 To reduce the likelihood of presenting spurious warnings, add the ability to delay the visibility of certain Warnables, based on a TimeToVisible time.Duration field on each Warnable. The default is zero, meaning that a Warnable is immediately visible to the user when it enters an unhealthy state. Signed-off-by: Andrea Gottardo <andrea@gottardo.me>
248 lines
11 KiB
Go
248 lines
11 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package health
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"time"
|
|
|
|
"tailscale.com/version"
|
|
)
|
|
|
|
/**
|
|
This file contains definitions for the Warnables maintained within this `health` package.
|
|
*/
|
|
|
|
// updateAvailableWarnable is a Warnable that warns the user that an update is available.
|
|
var updateAvailableWarnable = Register(&Warnable{
|
|
Code: "update-available",
|
|
Title: "Update available",
|
|
Severity: SeverityLow,
|
|
Text: func(args Args) string {
|
|
if version.IsMacAppStore() || version.IsAppleTV() || version.IsMacSys() || version.IsWindowsGUI() || runtime.GOOS == "android" {
|
|
return fmt.Sprintf("An update from version %s to %s is available.", args[ArgCurrentVersion], args[ArgAvailableVersion])
|
|
} else {
|
|
return fmt.Sprintf("An update from version %s to %s is available. Run `tailscale update` or `tailscale set --auto-update` to update now.", args[ArgCurrentVersion], args[ArgAvailableVersion])
|
|
}
|
|
},
|
|
})
|
|
|
|
// securityUpdateAvailableWarnable is a Warnable that warns the user that an important security update is available.
|
|
var securityUpdateAvailableWarnable = Register(&Warnable{
|
|
Code: "security-update-available",
|
|
Title: "Security update available",
|
|
Severity: SeverityMedium,
|
|
Text: func(args Args) string {
|
|
if version.IsMacAppStore() || version.IsAppleTV() || version.IsMacSys() || version.IsWindowsGUI() || runtime.GOOS == "android" {
|
|
return fmt.Sprintf("A security update from version %s to %s is available.", args[ArgCurrentVersion], args[ArgAvailableVersion])
|
|
} else {
|
|
return fmt.Sprintf("A security update from version %s to %s is available. Run `tailscale update` or `tailscale set --auto-update` to update now.", args[ArgCurrentVersion], args[ArgAvailableVersion])
|
|
}
|
|
},
|
|
})
|
|
|
|
// unstableWarnable is a Warnable that warns the user that they are using an unstable version of Tailscale
|
|
// so they won't be surprised by all the issues that may arise.
|
|
var unstableWarnable = Register(&Warnable{
|
|
Code: "is-using-unstable-version",
|
|
Title: "Using an unstable version",
|
|
Severity: SeverityLow,
|
|
Text: StaticMessage("This is an unstable version of Tailscale meant for testing and development purposes. Please report any issues to Tailscale."),
|
|
})
|
|
|
|
// NetworkStatusWarnable is a Warnable that warns the user that the network is down.
|
|
var NetworkStatusWarnable = Register(&Warnable{
|
|
Code: "network-status",
|
|
Title: "Network down",
|
|
Severity: SeverityMedium,
|
|
Text: StaticMessage("Tailscale cannot connect because the network is down. Check your Internet connection."),
|
|
ImpactsConnectivity: true,
|
|
TimeToVisible: 5 * time.Second,
|
|
})
|
|
|
|
// IPNStateWarnable is a Warnable that warns the user that Tailscale is stopped.
|
|
var IPNStateWarnable = Register(&Warnable{
|
|
Code: "wantrunning-false",
|
|
Title: "Not connected to Tailscale",
|
|
Severity: SeverityLow,
|
|
Text: StaticMessage("Tailscale is stopped."),
|
|
})
|
|
|
|
// localLogWarnable is a Warnable that warns the user that the local log is misconfigured.
|
|
var localLogWarnable = Register(&Warnable{
|
|
Code: "local-log-config-error",
|
|
Title: "Local log misconfiguration",
|
|
Severity: SeverityLow,
|
|
Text: func(args Args) string {
|
|
return fmt.Sprintf("The local log is misconfigured: %v", args[ArgError])
|
|
},
|
|
})
|
|
|
|
// LoginStateWarnable is a Warnable that warns the user that they are logged out,
|
|
// and provides the last login error if available.
|
|
var LoginStateWarnable = Register(&Warnable{
|
|
Code: "login-state",
|
|
Title: "Logged out",
|
|
Severity: SeverityMedium,
|
|
Text: func(args Args) string {
|
|
if args[ArgError] != "" {
|
|
return fmt.Sprintf("You are logged out. The last login error was: %v", args[ArgError])
|
|
} else {
|
|
return "You are logged out."
|
|
}
|
|
},
|
|
})
|
|
|
|
// notInMapPollWarnable is a Warnable that warns the user that we are using a stale network map.
|
|
var notInMapPollWarnable = Register(&Warnable{
|
|
Code: "not-in-map-poll",
|
|
Title: "Out of sync",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable},
|
|
Text: StaticMessage("Unable to connect to the Tailscale coordination server to synchronize the state of your tailnet. Peer reachability might degrade over time."),
|
|
// 8 minutes reflects a maximum maintenance window for the coordination server.
|
|
TimeToVisible: 8 * time.Minute,
|
|
})
|
|
|
|
// noDERPHomeWarnable is a Warnable that warns the user that Tailscale doesn't have a home DERP.
|
|
var noDERPHomeWarnable = Register(&Warnable{
|
|
Code: "no-derp-home",
|
|
Title: "No home relay server",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable},
|
|
Text: StaticMessage("Tailscale could not connect to any relay server. Check your Internet connection."),
|
|
ImpactsConnectivity: true,
|
|
TimeToVisible: 10 * time.Second,
|
|
})
|
|
|
|
// noDERPConnectionWarnable is a Warnable that warns the user that Tailscale couldn't connect to a specific DERP server.
|
|
var noDERPConnectionWarnable = Register(&Warnable{
|
|
Code: "no-derp-connection",
|
|
Title: "Relay server unavailable",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable},
|
|
Text: func(args Args) string {
|
|
if n := args[ArgDERPRegionName]; n != "" {
|
|
return fmt.Sprintf("Tailscale could not connect to the '%s' relay server. Your Internet connection might be down, or the server might be temporarily unavailable.", n)
|
|
} else {
|
|
return fmt.Sprintf("Tailscale could not connect to the relay server with ID '%s'. Your Internet connection might be down, or the server might be temporarily unavailable.", args[ArgDERPRegionID])
|
|
}
|
|
},
|
|
ImpactsConnectivity: true,
|
|
TimeToVisible: 10 * time.Second,
|
|
})
|
|
|
|
// derpTimeoutWarnable is a Warnable that warns the user that Tailscale hasn't heard from the home DERP region for a while.
|
|
var derpTimeoutWarnable = Register(&Warnable{
|
|
Code: "derp-timed-out",
|
|
Title: "Relay server timed out",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable},
|
|
Text: func(args Args) string {
|
|
if n := args[ArgDERPRegionName]; n != "" {
|
|
return fmt.Sprintf("Tailscale hasn't heard from the '%s' relay server in %v. The server might be temporarily unavailable, or your Internet connection might be down.", n, args[ArgDuration])
|
|
} else {
|
|
return fmt.Sprintf("Tailscale hasn't heard from the home relay server (region ID '%v') in %v. The server might be temporarily unavailable, or your Internet connection might be down.", args[ArgDERPRegionID], args[ArgDuration])
|
|
}
|
|
},
|
|
})
|
|
|
|
// derpRegionErrorWarnable is a Warnable that warns the user that a DERP region is reporting an issue.
|
|
var derpRegionErrorWarnable = Register(&Warnable{
|
|
Code: "derp-region-error",
|
|
Title: "Relay server error",
|
|
Severity: SeverityLow,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable},
|
|
Text: func(args Args) string {
|
|
return fmt.Sprintf("The relay server #%v is reporting an issue: %v", args[ArgDERPRegionID], args[ArgError])
|
|
},
|
|
})
|
|
|
|
// noUDP4BindWarnable is a Warnable that warns the user that Tailscale couldn't listen for incoming UDP connections.
|
|
var noUDP4BindWarnable = Register(&Warnable{
|
|
Code: "no-udp4-bind",
|
|
Title: "Incoming connections may fail",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable},
|
|
Text: StaticMessage("Tailscale couldn't listen for incoming UDP connections."),
|
|
ImpactsConnectivity: true,
|
|
})
|
|
|
|
// mapResponseTimeoutWarnable is a Warnable that warns the user that Tailscale hasn't received a network map from the coordination server in a while.
|
|
var mapResponseTimeoutWarnable = Register(&Warnable{
|
|
Code: "mapresponse-timeout",
|
|
Title: "Network map response timeout",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable},
|
|
Text: func(args Args) string {
|
|
return fmt.Sprintf("Tailscale hasn't received a network map from the coordination server in %s.", args[ArgDuration])
|
|
},
|
|
})
|
|
|
|
// tlsConnectionFailedWarnable is a Warnable that warns the user that Tailscale could not establish an encrypted connection with a server.
|
|
var tlsConnectionFailedWarnable = Register(&Warnable{
|
|
Code: "tls-connection-failed",
|
|
Title: "Encrypted connection failed",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable},
|
|
Text: func(args Args) string {
|
|
return fmt.Sprintf("Tailscale could not establish an encrypted connection with '%q': %v", args[ArgServerName], args[ArgError])
|
|
},
|
|
})
|
|
|
|
// magicsockReceiveFuncWarnable is a Warnable that warns the user that one of the Magicsock functions is not running.
|
|
var magicsockReceiveFuncWarnable = Register(&Warnable{
|
|
Code: "magicsock-receive-func-error",
|
|
Title: "MagicSock function not running",
|
|
Severity: SeverityMedium,
|
|
Text: func(args Args) string {
|
|
return fmt.Sprintf("The MagicSock function %s is not running. You might experience connectivity issues.", args[ArgMagicsockFunctionName])
|
|
},
|
|
})
|
|
|
|
// testWarnable is a Warnable that is used within this package for testing purposes only.
|
|
var testWarnable = Register(&Warnable{
|
|
Code: "test-warnable",
|
|
Title: "Test warnable",
|
|
Severity: SeverityLow,
|
|
Text: func(args Args) string {
|
|
return args[ArgError]
|
|
},
|
|
})
|
|
|
|
// applyDiskConfigWarnable is a Warnable that warns the user that there was an error applying the envknob config stored on disk.
|
|
var applyDiskConfigWarnable = Register(&Warnable{
|
|
Code: "apply-disk-config",
|
|
Title: "Could not apply configuration",
|
|
Severity: SeverityMedium,
|
|
Text: func(args Args) string {
|
|
return fmt.Sprintf("An error occurred applying the Tailscale envknob configuration stored on disk: %v", args[ArgError])
|
|
},
|
|
})
|
|
|
|
// controlHealthWarnable is a Warnable that warns the user that the coordination server is reporting an health issue.
|
|
var controlHealthWarnable = Register(&Warnable{
|
|
Code: "control-health",
|
|
Title: "Coordination server reports an issue",
|
|
Severity: SeverityMedium,
|
|
Text: func(args Args) string {
|
|
return fmt.Sprintf("The coordination server is reporting an health issue: %v", args[ArgError])
|
|
},
|
|
})
|
|
|
|
// warmingUpWarnableDuration is the duration for which the warmingUpWarnable is reported by the backend after the user
|
|
// has changed ipnWantRunning to true from false.
|
|
const warmingUpWarnableDuration = 5 * time.Second
|
|
|
|
// warmingUpWarnable is a Warnable that is reported by the backend when it is starting up, for a maximum time of
|
|
// warmingUpWarnableDuration. The GUIs use the presence of this Warnable to prevent showing any other warnings until
|
|
// the backend is fully started.
|
|
var warmingUpWarnable = Register(&Warnable{
|
|
Code: "warming-up",
|
|
Title: "Tailscale is starting",
|
|
Severity: SeverityLow,
|
|
Text: StaticMessage("Tailscale is starting. Please wait."),
|
|
})
|