mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-11-04 10:11:18 +01:00 
			
		
		
		
	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."),
 | 
						|
})
 |