all: use Go 1.26 things, run most gofix modernizers

I omitted a lot of the min/max modernizers because they didn't
result in more clear code.

Some of it's older "for x := range 123".

Also: errors.AsType, any, fmt.Appendf, etc.

Updates #18682

Change-Id: I83a451577f33877f962766a5b65ce86f7696471c
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2026-03-05 21:13:57 +00:00
committed by Brad Fitzpatrick
parent 4453cc5f53
commit bd2a2d53d3
168 changed files with 431 additions and 618 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ func ensureIPForwarding(root, clusterProxyTargetIP, tailnetTargetIP, tailnetTarg
v4Forwarding = true
}
if routes != nil && *routes != "" {
for _, route := range strings.Split(*routes, ",") {
for route := range strings.SplitSeq(*routes, ",") {
cidr, err := netip.ParsePrefix(route)
if err != nil {
return fmt.Errorf("invalid subnet route: %v", err)
+3 -4
View File
@@ -15,6 +15,7 @@ import (
"fmt"
"io"
"io/fs"
"maps"
"net"
"net/http"
"net/http/httptest"
@@ -1249,7 +1250,7 @@ func (b *lockingBuffer) String() string {
func waitLogLine(t *testing.T, timeout time.Duration, b *lockingBuffer, want string) {
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
for _, line := range strings.Split(b.String(), "\n") {
for line := range strings.SplitSeq(b.String(), "\n") {
if !strings.HasPrefix(line, "boot: ") {
continue
}
@@ -1438,9 +1439,7 @@ func (k *kubeServer) Secret() map[string]string {
k.Lock()
defer k.Unlock()
ret := map[string]string{}
for k, v := range k.secret {
ret[k] = v
}
maps.Copy(ret, k.secret)
return ret
}
+1 -1
View File
@@ -25,7 +25,7 @@ func startMesh(s *derpserver.Server) error {
if !s.HasMeshKey() {
return errors.New("--mesh-with requires --mesh-psk-file")
}
for _, hostTuple := range strings.Split(*meshWith, ",") {
for hostTuple := range strings.SplitSeq(*meshWith, ",") {
if err := startMeshWithHost(s, hostTuple); err != nil {
return err
}
+4 -5
View File
@@ -11,7 +11,6 @@ import (
"math/rand/v2"
"testing"
"github.com/AlekSi/pointer"
"go.uber.org/zap"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
@@ -106,11 +105,11 @@ func TestTailscaleEgressEndpointSlices(t *testing.T) {
expectReconciled(t, er, "operator-ns", "foo")
eps.Endpoints = append(eps.Endpoints, discoveryv1.Endpoint{
Addresses: []string{"10.0.0.1"},
Hostname: pointer.To("foo"),
Hostname: new("foo"),
Conditions: discoveryv1.EndpointConditions{
Serving: pointer.ToBool(true),
Ready: pointer.ToBool(true),
Terminating: pointer.ToBool(false),
Serving: new(true),
Ready: new(true),
Terminating: new(false),
},
})
expectEqual(t, fc, eps)
@@ -9,7 +9,6 @@ import (
"fmt"
"testing"
"github.com/AlekSi/pointer"
"go.uber.org/zap"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
@@ -145,9 +144,9 @@ func setEndpointForReplica(pg *tsapi.ProxyGroup, ordinal int32, eps *discoveryv1
eps.Endpoints = append(eps.Endpoints, discoveryv1.Endpoint{
Addresses: []string{p.Status.PodIPs[0].IP},
Conditions: discoveryv1.EndpointConditions{
Ready: pointer.ToBool(true),
Serving: pointer.ToBool(true),
Terminating: pointer.ToBool(false),
Ready: new(true),
Serving: new(true),
Terminating: new(false),
},
})
}
+1 -1
View File
@@ -243,7 +243,7 @@ func portsForEndpointSlice(svc *corev1.Service) []discoveryv1.EndpointPort {
ports = append(ports, discoveryv1.EndpointPort{
Name: &p.Name,
Protocol: &p.Protocol,
Port: pointer.ToInt32(p.TargetPort.IntVal),
Port: new(p.TargetPort.IntVal),
})
}
return ports
+4 -6
View File
@@ -10,6 +10,7 @@ import (
"encoding/json"
"errors"
"fmt"
"maps"
"math/rand/v2"
"net/http"
"reflect"
@@ -914,9 +915,7 @@ func ownerAnnotations(operatorID string, svc *tailscale.VIPService) (map[string]
}
newAnnots := make(map[string]string, len(svc.Annotations)+1)
for k, v := range svc.Annotations {
newAnnots[k] = v
}
maps.Copy(newAnnots, svc.Annotations)
newAnnots[ownerAnnotation] = string(json)
return newAnnots, nil
}
@@ -1129,8 +1128,7 @@ func hasCerts(ctx context.Context, cl client.Client, lc localClient, ns string,
}
func isErrorTailscaleServiceNotFound(err error) bool {
var errResp tailscale.ErrResponse
ok := errors.As(err, &errResp)
errResp, ok := errors.AsType[tailscale.ErrResponse](err)
return ok && errResp.Status == http.StatusNotFound
}
@@ -1144,7 +1142,7 @@ func tagViolations(obj client.Object) []string {
return nil
}
for _, tag := range strings.Split(tags, ",") {
for tag := range strings.SplitSeq(tags, ",") {
tag = strings.TrimSpace(tag)
if err := tailcfg.CheckTag(tag); err != nil {
violations = append(violations, fmt.Sprintf("invalid tag %q: %v", tag, err))
+1 -1
View File
@@ -1102,7 +1102,7 @@ func verifyTailscaledConfig(t *testing.T, fc client.Client, pgName string, expec
Labels: pgSecretLabels(pgName, kubetypes.LabelSecretTypeConfig),
},
Data: map[string][]byte{
tsoperator.TailscaledConfigFileName(pgMinCapabilityVersion): []byte(fmt.Sprintf(`{"Version":""%s}`, expected)),
tsoperator.TailscaledConfigFileName(pgMinCapabilityVersion): fmt.Appendf(nil, `{"Version":""%s}`, expected),
},
})
}
+3 -6
View File
@@ -8,6 +8,7 @@ package main
import (
"context"
"fmt"
"maps"
"reflect"
"go.uber.org/zap"
@@ -286,11 +287,7 @@ func isNamespacedProxyType(typ string) bool {
func mergeMapKeys(a, b map[string]string) map[string]string {
m := make(map[string]string, len(a)+len(b))
for key, val := range b {
m[key] = val
}
for key, val := range a {
m[key] = val
}
maps.Copy(m, b)
maps.Copy(m, a)
return m
}
+3 -6
View File
@@ -308,8 +308,7 @@ func (r *ProxyGroupReconciler) maybeProvision(ctx context.Context, tailscaleClie
var err error
svcToNodePorts, tailscaledPort, err = r.ensureNodePortServiceCreated(ctx, pg, proxyClass)
if err != nil {
var allocatePortErr *allocatePortsErr
if errors.As(err, &allocatePortErr) {
if _, ok := errors.AsType[*allocatePortsErr](err); ok {
reason := reasonProxyGroupCreationFailed
msg := fmt.Sprintf("error provisioning NodePort Services for static endpoints: %v", err)
r.recorder.Event(pg, corev1.EventTypeWarning, reason, msg)
@@ -321,8 +320,7 @@ func (r *ProxyGroupReconciler) maybeProvision(ctx context.Context, tailscaleClie
staticEndpoints, err := r.ensureConfigSecretsCreated(ctx, tailscaleClient, pg, proxyClass, svcToNodePorts)
if err != nil {
var selectorErr *FindStaticEndpointErr
if errors.As(err, &selectorErr) {
if _, ok := errors.AsType[*FindStaticEndpointErr](err); ok {
reason := reasonProxyGroupCreationFailed
msg := fmt.Sprintf("error provisioning config Secrets: %v", err)
r.recorder.Event(pg, corev1.EventTypeWarning, reason, msg)
@@ -718,8 +716,7 @@ func (r *ProxyGroupReconciler) maybeCleanup(ctx context.Context, tailscaleClient
func (r *ProxyGroupReconciler) deleteTailnetDevice(ctx context.Context, tailscaleClient tsClient, id tailcfg.StableNodeID, logger *zap.SugaredLogger) error {
logger.Debugf("deleting device %s from control", string(id))
if err := tailscaleClient.DeleteDevice(ctx, string(id)); err != nil {
errResp := &tailscale.ErrResponse{}
if ok := errors.As(err, errResp); ok && errResp.Status == http.StatusNotFound {
if errResp, ok := errors.AsType[tailscale.ErrResponse](err); ok && errResp.Status == http.StatusNotFound {
logger.Debugf("device %s not found, likely because it has already been deleted from control", string(id))
} else {
return fmt.Errorf("error deleting device: %w", err)
+2 -3
View File
@@ -7,6 +7,7 @@ package main
import (
"fmt"
"maps"
"slices"
"strconv"
"strings"
@@ -544,9 +545,7 @@ func pgSecretLabels(pgName, secretType string) map[string]string {
func pgLabels(pgName string, customLabels map[string]string) map[string]string {
labels := make(map[string]string, len(customLabels)+3)
for k, v := range customLabels {
labels[k] = v
}
maps.Copy(labels, customLabels)
labels[kubetypes.LabelManaged] = "true"
labels[LabelParentType] = "proxygroup"
+2 -2
View File
@@ -1826,10 +1826,10 @@ func addNodeIDToStateSecrets(t *testing.T, fc client.WithWatch, pg *tsapi.ProxyG
currentProfileKey: []byte(key),
key: bytes,
kubetypes.KeyDeviceIPs: []byte(`["1.2.3.4", "::1"]`),
kubetypes.KeyDeviceFQDN: []byte(fmt.Sprintf("hostname-nodeid-%d.tails-scales.ts.net", i)),
kubetypes.KeyDeviceFQDN: fmt.Appendf(nil, "hostname-nodeid-%d.tails-scales.ts.net", i),
// TODO(tomhjp): We have two different mechanisms to retrieve device IDs.
// Consolidate on this one.
kubetypes.KeyDeviceID: []byte(fmt.Sprintf("nodeid-%d", i)),
kubetypes.KeyDeviceID: fmt.Appendf(nil, "nodeid-%d", i),
kubetypes.KeyPodUID: []byte(podUID),
}
})
+6 -10
View File
@@ -11,6 +11,7 @@ import (
"encoding/json"
"errors"
"fmt"
"maps"
"net/http"
"os"
"path"
@@ -304,8 +305,7 @@ func (a *tailscaleSTSReconciler) Cleanup(ctx context.Context, tailnet string, lo
if dev.id != "" {
logger.Debugf("deleting device %s from control", string(dev.id))
if err = tailscaleClient.DeleteDevice(ctx, string(dev.id)); err != nil {
errResp := &tailscale.ErrResponse{}
if ok := errors.As(err, errResp); ok && errResp.Status == http.StatusNotFound {
if errResp, ok := errors.AsType[tailscale.ErrResponse](err); ok && errResp.Status == http.StatusNotFound {
logger.Debugf("device %s not found, likely because it has already been deleted from control", string(dev.id))
} else {
return false, fmt.Errorf("deleting device: %w", err)
@@ -499,14 +499,11 @@ func (a *tailscaleSTSReconciler) provisionSecrets(ctx context.Context, tailscale
}
if dev != nil && dev.id != "" {
var errResp *tailscale.ErrResponse
err = tailscaleClient.DeleteDevice(ctx, string(dev.id))
switch {
case errors.As(err, &errResp) && errResp.Status == http.StatusNotFound:
if errResp, ok := errors.AsType[*tailscale.ErrResponse](err); ok && errResp.Status == http.StatusNotFound {
// This device has possibly already been deleted in the admin console. So we can ignore this
// and move on to removing the secret.
case err != nil:
} else if err != nil {
return nil, err
}
}
@@ -677,9 +674,8 @@ func (a *tailscaleSTSReconciler) reconcileSTS(ctx context.Context, logger *zap.S
},
}
mak.Set(&pod.Labels, "app", sts.ParentResourceUID)
for key, val := range sts.ChildResourceLabels {
pod.Labels[key] = val // sync StatefulSet labels to Pod to make it easier for users to select the Pod
}
// sync StatefulSet labels to Pod to make it easier for users to select the Pod
maps.Copy(pod.Labels, sts.ChildResourceLabels)
if sts.Replicas > 0 {
ss.Spec.Replicas = new(sts.Replicas)
+2 -3
View File
@@ -8,6 +8,7 @@ package main
import (
_ "embed"
"fmt"
"maps"
"reflect"
"regexp"
"strings"
@@ -408,7 +409,5 @@ func Test_mergeStatefulSetLabelsOrAnnots(t *testing.T) {
// updateMap updates map a with the values from map b.
func updateMap(a, b map[string]string) {
for key, val := range b {
a[key] = val
}
maps.Copy(a, b)
}
+1 -2
View File
@@ -526,8 +526,7 @@ func (r *HAServiceReconciler) tailnetCertDomain(ctx context.Context) (string, er
func cleanupTailscaleService(ctx context.Context, tsClient tsClient, name tailcfg.ServiceName, operatorID string, logger *zap.SugaredLogger) (updated bool, err error) {
svc, err := tsClient.GetVIPService(ctx, name)
if err != nil {
errResp := &tailscale.ErrResponse{}
ok := errors.As(err, errResp)
errResp, ok := errors.AsType[tailscale.ErrResponse](err)
if ok && errResp.Status == http.StatusNotFound {
return false, nil
}
+5 -7
View File
@@ -13,6 +13,7 @@ import (
"net/netip"
"path"
"reflect"
"slices"
"strings"
"sync"
"testing"
@@ -555,7 +556,7 @@ func expectedSecret(t *testing.T, cl client.Client, opts configOpts) *corev1.Sec
if opts.isExitNode {
r = "0.0.0.0/0,::/0," + r
}
for _, rr := range strings.Split(r, ",") {
for rr := range strings.SplitSeq(r, ",") {
prefix, err := netip.ParsePrefix(rr)
if err != nil {
t.Fatal(err)
@@ -822,12 +823,9 @@ func expectEvents(t *testing.T, rec *record.FakeRecorder, wantsEvents []string)
select {
case gotEvent := <-rec.Events:
found := false
for _, wantEvent := range wantsEvents {
if wantEvent == gotEvent {
found = true
seenEvents = append(seenEvents, gotEvent)
break
}
if slices.Contains(wantsEvents, gotEvent) {
found = true
seenEvents = append(seenEvents, gotEvent)
}
if !found {
t.Errorf("got unexpected event %q, expected events: %+#v", gotEvent, wantsEvents)
+3 -7
View File
@@ -363,15 +363,12 @@ func (r *RecorderReconciler) maybeCleanupSecrets(ctx context.Context, tailscaleC
}
if ok {
var errResp *tailscale.ErrResponse
r.log.Debugf("deleting device %s", devicePrefs.Config.NodeID)
err = tailscaleClient.DeleteDevice(ctx, string(devicePrefs.Config.NodeID))
switch {
case errors.As(err, &errResp) && errResp.Status == http.StatusNotFound:
if errResp, ok := errors.AsType[*tailscale.ErrResponse](err); ok && errResp.Status == http.StatusNotFound {
// This device has possibly already been deleted in the admin console. So we can ignore this
// and move on to removing the secret.
case err != nil:
} else if err != nil {
return err
}
}
@@ -412,8 +409,7 @@ func (r *RecorderReconciler) maybeCleanup(ctx context.Context, tsr *tsapi.Record
nodeID := string(devicePrefs.Config.NodeID)
logger.Debugf("deleting device %s from control", nodeID)
if err = tailscaleClient.DeleteDevice(ctx, nodeID); err != nil {
errResp := &tailscale.ErrResponse{}
if errors.As(err, errResp) && errResp.Status == http.StatusNotFound {
if errResp, ok := errors.AsType[tailscale.ErrResponse](err); ok && errResp.Status == http.StatusNotFound {
logger.Debugf("device %s not found, likely because it has already been deleted from control", nodeID)
continue
}
+2 -3
View File
@@ -7,6 +7,7 @@ package main
import (
"fmt"
"maps"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
@@ -312,9 +313,7 @@ func tsrEnv(tsr *tsapi.Recorder, loginServer string) []corev1.EnvVar {
func tsrLabels(app, instance string, customLabels map[string]string) map[string]string {
labels := make(map[string]string, len(customLabels)+3)
for k, v := range customLabels {
labels[k] = v
}
maps.Copy(labels, customLabels)
// ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/
labels["app.kubernetes.io/name"] = app
+2 -2
View File
@@ -24,7 +24,7 @@ func parseFiles(s string, typ string) (files.Contents, error) {
return nil, nil
}
var contents files.Contents
for _, f := range strings.Split(s, ",") {
for f := range strings.SplitSeq(s, ",") {
fs := strings.Split(f, ":")
if len(fs) != 2 {
return nil, fmt.Errorf("unparseable file field %q", f)
@@ -41,7 +41,7 @@ func parseEmptyDirs(s string) files.Contents {
return nil
}
var contents files.Contents
for _, d := range strings.Split(s, ",") {
for d := range strings.SplitSeq(s, ",") {
contents = append(contents, &files.Content{Type: files.TypeDir, Destination: d})
}
return contents
+1 -1
View File
@@ -30,7 +30,7 @@ func TestIPPoolExhaustion(t *testing.T) {
from := tailcfg.NodeID(12345)
for i := 0; i < 5; i++ {
for range 5 {
for _, domain := range domains {
addr, err := pool.IPForDomain(from, domain)
if err != nil {
+2 -3
View File
@@ -149,7 +149,7 @@ func main() {
}
var prefixes []netip.Prefix
for _, s := range strings.Split(*v4PfxStr, ",") {
for s := range strings.SplitSeq(*v4PfxStr, ",") {
p := netip.MustParsePrefix(strings.TrimSpace(s))
if p.Masked() != p {
log.Fatalf("v4 prefix %v is not a masked prefix", p)
@@ -372,8 +372,7 @@ func (c *connector) handleDNS(pc net.PacketConn, buf []byte, remoteAddr *net.UDP
addrQCount++
if _, ok := resolves[q.Name.String()]; !ok {
addrs, err := c.resolver.LookupNetIP(ctx, "ip", q.Name.String())
var dnsErr *net.DNSError
if errors.As(err, &dnsErr) && dnsErr.IsNotFound {
if dnsErr, ok := errors.AsType[*net.DNSError](err); ok && dnsErr.IsNotFound {
continue
}
if err != nil {
+2 -2
View File
@@ -225,7 +225,7 @@ func (s *sniproxy) mergeConfigFromFlags(out *appctype.AppConnectorConfig, ports,
Addrs: []netip.Addr{ip4, ip6},
}
if ports != "" {
for _, portStr := range strings.Split(ports, ",") {
for portStr := range strings.SplitSeq(ports, ",") {
port, err := strconv.ParseUint(portStr, 10, 16)
if err != nil {
log.Fatalf("invalid port: %s", portStr)
@@ -238,7 +238,7 @@ func (s *sniproxy) mergeConfigFromFlags(out *appctype.AppConnectorConfig, ports,
}
var forwardConfigFromFlags []appctype.DNATConfig
for _, forwStr := range strings.Split(forwards, ",") {
for forwStr := range strings.SplitSeq(forwards, ",") {
if forwStr == "" {
continue
}
+1 -2
View File
@@ -72,8 +72,7 @@ var speedtestArgs struct {
func runSpeedtest(ctx context.Context, args []string) error {
if _, _, err := net.SplitHostPort(speedtestArgs.host); err != nil {
var addrErr *net.AddrError
if errors.As(err, &addrErr) && addrErr.Err == "missing port in address" {
if addrErr, ok := errors.AsType[*net.AddrError](err); ok && addrErr.Err == "missing port in address" {
// if no port is provided, append the default port
speedtestArgs.host = net.JoinHostPort(speedtestArgs.host, strconv.Itoa(speedtest.DefaultPort))
}
+1 -2
View File
@@ -889,8 +889,7 @@ func remoteWriteTimeSeries(client *remoteWriteClient, tsCh chan []prompb.TimeSer
reqCtx, cancel := context.WithTimeout(context.Background(), time.Second*30)
writeErr = client.write(reqCtx, ts)
cancel()
var re recoverableErr
recoverable := errors.As(writeErr, &re)
_, recoverable := errors.AsType[recoverableErr](writeErr)
if writeErr != nil {
log.Printf("remote write error(recoverable=%v): %v", recoverable, writeErr)
}
+3 -3
View File
@@ -102,12 +102,12 @@ func getSummarizeLearnedOutput(ri *appctype.RouteInfo) string {
}
return 0
})
s := ""
var s strings.Builder
fmtString := fmt.Sprintf("%%-%ds %%d\n", maxDomainWidth) // eg "%-10s %d\n"
for _, dc := range x {
s += fmt.Sprintf(fmtString, dc.domain, dc.count)
s.WriteString(fmt.Sprintf(fmtString, dc.domain, dc.count))
}
return s
return s.String()
}
func runAppcRoutesInfo(ctx context.Context, args []string) error {
+1 -1
View File
@@ -124,7 +124,7 @@ func Run(args []string) (err error) {
if errors.Is(err, flag.ErrHelp) {
return nil
}
if noexec := (ffcli.NoExecError{}); errors.As(err, &noexec) {
if noexec, ok := errors.AsType[ffcli.NoExecError](err); ok {
// When the user enters an unknown subcommand, ffcli tries to run
// the closest valid parent subcommand with everything else as args,
// returning NoExecError if it doesn't have an Exec function.
+2 -2
View File
@@ -962,8 +962,8 @@ func TestPrefFlagMapping(t *testing.T) {
}
prefType := reflect.TypeFor[ipn.Prefs]()
for i := range prefType.NumField() {
prefName := prefType.Field(i).Name
for field := range prefType.Fields() {
prefName := field.Name
if prefHasFlag[prefName] {
continue
}
+3 -5
View File
@@ -16,6 +16,7 @@ import (
"os/exec"
"path"
"runtime"
"slices"
"strings"
"github.com/peterbourgon/ff/v3/ffcli"
@@ -85,11 +86,8 @@ func runConfigureSynologyCert(ctx context.Context, args []string) error {
domain = st.CertDomains[0]
} else {
var found bool
for _, d := range st.CertDomains {
if d == domain {
found = true
break
}
if slices.Contains(st.CertDomains, domain) {
found = true
}
if !found {
return fmt.Errorf("Domain %q was not one of the valid domain options: %q.", domain, st.CertDomains)
+3 -4
View File
@@ -19,6 +19,7 @@ import (
"os"
"path"
"path/filepath"
"slices"
"strings"
"sync"
"sync/atomic"
@@ -126,10 +127,8 @@ func runCp(ctx context.Context, args []string) error {
if cpArgs.name != "" {
return errors.New("can't use --name= with multiple files")
}
for _, fileArg := range files {
if fileArg == "-" {
return errors.New("can't use '-' as STDIN file when providing filename arguments")
}
if slices.Contains(files, "-") {
return errors.New("can't use '-' as STDIN file when providing filename arguments")
}
}
+5 -8
View File
@@ -9,6 +9,7 @@ import (
"flag"
"fmt"
"net/netip"
"slices"
"github.com/peterbourgon/ff/v3/ffcli"
"tailscale.com/ipn/ipnstate"
@@ -114,17 +115,13 @@ func peerMatchingIP(st *ipnstate.Status, ipStr string) (ps *ipnstate.PeerStatus,
return
}
for _, ps = range st.Peer {
for _, pip := range ps.TailscaleIPs {
if ip == pip {
return ps, true
}
if slices.Contains(ps.TailscaleIPs, ip) {
return ps, true
}
}
if ps := st.Self; ps != nil {
for _, pip := range ps.TailscaleIPs {
if ip == pip {
return ps, true
}
if slices.Contains(ps.TailscaleIPs, ip) {
return ps, true
}
}
return nil, false
+1 -1
View File
@@ -39,7 +39,7 @@ func registerAcceptRiskFlag(f *flag.FlagSet, acceptedRisks *string) {
// isRiskAccepted reports whether riskType is in the comma-separated list of
// risks in acceptedRisks.
func isRiskAccepted(riskType, acceptedRisks string) bool {
for _, r := range strings.Split(acceptedRisks, ",") {
for r := range strings.SplitSeq(acceptedRisks, ",") {
if r == riskType || r == riskAll {
return true
}
+2 -2
View File
@@ -114,8 +114,8 @@ func (u *acceptAppCapsFlag) Set(s string) error {
if s == "" {
return nil
}
appCaps := strings.Split(s, ",")
for _, appCap := range appCaps {
appCaps := strings.SplitSeq(s, ",")
for appCap := range appCaps {
appCap = strings.TrimSpace(appCap)
if !validAppCap.MatchString(appCap) {
return fmt.Errorf("%q does not match the form {domain}/{name}, where domain must be a fully qualified domain name", appCap)
+3 -4
View File
@@ -183,8 +183,7 @@ func runSet(ctx context.Context, args []string) (retErr error) {
maskedPrefs.AutoExitNode = expr
maskedPrefs.AutoExitNodeSet = true
} else if err := maskedPrefs.Prefs.SetExitNodeIP(setArgs.exitNodeIP, st); err != nil {
var e ipn.ExitNodeLocalIPError
if errors.As(err, &e) {
if _, ok := errors.AsType[ipn.ExitNodeLocalIPError](err); ok {
return fmt.Errorf("%w; did you mean --advertise-exit-node?", err)
}
return err
@@ -251,8 +250,8 @@ func runSet(ctx context.Context, args []string) (retErr error) {
if setArgs.relayServerStaticEndpoints != "" {
endpointsSet := make(set.Set[netip.AddrPort])
endpointsSplit := strings.Split(setArgs.relayServerStaticEndpoints, ",")
for _, s := range endpointsSplit {
endpointsSplit := strings.SplitSeq(setArgs.relayServerStaticEndpoints, ",")
for s := range endpointsSplit {
ap, err := netip.ParseAddrPort(s)
if err != nil {
return fmt.Errorf("failed to set relay server static endpoints: %q is not a valid IP:port", s)
+5 -8
View File
@@ -14,6 +14,7 @@ import (
"os/user"
"path/filepath"
"runtime"
"slices"
"strings"
"github.com/peterbourgon/ff/v3/ffcli"
@@ -202,10 +203,8 @@ func peerStatusFromArg(st *ipnstate.Status, arg string) (*ipnstate.PeerStatus, b
argIP, _ := netip.ParseAddr(arg)
for _, ps := range st.Peer {
if argIP.IsValid() {
for _, ip := range ps.TailscaleIPs {
if ip == argIP {
return ps, true
}
if slices.Contains(ps.TailscaleIPs, argIP) {
return ps, true
}
continue
}
@@ -230,10 +229,8 @@ func nodeDNSNameFromArg(st *ipnstate.Status, arg string) (dnsName string, ok boo
for _, ps := range st.Peer {
dnsName = ps.DNSName
if argIP.IsValid() {
for _, ip := range ps.TailscaleIPs {
if ip == argIP {
return dnsName, true
}
if slices.Contains(ps.TailscaleIPs, argIP) {
return dnsName, true
}
continue
}
+1 -2
View File
@@ -28,9 +28,8 @@ func execSSH(ssh string, argv []string) error {
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
var ee *exec.ExitError
err := cmd.Run()
if errors.As(err, &ee) {
if ee, ok := errors.AsType[*exec.ExitError](err); ok {
os.Exit(ee.ExitCode())
}
return err
+1 -1
View File
@@ -39,7 +39,7 @@ func init() {
return ""
}
prefix := []byte("SSH_CLIENT=")
for _, env := range bytes.Split(b, []byte{0}) {
for env := range bytes.SplitSeq(b, []byte{0}) {
if bytes.HasPrefix(env, prefix) {
return string(env[len(prefix):])
}
+2 -3
View File
@@ -334,8 +334,7 @@ func prefsFromUpArgs(upArgs upArgsT, warnf logger.Logf, st *ipnstate.Status, goo
if expr, useAutoExitNode := ipn.ParseAutoExitNodeString(upArgs.exitNodeIP); useAutoExitNode {
prefs.AutoExitNode = expr
} else if err := prefs.SetExitNodeIP(upArgs.exitNodeIP, st); err != nil {
var e ipn.ExitNodeLocalIPError
if errors.As(err, &e) {
if _, ok := errors.AsType[ipn.ExitNodeLocalIPError](err); ok {
return nil, fmt.Errorf("%w; did you mean --advertise-exit-node?", err)
}
return nil, err
@@ -912,7 +911,7 @@ func addPrefFlagMapping(flagName string, prefNames ...string) {
prefType := reflect.TypeFor[ipn.Prefs]()
for _, pref := range prefNames {
t := prefType
for _, name := range strings.Split(pref, ".") {
for name := range strings.SplitSeq(pref, ".") {
// Crash at runtime if there's a typo in the prefName.
f, ok := t.FieldByName(name)
if !ok {
+1 -2
View File
@@ -352,8 +352,7 @@ func main() {
// If there's nothing to retry and no non-retryable tests have
// failed then we've probably hit a build error.
if err := <-runErr; len(toRetry) == 0 && err != nil {
var exit *exec.ExitError
if errors.As(err, &exit) {
if exit, ok := errors.AsType[*exec.ExitError](err); ok {
if code := exit.ExitCode(); code > -1 {
os.Exit(exit.ExitCode())
}
+1 -2
View File
@@ -273,8 +273,7 @@ func TestCached(t *testing.T) {}
}
func errExitCode(err error) (int, bool) {
var exit *exec.ExitError
if errors.As(err, &exit) {
if exit, ok := errors.AsType[*exec.ExitError](err); ok {
return exit.ExitCode(), true
}
return 0, false
+1 -1
View File
@@ -91,7 +91,7 @@ func main() {
if distro.Get() == distro.Gokrazy {
cmdLine, _ := os.ReadFile("/proc/cmdline")
explicitNS := false
for _, s := range strings.Fields(string(cmdLine)) {
for s := range strings.FieldsSeq(string(cmdLine)) {
if ns, ok := strings.CutPrefix(s, "tta.nameserver="); ok {
err := atomicfile.WriteFile("/tmp/resolv.conf", []byte("nameserver "+ns+"\n"), 0644)
log.Printf("Wrote /tmp/resolv.conf: %v", err)
+2 -3
View File
@@ -500,8 +500,7 @@ func genView(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named, fie
}
writeTemplateWithComment("unsupportedField", fname)
}
for i := range typ.NumMethods() {
f := typ.Method(i)
for f := range typ.Methods() {
if !f.Exported() {
continue
}
@@ -720,7 +719,7 @@ func main() {
fieldComments := getFieldComments(pkg.Syntax)
cloneOnlyType := map[string]bool{}
for _, t := range strings.Split(*flagCloneOnlyTypes, ",") {
for t := range strings.SplitSeq(*flagCloneOnlyTypes, ",") {
cloneOnlyType[t] = true
}