util/cmpx: delete now that we're using Go 1.22

Updates #11058

Change-Id: I09dea8e86f03ec148b715efca339eab8b1f0f644
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/11066/head
Brad Fitzpatrick 3 months ago committed by Brad Fitzpatrick
parent 5ea071186e
commit 2bd3c1474b

@ -7,6 +7,7 @@ package tailscale
import ( import (
"bytes" "bytes"
"cmp"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
@ -37,7 +38,6 @@ import (
"tailscale.com/tka" "tailscale.com/tka"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/tkatype" "tailscale.com/types/tkatype"
"tailscale.com/util/cmpx"
) )
// defaultLocalClient is the default LocalClient when using the legacy // defaultLocalClient is the default LocalClient when using the legacy
@ -479,7 +479,7 @@ func (lc *LocalClient) DebugPortmap(ctx context.Context, opts *DebugPortmapOpts)
opts = &DebugPortmapOpts{} opts = &DebugPortmapOpts{}
} }
vals.Set("duration", cmpx.Or(opts.Duration, 5*time.Second).String()) vals.Set("duration", cmp.Or(opts.Duration, 5*time.Second).String())
vals.Set("type", opts.Type) vals.Set("type", opts.Type)
vals.Set("log_http", strconv.FormatBool(opts.LogHTTP)) vals.Set("log_http", strconv.FormatBool(opts.LogHTTP))

@ -138,7 +138,6 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
tailscale.com/util/clientmetric from tailscale.com/net/tshttpproxy+ tailscale.com/util/clientmetric from tailscale.com/net/tshttpproxy+
tailscale.com/util/cloudenv from tailscale.com/hostinfo+ tailscale.com/util/cloudenv from tailscale.com/hostinfo+
W tailscale.com/util/cmpver from tailscale.com/net/tshttpproxy W tailscale.com/util/cmpver from tailscale.com/net/tshttpproxy
tailscale.com/util/cmpx from tailscale.com/cmd/derper+
tailscale.com/util/ctxkey from tailscale.com/tsweb+ tailscale.com/util/ctxkey from tailscale.com/tsweb+
L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
tailscale.com/util/dnsname from tailscale.com/hostinfo+ tailscale.com/util/dnsname from tailscale.com/hostinfo+

@ -5,6 +5,7 @@
package main // import "tailscale.com/cmd/derper" package main // import "tailscale.com/cmd/derper"
import ( import (
"cmp"
"context" "context"
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
@ -34,7 +35,6 @@ import (
"tailscale.com/net/stunserver" "tailscale.com/net/stunserver"
"tailscale.com/tsweb" "tailscale.com/tsweb"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/util/cmpx"
) )
var ( var (
@ -369,7 +369,7 @@ func defaultMeshPSKFile() string {
} }
func rateLimitedListenAndServeTLS(srv *http.Server) error { func rateLimitedListenAndServeTLS(srv *http.Server) error {
ln, err := net.Listen("tcp", cmpx.Or(srv.Addr, ":https")) ln, err := net.Listen("tcp", cmp.Or(srv.Addr, ":https"))
if err != nil { if err != nil {
return err return err
} }

@ -7,6 +7,7 @@
package main package main
import ( import (
"cmp"
"context" "context"
"flag" "flag"
"fmt" "fmt"
@ -16,7 +17,6 @@ import (
"golang.org/x/oauth2/clientcredentials" "golang.org/x/oauth2/clientcredentials"
"tailscale.com/client/tailscale" "tailscale.com/client/tailscale"
"tailscale.com/util/cmpx"
) )
func main() { func main() {
@ -40,7 +40,7 @@ func main() {
log.Fatal("at least one tag must be specified") log.Fatal("at least one tag must be specified")
} }
baseURL := cmpx.Or(os.Getenv("TS_BASE_URL"), "https://api.tailscale.com") baseURL := cmp.Or(os.Getenv("TS_BASE_URL"), "https://api.tailscale.com")
credentials := clientcredentials.Config{ credentials := clientcredentials.Config{
ClientID: clientID, ClientID: clientID,

@ -62,7 +62,6 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar
tailscale.com/types/structs from tailscale.com/tailcfg+ tailscale.com/types/structs from tailscale.com/tailcfg+
tailscale.com/types/tkatype from tailscale.com/tailcfg+ tailscale.com/types/tkatype from tailscale.com/tailcfg+
tailscale.com/types/views from tailscale.com/net/tsaddr+ tailscale.com/types/views from tailscale.com/net/tsaddr+
tailscale.com/util/cmpx from tailscale.com/tailcfg+
tailscale.com/util/ctxkey from tailscale.com/tsweb+ tailscale.com/util/ctxkey from tailscale.com/tsweb+
L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
tailscale.com/util/dnsname from tailscale.com/tailcfg tailscale.com/util/dnsname from tailscale.com/tailcfg

@ -5,6 +5,7 @@ package cli
import ( import (
"bytes" "bytes"
stdcmp "cmp"
"encoding/json" "encoding/json"
"flag" "flag"
"fmt" "fmt"
@ -24,7 +25,6 @@ import (
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/persist" "tailscale.com/types/persist"
"tailscale.com/types/preftype" "tailscale.com/types/preftype"
"tailscale.com/util/cmpx"
"tailscale.com/version/distro" "tailscale.com/version/distro"
) )
@ -758,7 +758,7 @@ func TestPrefsFromUpArgs(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
var warnBuf tstest.MemLogger var warnBuf tstest.MemLogger
goos := cmpx.Or(tt.goos, "linux") goos := stdcmp.Or(tt.goos, "linux")
st := tt.st st := tt.st
if st == nil { if st == nil {
st = new(ipnstate.Status) st = new(ipnstate.Status)

@ -5,6 +5,7 @@ package cli
import ( import (
"bytes" "bytes"
"cmp"
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
@ -23,7 +24,6 @@ import (
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/ipn/ipnstate" "tailscale.com/ipn/ipnstate"
"tailscale.com/net/interfaces" "tailscale.com/net/interfaces"
"tailscale.com/util/cmpx"
"tailscale.com/util/dnsname" "tailscale.com/util/dnsname"
) )
@ -316,7 +316,7 @@ func ownerLogin(st *ipnstate.Status, ps *ipnstate.PeerStatus) string {
// their netmap. We've historically (2021-01..2023-08) always shown the // their netmap. We've historically (2021-01..2023-08) always shown the
// sharer's name in the UI. Perhaps we want to show both here? But the CLI's // sharer's name in the UI. Perhaps we want to show both here? But the CLI's
// a bit space constrained. // a bit space constrained.
uid := cmpx.Or(ps.AltSharerUserID, ps.UserID) uid := cmp.Or(ps.AltSharerUserID, ps.UserID)
if uid.IsZero() { if uid.IsZero() {
return "-" return "-"
} }

@ -4,6 +4,7 @@
package cli package cli
import ( import (
"cmp"
"context" "context"
"crypto/tls" "crypto/tls"
_ "embed" _ "embed"
@ -21,7 +22,6 @@ import (
"github.com/peterbourgon/ff/v3/ffcli" "github.com/peterbourgon/ff/v3/ffcli"
"tailscale.com/client/web" "tailscale.com/client/web"
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/util/cmpx"
) )
var webCmd = &ffcli.Command{ var webCmd = &ffcli.Command{
@ -160,5 +160,5 @@ func setRunWebClient(ctx context.Context, val bool) error {
// urlOfListenAddr parses a given listen address into a formatted URL // urlOfListenAddr parses a given listen address into a formatted URL
func urlOfListenAddr(addr string) string { func urlOfListenAddr(addr string) string {
host, port, _ := net.SplitHostPort(addr) host, port, _ := net.SplitHostPort(addr)
return fmt.Sprintf("http://%s", net.JoinHostPort(cmpx.Or(host, "127.0.0.1"), port)) return fmt.Sprintf("http://%s", net.JoinHostPort(cmp.Or(host, "127.0.0.1"), port))
} }

@ -141,7 +141,6 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
tailscale.com/util/clientmetric from tailscale.com/net/netcheck+ tailscale.com/util/clientmetric from tailscale.com/net/netcheck+
tailscale.com/util/cloudenv from tailscale.com/net/dnscache+ tailscale.com/util/cloudenv from tailscale.com/net/dnscache+
tailscale.com/util/cmpver from tailscale.com/net/tshttpproxy+ tailscale.com/util/cmpver from tailscale.com/net/tshttpproxy+
tailscale.com/util/cmpx from tailscale.com/cmd/tailscale/cli+
tailscale.com/util/ctxkey from tailscale.com/types/logger tailscale.com/util/ctxkey from tailscale.com/types/logger
L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics
tailscale.com/util/dnsname from tailscale.com/cmd/tailscale/cli+ tailscale.com/util/dnsname from tailscale.com/cmd/tailscale/cli+

@ -347,7 +347,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/util/clientmetric from tailscale.com/control/controlclient+ tailscale.com/util/clientmetric from tailscale.com/control/controlclient+
tailscale.com/util/cloudenv from tailscale.com/net/dns/resolver+ tailscale.com/util/cloudenv from tailscale.com/net/dns/resolver+
tailscale.com/util/cmpver from tailscale.com/net/dns+ tailscale.com/util/cmpver from tailscale.com/net/dns+
tailscale.com/util/cmpx from tailscale.com/derp/derphttp+
tailscale.com/util/ctxkey from tailscale.com/ipn/ipnlocal+ tailscale.com/util/ctxkey from tailscale.com/ipn/ipnlocal+
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+ 💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics+ L 💣 tailscale.com/util/dirwalk from tailscale.com/metrics+

@ -4,6 +4,7 @@
package controlclient package controlclient
import ( import (
"cmp"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -26,7 +27,6 @@ import (
"tailscale.com/types/ptr" "tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/cmpx"
"tailscale.com/util/mak" "tailscale.com/util/mak"
"tailscale.com/wgengine/filter" "tailscale.com/wgengine/filter"
) )
@ -130,7 +130,7 @@ func (ms *mapSession) occasionallyPrintSummary(summary string) {
} }
func (ms *mapSession) clock() tstime.Clock { func (ms *mapSession) clock() tstime.Clock {
return cmpx.Or[tstime.Clock](ms.altClock, tstime.StdClock{}) return cmp.Or[tstime.Clock](ms.altClock, tstime.StdClock{})
} }
func (ms *mapSession) Close() { func (ms *mapSession) Close() {
@ -171,7 +171,7 @@ func (ms *mapSession) HandleNonKeepAliveMapResponse(ctx context.Context, resp *t
} }
// Call Node.InitDisplayNames on any changed nodes. // Call Node.InitDisplayNames on any changed nodes.
initDisplayNames(cmpx.Or(resp.Node.View(), ms.lastNode), resp) initDisplayNames(cmp.Or(resp.Node.View(), ms.lastNode), resp)
ms.patchifyPeersChanged(resp) ms.patchifyPeersChanged(resp)

@ -11,6 +11,7 @@ package derphttp
import ( import (
"bufio" "bufio"
"cmp"
"context" "context"
"crypto/rand" "crypto/rand"
"crypto/tls" "crypto/tls"
@ -41,7 +42,6 @@ import (
"tailscale.com/tstime" "tailscale.com/tstime"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/util/cmpx"
) )
// Client is a DERP-over-HTTP client. // Client is a DERP-over-HTTP client.
@ -701,7 +701,7 @@ func (c *Client) dialNode(ctx context.Context, n *tailcfg.DERPNode) (net.Conn, e
// Start v4 dial // Start v4 dial
} }
} }
dst := cmpx.Or(dstPrimary, n.HostName) dst := cmp.Or(dstPrimary, n.HostName)
port := "443" port := "443"
if n.DERPPort != 0 { if n.DERPPort != 0 {
port = fmt.Sprint(n.DERPPort) port = fmt.Sprint(n.DERPPort)

@ -4,6 +4,7 @@
package ipnlocal package ipnlocal
import ( import (
"cmp"
"crypto/x509" "crypto/x509"
"encoding/json" "encoding/json"
"net/http/httptest" "net/http/httptest"
@ -18,7 +19,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/util/cmpx"
"tailscale.com/util/must" "tailscale.com/util/must"
) )
@ -111,7 +111,7 @@ func TestHandleC2NTLSCertStatus(t *testing.T) {
rec := httptest.NewRecorder() rec := httptest.NewRecorder()
handleC2NTLSCertStatus(b, rec, httptest.NewRequest("GET", "/tls-cert-status?domain="+url.QueryEscape(tt.domain), nil)) handleC2NTLSCertStatus(b, rec, httptest.NewRequest("GET", "/tls-cert-status?domain="+url.QueryEscape(tt.domain), nil))
res := rec.Result() res := rec.Result()
wantStatus := cmpx.Or(tt.wantStatus, 200) wantStatus := cmp.Or(tt.wantStatus, 200)
if res.StatusCode != wantStatus { if res.StatusCode != wantStatus {
t.Fatalf("status code = %v; want %v. Body: %s", res.Status, wantStatus, rec.Body.Bytes()) t.Fatalf("status code = %v; want %v. Body: %s", res.Status, wantStatus, rec.Body.Bytes())
} }

@ -4,6 +4,7 @@
package ipnlocal package ipnlocal
import ( import (
"cmp"
"encoding/json" "encoding/json"
"net/netip" "net/netip"
"reflect" "reflect"
@ -16,7 +17,6 @@ import (
"tailscale.com/types/dnstype" "tailscale.com/types/dnstype"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/util/cloudenv" "tailscale.com/util/cloudenv"
"tailscale.com/util/cmpx"
"tailscale.com/util/dnsname" "tailscale.com/util/dnsname"
) )
@ -330,7 +330,7 @@ func TestDNSConfigForNetmap(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
verOS := cmpx.Or(tt.os, "linux") verOS := cmp.Or(tt.os, "linux")
var log tstest.MemLogger var log tstest.MemLogger
got := dnsConfigForNetmap(tt.nm, peersMap(tt.peers), tt.prefs.View(), log.Logf, verOS) got := dnsConfigForNetmap(tt.nm, peersMap(tt.peers), tt.prefs.View(), log.Logf, verOS)
if !reflect.DeepEqual(got, tt.want) { if !reflect.DeepEqual(got, tt.want) {

@ -82,7 +82,6 @@ import (
"tailscale.com/types/preftype" "tailscale.com/types/preftype"
"tailscale.com/types/ptr" "tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/cmpx"
"tailscale.com/util/deephash" "tailscale.com/util/deephash"
"tailscale.com/util/dnsname" "tailscale.com/util/dnsname"
"tailscale.com/util/mak" "tailscale.com/util/mak"
@ -4527,7 +4526,7 @@ func (b *LocalBackend) setNetMapLocked(nm *netmap.NetworkMap) {
} }
var login string var login string
if nm != nil { if nm != nil {
login = cmpx.Or(nm.UserProfiles[nm.User()].LoginName, "<missing-profile>") login = cmp.Or(nm.UserProfiles[nm.User()].LoginName, "<missing-profile>")
} }
b.netMap = nm b.netMap = nm
b.updatePeersFromNetmapLocked(nm) b.updatePeersFromNetmapLocked(nm)

@ -5,6 +5,7 @@ package ipnlocal
import ( import (
"bytes" "bytes"
"cmp"
"context" "context"
"crypto/sha256" "crypto/sha256"
"crypto/tls" "crypto/tls"
@ -29,7 +30,6 @@ import (
"tailscale.com/tsd" "tailscale.com/tsd"
"tailscale.com/types/logid" "tailscale.com/types/logid"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/util/cmpx"
"tailscale.com/util/mak" "tailscale.com/util/mak"
"tailscale.com/util/must" "tailscale.com/util/must"
"tailscale.com/wgengine" "tailscale.com/wgengine"
@ -157,7 +157,7 @@ func TestGetServeHandler(t *testing.T) {
}, },
TLS: &tls.ConnectionState{ServerName: serverName}, TLS: &tls.ConnectionState{ServerName: serverName},
} }
port := cmpx.Or(tt.port, 443) port := cmp.Or(tt.port, 443)
req = req.WithContext(serveHTTPContextKey.WithValue(req.Context(), &serveHTTPContext{ req = req.WithContext(serveHTTPContextKey.WithValue(req.Context(), &serveHTTPContext{
DestPort: port, DestPort: port,
})) }))

@ -4,6 +4,7 @@
package dnscache package dnscache
import ( import (
"cmp"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
@ -13,7 +14,6 @@ import (
"github.com/golang/groupcache/lru" "github.com/golang/groupcache/lru"
"golang.org/x/net/dns/dnsmessage" "golang.org/x/net/dns/dnsmessage"
"tailscale.com/util/cmpx"
) )
// MessageCache is a cache that works at the DNS message layer, // MessageCache is a cache that works at the DNS message layer,
@ -60,7 +60,7 @@ func (c *MessageCache) Flush() {
// pruneLocked prunes down the cache size to the configured (or // pruneLocked prunes down the cache size to the configured (or
// default) max size. // default) max size.
func (c *MessageCache) pruneLocked() { func (c *MessageCache) pruneLocked() {
max := cmpx.Or(c.cacheSizeSet, 500) max := cmp.Or(c.cacheSizeSet, 500)
for c.cache.Len() > max { for c.cache.Len() > max {
c.cache.RemoveOldest() c.cache.RemoveOldest()
} }

@ -6,6 +6,7 @@ package netcheck
import ( import (
"bufio" "bufio"
"cmp"
"context" "context"
"crypto/tls" "crypto/tls"
"errors" "errors"
@ -41,7 +42,6 @@ import (
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/cmpx"
"tailscale.com/util/mak" "tailscale.com/util/mak"
) )
@ -447,7 +447,7 @@ func makeProbePlan(dm *tailcfg.DERPMap, ifState *interfaces.State, last *Report)
do6 = false do6 = false
} }
n := reg.Nodes[try%len(reg.Nodes)] n := reg.Nodes[try%len(reg.Nodes)]
prevLatency := cmpx.Or( prevLatency := cmp.Or(
last.RegionLatency[reg.RegionID]*120/100, last.RegionLatency[reg.RegionID]*120/100,
defaultActiveRetransmitTime) defaultActiveRetransmitTime)
delay := time.Duration(try) * prevLatency delay := time.Duration(try) * prevLatency
@ -1602,7 +1602,7 @@ func (rs *reportState) runProbe(ctx context.Context, dm *tailcfg.DERPMap, probe
// proto is 4 or 6 // proto is 4 or 6
// If it returns nil, the node is skipped. // If it returns nil, the node is skipped.
func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeProto) (ap netip.AddrPort) { func (c *Client) nodeAddr(ctx context.Context, n *tailcfg.DERPNode, proto probeProto) (ap netip.AddrPort) {
port := cmpx.Or(n.STUNPort, 3478) port := cmp.Or(n.STUNPort, 3478)
if port < 0 || port > 1<<16-1 { if port < 0 || port > 1<<16-1 {
return return
} }

@ -7,6 +7,7 @@ package tailcfg
import ( import (
"bytes" "bytes"
"cmp"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@ -22,7 +23,6 @@ import (
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/structs" "tailscale.com/types/structs"
"tailscale.com/types/tkatype" "tailscale.com/types/tkatype"
"tailscale.com/util/cmpx"
"tailscale.com/util/dnsname" "tailscale.com/util/dnsname"
"tailscale.com/util/slicesx" "tailscale.com/util/slicesx"
) )
@ -475,7 +475,7 @@ func (n *Node) IsTagged() bool {
// SharerOrUser Sharer if set, else User. // SharerOrUser Sharer if set, else User.
func (n *Node) SharerOrUser() UserID { func (n *Node) SharerOrUser() UserID {
return cmpx.Or(n.Sharer, n.User) return cmp.Or(n.Sharer, n.User)
} }
// IsTagged reports whether the node has any tags. // IsTagged reports whether the node has any tags.

@ -7,6 +7,7 @@ package tsweb
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"cmp"
"context" "context"
"errors" "errors"
"expvar" "expvar"
@ -30,7 +31,6 @@ import (
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
"tailscale.com/tsweb/varz" "tailscale.com/tsweb/varz"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/util/cmpx"
"tailscale.com/util/vizerror" "tailscale.com/util/vizerror"
) )
@ -156,7 +156,7 @@ func (h Port80Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Redirect authorized user to the debug handler. // Redirect authorized user to the debug handler.
path = "/debug/" path = "/debug/"
} }
host := cmpx.Or(h.FQDN, r.Host) host := cmp.Or(h.FQDN, r.Host)
target := "https://" + host + path target := "https://" + host + path
http.Redirect(w, r, target, http.StatusFound) http.Redirect(w, r, target, http.StatusFound)
} }

@ -5,6 +5,7 @@
package varz package varz
import ( import (
"cmp"
"expvar" "expvar"
"fmt" "fmt"
"io" "io"
@ -18,7 +19,6 @@ import (
"time" "time"
"tailscale.com/metrics" "tailscale.com/metrics"
"tailscale.com/util/cmpx"
"tailscale.com/version" "tailscale.com/version"
) )
@ -100,10 +100,10 @@ func writePromExpVar(w io.Writer, prefix string, kv expvar.KeyValue) {
switch v := kv.Value.(type) { switch v := kv.Value.(type) {
case *expvar.Int: case *expvar.Int:
fmt.Fprintf(w, "# TYPE %s %s\n%s %v\n", name, cmpx.Or(typ, "counter"), name, v.Value()) fmt.Fprintf(w, "# TYPE %s %s\n%s %v\n", name, cmp.Or(typ, "counter"), name, v.Value())
return return
case *expvar.Float: case *expvar.Float:
fmt.Fprintf(w, "# TYPE %s %s\n%s %v\n", name, cmpx.Or(typ, "gauge"), name, v.Value()) fmt.Fprintf(w, "# TYPE %s %s\n%s %v\n", name, cmp.Or(typ, "gauge"), name, v.Value())
return return
case *metrics.Set: case *metrics.Set:
v.Do(func(kv expvar.KeyValue) { v.Do(func(kv expvar.KeyValue) {
@ -192,7 +192,7 @@ func writePromExpVar(w io.Writer, prefix string, kv expvar.KeyValue) {
// IntMap uses expvar.Map on the inside, which presorts // IntMap uses expvar.Map on the inside, which presorts
// keys. The output ordering is deterministic. // keys. The output ordering is deterministic.
v.Do(func(kv expvar.KeyValue) { v.Do(func(kv expvar.KeyValue) {
fmt.Fprintf(w, "%s{%s=%q} %v\n", name, cmpx.Or(v.Label, "label"), kv.Key, kv.Value) fmt.Fprintf(w, "%s{%s=%q} %v\n", name, cmp.Or(v.Label, "label"), kv.Key, kv.Value)
}) })
case *metrics.Histogram: case *metrics.Histogram:
v.PromExport(w, name) v.PromExport(w, name)

@ -1,22 +0,0 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
// Package cmpx has code that will likely land in a future version of Go, but
// we want sooner.
package cmpx
// Or returns the first non-zero element of list, or else returns the zero T.
//
// This is the proposal from
// https://github.com/golang/go/issues/60204#issuecomment-1581245334.
func Or[T comparable](list ...T) T {
// TODO(bradfitz): remove the comparable constraint so we can use this
// with funcs too and use reflect to see whether they're non-zero? 🤷‍♂️
var zero T
for _, v := range list {
if v != zero {
return v
}
}
return zero
}

@ -1,24 +0,0 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
package cmpx
import "testing"
func TestOr(t *testing.T) {
if g, w := Or[string](), ""; g != w {
t.Errorf("got %v; want %v", g, w)
}
if g, w := Or[int](), 0; g != w {
t.Errorf("got %v; want %v", g, w)
}
if g, w := Or("", "foo", "bar"), "foo"; g != w {
t.Errorf("got %v; want %v", g, w)
}
if g, w := Or("foo", "bar"), "foo"; g != w {
t.Errorf("got %v; want %v", g, w)
}
if g, w := Or("", "", "bar"), "bar"; g != w {
t.Errorf("got %v; want %v", g, w)
}
}

@ -7,6 +7,7 @@
package linuxfw package linuxfw
import ( import (
"cmp"
"fmt" "fmt"
"sort" "sort"
"strings" "strings"
@ -17,7 +18,6 @@ import (
"github.com/josharian/native" "github.com/josharian/native"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/util/cmpx"
) )
// DebugNetfilter prints debug information about netfilter rules to the // DebugNetfilter prints debug information about netfilter rules to the
@ -54,18 +54,18 @@ func DebugNetfilter(logf logger.Logf) error {
for _, ex := range rule.Exprs { for _, ex := range rule.Exprs {
switch v := ex.(type) { switch v := ex.(type) {
case *expr.Meta: case *expr.Meta:
key := cmpx.Or(metaKeyNames[v.Key], "UNKNOWN") key := cmp.Or(metaKeyNames[v.Key], "UNKNOWN")
logf("netfilter: Meta: key=%s source_register=%v register=%d", key, v.SourceRegister, v.Register) logf("netfilter: Meta: key=%s source_register=%v register=%d", key, v.SourceRegister, v.Register)
case *expr.Cmp: case *expr.Cmp:
op := cmpx.Or(cmpOpNames[v.Op], "UNKNOWN") op := cmp.Or(cmpOpNames[v.Op], "UNKNOWN")
logf("netfilter: Cmp: op=%s register=%d data=%s", op, v.Register, formatMaybePrintable(v.Data)) logf("netfilter: Cmp: op=%s register=%d data=%s", op, v.Register, formatMaybePrintable(v.Data))
case *expr.Counter: case *expr.Counter:
// don't print // don't print
case *expr.Verdict: case *expr.Verdict:
kind := cmpx.Or(verdictNames[v.Kind], "UNKNOWN") kind := cmp.Or(verdictNames[v.Kind], "UNKNOWN")
logf("netfilter: Verdict: kind=%s data=%s", kind, v.Chain) logf("netfilter: Verdict: kind=%s data=%s", kind, v.Chain)
case *expr.Target: case *expr.Target:

Loading…
Cancel
Save