Browse Source

health: compare warnable codes to avoid errors on release branch (#17637)

This compares the warnings we actually care about and skips the unstable
warnings and the changes with no warnings.

Fixes #17635

Signed-off-by: Claus Lensbøl <[email protected]>
Claus Lensbøl 4 months ago
parent
commit
7418583e47
5 changed files with 77 additions and 27 deletions
  1. 1 1
      cmd/derper/depaware.txt
  2. 1 1
      cmd/tailscaled/depaware-min.txt
  3. 29 6
      health/health_test.go
  4. 20 19
      health/warnings.go
  5. 26 0
      tsconst/health.go

+ 1 - 1
cmd/derper/depaware.txt

@@ -116,7 +116,7 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
         tailscale.com/syncs                                          from tailscale.com/cmd/derper+
         tailscale.com/tailcfg                                        from tailscale.com/client/local+
         tailscale.com/tka                                            from tailscale.com/client/local+
-  LW    tailscale.com/tsconst                                        from tailscale.com/net/netmon+
+        tailscale.com/tsconst                                        from tailscale.com/net/netmon+
         tailscale.com/tstime                                         from tailscale.com/derp+
         tailscale.com/tstime/mono                                    from tailscale.com/tstime/rate
         tailscale.com/tstime/rate                                    from tailscale.com/derp/derpserver

+ 1 - 1
cmd/tailscaled/depaware-min.txt

@@ -116,7 +116,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
         tailscale.com/tailcfg                                        from tailscale.com/client/tailscale/apitype+
         tailscale.com/tempfork/heap                                  from tailscale.com/wgengine/magicsock
         tailscale.com/tka                                            from tailscale.com/control/controlclient+
-        tailscale.com/tsconst                                        from tailscale.com/net/netns
+        tailscale.com/tsconst                                        from tailscale.com/net/netns+
         tailscale.com/tsd                                            from tailscale.com/cmd/tailscaled+
         tailscale.com/tstime                                         from tailscale.com/control/controlclient+
         tailscale.com/tstime/mono                                    from tailscale.com/net/tstun+

+ 29 - 6
health/health_test.go

@@ -19,6 +19,7 @@ import (
 	"github.com/google/go-cmp/cmp/cmpopts"
 	"tailscale.com/metrics"
 	"tailscale.com/tailcfg"
+	"tailscale.com/tsconst"
 	"tailscale.com/tstest"
 	"tailscale.com/tstime"
 	"tailscale.com/types/opt"
@@ -739,21 +740,27 @@ func TestControlHealthNotifies(t *testing.T) {
 				ht.SetIPNState("NeedsLogin", true)
 				ht.GotStreamedMapResponse()
 
-				// Expect events at starup, before doing anything else
+				// Expect events at starup, before doing anything else, skip unstable
+				// event and no warning event as they show up at different times.
 				synctest.Wait()
-				if err := eventbustest.ExpectExactly(tw,
-					eventbustest.Type[Change](), // warming-up
-					eventbustest.Type[Change](), // is-using-unstable-version
-					eventbustest.Type[Change](), // not-in-map-poll
+				if err := eventbustest.Expect(tw,
+					CompareWarnableCode(t, tsconst.HealthWarnableWarmingUp),
+					CompareWarnableCode(t, tsconst.HealthWarnableNotInMapPoll),
+					CompareWarnableCode(t, tsconst.HealthWarnableWarmingUp),
 				); err != nil {
 					t.Errorf("startup error: %v", err)
 				}
 
 				// Only set initial state if we need to
 				if len(test.initialState) != 0 {
+					t.Log("Setting initial state")
 					ht.SetControlHealth(test.initialState)
 					synctest.Wait()
-					if err := eventbustest.ExpectExactly(tw, eventbustest.Type[Change]()); err != nil {
+					if err := eventbustest.Expect(tw,
+						CompareWarnableCode(t, tsconst.HealthWarnableMagicsockReceiveFuncError),
+						// Skip event with no warnable
+						CompareWarnableCode(t, tsconst.HealthWarnableNoDERPHome),
+					); err != nil {
 						t.Errorf("initial state error: %v", err)
 					}
 				}
@@ -771,6 +778,22 @@ func TestControlHealthNotifies(t *testing.T) {
 	}
 }
 
+func CompareWarnableCode(t *testing.T, code string) func(Change) bool {
+	t.Helper()
+	return func(c Change) bool {
+		t.Helper()
+		if c.Warnable != nil {
+			t.Logf("Warnable code: %s", c.Warnable.Code)
+			if string(c.Warnable.Code) == code {
+				return true
+			}
+		} else {
+			t.Log("No Warnable")
+		}
+		return false
+	}
+}
+
 func TestControlHealthIgnoredOutsideMapPoll(t *testing.T) {
 	synctest.Test(t, func(t *testing.T) {
 		bus := eventbustest.NewBus(t)

+ 20 - 19
health/warnings.go

@@ -9,6 +9,7 @@ import (
 	"time"
 
 	"tailscale.com/feature/buildfeatures"
+	"tailscale.com/tsconst"
 	"tailscale.com/version"
 )
 
@@ -26,7 +27,7 @@ This file contains definitions for the Warnables maintained within this `health`
 // updateAvailableWarnable is a Warnable that warns the user that an update is available.
 var updateAvailableWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:     "update-available",
+		Code:     tsconst.HealthWarnableUpdateAvailable,
 		Title:    "Update available",
 		Severity: SeverityLow,
 		Text: func(args Args) string {
@@ -42,7 +43,7 @@ var updateAvailableWarnable = condRegister(func() *Warnable {
 // securityUpdateAvailableWarnable is a Warnable that warns the user that an important security update is available.
 var securityUpdateAvailableWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:     "security-update-available",
+		Code:     tsconst.HealthWarnableSecurityUpdateAvailable,
 		Title:    "Security update available",
 		Severity: SeverityMedium,
 		Text: func(args Args) string {
@@ -59,7 +60,7 @@ var securityUpdateAvailableWarnable = condRegister(func() *Warnable {
 // so they won't be surprised by all the issues that may arise.
 var unstableWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:     "is-using-unstable-version",
+		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."),
@@ -69,7 +70,7 @@ var unstableWarnable = condRegister(func() *Warnable {
 // NetworkStatusWarnable is a Warnable that warns the user that the network is down.
 var NetworkStatusWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:                "network-status",
+		Code:                tsconst.HealthWarnableNetworkStatus,
 		Title:               "Network down",
 		Severity:            SeverityMedium,
 		Text:                StaticMessage("Tailscale cannot connect because the network is down. Check your Internet connection."),
@@ -81,7 +82,7 @@ var NetworkStatusWarnable = condRegister(func() *Warnable {
 // IPNStateWarnable is a Warnable that warns the user that Tailscale is stopped.
 var IPNStateWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:     "wantrunning-false",
+		Code:     tsconst.HealthWarnableWantRunningFalse,
 		Title:    "Tailscale off",
 		Severity: SeverityLow,
 		Text:     StaticMessage("Tailscale is stopped."),
@@ -91,7 +92,7 @@ var IPNStateWarnable = condRegister(func() *Warnable {
 // localLogWarnable is a Warnable that warns the user that the local log is misconfigured.
 var localLogWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:     "local-log-config-error",
+		Code:     tsconst.HealthWarnableLocalLogConfigError,
 		Title:    "Local log misconfiguration",
 		Severity: SeverityLow,
 		Text: func(args Args) string {
@@ -104,7 +105,7 @@ var localLogWarnable = condRegister(func() *Warnable {
 // and provides the last login error if available.
 var LoginStateWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:     "login-state",
+		Code:     tsconst.HealthWarnableLoginState,
 		Title:    "Logged out",
 		Severity: SeverityMedium,
 		Text: func(args Args) string {
@@ -121,7 +122,7 @@ var LoginStateWarnable = condRegister(func() *Warnable {
 // notInMapPollWarnable is a Warnable that warns the user that we are using a stale network map.
 var notInMapPollWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:      "not-in-map-poll",
+		Code:      tsconst.HealthWarnableNotInMapPoll,
 		Title:     "Out of sync",
 		Severity:  SeverityMedium,
 		DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable},
@@ -134,7 +135,7 @@ var notInMapPollWarnable = condRegister(func() *Warnable {
 // noDERPHomeWarnable is a Warnable that warns the user that Tailscale doesn't have a home DERP.
 var noDERPHomeWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:                "no-derp-home",
+		Code:                tsconst.HealthWarnableNoDERPHome,
 		Title:               "No home relay server",
 		Severity:            SeverityMedium,
 		DependsOn:           []*Warnable{NetworkStatusWarnable},
@@ -147,7 +148,7 @@ var noDERPHomeWarnable = condRegister(func() *Warnable {
 // 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:     "no-derp-connection",
+		Code:     tsconst.HealthWarnableNoDERPConnection,
 		Title:    "Relay server unavailable",
 		Severity: SeverityMedium,
 		DependsOn: []*Warnable{
@@ -177,7 +178,7 @@ var noDERPConnectionWarnable = condRegister(func() *Warnable {
 // heard from the home DERP region for a while.
 var derpTimeoutWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:     "derp-timed-out",
+		Code:     tsconst.HealthWarnableDERPTimedOut,
 		Title:    "Relay server timed out",
 		Severity: SeverityMedium,
 		DependsOn: []*Warnable{
@@ -198,7 +199,7 @@ var derpTimeoutWarnable = condRegister(func() *Warnable {
 // derpRegionErrorWarnable is a Warnable that warns the user that a DERP region is reporting an issue.
 var derpRegionErrorWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:      "derp-region-error",
+		Code:      tsconst.HealthWarnableDERPRegionError,
 		Title:     "Relay server error",
 		Severity:  SeverityLow,
 		DependsOn: []*Warnable{NetworkStatusWarnable},
@@ -211,7 +212,7 @@ var derpRegionErrorWarnable = condRegister(func() *Warnable {
 // 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:                "no-udp4-bind",
+		Code:                tsconst.HealthWarnableNoUDP4Bind,
 		Title:               "NAT traversal setup failure",
 		Severity:            SeverityMedium,
 		DependsOn:           []*Warnable{NetworkStatusWarnable, IPNStateWarnable},
@@ -223,7 +224,7 @@ var noUDP4BindWarnable = condRegister(func() *Warnable {
 // 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:      "mapresponse-timeout",
+		Code:      tsconst.HealthWarnableMapResponseTimeout,
 		Title:     "Network map response timeout",
 		Severity:  SeverityMedium,
 		DependsOn: []*Warnable{NetworkStatusWarnable, IPNStateWarnable},
@@ -236,7 +237,7 @@ var mapResponseTimeoutWarnable = condRegister(func() *Warnable {
 // 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:      "tls-connection-failed",
+		Code:      tsconst.HealthWarnableTLSConnectionFailed,
 		Title:     "Encrypted connection failed",
 		Severity:  SeverityMedium,
 		DependsOn: []*Warnable{NetworkStatusWarnable},
@@ -249,7 +250,7 @@ var tlsConnectionFailedWarnable = condRegister(func() *Warnable {
 // 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:     "magicsock-receive-func-error",
+		Code:     tsconst.HealthWarnableMagicsockReceiveFuncError,
 		Title:    "MagicSock function not running",
 		Severity: SeverityMedium,
 		Text: func(args Args) string {
@@ -261,7 +262,7 @@ var magicsockReceiveFuncWarnable = condRegister(func() *Warnable {
 // testWarnable is a Warnable that is used within this package for testing purposes only.
 var testWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:     "test-warnable",
+		Code:     tsconst.HealthWarnableTestWarnable,
 		Title:    "Test warnable",
 		Severity: SeverityLow,
 		Text: func(args Args) string {
@@ -273,7 +274,7 @@ var testWarnable = condRegister(func() *Warnable {
 // 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:     "apply-disk-config",
+		Code:     tsconst.HealthWarnableApplyDiskConfig,
 		Title:    "Could not apply configuration",
 		Severity: SeverityMedium,
 		Text: func(args Args) string {
@@ -291,7 +292,7 @@ const warmingUpWarnableDuration = 5 * time.Second
 // the backend is fully started.
 var warmingUpWarnable = condRegister(func() *Warnable {
 	return &Warnable{
-		Code:     "warming-up",
+		Code:     tsconst.HealthWarnableWarmingUp,
 		Title:    "Tailscale is starting",
 		Severity: SeverityLow,
 		Text:     StaticMessage("Tailscale is starting. Please wait."),

+ 26 - 0
tsconst/health.go

@@ -0,0 +1,26 @@
+// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+package tsconst
+
+const (
+	HealthWarnableUpdateAvailable           = "update-available"
+	HealthWarnableSecurityUpdateAvailable   = "security-update-available"
+	HealthWarnableIsUsingUnstableVersion    = "is-using-unstable-version"
+	HealthWarnableNetworkStatus             = "network-status"
+	HealthWarnableWantRunningFalse          = "wantrunning-false"
+	HealthWarnableLocalLogConfigError       = "local-log-config-error"
+	HealthWarnableLoginState                = "login-state"
+	HealthWarnableNotInMapPoll              = "not-in-map-poll"
+	HealthWarnableNoDERPHome                = "no-derp-home"
+	HealthWarnableNoDERPConnection          = "no-derp-connection"
+	HealthWarnableDERPTimedOut              = "derp-timed-out"
+	HealthWarnableDERPRegionError           = "derp-region-error"
+	HealthWarnableNoUDP4Bind                = "no-udp4-bind"
+	HealthWarnableMapResponseTimeout        = "mapresponse-timeout"
+	HealthWarnableTLSConnectionFailed       = "tls-connection-failed"
+	HealthWarnableMagicsockReceiveFuncError = "magicsock-receive-func-error"
+	HealthWarnableTestWarnable              = "test-warnable"
+	HealthWarnableApplyDiskConfig           = "apply-disk-config"
+	HealthWarnableWarmingUp                 = "warming-up"
+)