mirror of
https://github.com/tailscale/tailscale.git
synced 2026-02-09 01:32:09 +01:00
This file was never truly necessary and has never actually been used in the history of Tailscale's open source releases. A Brief History of AUTHORS files --- The AUTHORS file was a pattern developed at Google, originally for Chromium, then adopted by Go and a bunch of other projects. The problem was that Chromium originally had a copyright line only recognizing Google as the copyright holder. Because Google (and most open source projects) do not require copyright assignemnt for contributions, each contributor maintains their copyright. Some large corporate contributors then tried to add their own name to the copyright line in the LICENSE file or in file headers. This quickly becomes unwieldy, and puts a tremendous burden on anyone building on top of Chromium, since the license requires that they keep all copyright lines intact. The compromise was to create an AUTHORS file that would list all of the copyright holders. The LICENSE file and source file headers would then include that list by reference, listing the copyright holder as "The Chromium Authors". This also become cumbersome to simply keep the file up to date with a high rate of new contributors. Plus it's not always obvious who the copyright holder is. Sometimes it is the individual making the contribution, but many times it may be their employer. There is no way for the proejct maintainer to know. Eventually, Google changed their policy to no longer recommend trying to keep the AUTHORS file up to date proactively, and instead to only add to it when requested: https://opensource.google/docs/releasing/authors. They are also clear that: > Adding contributors to the AUTHORS file is entirely within the > project's discretion and has no implications for copyright ownership. It was primarily added to appease a small number of large contributors that insisted that they be recognized as copyright holders (which was entirely their right to do). But it's not truly necessary, and not even the most accurate way of identifying contributors and/or copyright holders. In practice, we've never added anyone to our AUTHORS file. It only lists Tailscale, so it's not really serving any purpose. It also causes confusion because Tailscalars put the "Tailscale Inc & AUTHORS" header in other open source repos which don't actually have an AUTHORS file, so it's ambiguous what that means. Instead, we just acknowledge that the contributors to Tailscale (whoever they are) are copyright holders for their individual contributions. We also have the benefit of using the DCO (developercertificate.org) which provides some additional certification of their right to make the contribution. The source file changes were purely mechanical with: git ls-files | xargs sed -i -e 's/\(Tailscale Inc &\) AUTHORS/\1 contributors/g' Updates #cleanup Change-Id: Ia101a4a3005adb9118051b3416f5a64a4a45987d Signed-off-by: Will Norris <will@tailscale.com>
301 lines
12 KiB
Go
301 lines
12 KiB
Go
// Copyright (c) Tailscale Inc & contributors
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package health
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"time"
|
|
|
|
"tailscale.com/feature/buildfeatures"
|
|
"tailscale.com/tsconst"
|
|
"tailscale.com/version"
|
|
)
|
|
|
|
func condRegister(f func() *Warnable) *Warnable {
|
|
if !buildfeatures.HasHealth {
|
|
return nil
|
|
}
|
|
return f()
|
|
}
|
|
|
|
/**
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableUpdateAvailable,
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableSecurityUpdateAvailable,
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableIsUsingUnstableVersion,
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableNetworkStatus,
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableWantRunningFalse,
|
|
Title: "Tailscale off",
|
|
Severity: SeverityLow,
|
|
Text: StaticMessage("Tailscale is stopped."),
|
|
}
|
|
})
|
|
|
|
// localLogWarnable is a Warnable that warns the user that the local log is misconfigured.
|
|
var localLogWarnable = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableLocalLogConfigError,
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableLoginState,
|
|
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."
|
|
}
|
|
},
|
|
DependsOn: []*Warnable{IPNStateWarnable},
|
|
}
|
|
})
|
|
|
|
// notInMapPollWarnable is a Warnable that warns the user that we are using a stale network map.
|
|
var notInMapPollWarnable = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableNotInMapPoll,
|
|
Title: "Out of sync",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable},
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableNoDERPHome,
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableNoDERPConnection,
|
|
Title: "Relay server unavailable",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{
|
|
NetworkStatusWarnable,
|
|
|
|
// Technically noDERPConnectionWarnable could be used to warn about
|
|
// failure to connect to a specific DERP server (e.g. your home is derp1
|
|
// but you're trying to connect to a peer's derp4 and are unable) but as
|
|
// of 2024-09-25 we only use this for connecting to your home DERP, so
|
|
// we depend on noDERPHomeWarnable which is the ability to figure out
|
|
// what your DERP home even is.
|
|
noDERPHomeWarnable,
|
|
},
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableDERPTimedOut,
|
|
Title: "Relay server timed out",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{
|
|
NetworkStatusWarnable,
|
|
noDERPConnectionWarnable, // don't warn about it being stalled if we're not connected
|
|
noDERPHomeWarnable, // same reason as noDERPConnectionWarnable's dependency
|
|
},
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableDERPRegionError,
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableNoUDP4Bind,
|
|
Title: "NAT traversal setup failure",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable},
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableMapResponseTimeout,
|
|
Title: "Network map response timeout",
|
|
Severity: SeverityMedium,
|
|
DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable},
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableTLSConnectionFailed,
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableMagicsockReceiveFuncError,
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableTestWarnable,
|
|
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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableApplyDiskConfig,
|
|
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])
|
|
},
|
|
}
|
|
})
|
|
|
|
// 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 = condRegister(func() *Warnable {
|
|
return &Warnable{
|
|
Code: tsconst.HealthWarnableWarmingUp,
|
|
Title: "Tailscale is starting",
|
|
Severity: SeverityLow,
|
|
Text: StaticMessage("Tailscale is starting. Please wait."),
|
|
}
|
|
})
|