types/ptr: deprecate ptr.To, use Go 1.26 new

Updates #18682

Change-Id: I62f6aa0de2a15ef8c1435032c6aa74a181c25f8f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
main
Brad Fitzpatrick 1 month ago committed by Brad Fitzpatrick
parent 8cfbaa717d
commit 2a64c03c95
  1. 17
      cmd/cloner/cloner.go
  2. 6
      cmd/cloner/clonerex/clonerex_clone.go
  3. 3
      cmd/containerboot/main.go
  4. 25
      cmd/containerboot/main_test.go
  5. 1
      cmd/derper/depaware.txt
  6. 7
      cmd/k8s-operator/api-server-proxy-pg_test.go
  7. 7
      cmd/k8s-operator/api-server-proxy.go
  8. 13
      cmd/k8s-operator/connector_test.go
  9. 1
      cmd/k8s-operator/depaware.txt
  10. 21
      cmd/k8s-operator/dnsrecords_test.go
  11. 3
      cmd/k8s-operator/e2e/ingress_test.go
  12. 4
      cmd/k8s-operator/e2e/pebble.go
  13. 5
      cmd/k8s-operator/e2e/proxygrouppolicy_test.go
  14. 5
      cmd/k8s-operator/e2e/ssh.go
  15. 7
      cmd/k8s-operator/egress-eps.go
  16. 3
      cmd/k8s-operator/egress-pod-readiness_test.go
  17. 21
      cmd/k8s-operator/ingress-for-pg_test.go
  18. 26
      cmd/k8s-operator/ingress_test.go
  19. 3
      cmd/k8s-operator/nameserver.go
  20. 5
      cmd/k8s-operator/nameserver_test.go
  21. 63
      cmd/k8s-operator/operator_test.go
  22. 15
      cmd/k8s-operator/proxygroup.go
  23. 11
      cmd/k8s-operator/proxygroup_specs.go
  24. 59
      cmd/k8s-operator/proxygroup_test.go
  25. 7
      cmd/k8s-operator/sts.go
  26. 17
      cmd/k8s-operator/sts_test.go
  27. 9
      cmd/k8s-operator/svc-for-pg_test.go
  28. 17
      cmd/k8s-operator/testutils_test.go
  29. 3
      cmd/k8s-operator/tsrecorder_specs.go
  30. 7
      cmd/k8s-operator/tsrecorder_specs_test.go
  31. 3
      cmd/k8s-operator/tsrecorder_test.go
  32. 5
      cmd/k8s-proxy/internal/config/config.go
  33. 11
      cmd/k8s-proxy/internal/config/config_test.go
  34. 1
      cmd/stund/depaware.txt
  35. 3
      cmd/tailscale/cli/set.go
  36. 33
      cmd/tailscale/cli/set_test.go
  37. 1
      cmd/tailscale/depaware.txt
  38. 1
      cmd/tailscaled/depaware-min.txt
  39. 1
      cmd/tailscaled/depaware-minbox.txt
  40. 1
      cmd/tailscaled/depaware.txt
  41. 1
      cmd/tsidp/depaware.txt
  42. 3
      cmd/tta/fw_linux.go
  43. 3
      cmd/viewer/tests/tests.go
  44. 37
      cmd/viewer/tests/tests_clone.go
  45. 3
      control/controlclient/direct.go
  46. 19
      control/controlclient/map.go
  47. 45
      control/controlclient/map_test.go
  48. 5
      feature/relayserver/relayserver.go
  49. 49
      feature/relayserver/relayserver_test.go
  50. 5
      hostinfo/hostinfo.go
  51. 3
      hostinfo/hostinfo_darwin.go
  52. 5
      hostinfo/hostinfo_freebsd.go
  53. 5
      hostinfo/hostinfo_linux.go
  54. 3
      hostinfo/hostinfo_uname.go
  55. 7
      hostinfo/hostinfo_windows.go
  56. 7
      ipn/ipn_clone.go
  57. 15
      ipn/ipnlocal/local.go
  58. 83
      ipn/ipnlocal/local_test.go
  59. 3
      ipn/ipnlocal/netstack.go
  60. 3
      ipn/ipnlocal/node_backend.go
  61. 9
      ipn/ipnlocal/node_backend_test.go
  62. 7
      ipn/ipnserver/server_test.go
  63. 3
      ipn/ipnstate/ipnstate.go
  64. 3
      ipn/lapitest/server.go
  65. 5
      ipn/localapi/localapi.go
  66. 5
      k8s-operator/reconciler/proxygrouppolicy/proxygrouppolicy.go
  67. 7
      kube/k8s-proxy/conf/conf_test.go
  68. 9
      net/packet/geneve_test.go
  69. 5
      net/tstun/wrap_test.go
  70. 3
      ssh/tailssh/tailssh_test.go
  71. 23
      tailcfg/tailcfg_clone.go
  72. 13
      tailcfg/tailcfg_test.go
  73. 1
      tsnet/depaware.txt
  74. 7
      tstest/integration/integration_test.go
  75. 5
      tstest/integration/testcontrol/testcontrol.go
  76. 4
      tstest/reflect.go
  77. 3
      types/jsonx/json_test.go
  78. 4
      types/lazy/deferred.go
  79. 8
      types/lazy/lazy.go
  80. 9
      types/netmap/nodemut.go
  81. 7
      types/netmap/nodemut_test.go
  82. 3
      types/prefs/item.go
  83. 3
      types/prefs/list.go
  84. 3
      types/prefs/map.go
  85. 4
      types/prefs/prefs_clone_test.go
  86. 3
      types/prefs/struct_list.go
  87. 3
      types/prefs/struct_map.go
  88. 11
      types/ptr/ptr.go
  89. 3
      types/views/views.go
  90. 9
      util/deephash/deephash_test.go
  91. 3
      util/linuxfw/nftables_runner.go
  92. 4
      util/pool/pool.go
  93. 6
      util/syspolicy/setting/errors.go
  94. 3
      util/syspolicy/setting/setting_test.go
  95. 3
      wgengine/magicsock/magicsock_test.go
  96. 5
      wgengine/wgcfg/wgcfg_clone.go

@ -141,14 +141,12 @@ func gen(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named) {
writef("if src.%s[i] == nil { dst.%s[i] = nil } else {", fname, fname) writef("if src.%s[i] == nil { dst.%s[i] = nil } else {", fname, fname)
if codegen.ContainsPointers(ptr.Elem()) { if codegen.ContainsPointers(ptr.Elem()) {
if _, isIface := ptr.Elem().Underlying().(*types.Interface); isIface { if _, isIface := ptr.Elem().Underlying().(*types.Interface); isIface {
it.Import("", "tailscale.com/types/ptr") writef("\tdst.%s[i] = new((*src.%s[i]).Clone())", fname, fname)
writef("\tdst.%s[i] = ptr.To((*src.%s[i]).Clone())", fname, fname)
} else { } else {
writef("\tdst.%s[i] = src.%s[i].Clone()", fname, fname) writef("\tdst.%s[i] = src.%s[i].Clone()", fname, fname)
} }
} else { } else {
it.Import("", "tailscale.com/types/ptr") writef("\tdst.%s[i] = new(*src.%s[i])", fname, fname)
writef("\tdst.%s[i] = ptr.To(*src.%s[i])", fname, fname)
} }
writef("}") writef("}")
} else if ft.Elem().String() == "encoding/json.RawMessage" { } else if ft.Elem().String() == "encoding/json.RawMessage" {
@ -170,12 +168,11 @@ func gen(buf *bytes.Buffer, it *codegen.ImportTracker, typ *types.Named) {
writef("dst.%s = src.%s.Clone()", fname, fname) writef("dst.%s = src.%s.Clone()", fname, fname)
continue continue
} }
it.Import("", "tailscale.com/types/ptr")
writef("if dst.%s != nil {", fname) writef("if dst.%s != nil {", fname)
if _, isIface := base.Underlying().(*types.Interface); isIface && hasPtrs { if _, isIface := base.Underlying().(*types.Interface); isIface && hasPtrs {
writef("\tdst.%s = ptr.To((*src.%s).Clone())", fname, fname) writef("\tdst.%s = new((*src.%s).Clone())", fname, fname)
} else if !hasPtrs { } else if !hasPtrs {
writef("\tdst.%s = ptr.To(*src.%s)", fname, fname) writef("\tdst.%s = new(*src.%s)", fname, fname)
} else { } else {
writef("\t" + `panic("TODO pointers in pointers")`) writef("\t" + `panic("TODO pointers in pointers")`)
} }
@ -293,14 +290,12 @@ func writeMapValueClone(params mapValueCloneParams) {
writef("if %s == nil { %s = nil } else {", params.SrcExpr, params.DstExpr) writef("if %s == nil { %s = nil } else {", params.SrcExpr, params.DstExpr)
if base := elem.Elem().Underlying(); codegen.ContainsPointers(base) { if base := elem.Elem().Underlying(); codegen.ContainsPointers(base) {
if _, isIface := base.(*types.Interface); isIface { if _, isIface := base.(*types.Interface); isIface {
params.It.Import("", "tailscale.com/types/ptr") writef("\t%s = new((*%s).Clone())", params.DstExpr, params.SrcExpr)
writef("\t%s = ptr.To((*%s).Clone())", params.DstExpr, params.SrcExpr)
} else { } else {
writef("\t%s = %s.Clone()", params.DstExpr, params.SrcExpr) writef("\t%s = %s.Clone()", params.DstExpr, params.SrcExpr)
} }
} else { } else {
params.It.Import("", "tailscale.com/types/ptr") writef("\t%s = new(*%s)", params.DstExpr, params.SrcExpr)
writef("\t%s = ptr.To(*%s)", params.DstExpr, params.SrcExpr)
} }
writef("}") writef("}")

@ -7,8 +7,6 @@ package clonerex
import ( import (
"maps" "maps"
"tailscale.com/types/ptr"
) )
// Clone makes a deep copy of SliceContainer. // Clone makes a deep copy of SliceContainer.
@ -25,7 +23,7 @@ func (src *SliceContainer) Clone() *SliceContainer {
if src.Slice[i] == nil { if src.Slice[i] == nil {
dst.Slice[i] = nil dst.Slice[i] = nil
} else { } else {
dst.Slice[i] = ptr.To(*src.Slice[i]) dst.Slice[i] = new(*src.Slice[i])
} }
} }
} }
@ -70,7 +68,7 @@ func (src *MapWithPointers) Clone() *MapWithPointers {
if v == nil { if v == nil {
dst.Nested[k] = nil dst.Nested[k] = nil
} else { } else {
dst.Nested[k] = ptr.To(*v) dst.Nested[k] = new(*v)
} }
} }
} }

@ -147,7 +147,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/ptr"
"tailscale.com/util/deephash" "tailscale.com/util/deephash"
"tailscale.com/util/dnsname" "tailscale.com/util/dnsname"
"tailscale.com/util/linuxfw" "tailscale.com/util/linuxfw"
@ -612,7 +611,7 @@ runLoop:
if cd == "" { if cd == "" {
cd = kubetypes.ValueNoHTTPS cd = kubetypes.ValueNoHTTPS
} }
prev := certDomain.Swap(ptr.To(cd)) prev := certDomain.Swap(new(cd))
if prev == nil || *prev != cd { if prev == nil || *prev != cd {
select { select {
case certDomainChanged <- true: case certDomainChanged <- true:

@ -38,7 +38,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/ptr"
) )
func TestContainerBoot(t *testing.T) { func TestContainerBoot(t *testing.T) {
@ -95,7 +94,7 @@ func TestContainerBoot(t *testing.T) {
EndpointStatuses map[string]int EndpointStatuses map[string]int
} }
runningNotify := &ipn.Notify{ runningNotify := &ipn.Notify{
State: ptr.To(ipn.Running), State: new(ipn.Running),
NetMap: &netmap.NetworkMap{ NetMap: &netmap.NetworkMap{
SelfNode: (&tailcfg.Node{ SelfNode: (&tailcfg.Node{
StableID: tailcfg.StableNodeID("myID"), StableID: tailcfg.StableNodeID("myID"),
@ -373,7 +372,7 @@ func TestContainerBoot(t *testing.T) {
}, },
{ {
Notify: &ipn.Notify{ Notify: &ipn.Notify{
State: ptr.To(ipn.Running), State: new(ipn.Running),
NetMap: &netmap.NetworkMap{ NetMap: &netmap.NetworkMap{
SelfNode: (&tailcfg.Node{ SelfNode: (&tailcfg.Node{
StableID: tailcfg.StableNodeID("myID"), StableID: tailcfg.StableNodeID("myID"),
@ -390,7 +389,7 @@ func TestContainerBoot(t *testing.T) {
}, },
}, },
WantLog: "no forwarding rules for egress addresses [::1/128], host supports IPv6: false", WantLog: "no forwarding rules for egress addresses [::1/128], host supports IPv6: false",
WantExitCode: ptr.To(1), WantExitCode: new(1),
}, },
}, },
} }
@ -409,7 +408,7 @@ func TestContainerBoot(t *testing.T) {
}, },
{ {
Notify: &ipn.Notify{ Notify: &ipn.Notify{
State: ptr.To(ipn.NeedsLogin), State: new(ipn.NeedsLogin),
}, },
WantCmds: []string{ WantCmds: []string{
"/usr/bin/tailscale --socket=/tmp/tailscaled.sock up --accept-dns=false --authkey=tskey-key", "/usr/bin/tailscale --socket=/tmp/tailscaled.sock up --accept-dns=false --authkey=tskey-key",
@ -440,7 +439,7 @@ func TestContainerBoot(t *testing.T) {
}, },
{ {
Notify: &ipn.Notify{ Notify: &ipn.Notify{
State: ptr.To(ipn.NeedsLogin), State: new(ipn.NeedsLogin),
}, },
WantCmds: []string{ WantCmds: []string{
"/usr/bin/tailscale --socket=/tmp/tailscaled.sock up --accept-dns=true --authkey=tskey-key", "/usr/bin/tailscale --socket=/tmp/tailscaled.sock up --accept-dns=true --authkey=tskey-key",
@ -564,7 +563,7 @@ func TestContainerBoot(t *testing.T) {
}, },
{ {
Notify: &ipn.Notify{ Notify: &ipn.Notify{
State: ptr.To(ipn.NeedsLogin), State: new(ipn.NeedsLogin),
}, },
WantCmds: []string{ WantCmds: []string{
"/usr/bin/tailscale --socket=/tmp/tailscaled.sock up --accept-dns=false --authkey=tskey-key", "/usr/bin/tailscale --socket=/tmp/tailscaled.sock up --accept-dns=false --authkey=tskey-key",
@ -621,7 +620,7 @@ func TestContainerBoot(t *testing.T) {
}, },
{ {
Notify: &ipn.Notify{ Notify: &ipn.Notify{
State: ptr.To(ipn.Running), State: new(ipn.Running),
NetMap: &netmap.NetworkMap{ NetMap: &netmap.NetworkMap{
SelfNode: (&tailcfg.Node{ SelfNode: (&tailcfg.Node{
StableID: tailcfg.StableNodeID("newID"), StableID: tailcfg.StableNodeID("newID"),
@ -964,7 +963,7 @@ func TestContainerBoot(t *testing.T) {
}, },
{ {
Notify: &ipn.Notify{ Notify: &ipn.Notify{
State: ptr.To(ipn.Running), State: new(ipn.Running),
NetMap: &netmap.NetworkMap{ NetMap: &netmap.NetworkMap{
SelfNode: (&tailcfg.Node{ SelfNode: (&tailcfg.Node{
StableID: tailcfg.StableNodeID("myID"), StableID: tailcfg.StableNodeID("myID"),
@ -1004,7 +1003,7 @@ func TestContainerBoot(t *testing.T) {
Phases: []phase{ Phases: []phase{
{ {
WantLog: "TS_EGRESS_PROXIES_CONFIG_PATH is only supported for Tailscale running on Kubernetes", WantLog: "TS_EGRESS_PROXIES_CONFIG_PATH is only supported for Tailscale running on Kubernetes",
WantExitCode: ptr.To(1), WantExitCode: new(1),
}, },
}, },
} }
@ -1053,7 +1052,7 @@ func TestContainerBoot(t *testing.T) {
{ {
// SIGTERM before state is finished writing, should wait for // SIGTERM before state is finished writing, should wait for
// consistent state before propagating SIGTERM to tailscaled. // consistent state before propagating SIGTERM to tailscaled.
Signal: ptr.To(unix.SIGTERM), Signal: new(unix.SIGTERM),
UpdateKubeSecret: map[string]string{ UpdateKubeSecret: map[string]string{
"_machinekey": "foo", "_machinekey": "foo",
"_profiles": "foo", "_profiles": "foo",
@ -1083,7 +1082,7 @@ func TestContainerBoot(t *testing.T) {
kubetypes.KeyCapVer: capver, kubetypes.KeyCapVer: capver,
}, },
WantLog: "HTTP server at [::]:9002 closed", WantLog: "HTTP server at [::]:9002 closed",
WantExitCode: ptr.To(0), WantExitCode: new(0),
}, },
}, },
} }
@ -1661,7 +1660,7 @@ func newTestEnv(t *testing.T) testEnv {
kube.Start(t) kube.Start(t)
t.Cleanup(kube.Close) t.Cleanup(kube.Close)
tailscaledConf := &ipn.ConfigVAlpha{AuthKey: ptr.To("foo"), Version: "alpha0"} tailscaledConf := &ipn.ConfigVAlpha{AuthKey: new("foo"), Version: "alpha0"}
serveConf := ipn.ServeConfig{TCP: map[uint16]*ipn.TCPPortHandler{80: {HTTP: true}}} serveConf := ipn.ServeConfig{TCP: map[uint16]*ipn.TCPPortHandler{80: {HTTP: true}}}
serveConfWithServices := ipn.ServeConfig{ serveConfWithServices := ipn.ServeConfig{
TCP: map[uint16]*ipn.TCPPortHandler{80: {HTTP: true}}, TCP: map[uint16]*ipn.TCPPortHandler{80: {HTTP: true}},

@ -138,7 +138,6 @@ tailscale.com/cmd/derper dependencies: (generated by github.com/tailscale/depawa
tailscale.com/types/opt from tailscale.com/envknob+ tailscale.com/types/opt from tailscale.com/envknob+
tailscale.com/types/persist from tailscale.com/ipn+ tailscale.com/types/persist from tailscale.com/ipn+
tailscale.com/types/preftype from tailscale.com/ipn tailscale.com/types/preftype from tailscale.com/ipn
tailscale.com/types/ptr from tailscale.com/hostinfo+
tailscale.com/types/result from tailscale.com/util/lineiter tailscale.com/types/result from tailscale.com/util/lineiter
tailscale.com/types/structs from tailscale.com/ipn+ tailscale.com/types/structs from tailscale.com/ipn+
tailscale.com/types/tkatype from tailscale.com/client/local+ tailscale.com/types/tkatype from tailscale.com/client/local+

@ -25,7 +25,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
) )
func TestAPIServerProxyReconciler(t *testing.T) { func TestAPIServerProxyReconciler(t *testing.T) {
@ -57,7 +56,7 @@ func TestAPIServerProxyReconciler(t *testing.T) {
initialCfg := &conf.VersionedConfig{ initialCfg := &conf.VersionedConfig{
Version: "v1alpha1", Version: "v1alpha1",
ConfigV1Alpha1: &conf.ConfigV1Alpha1{ ConfigV1Alpha1: &conf.ConfigV1Alpha1{
AuthKey: ptr.To("test-key"), AuthKey: new("test-key"),
APIServerProxy: &conf.APIServerProxyConfig{ APIServerProxy: &conf.APIServerProxyConfig{
Enabled: opt.NewBool(true), Enabled: opt.NewBool(true),
}, },
@ -174,7 +173,7 @@ func TestAPIServerProxyReconciler(t *testing.T) {
tsoperator.SetProxyGroupCondition(pg, tsapi.KubeAPIServerProxyConfigured, metav1.ConditionFalse, reasonKubeAPIServerProxyNoBackends, "", 1, r.clock, r.logger) tsoperator.SetProxyGroupCondition(pg, tsapi.KubeAPIServerProxyConfigured, metav1.ConditionFalse, reasonKubeAPIServerProxyNoBackends, "", 1, r.clock, r.logger)
expectEqual(t, fc, pg, omitPGStatusConditionMessages) expectEqual(t, fc, pg, omitPGStatusConditionMessages)
expectedCfg.APIServerProxy.ServiceName = ptr.To(tailcfg.ServiceName("svc:" + pgName)) expectedCfg.APIServerProxy.ServiceName = new(tailcfg.ServiceName("svc:" + pgName))
expectCfg(&expectedCfg) expectCfg(&expectedCfg)
expectEqual(t, fc, certSecret(pgName, ns, defaultDomain, pg)) expectEqual(t, fc, certSecret(pgName, ns, defaultDomain, pg))
@ -230,7 +229,7 @@ func TestAPIServerProxyReconciler(t *testing.T) {
t.Fatalf("expected Tailscale Service to be %+v, got %+v", expectedTSSvc, tsSvc) t.Fatalf("expected Tailscale Service to be %+v, got %+v", expectedTSSvc, tsSvc)
} }
// Check cfg and status reset until TLS certs are available again. // Check cfg and status reset until TLS certs are available again.
expectedCfg.APIServerProxy.ServiceName = ptr.To(updatedServiceName) expectedCfg.APIServerProxy.ServiceName = new(updatedServiceName)
expectedCfg.AdvertiseServices = nil expectedCfg.AdvertiseServices = nil
expectCfg(&expectedCfg) expectCfg(&expectedCfg)
tsoperator.SetProxyGroupCondition(pg, tsapi.KubeAPIServerProxyConfigured, metav1.ConditionFalse, reasonKubeAPIServerProxyNoBackends, "", 1, r.clock, r.logger) tsoperator.SetProxyGroupCondition(pg, tsapi.KubeAPIServerProxyConfigured, metav1.ConditionFalse, reasonKubeAPIServerProxyNoBackends, "", 1, r.clock, r.logger)

@ -11,7 +11,6 @@ import (
"os" "os"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/types/ptr"
) )
func parseAPIProxyMode() *kubetypes.APIServerProxyMode { func parseAPIProxyMode() *kubetypes.APIServerProxyMode {
@ -23,18 +22,18 @@ func parseAPIProxyMode() *kubetypes.APIServerProxyMode {
case haveAuthProxyEnv: case haveAuthProxyEnv:
var authProxyEnv = defaultBool("AUTH_PROXY", false) // deprecated var authProxyEnv = defaultBool("AUTH_PROXY", false) // deprecated
if authProxyEnv { if authProxyEnv {
return ptr.To(kubetypes.APIServerProxyModeAuth) return new(kubetypes.APIServerProxyModeAuth)
} }
return nil return nil
case haveAPIProxyEnv: case haveAPIProxyEnv:
var apiProxyEnv = defaultEnv("APISERVER_PROXY", "") // true, false or "noauth" var apiProxyEnv = defaultEnv("APISERVER_PROXY", "") // true, false or "noauth"
switch apiProxyEnv { switch apiProxyEnv {
case "true": case "true":
return ptr.To(kubetypes.APIServerProxyModeAuth) return new(kubetypes.APIServerProxyModeAuth)
case "false", "": case "false", "":
return nil return nil
case "noauth": case "noauth":
return ptr.To(kubetypes.APIServerProxyModeNoAuth) return new(kubetypes.APIServerProxyModeNoAuth)
default: default:
panic(fmt.Sprintf("unknown APISERVER_PROXY value %q", apiProxyEnv)) panic(fmt.Sprintf("unknown APISERVER_PROXY value %q", apiProxyEnv))
} }

@ -22,7 +22,6 @@ import (
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/ptr"
"tailscale.com/util/mak" "tailscale.com/util/mak"
) )
@ -39,7 +38,7 @@ func TestConnector(t *testing.T) {
APIVersion: "tailscale.com/v1alpha1", APIVersion: "tailscale.com/v1alpha1",
}, },
Spec: tsapi.ConnectorSpec{ Spec: tsapi.ConnectorSpec{
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
SubnetRouter: &tsapi.SubnetRouter{ SubnetRouter: &tsapi.SubnetRouter{
AdvertiseRoutes: []tsapi.Route{"10.40.0.0/14"}, AdvertiseRoutes: []tsapi.Route{"10.40.0.0/14"},
}, },
@ -166,7 +165,7 @@ func TestConnector(t *testing.T) {
APIVersion: "tailscale.io/v1alpha1", APIVersion: "tailscale.io/v1alpha1",
}, },
Spec: tsapi.ConnectorSpec{ Spec: tsapi.ConnectorSpec{
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
SubnetRouter: &tsapi.SubnetRouter{ SubnetRouter: &tsapi.SubnetRouter{
AdvertiseRoutes: []tsapi.Route{"10.40.0.0/14"}, AdvertiseRoutes: []tsapi.Route{"10.40.0.0/14"},
}, },
@ -229,7 +228,7 @@ func TestConnectorWithProxyClass(t *testing.T) {
APIVersion: "tailscale.io/v1alpha1", APIVersion: "tailscale.io/v1alpha1",
}, },
Spec: tsapi.ConnectorSpec{ Spec: tsapi.ConnectorSpec{
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
SubnetRouter: &tsapi.SubnetRouter{ SubnetRouter: &tsapi.SubnetRouter{
AdvertiseRoutes: []tsapi.Route{"10.40.0.0/14"}, AdvertiseRoutes: []tsapi.Route{"10.40.0.0/14"},
}, },
@ -326,7 +325,7 @@ func TestConnectorWithAppConnector(t *testing.T) {
APIVersion: "tailscale.io/v1alpha1", APIVersion: "tailscale.io/v1alpha1",
}, },
Spec: tsapi.ConnectorSpec{ Spec: tsapi.ConnectorSpec{
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
AppConnector: &tsapi.AppConnector{}, AppConnector: &tsapi.AppConnector{},
}, },
} }
@ -425,7 +424,7 @@ func TestConnectorWithMultipleReplicas(t *testing.T) {
APIVersion: "tailscale.io/v1alpha1", APIVersion: "tailscale.io/v1alpha1",
}, },
Spec: tsapi.ConnectorSpec{ Spec: tsapi.ConnectorSpec{
Replicas: ptr.To[int32](3), Replicas: new(int32(3)),
AppConnector: &tsapi.AppConnector{}, AppConnector: &tsapi.AppConnector{},
HostnamePrefix: "test-connector", HostnamePrefix: "test-connector",
}, },
@ -496,7 +495,7 @@ func TestConnectorWithMultipleReplicas(t *testing.T) {
// 5. We'll scale the connector down by 1 replica and make sure its secret is cleaned up // 5. We'll scale the connector down by 1 replica and make sure its secret is cleaned up
mustUpdate[tsapi.Connector](t, fc, "", "test", func(conn *tsapi.Connector) { mustUpdate[tsapi.Connector](t, fc, "", "test", func(conn *tsapi.Connector) {
conn.Spec.Replicas = ptr.To[int32](2) conn.Spec.Replicas = new(int32(2))
}) })
expectReconciled(t, cr, "", "test") expectReconciled(t, cr, "", "test")
names = findGenNames(t, fc, "", "test", "connector") names = findGenNames(t, fc, "", "test", "connector")

@ -927,7 +927,6 @@ tailscale.com/cmd/k8s-operator dependencies: (generated by github.com/tailscale/
tailscale.com/types/opt from tailscale.com/client/tailscale+ tailscale.com/types/opt from tailscale.com/client/tailscale+
tailscale.com/types/persist from tailscale.com/control/controlclient+ tailscale.com/types/persist from tailscale.com/control/controlclient+
tailscale.com/types/preftype from tailscale.com/ipn+ tailscale.com/types/preftype from tailscale.com/ipn+
tailscale.com/types/ptr from tailscale.com/cmd/k8s-operator+
tailscale.com/types/result from tailscale.com/util/lineiter tailscale.com/types/result from tailscale.com/util/lineiter
tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/structs from tailscale.com/control/controlclient+
tailscale.com/types/tkatype from tailscale.com/client/local+ tailscale.com/types/tkatype from tailscale.com/client/local+

@ -25,7 +25,6 @@ import (
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/ptr"
) )
func TestDNSRecordsReconciler(t *testing.T) { func TestDNSRecordsReconciler(t *testing.T) {
@ -44,7 +43,7 @@ func TestDNSRecordsReconciler(t *testing.T) {
Namespace: "test", Namespace: "test",
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
}, },
Status: networkingv1.IngressStatus{ Status: networkingv1.IngressStatus{
LoadBalancer: networkingv1.IngressLoadBalancerStatus{ LoadBalancer: networkingv1.IngressLoadBalancerStatus{
@ -150,7 +149,7 @@ func TestDNSRecordsReconciler(t *testing.T) {
// 7. A not-ready Endpoint is removed from DNS config. // 7. A not-ready Endpoint is removed from DNS config.
mustUpdate(t, fc, ep.Namespace, ep.Name, func(ep *discoveryv1.EndpointSlice) { mustUpdate(t, fc, ep.Namespace, ep.Name, func(ep *discoveryv1.EndpointSlice) {
ep.Endpoints[0].Conditions.Ready = ptr.To(false) ep.Endpoints[0].Conditions.Ready = new(false)
ep.Endpoints = append(ep.Endpoints, discoveryv1.Endpoint{ ep.Endpoints = append(ep.Endpoints, discoveryv1.Endpoint{
Addresses: []string{"1.2.3.4"}, Addresses: []string{"1.2.3.4"},
}) })
@ -220,13 +219,13 @@ func TestDNSRecordsReconciler(t *testing.T) {
Endpoints: []discoveryv1.Endpoint{{ Endpoints: []discoveryv1.Endpoint{{
Addresses: []string{"10.1.0.100", "10.1.0.101", "10.1.0.102"}, // Pod IPs that should NOT be used Addresses: []string{"10.1.0.100", "10.1.0.101", "10.1.0.102"}, // Pod IPs that should NOT be used
Conditions: discoveryv1.EndpointConditions{ Conditions: discoveryv1.EndpointConditions{
Ready: ptr.To(true), Ready: new(true),
Serving: ptr.To(true), Serving: new(true),
Terminating: ptr.To(false), Terminating: new(false),
}, },
}}, }},
Ports: []discoveryv1.EndpointPort{{ Ports: []discoveryv1.EndpointPort{{
Port: ptr.To(int32(10443)), Port: new(int32(10443)),
}}, }},
} }
@ -316,7 +315,7 @@ func TestDNSRecordsReconcilerDualStack(t *testing.T) {
Namespace: "test", Namespace: "test",
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
}, },
Status: networkingv1.IngressStatus{ Status: networkingv1.IngressStatus{
LoadBalancer: networkingv1.IngressLoadBalancerStatus{ LoadBalancer: networkingv1.IngressLoadBalancerStatus{
@ -447,9 +446,9 @@ func endpointSliceForService(svc *corev1.Service, ip string, fam discoveryv1.Add
Endpoints: []discoveryv1.Endpoint{{ Endpoints: []discoveryv1.Endpoint{{
Addresses: []string{ip}, Addresses: []string{ip},
Conditions: discoveryv1.EndpointConditions{ Conditions: discoveryv1.EndpointConditions{
Ready: ptr.To(true), Ready: new(true),
Serving: ptr.To(true), Serving: new(true),
Terminating: ptr.To(false), Terminating: new(false),
}, },
}}, }},
} }

@ -22,7 +22,6 @@ import (
"tailscale.com/cmd/testwrapper/flakytest" "tailscale.com/cmd/testwrapper/flakytest"
kube "tailscale.com/k8s-operator" kube "tailscale.com/k8s-operator"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/ptr"
"tailscale.com/util/httpm" "tailscale.com/util/httpm"
) )
@ -44,7 +43,7 @@ func TestIngress(t *testing.T) {
}, },
}, },
Spec: appsv1.DeploymentSpec{ Spec: appsv1.DeploymentSpec{
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
Selector: &metav1.LabelSelector{ Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{ MatchLabels: map[string]string{
"app.kubernetes.io/name": "nginx", "app.kubernetes.io/name": "nginx",

@ -12,8 +12,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"tailscale.com/types/ptr"
) )
func applyPebbleResources(ctx context.Context, cl client.Client) error { func applyPebbleResources(ctx context.Context, cl client.Client) error {
@ -46,7 +44,7 @@ func pebbleDeployment(tag string) *appsv1.Deployment {
Namespace: ns, Namespace: ns,
}, },
Spec: appsv1.DeploymentSpec{ Spec: appsv1.DeploymentSpec{
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
Selector: &metav1.LabelSelector{ Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{ MatchLabels: map[string]string{
"app": "pebble", "app": "pebble",

@ -13,7 +13,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/types/ptr"
) )
// See [TestMain] for test requirements. // See [TestMain] for test requirements.
@ -82,7 +81,7 @@ func TestProxyGroupPolicy(t *testing.T) {
}, },
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
Ports: []corev1.ServicePort{ Ports: []corev1.ServicePort{
{ {
Port: 8080, Port: 8080,
@ -112,7 +111,7 @@ func TestProxyGroupPolicy(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
DefaultBackend: &networkingv1.IngressBackend{ DefaultBackend: &networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{ Service: &networkingv1.IngressServiceBackend{
Name: "nginx", Name: "nginx",

@ -26,7 +26,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
tailscaleroot "tailscale.com" tailscaleroot "tailscale.com"
"tailscale.com/types/ptr"
) )
const ( const (
@ -206,7 +205,7 @@ func applySSHResources(ctx context.Context, cl client.Client, alpineTag string,
func cleanupSSHResources(ctx context.Context, cl client.Client) error { func cleanupSSHResources(ctx context.Context, cl client.Client) error {
noGrace := &client.DeleteOptions{ noGrace := &client.DeleteOptions{
GracePeriodSeconds: ptr.To[int64](0), GracePeriodSeconds: new(int64(0)),
} }
if err := cl.Delete(ctx, sshDeployment("", nil), noGrace); err != nil { if err := cl.Delete(ctx, sshDeployment("", nil), noGrace); err != nil {
return fmt.Errorf("failed to delete ssh-server Deployment: %w", err) return fmt.Errorf("failed to delete ssh-server Deployment: %w", err)
@ -232,7 +231,7 @@ func sshDeployment(tag string, pubKey []byte) *appsv1.Deployment {
Namespace: ns, Namespace: ns,
}, },
Spec: appsv1.DeploymentSpec{ Spec: appsv1.DeploymentSpec{
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
Selector: &metav1.LabelSelector{ Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{ MatchLabels: map[string]string{
"app": "ssh-server", "app": "ssh-server",

@ -21,7 +21,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/reconcile"
"tailscale.com/kube/egressservices" "tailscale.com/kube/egressservices"
"tailscale.com/types/ptr"
) )
// egressEpsReconciler reconciles EndpointSlices for tailnet services exposed to cluster via egress ProxyGroup proxies. // egressEpsReconciler reconciles EndpointSlices for tailnet services exposed to cluster via egress ProxyGroup proxies.
@ -120,9 +119,9 @@ func (er *egressEpsReconciler) Reconcile(ctx context.Context, req reconcile.Requ
Hostname: (*string)(&pod.UID), Hostname: (*string)(&pod.UID),
Addresses: []string{podIP}, Addresses: []string{podIP},
Conditions: discoveryv1.EndpointConditions{ Conditions: discoveryv1.EndpointConditions{
Ready: ptr.To(true), Ready: new(true),
Serving: ptr.To(true), Serving: new(true),
Terminating: ptr.To(false), Terminating: new(false),
}, },
}) })
} }

@ -24,7 +24,6 @@ import (
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/ptr"
) )
func TestEgressPodReadiness(t *testing.T) { func TestEgressPodReadiness(t *testing.T) {
@ -48,7 +47,7 @@ func TestEgressPodReadiness(t *testing.T) {
}, },
Spec: tsapi.ProxyGroupSpec{ Spec: tsapi.ProxyGroupSpec{
Type: "egress", Type: "egress",
Replicas: ptr.To(int32(3)), Replicas: new(int32(3)),
}, },
} }
mustCreate(t, fc, pg) mustCreate(t, fc, pg)

@ -33,7 +33,6 @@ import (
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/ptr"
) )
func TestIngressPGReconciler(t *testing.T) { func TestIngressPGReconciler(t *testing.T) {
@ -50,7 +49,7 @@ func TestIngressPGReconciler(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
DefaultBackend: &networkingv1.IngressBackend{ DefaultBackend: &networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{ Service: &networkingv1.IngressServiceBackend{
Name: "test", Name: "test",
@ -117,7 +116,7 @@ func TestIngressPGReconciler(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
DefaultBackend: &networkingv1.IngressBackend{ DefaultBackend: &networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{ Service: &networkingv1.IngressServiceBackend{
Name: "test", Name: "test",
@ -242,7 +241,7 @@ func TestIngressPGReconciler(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
DefaultBackend: &networkingv1.IngressBackend{ DefaultBackend: &networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{ Service: &networkingv1.IngressServiceBackend{
Name: "test", Name: "test",
@ -286,7 +285,7 @@ func TestIngressPGReconciler_UpdateIngressHostname(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
DefaultBackend: &networkingv1.IngressBackend{ DefaultBackend: &networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{ Service: &networkingv1.IngressServiceBackend{
Name: "test", Name: "test",
@ -341,7 +340,7 @@ func TestValidateIngress(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
TLS: []networkingv1.IngressTLS{ TLS: []networkingv1.IngressTLS{
{Hosts: []string{"test"}}, {Hosts: []string{"test"}},
}, },
@ -475,7 +474,7 @@ func TestValidateIngress(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
TLS: []networkingv1.IngressTLS{ TLS: []networkingv1.IngressTLS{
{Hosts: []string{"test"}}, {Hosts: []string{"test"}},
}, },
@ -522,7 +521,7 @@ func TestIngressPGReconciler_HTTPEndpoint(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
DefaultBackend: &networkingv1.IngressBackend{ DefaultBackend: &networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{ Service: &networkingv1.IngressServiceBackend{
Name: "test", Name: "test",
@ -651,7 +650,7 @@ func TestIngressPGReconciler_HTTPRedirect(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
DefaultBackend: &networkingv1.IngressBackend{ DefaultBackend: &networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{ Service: &networkingv1.IngressServiceBackend{
Name: "test", Name: "test",
@ -775,7 +774,7 @@ func TestIngressPGReconciler_HTTPEndpointAndRedirectConflict(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
DefaultBackend: &networkingv1.IngressBackend{ DefaultBackend: &networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{ Service: &networkingv1.IngressServiceBackend{
Name: "test", Name: "test",
@ -864,7 +863,7 @@ func TestIngressPGReconciler_MultiCluster(t *testing.T) {
}, },
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
TLS: []networkingv1.IngressTLS{ TLS: []networkingv1.IngressTLS{
{Hosts: []string{"my-svc"}}, {Hosts: []string{"my-svc"}},
}, },

@ -25,7 +25,6 @@ import (
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/ptr"
"tailscale.com/util/mak" "tailscale.com/util/mak"
) )
@ -59,7 +58,7 @@ func TestTailscaleIngress(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "ingress") fullName, shortName := findGenName(t, fc, "default", "test", "ingress")
opts := configOpts{ opts := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -109,7 +108,7 @@ func TestTailscaleIngress(t *testing.T) {
// 4. Resources get cleaned up when Ingress class is unset // 4. Resources get cleaned up when Ingress class is unset
mustUpdate(t, fc, "default", "test", func(ing *networkingv1.Ingress) { mustUpdate(t, fc, "default", "test", func(ing *networkingv1.Ingress) {
ing.Spec.IngressClassName = ptr.To("nginx") ing.Spec.IngressClassName = new("nginx")
}) })
expectReconciled(t, ingR, "default", "test") expectReconciled(t, ingR, "default", "test")
expectReconciled(t, ingR, "default", "test") // deleting Ingress STS requires two reconciles expectReconciled(t, ingR, "default", "test") // deleting Ingress STS requires two reconciles
@ -639,7 +638,7 @@ func TestEmptyPath(t *testing.T) {
name: "empty_path_with_prefix_type", name: "empty_path_with_prefix_type",
paths: []networkingv1.HTTPIngressPath{ paths: []networkingv1.HTTPIngressPath{
{ {
PathType: ptrPathType(networkingv1.PathTypePrefix), PathType: new(networkingv1.PathTypePrefix),
Path: "", Path: "",
Backend: *backend(), Backend: *backend(),
}, },
@ -652,7 +651,7 @@ func TestEmptyPath(t *testing.T) {
name: "empty_path_with_implementation_specific_type", name: "empty_path_with_implementation_specific_type",
paths: []networkingv1.HTTPIngressPath{ paths: []networkingv1.HTTPIngressPath{
{ {
PathType: ptrPathType(networkingv1.PathTypeImplementationSpecific), PathType: new(networkingv1.PathTypeImplementationSpecific),
Path: "", Path: "",
Backend: *backend(), Backend: *backend(),
}, },
@ -665,7 +664,7 @@ func TestEmptyPath(t *testing.T) {
name: "empty_path_with_exact_type", name: "empty_path_with_exact_type",
paths: []networkingv1.HTTPIngressPath{ paths: []networkingv1.HTTPIngressPath{
{ {
PathType: ptrPathType(networkingv1.PathTypeExact), PathType: new(networkingv1.PathTypeExact),
Path: "", Path: "",
Backend: *backend(), Backend: *backend(),
}, },
@ -679,12 +678,12 @@ func TestEmptyPath(t *testing.T) {
name: "two_competing_but_not_identical_paths_including_one_empty", name: "two_competing_but_not_identical_paths_including_one_empty",
paths: []networkingv1.HTTPIngressPath{ paths: []networkingv1.HTTPIngressPath{
{ {
PathType: ptrPathType(networkingv1.PathTypeImplementationSpecific), PathType: new(networkingv1.PathTypeImplementationSpecific),
Path: "", Path: "",
Backend: *backend(), Backend: *backend(),
}, },
{ {
PathType: ptrPathType(networkingv1.PathTypeImplementationSpecific), PathType: new(networkingv1.PathTypeImplementationSpecific),
Path: "/", Path: "/",
Backend: *backend(), Backend: *backend(),
}, },
@ -760,11 +759,6 @@ func TestEmptyPath(t *testing.T) {
} }
} }
// ptrPathType is a helper function to return a pointer to the pathtype string (required for TestEmptyPath)
func ptrPathType(p networkingv1.PathType) *networkingv1.PathType {
return &p
}
func ingressClass() *networkingv1.IngressClass { func ingressClass() *networkingv1.IngressClass {
return &networkingv1.IngressClass{ return &networkingv1.IngressClass{
ObjectMeta: metav1.ObjectMeta{Name: "tailscale"}, ObjectMeta: metav1.ObjectMeta{Name: "tailscale"},
@ -799,7 +793,7 @@ func ingress() *networkingv1.Ingress {
UID: "1234-UID", UID: "1234-UID",
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
DefaultBackend: backend(), DefaultBackend: backend(),
TLS: []networkingv1.IngressTLS{ TLS: []networkingv1.IngressTLS{
{Hosts: []string{"default-test"}}, {Hosts: []string{"default-test"}},
@ -817,7 +811,7 @@ func ingressWithPaths(paths []networkingv1.HTTPIngressPath) *networkingv1.Ingres
UID: types.UID("1234-UID"), UID: types.UID("1234-UID"),
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
Rules: []networkingv1.IngressRule{ Rules: []networkingv1.IngressRule{
{ {
Host: "foo.tailnetxyz.ts.net", Host: "foo.tailnetxyz.ts.net",
@ -878,7 +872,7 @@ func TestTailscaleIngressWithHTTPRedirect(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "ingress") fullName, shortName := findGenName(t, fc, "default", "test", "ingress")
opts := configOpts{ opts := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",

@ -31,7 +31,6 @@ import (
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/tstime" "tailscale.com/tstime"
"tailscale.com/types/ptr"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/set" "tailscale.com/util/set"
) )
@ -245,7 +244,7 @@ var (
if err := yaml.Unmarshal(deployYaml, &d); err != nil { if err := yaml.Unmarshal(deployYaml, &d); err != nil {
return fmt.Errorf("error unmarshalling Deployment yaml: %w", err) return fmt.Errorf("error unmarshalling Deployment yaml: %w", err)
} }
d.Spec.Replicas = ptr.To(cfg.replicas) d.Spec.Replicas = new(cfg.replicas)
d.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:%s", cfg.imageRepo, cfg.imageTag) d.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:%s", cfg.imageRepo, cfg.imageTag)
d.ObjectMeta.Namespace = cfg.namespace d.ObjectMeta.Namespace = cfg.namespace
d.ObjectMeta.Labels = cfg.labels d.ObjectMeta.Labels = cfg.labels

@ -23,7 +23,6 @@ import (
operatorutils "tailscale.com/k8s-operator" operatorutils "tailscale.com/k8s-operator"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/ptr"
"tailscale.com/util/mak" "tailscale.com/util/mak"
) )
@ -35,7 +34,7 @@ func TestNameserverReconciler(t *testing.T) {
}, },
Spec: tsapi.DNSConfigSpec{ Spec: tsapi.DNSConfigSpec{
Nameserver: &tsapi.Nameserver{ Nameserver: &tsapi.Nameserver{
Replicas: ptr.To[int32](3), Replicas: new(int32(3)),
Image: &tsapi.NameserverImage{ Image: &tsapi.NameserverImage{
Repo: "test", Repo: "test",
Tag: "v0.0.1", Tag: "v0.0.1",
@ -87,7 +86,7 @@ func TestNameserverReconciler(t *testing.T) {
} }
wantsDeploy.OwnerReferences = []metav1.OwnerReference{*ownerReference} wantsDeploy.OwnerReferences = []metav1.OwnerReference{*ownerReference}
wantsDeploy.Spec.Template.Spec.Containers[0].Image = "test:v0.0.1" wantsDeploy.Spec.Template.Spec.Containers[0].Image = "test:v0.0.1"
wantsDeploy.Spec.Replicas = ptr.To[int32](3) wantsDeploy.Spec.Replicas = new(int32(3))
wantsDeploy.Namespace = tsNamespace wantsDeploy.Namespace = tsNamespace
wantsDeploy.ObjectMeta.Labels = nameserverLabels wantsDeploy.ObjectMeta.Labels = nameserverLabels
wantsDeploy.Spec.Template.Spec.Tolerations = []corev1.Toleration{ wantsDeploy.Spec.Template.Spec.Tolerations = []corev1.Toleration{

@ -30,7 +30,6 @@ import (
"tailscale.com/net/dns/resolvconffile" "tailscale.com/net/dns/resolvconffile"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/tstime" "tailscale.com/tstime"
"tailscale.com/types/ptr"
"tailscale.com/util/dnsname" "tailscale.com/util/dnsname"
"tailscale.com/util/mak" "tailscale.com/util/mak"
) )
@ -71,7 +70,7 @@ func TestLoadBalancerClass(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
}) })
@ -94,7 +93,7 @@ func TestLoadBalancerClass(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
Status: corev1.ServiceStatus{ Status: corev1.ServiceStatus{
Conditions: []metav1.Condition{{ Conditions: []metav1.Condition{{
@ -119,7 +118,7 @@ func TestLoadBalancerClass(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
opts := configOpts{ opts := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -259,7 +258,7 @@ func TestTailnetTargetFQDNAnnotation(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
o := configOpts{ o := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -369,7 +368,7 @@ func TestTailnetTargetIPAnnotation(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
o := configOpts{ o := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -466,7 +465,7 @@ func TestTailnetTargetIPAnnotation_IPCouldNotBeParsed(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
}) })
@ -486,7 +485,7 @@ func TestTailnetTargetIPAnnotation_IPCouldNotBeParsed(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
Status: corev1.ServiceStatus{ Status: corev1.ServiceStatus{
Conditions: []metav1.Condition{{ Conditions: []metav1.Condition{{
@ -534,7 +533,7 @@ func TestTailnetTargetIPAnnotation_InvalidIP(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
}) })
@ -554,7 +553,7 @@ func TestTailnetTargetIPAnnotation_InvalidIP(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
Status: corev1.ServiceStatus{ Status: corev1.ServiceStatus{
Conditions: []metav1.Condition{{ Conditions: []metav1.Condition{{
@ -612,7 +611,7 @@ func TestAnnotations(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
o := configOpts{ o := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -716,7 +715,7 @@ func TestAnnotationIntoLB(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
o := configOpts{ o := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -767,7 +766,7 @@ func TestAnnotationIntoLB(t *testing.T) {
mustUpdate(t, fc, "default", "test", func(s *corev1.Service) { mustUpdate(t, fc, "default", "test", func(s *corev1.Service) {
delete(s.ObjectMeta.Annotations, "tailscale.com/expose") delete(s.ObjectMeta.Annotations, "tailscale.com/expose")
s.Spec.Type = corev1.ServiceTypeLoadBalancer s.Spec.Type = corev1.ServiceTypeLoadBalancer
s.Spec.LoadBalancerClass = ptr.To("tailscale") s.Spec.LoadBalancerClass = new("tailscale")
}) })
expectReconciled(t, sr, "default", "test") expectReconciled(t, sr, "default", "test")
// None of the proxy machinery should have changed... // None of the proxy machinery should have changed...
@ -785,7 +784,7 @@ func TestAnnotationIntoLB(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
Status: corev1.ServiceStatus{ Status: corev1.ServiceStatus{
LoadBalancer: corev1.LoadBalancerStatus{ LoadBalancer: corev1.LoadBalancerStatus{
@ -836,7 +835,7 @@ func TestLBIntoAnnotation(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
}) })
@ -844,7 +843,7 @@ func TestLBIntoAnnotation(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
o := configOpts{ o := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -880,7 +879,7 @@ func TestLBIntoAnnotation(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
Status: corev1.ServiceStatus{ Status: corev1.ServiceStatus{
LoadBalancer: corev1.LoadBalancerStatus{ LoadBalancer: corev1.LoadBalancerStatus{
@ -982,7 +981,7 @@ func TestCustomHostname(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
o := configOpts{ o := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -1092,7 +1091,7 @@ func TestCustomPriorityClassName(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
o := configOpts{ o := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -1332,13 +1331,13 @@ func TestProxyClassForService(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
}) })
expectReconciled(t, sr, "default", "test") expectReconciled(t, sr, "default", "test")
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
opts := configOpts{ opts := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -1431,7 +1430,7 @@ func TestDefaultLoadBalancer(t *testing.T) {
expectEqual(t, fc, expectedHeadlessService(shortName, "svc")) expectEqual(t, fc, expectedHeadlessService(shortName, "svc"))
o := configOpts{ o := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -1484,7 +1483,7 @@ func TestProxyFirewallMode(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
o := configOpts{ o := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -1596,7 +1595,7 @@ func Test_serviceHandlerForIngress(t *testing.T) {
Name: "ing-1", Name: "ing-1",
Namespace: "ns-1", Namespace: "ns-1",
}, },
Spec: networkingv1.IngressSpec{IngressClassName: ptr.To(tailscaleIngressClassName)}, Spec: networkingv1.IngressSpec{IngressClassName: new(tailscaleIngressClassName)},
}) })
svc1 := &corev1.Service{ svc1 := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
@ -1628,7 +1627,7 @@ func Test_serviceHandlerForIngress(t *testing.T) {
DefaultBackend: &networkingv1.IngressBackend{ DefaultBackend: &networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{Name: "def-backend"}, Service: &networkingv1.IngressServiceBackend{Name: "def-backend"},
}, },
IngressClassName: ptr.To(tailscaleIngressClassName), IngressClassName: new(tailscaleIngressClassName),
}, },
}) })
backendSvc := &corev1.Service{ backendSvc := &corev1.Service{
@ -1652,7 +1651,7 @@ func Test_serviceHandlerForIngress(t *testing.T) {
Namespace: "ns-3", Namespace: "ns-3",
}, },
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To(tailscaleIngressClassName), IngressClassName: new(tailscaleIngressClassName),
Rules: []networkingv1.IngressRule{{IngressRuleValue: networkingv1.IngressRuleValue{HTTP: &networkingv1.HTTPIngressRuleValue{ Rules: []networkingv1.IngressRule{{IngressRuleValue: networkingv1.IngressRuleValue{HTTP: &networkingv1.HTTPIngressRuleValue{
Paths: []networkingv1.HTTPIngressPath{ Paths: []networkingv1.HTTPIngressPath{
{Backend: networkingv1.IngressBackend{Service: &networkingv1.IngressServiceBackend{Name: "backend"}}}, {Backend: networkingv1.IngressBackend{Service: &networkingv1.IngressServiceBackend{Name: "backend"}}},
@ -1727,7 +1726,7 @@ func Test_serviceHandlerForIngress_multipleIngressClasses(t *testing.T) {
mustCreate(t, fc, &networkingv1.Ingress{ mustCreate(t, fc, &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{Name: "nginx-ing", Namespace: "default"}, ObjectMeta: metav1.ObjectMeta{Name: "nginx-ing", Namespace: "default"},
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("nginx"), IngressClassName: new("nginx"),
DefaultBackend: &networkingv1.IngressBackend{Service: &networkingv1.IngressServiceBackend{Name: "backend"}}, DefaultBackend: &networkingv1.IngressBackend{Service: &networkingv1.IngressServiceBackend{Name: "backend"}},
}, },
}) })
@ -1735,7 +1734,7 @@ func Test_serviceHandlerForIngress_multipleIngressClasses(t *testing.T) {
mustCreate(t, fc, &networkingv1.Ingress{ mustCreate(t, fc, &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{Name: "ts-ing", Namespace: "default"}, ObjectMeta: metav1.ObjectMeta{Name: "ts-ing", Namespace: "default"},
Spec: networkingv1.IngressSpec{ Spec: networkingv1.IngressSpec{
IngressClassName: ptr.To("tailscale"), IngressClassName: new("tailscale"),
DefaultBackend: &networkingv1.IngressBackend{Service: &networkingv1.IngressServiceBackend{Name: "backend"}}, DefaultBackend: &networkingv1.IngressBackend{Service: &networkingv1.IngressServiceBackend{Name: "backend"}},
}, },
}) })
@ -1844,7 +1843,7 @@ func Test_authKeyRemoval(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
}) })
@ -1859,7 +1858,7 @@ func Test_authKeyRemoval(t *testing.T) {
hostname: "default-test", hostname: "default-test",
clusterTargetIP: "10.20.30.40", clusterTargetIP: "10.20.30.40",
app: kubetypes.AppIngressProxy, app: kubetypes.AppIngressProxy,
replicas: ptr.To[int32](1), replicas: new(int32(1)),
} }
expectEqual(t, fc, expectedSecret(t, fc, opts)) expectEqual(t, fc, expectedSecret(t, fc, opts))
@ -1924,7 +1923,7 @@ func Test_externalNameService(t *testing.T) {
fullName, shortName := findGenName(t, fc, "default", "test", "svc") fullName, shortName := findGenName(t, fc, "default", "test", "svc")
opts := configOpts{ opts := configOpts{
replicas: ptr.To[int32](1), replicas: new(int32(1)),
stsName: shortName, stsName: shortName,
secretName: fullName, secretName: fullName,
namespace: "default", namespace: "default",
@ -1969,7 +1968,7 @@ func Test_metricsResourceCreation(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "10.20.30.40", ClusterIP: "10.20.30.40",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
} }
crd := &apiextensionsv1.CustomResourceDefinition{ObjectMeta: metav1.ObjectMeta{Name: serviceMonitorCRD}} crd := &apiextensionsv1.CustomResourceDefinition{ObjectMeta: metav1.ObjectMeta{Name: serviceMonitorCRD}}

@ -42,7 +42,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tstime" "tailscale.com/tstime"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/mak" "tailscale.com/util/mak"
"tailscale.com/util/set" "tailscale.com/util/set"
@ -624,7 +623,7 @@ func (r *ProxyGroupReconciler) ensureNodePortServiceCreated(ctx context.Context,
} }
} }
return svcToNodePorts, ptr.To(tailscaledPort), nil return svcToNodePorts, new(tailscaledPort), nil
} }
// cleanupDanglingResources ensures we don't leak config secrets, state secrets, and // cleanupDanglingResources ensures we don't leak config secrets, state secrets, and
@ -837,9 +836,9 @@ func (r *ProxyGroupReconciler) ensureConfigSecretsCreated(
Version: "v1alpha1", Version: "v1alpha1",
ConfigV1Alpha1: &conf.ConfigV1Alpha1{ ConfigV1Alpha1: &conf.ConfigV1Alpha1{
AuthKey: authKey, AuthKey: authKey,
State: ptr.To(fmt.Sprintf("kube:%s", pgPodName(pg.Name, i))), State: new(fmt.Sprintf("kube:%s", pgPodName(pg.Name, i))),
App: ptr.To(kubetypes.AppProxyGroupKubeAPIServer), App: new(kubetypes.AppProxyGroupKubeAPIServer),
LogLevel: ptr.To(logger.Level().String()), LogLevel: new(logger.Level().String()),
// Reloadable fields. // Reloadable fields.
Hostname: &hostname, Hostname: &hostname,
@ -850,7 +849,7 @@ func (r *ProxyGroupReconciler) ensureConfigSecretsCreated(
// as containerboot does for ingress-pg-reconciler. // as containerboot does for ingress-pg-reconciler.
IssueCerts: opt.NewBool(i == 0), IssueCerts: opt.NewBool(i == 0),
}, },
LocalPort: ptr.To(uint16(9002)), LocalPort: new(uint16(9002)),
HealthCheckEnabled: opt.NewBool(true), HealthCheckEnabled: opt.NewBool(true),
}, },
} }
@ -1021,7 +1020,7 @@ func getStaticEndpointAddress(a *corev1.NodeAddress, port uint16) *netip.AddrPor
return nil return nil
} }
return ptr.To(netip.AddrPortFrom(addr, port)) return new(netip.AddrPortFrom(addr, port))
} }
// ensureAddedToGaugeForProxyGroup ensures the gauge metric for the ProxyGroup resource is updated when the ProxyGroup // ensureAddedToGaugeForProxyGroup ensures the gauge metric for the ProxyGroup resource is updated when the ProxyGroup
@ -1062,7 +1061,7 @@ func pgTailscaledConfig(pg *tsapi.ProxyGroup, pc *tsapi.ProxyClass, idx int32, a
AcceptDNS: "false", AcceptDNS: "false",
AcceptRoutes: "false", // AcceptRoutes defaults to true AcceptRoutes: "false", // AcceptRoutes defaults to true
Locked: "false", Locked: "false",
Hostname: ptr.To(pgHostname(pg, idx)), Hostname: new(pgHostname(pg, idx)),
AdvertiseServices: oldAdvertiseServices, AdvertiseServices: oldAdvertiseServices,
AuthKey: authKey, AuthKey: authKey,
} }

@ -22,7 +22,6 @@ import (
"tailscale.com/kube/egressservices" "tailscale.com/kube/egressservices"
"tailscale.com/kube/ingressservices" "tailscale.com/kube/ingressservices"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/types/ptr"
) )
const ( const (
@ -87,7 +86,7 @@ func pgStatefulSet(pg *tsapi.ProxyGroup, namespace, image, tsFirewallMode string
Labels: pgLabels(pg.Name, nil), Labels: pgLabels(pg.Name, nil),
OwnerReferences: pgOwnerReference(pg), OwnerReferences: pgOwnerReference(pg),
} }
ss.Spec.Replicas = ptr.To(pgReplicas(pg)) ss.Spec.Replicas = new(pgReplicas(pg))
ss.Spec.Selector = &metav1.LabelSelector{ ss.Spec.Selector = &metav1.LabelSelector{
MatchLabels: pgLabels(pg.Name, nil), MatchLabels: pgLabels(pg.Name, nil),
} }
@ -98,7 +97,7 @@ func pgStatefulSet(pg *tsapi.ProxyGroup, namespace, image, tsFirewallMode string
Name: pg.Name, Name: pg.Name,
Namespace: namespace, Namespace: namespace,
Labels: pgLabels(pg.Name, nil), Labels: pgLabels(pg.Name, nil),
DeletionGracePeriodSeconds: ptr.To[int64](10), DeletionGracePeriodSeconds: new(int64(10)),
} }
tmpl.Spec.ServiceAccountName = pg.Name tmpl.Spec.ServiceAccountName = pg.Name
tmpl.Spec.InitContainers[0].Image = image tmpl.Spec.InitContainers[0].Image = image
@ -282,7 +281,7 @@ func pgStatefulSet(pg *tsapi.ProxyGroup, namespace, image, tsFirewallMode string
} }
// Set the deletion grace period to 6 minutes to ensure that the pre-stop hook has enough time to terminate // Set the deletion grace period to 6 minutes to ensure that the pre-stop hook has enough time to terminate
// gracefully. // gracefully.
ss.Spec.Template.DeletionGracePeriodSeconds = ptr.To(deletionGracePeriodSeconds) ss.Spec.Template.DeletionGracePeriodSeconds = new(deletionGracePeriodSeconds)
} }
return ss, nil return ss, nil
@ -297,7 +296,7 @@ func kubeAPIServerStatefulSet(pg *tsapi.ProxyGroup, namespace, image string, por
OwnerReferences: pgOwnerReference(pg), OwnerReferences: pgOwnerReference(pg),
}, },
Spec: appsv1.StatefulSetSpec{ Spec: appsv1.StatefulSetSpec{
Replicas: ptr.To(pgReplicas(pg)), Replicas: new(pgReplicas(pg)),
Selector: &metav1.LabelSelector{ Selector: &metav1.LabelSelector{
MatchLabels: pgLabels(pg.Name, nil), MatchLabels: pgLabels(pg.Name, nil),
}, },
@ -306,7 +305,7 @@ func kubeAPIServerStatefulSet(pg *tsapi.ProxyGroup, namespace, image string, por
Name: pg.Name, Name: pg.Name,
Namespace: namespace, Namespace: namespace,
Labels: pgLabels(pg.Name, nil), Labels: pgLabels(pg.Name, nil),
DeletionGracePeriodSeconds: ptr.To[int64](10), DeletionGracePeriodSeconds: new(int64(10)),
}, },
Spec: corev1.PodSpec{ Spec: corev1.PodSpec{
ServiceAccountName: pgServiceAccountName(pg), ServiceAccountName: pgServiceAccountName(pg),

@ -36,7 +36,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
) )
const ( const (
@ -49,7 +48,7 @@ var (
"some-annotation": "from-the-proxy-class", "some-annotation": "from-the-proxy-class",
} }
defaultReplicas = ptr.To(int32(2)) defaultReplicas = new(int32(2))
defaultStaticEndpointConfig = &tsapi.StaticEndpointsConfig{ defaultStaticEndpointConfig = &tsapi.StaticEndpointsConfig{
NodePort: &tsapi.NodePortConfig{ NodePort: &tsapi.NodePortConfig{
Ports: []tsapi.PortRange{ Ports: []tsapi.PortRange{
@ -107,7 +106,7 @@ func TestProxyGroupWithStaticEndpoints(t *testing.T) {
}, },
}, },
}, },
replicas: ptr.To(int32(4)), replicas: new(int32(4)),
nodes: []testNode{ nodes: []testNode{
{ {
name: "foobar", name: "foobar",
@ -150,7 +149,7 @@ func TestProxyGroupWithStaticEndpoints(t *testing.T) {
}, },
}, },
}, },
replicas: ptr.To(int32(4)), replicas: new(int32(4)),
nodes: []testNode{ nodes: []testNode{
{ {
name: "foobar", name: "foobar",
@ -192,7 +191,7 @@ func TestProxyGroupWithStaticEndpoints(t *testing.T) {
}, },
}, },
}, },
replicas: ptr.To(int32(4)), replicas: new(int32(4)),
nodes: []testNode{ nodes: []testNode{
{ {
name: "foobar", name: "foobar",
@ -234,7 +233,7 @@ func TestProxyGroupWithStaticEndpoints(t *testing.T) {
}, },
}, },
}, },
replicas: ptr.To(int32(3)), replicas: new(int32(3)),
nodes: []testNode{ nodes: []testNode{
{name: "node1", addresses: []testNodeAddr{{ip: "10.0.0.1", addrType: corev1.NodeExternalIP}}, labels: map[string]string{"foo/bar": "baz"}}, {name: "node1", addresses: []testNodeAddr{{ip: "10.0.0.1", addrType: corev1.NodeExternalIP}}, labels: map[string]string{"foo/bar": "baz"}},
{name: "node2", addresses: []testNodeAddr{{ip: "10.0.0.2", addrType: corev1.NodeExternalIP}}, labels: map[string]string{"foo/bar": "baz"}}, {name: "node2", addresses: []testNodeAddr{{ip: "10.0.0.2", addrType: corev1.NodeExternalIP}}, labels: map[string]string{"foo/bar": "baz"}},
@ -294,7 +293,7 @@ func TestProxyGroupWithStaticEndpoints(t *testing.T) {
}, },
}, },
}, },
replicas: ptr.To(int32(4)), replicas: new(int32(4)),
nodes: []testNode{ nodes: []testNode{
{ {
name: "foobar", name: "foobar",
@ -942,7 +941,7 @@ func TestProxyGroup(t *testing.T) {
}) })
t.Run("scale_up_to_3", func(t *testing.T) { t.Run("scale_up_to_3", func(t *testing.T) {
pg.Spec.Replicas = ptr.To[int32](3) pg.Spec.Replicas = new(int32(3))
mustUpdate(t, fc, "", pg.Name, func(p *tsapi.ProxyGroup) { mustUpdate(t, fc, "", pg.Name, func(p *tsapi.ProxyGroup) {
p.Spec = pg.Spec p.Spec = pg.Spec
}) })
@ -965,7 +964,7 @@ func TestProxyGroup(t *testing.T) {
}) })
t.Run("scale_down_to_1", func(t *testing.T) { t.Run("scale_down_to_1", func(t *testing.T) {
pg.Spec.Replicas = ptr.To[int32](1) pg.Spec.Replicas = new(int32(1))
mustUpdate(t, fc, "", pg.Name, func(p *tsapi.ProxyGroup) { mustUpdate(t, fc, "", pg.Name, func(p *tsapi.ProxyGroup) {
p.Spec = pg.Spec p.Spec = pg.Spec
}) })
@ -1062,7 +1061,7 @@ func TestProxyGroupTypes(t *testing.T) {
}, },
Spec: tsapi.ProxyGroupSpec{ Spec: tsapi.ProxyGroupSpec{
Type: tsapi.ProxyGroupTypeEgress, Type: tsapi.ProxyGroupTypeEgress,
Replicas: ptr.To[int32](0), Replicas: new(int32(0)),
}, },
} }
mustCreate(t, fc, pg) mustCreate(t, fc, pg)
@ -1137,7 +1136,7 @@ func TestProxyGroupTypes(t *testing.T) {
}, },
Spec: tsapi.ProxyGroupSpec{ Spec: tsapi.ProxyGroupSpec{
Type: tsapi.ProxyGroupTypeEgress, Type: tsapi.ProxyGroupTypeEgress,
Replicas: ptr.To[int32](0), Replicas: new(int32(0)),
ProxyClass: "test", ProxyClass: "test",
}, },
} }
@ -1174,7 +1173,7 @@ func TestProxyGroupTypes(t *testing.T) {
}, },
Spec: tsapi.ProxyGroupSpec{ Spec: tsapi.ProxyGroupSpec{
Type: tsapi.ProxyGroupTypeIngress, Type: tsapi.ProxyGroupTypeIngress,
Replicas: ptr.To[int32](0), Replicas: new(int32(0)),
}, },
} }
if err := fc.Create(t.Context(), pg); err != nil { if err := fc.Create(t.Context(), pg); err != nil {
@ -1228,9 +1227,9 @@ func TestProxyGroupTypes(t *testing.T) {
}, },
Spec: tsapi.ProxyGroupSpec{ Spec: tsapi.ProxyGroupSpec{
Type: tsapi.ProxyGroupTypeKubernetesAPIServer, Type: tsapi.ProxyGroupTypeKubernetesAPIServer,
Replicas: ptr.To[int32](2), Replicas: new(int32(2)),
KubeAPIServer: &tsapi.KubeAPIServerConfig{ KubeAPIServer: &tsapi.KubeAPIServerConfig{
Mode: ptr.To(tsapi.APIServerProxyModeNoAuth), Mode: new(tsapi.APIServerProxyModeNoAuth),
}, },
}, },
} }
@ -1268,9 +1267,9 @@ func TestKubeAPIServerStatusConditionFlow(t *testing.T) {
}, },
Spec: tsapi.ProxyGroupSpec{ Spec: tsapi.ProxyGroupSpec{
Type: tsapi.ProxyGroupTypeKubernetesAPIServer, Type: tsapi.ProxyGroupTypeKubernetesAPIServer,
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
KubeAPIServer: &tsapi.KubeAPIServerConfig{ KubeAPIServer: &tsapi.KubeAPIServerConfig{
Mode: ptr.To(tsapi.APIServerProxyModeNoAuth), Mode: new(tsapi.APIServerProxyModeNoAuth),
}, },
}, },
} }
@ -1354,9 +1353,9 @@ func TestKubeAPIServerType_DoesNotOverwriteServicesConfig(t *testing.T) {
}, },
Spec: tsapi.ProxyGroupSpec{ Spec: tsapi.ProxyGroupSpec{
Type: tsapi.ProxyGroupTypeKubernetesAPIServer, Type: tsapi.ProxyGroupTypeKubernetesAPIServer,
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
KubeAPIServer: &tsapi.KubeAPIServerConfig{ KubeAPIServer: &tsapi.KubeAPIServerConfig{
Mode: ptr.To(tsapi.APIServerProxyModeNoAuth), // Avoid needing to pre-create the static ServiceAccount. Mode: new(tsapi.APIServerProxyModeNoAuth), // Avoid needing to pre-create the static ServiceAccount.
}, },
}, },
} }
@ -1368,18 +1367,18 @@ func TestKubeAPIServerType_DoesNotOverwriteServicesConfig(t *testing.T) {
cfg := conf.VersionedConfig{ cfg := conf.VersionedConfig{
Version: "v1alpha1", Version: "v1alpha1",
ConfigV1Alpha1: &conf.ConfigV1Alpha1{ ConfigV1Alpha1: &conf.ConfigV1Alpha1{
AuthKey: ptr.To("secret-authkey"), AuthKey: new("secret-authkey"),
State: ptr.To(fmt.Sprintf("kube:%s", pgPodName(pg.Name, 0))), State: new(fmt.Sprintf("kube:%s", pgPodName(pg.Name, 0))),
App: ptr.To(kubetypes.AppProxyGroupKubeAPIServer), App: new(kubetypes.AppProxyGroupKubeAPIServer),
LogLevel: ptr.To("debug"), LogLevel: new("debug"),
Hostname: ptr.To("test-k8s-apiserver-0"), Hostname: new("test-k8s-apiserver-0"),
APIServerProxy: &conf.APIServerProxyConfig{ APIServerProxy: &conf.APIServerProxyConfig{
Enabled: opt.NewBool(true), Enabled: opt.NewBool(true),
Mode: ptr.To(kubetypes.APIServerProxyModeNoAuth), Mode: new(kubetypes.APIServerProxyModeNoAuth),
IssueCerts: opt.NewBool(true), IssueCerts: opt.NewBool(true),
}, },
LocalPort: ptr.To(uint16(9002)), LocalPort: new(uint16(9002)),
HealthCheckEnabled: opt.NewBool(true), HealthCheckEnabled: opt.NewBool(true),
}, },
} }
@ -1403,7 +1402,7 @@ func TestKubeAPIServerType_DoesNotOverwriteServicesConfig(t *testing.T) {
// Now simulate the kube-apiserver services reconciler updating config, // Now simulate the kube-apiserver services reconciler updating config,
// then check the proxygroup reconciler doesn't overwrite it. // then check the proxygroup reconciler doesn't overwrite it.
cfg.APIServerProxy.ServiceName = ptr.To(tailcfg.ServiceName("svc:some-svc-name")) cfg.APIServerProxy.ServiceName = new(tailcfg.ServiceName("svc:some-svc-name"))
cfg.AdvertiseServices = []string{"svc:should-not-be-overwritten"} cfg.AdvertiseServices = []string{"svc:should-not-be-overwritten"}
cfgB, err = json.Marshal(cfg) cfgB, err = json.Marshal(cfg)
if err != nil { if err != nil {
@ -1459,7 +1458,7 @@ func TestIngressAdvertiseServicesConfigPreserved(t *testing.T) {
}, },
Spec: tsapi.ProxyGroupSpec{ Spec: tsapi.ProxyGroupSpec{
Type: tsapi.ProxyGroupTypeIngress, Type: tsapi.ProxyGroupTypeIngress,
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
}, },
}) })
expectReconciled(t, reconciler, "", pgName) expectReconciled(t, reconciler, "", pgName)
@ -1473,7 +1472,7 @@ func TestIngressAdvertiseServicesConfigPreserved(t *testing.T) {
AcceptDNS: "false", AcceptDNS: "false",
AcceptRoutes: "false", AcceptRoutes: "false",
Locked: "false", Locked: "false",
Hostname: ptr.To(fmt.Sprintf("%s-%d", pgName, 0)), Hostname: new(fmt.Sprintf("%s-%d", pgName, 0)),
}) })
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -1609,7 +1608,7 @@ func TestValidateProxyGroup(t *testing.T) {
} }
if tc.noauth { if tc.noauth {
pg.Spec.KubeAPIServer = &tsapi.KubeAPIServerConfig{ pg.Spec.KubeAPIServer = &tsapi.KubeAPIServerConfig{
Mode: ptr.To(tsapi.APIServerProxyModeNoAuth), Mode: new(tsapi.APIServerProxyModeNoAuth),
} }
} }
@ -1875,7 +1874,7 @@ func TestProxyGroupLetsEncryptStaging(t *testing.T) {
}, },
Spec: tsapi.ProxyGroupSpec{ Spec: tsapi.ProxyGroupSpec{
Type: tt.pgType, Type: tt.pgType,
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
ProxyClass: tt.proxyClassPerResource, ProxyClass: tt.proxyClassPerResource,
}, },
} }

@ -38,7 +38,6 @@ import (
"tailscale.com/net/netutil" "tailscale.com/net/netutil"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/util/mak" "tailscale.com/util/mak"
) )
@ -378,7 +377,7 @@ func (a *tailscaleSTSReconciler) reconcileHeadlessService(ctx context.Context, l
Selector: map[string]string{ Selector: map[string]string{
"app": sts.ParentResourceUID, "app": sts.ParentResourceUID,
}, },
IPFamilyPolicy: ptr.To(corev1.IPFamilyPolicyPreferDualStack), IPFamilyPolicy: new(corev1.IPFamilyPolicyPreferDualStack),
}, },
} }
logger.Debugf("reconciling headless service for StatefulSet") logger.Debugf("reconciling headless service for StatefulSet")
@ -526,7 +525,7 @@ func sanitizeConfig(c ipn.ConfigVAlpha) ipn.ConfigVAlpha {
// Explicitly redact AuthKey because we never want it appearing in logs. Never populate this with the // Explicitly redact AuthKey because we never want it appearing in logs. Never populate this with the
// actual auth key. // actual auth key.
if c.AuthKey != nil { if c.AuthKey != nil {
c.AuthKey = ptr.To("**redacted**") c.AuthKey = new("**redacted**")
} }
return c return c
@ -683,7 +682,7 @@ func (a *tailscaleSTSReconciler) reconcileSTS(ctx context.Context, logger *zap.S
} }
if sts.Replicas > 0 { if sts.Replicas > 0 {
ss.Spec.Replicas = ptr.To(sts.Replicas) ss.Spec.Replicas = new(sts.Replicas)
} }
// Generic containerboot configuration options. // Generic containerboot configuration options.

@ -22,7 +22,6 @@ import (
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/types/ptr"
) )
// Test_statefulSetNameBase tests that parent name portion in a StatefulSet name // Test_statefulSetNameBase tests that parent name portion in a StatefulSet name
@ -69,7 +68,7 @@ func Test_applyProxyClassToStatefulSet(t *testing.T) {
Labels: tsapi.Labels{"bar": "foo"}, Labels: tsapi.Labels{"bar": "foo"},
Annotations: map[string]string{"bar.io/foo": "foo"}, Annotations: map[string]string{"bar.io/foo": "foo"},
SecurityContext: &corev1.PodSecurityContext{ SecurityContext: &corev1.PodSecurityContext{
RunAsUser: ptr.To(int64(0)), RunAsUser: new(int64(0)),
}, },
ImagePullSecrets: []corev1.LocalObjectReference{{Name: "docker-creds"}}, ImagePullSecrets: []corev1.LocalObjectReference{{Name: "docker-creds"}},
NodeName: "some-node", NodeName: "some-node",
@ -87,18 +86,18 @@ func Test_applyProxyClassToStatefulSet(t *testing.T) {
}, },
}, },
}, },
DNSPolicy: ptr.To(corev1.DNSClusterFirstWithHostNet), DNSPolicy: new(corev1.DNSClusterFirstWithHostNet),
DNSConfig: &corev1.PodDNSConfig{ DNSConfig: &corev1.PodDNSConfig{
Nameservers: []string{"1.1.1.1", "8.8.8.8"}, Nameservers: []string{"1.1.1.1", "8.8.8.8"},
Searches: []string{"example.com", "test.local"}, Searches: []string{"example.com", "test.local"},
Options: []corev1.PodDNSConfigOption{ Options: []corev1.PodDNSConfigOption{
{Name: "ndots", Value: ptr.To("2")}, {Name: "ndots", Value: new("2")},
{Name: "edns0"}, {Name: "edns0"},
}, },
}, },
TailscaleContainer: &tsapi.Container{ TailscaleContainer: &tsapi.Container{
SecurityContext: &corev1.SecurityContext{ SecurityContext: &corev1.SecurityContext{
Privileged: ptr.To(true), Privileged: new(true),
}, },
Resources: corev1.ResourceRequirements{ Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("1000m"), corev1.ResourceMemory: resource.MustParse("128Mi")}, Limits: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("1000m"), corev1.ResourceMemory: resource.MustParse("128Mi")},
@ -110,8 +109,8 @@ func Test_applyProxyClassToStatefulSet(t *testing.T) {
}, },
TailscaleInitContainer: &tsapi.Container{ TailscaleInitContainer: &tsapi.Container{
SecurityContext: &corev1.SecurityContext{ SecurityContext: &corev1.SecurityContext{
Privileged: ptr.To(true), Privileged: new(true),
RunAsUser: ptr.To(int64(0)), RunAsUser: new(int64(0)),
}, },
Resources: corev1.ResourceRequirements{ Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("1000m"), corev1.ResourceMemory: resource.MustParse("128Mi")}, Limits: corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("1000m"), corev1.ResourceMemory: resource.MustParse("128Mi")},
@ -293,7 +292,7 @@ func Test_applyProxyClassToStatefulSet(t *testing.T) {
corev1.EnvVar{Name: "TS_ENABLE_METRICS", Value: "true"}, corev1.EnvVar{Name: "TS_ENABLE_METRICS", Value: "true"},
) )
wantSS.Spec.Template.Spec.Containers[0].Ports = []corev1.ContainerPort{{Name: "metrics", Protocol: "TCP", ContainerPort: 9002}} wantSS.Spec.Template.Spec.Containers[0].Ports = []corev1.ContainerPort{{Name: "metrics", Protocol: "TCP", ContainerPort: 9002}}
gotSS = applyProxyClassToStatefulSet(proxyClassWithMetricsDebug(true, ptr.To(false)), nonUserspaceProxySS.DeepCopy(), new(tailscaleSTSConfig), zl.Sugar()) gotSS = applyProxyClassToStatefulSet(proxyClassWithMetricsDebug(true, new(false)), nonUserspaceProxySS.DeepCopy(), new(tailscaleSTSConfig), zl.Sugar())
if diff := cmp.Diff(gotSS, wantSS); diff != "" { if diff := cmp.Diff(gotSS, wantSS); diff != "" {
t.Errorf("Unexpected result applying ProxyClass with metrics enabled to a StatefulSet (-got +want):\n%s", diff) t.Errorf("Unexpected result applying ProxyClass with metrics enabled to a StatefulSet (-got +want):\n%s", diff)
} }
@ -305,7 +304,7 @@ func Test_applyProxyClassToStatefulSet(t *testing.T) {
corev1.EnvVar{Name: "TS_TAILSCALED_EXTRA_ARGS", Value: "--debug=$(TS_DEBUG_ADDR_PORT)"}, corev1.EnvVar{Name: "TS_TAILSCALED_EXTRA_ARGS", Value: "--debug=$(TS_DEBUG_ADDR_PORT)"},
) )
wantSS.Spec.Template.Spec.Containers[0].Ports = []corev1.ContainerPort{{Name: "debug", Protocol: "TCP", ContainerPort: 9001}} wantSS.Spec.Template.Spec.Containers[0].Ports = []corev1.ContainerPort{{Name: "debug", Protocol: "TCP", ContainerPort: 9001}}
gotSS = applyProxyClassToStatefulSet(proxyClassWithMetricsDebug(false, ptr.To(true)), nonUserspaceProxySS.DeepCopy(), new(tailscaleSTSConfig), zl.Sugar()) gotSS = applyProxyClassToStatefulSet(proxyClassWithMetricsDebug(false, new(true)), nonUserspaceProxySS.DeepCopy(), new(tailscaleSTSConfig), zl.Sugar())
if diff := cmp.Diff(gotSS, wantSS); diff != "" { if diff := cmp.Diff(gotSS, wantSS); diff != "" {
t.Errorf("Unexpected result applying ProxyClass with metrics enabled to a StatefulSet (-got +want):\n%s", diff) t.Errorf("Unexpected result applying ProxyClass with metrics enabled to a StatefulSet (-got +want):\n%s", diff)
} }

@ -28,7 +28,6 @@ import (
"tailscale.com/kube/ingressservices" "tailscale.com/kube/ingressservices"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/ptr"
"tailscale.com/util/mak" "tailscale.com/util/mak"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
@ -235,7 +234,7 @@ func TestValidateService(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "1.2.3.4", ClusterIP: "1.2.3.4",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
} }
svc2 := &corev1.Service{ svc2 := &corev1.Service{
@ -252,7 +251,7 @@ func TestValidateService(t *testing.T) {
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
ClusterIP: "1.2.3.5", ClusterIP: "1.2.3.5",
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
}, },
} }
wantSvc := &corev1.Service{ wantSvc := &corev1.Service{
@ -392,7 +391,7 @@ func setupTestService(t *testing.T, svcName string, hostname string, clusterIP s
}, },
Spec: corev1.ServiceSpec{ Spec: corev1.ServiceSpec{
Type: corev1.ServiceTypeLoadBalancer, Type: corev1.ServiceTypeLoadBalancer,
LoadBalancerClass: ptr.To("tailscale"), LoadBalancerClass: new("tailscale"),
ClusterIP: clusterIP, ClusterIP: clusterIP,
ClusterIPs: []string{clusterIP}, ClusterIPs: []string{clusterIP},
}, },
@ -412,7 +411,7 @@ func setupTestService(t *testing.T, svcName string, hostname string, clusterIP s
{ {
Addresses: []string{"4.3.2.1"}, Addresses: []string{"4.3.2.1"},
Conditions: discoveryv1.EndpointConditions{ Conditions: discoveryv1.EndpointConditions{
Ready: ptr.To(true), Ready: new(true),
}, },
}, },
}, },

@ -36,7 +36,6 @@ import (
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/ptr"
"tailscale.com/util/mak" "tailscale.com/util/mak"
) )
@ -96,7 +95,7 @@ func expectedSTS(t *testing.T, cl client.Client, opts configOpts) *appsv1.Statef
{Name: "TS_DEBUG_ACME_FORCE_RENEWAL", Value: "true"}, {Name: "TS_DEBUG_ACME_FORCE_RENEWAL", Value: "true"},
}, },
SecurityContext: &corev1.SecurityContext{ SecurityContext: &corev1.SecurityContext{
Privileged: ptr.To(true), Privileged: new(true),
}, },
Resources: corev1.ResourceRequirements{ Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{ Requests: corev1.ResourceList{
@ -231,7 +230,7 @@ func expectedSTS(t *testing.T, cl client.Client, opts configOpts) *appsv1.Statef
Template: corev1.PodTemplateSpec{ Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Annotations: annots, Annotations: annots,
DeletionGracePeriodSeconds: ptr.To[int64](10), DeletionGracePeriodSeconds: new(int64(10)),
Labels: map[string]string{ Labels: map[string]string{
"tailscale.com/managed": "true", "tailscale.com/managed": "true",
"tailscale.com/parent-resource": "test", "tailscale.com/parent-resource": "test",
@ -250,7 +249,7 @@ func expectedSTS(t *testing.T, cl client.Client, opts configOpts) *appsv1.Statef
Command: []string{"/bin/sh", "-c"}, Command: []string{"/bin/sh", "-c"},
Args: []string{"sysctl -w net.ipv4.ip_forward=1 && if sysctl net.ipv6.conf.all.forwarding; then sysctl -w net.ipv6.conf.all.forwarding=1; fi"}, Args: []string{"sysctl -w net.ipv4.ip_forward=1 && if sysctl net.ipv6.conf.all.forwarding; then sysctl -w net.ipv6.conf.all.forwarding=1; fi"},
SecurityContext: &corev1.SecurityContext{ SecurityContext: &corev1.SecurityContext{
Privileged: ptr.To(true), Privileged: new(true),
}, },
}, },
}, },
@ -364,14 +363,14 @@ func expectedSTSUserspace(t *testing.T, cl client.Client, opts configOpts) *apps
}, },
}, },
Spec: appsv1.StatefulSetSpec{ Spec: appsv1.StatefulSetSpec{
Replicas: ptr.To[int32](1), Replicas: new(int32(1)),
Selector: &metav1.LabelSelector{ Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": "1234-UID"}, MatchLabels: map[string]string{"app": "1234-UID"},
}, },
ServiceName: opts.stsName, ServiceName: opts.stsName,
Template: corev1.PodTemplateSpec{ Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
DeletionGracePeriodSeconds: ptr.To[int64](10), DeletionGracePeriodSeconds: new(int64(10)),
Labels: map[string]string{ Labels: map[string]string{
"tailscale.com/managed": "true", "tailscale.com/managed": "true",
"tailscale.com/parent-resource": "test", "tailscale.com/parent-resource": "test",
@ -420,7 +419,7 @@ func expectedHeadlessService(name string, parentType string) *corev1.Service {
"app": "1234-UID", "app": "1234-UID",
}, },
ClusterIP: "None", ClusterIP: "None",
IPFamilyPolicy: ptr.To(corev1.IPFamilyPolicyPreferDualStack), IPFamilyPolicy: new(corev1.IPFamilyPolicyPreferDualStack),
}, },
} }
} }
@ -480,7 +479,7 @@ func expectedServiceMonitor(t *testing.T, opts configOpts) *unstructured.Unstruc
Namespace: opts.tailscaleNamespace, Namespace: opts.tailscaleNamespace,
Labels: smLabels, Labels: smLabels,
ResourceVersion: opts.resourceVersion, ResourceVersion: opts.resourceVersion,
OwnerReferences: []metav1.OwnerReference{{APIVersion: "v1", Kind: "Service", Name: name, BlockOwnerDeletion: ptr.To(true), Controller: ptr.To(true)}}, OwnerReferences: []metav1.OwnerReference{{APIVersion: "v1", Kind: "Service", Name: name, BlockOwnerDeletion: new(true), Controller: new(true)}},
}, },
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
Kind: "ServiceMonitor", Kind: "ServiceMonitor",
@ -529,7 +528,7 @@ func expectedSecret(t *testing.T, cl client.Client, opts configOpts) *corev1.Sec
AcceptDNS: "false", AcceptDNS: "false",
Hostname: &opts.hostname, Hostname: &opts.hostname,
Locked: "false", Locked: "false",
AuthKey: ptr.To("secret-authkey"), AuthKey: new("secret-authkey"),
AcceptRoutes: "false", AcceptRoutes: "false",
AppConnector: &ipn.AppConnectorPrefs{Advertise: false}, AppConnector: &ipn.AppConnectorPrefs{Advertise: false},
NoStatefulFiltering: "true", NoStatefulFiltering: "true",

@ -14,7 +14,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/types/ptr"
"tailscale.com/version" "tailscale.com/version"
) )
@ -33,7 +32,7 @@ func tsrStatefulSet(tsr *tsapi.Recorder, namespace string, loginServer string) *
Annotations: tsr.Spec.StatefulSet.Annotations, Annotations: tsr.Spec.StatefulSet.Annotations,
}, },
Spec: appsv1.StatefulSetSpec{ Spec: appsv1.StatefulSetSpec{
Replicas: ptr.To(replicas), Replicas: new(replicas),
Selector: &metav1.LabelSelector{ Selector: &metav1.LabelSelector{
MatchLabels: tsrLabels("recorder", tsr.Name, tsr.Spec.StatefulSet.Pod.Labels), MatchLabels: tsrLabels("recorder", tsr.Name, tsr.Spec.StatefulSet.Pod.Labels),
}, },

@ -14,7 +14,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/types/ptr"
) )
func TestRecorderSpecs(t *testing.T) { func TestRecorderSpecs(t *testing.T) {
@ -24,7 +23,7 @@ func TestRecorderSpecs(t *testing.T) {
Name: "test", Name: "test",
}, },
Spec: tsapi.RecorderSpec{ Spec: tsapi.RecorderSpec{
Replicas: ptr.To[int32](3), Replicas: new(int32(3)),
StatefulSet: tsapi.RecorderStatefulSet{ StatefulSet: tsapi.RecorderStatefulSet{
Labels: map[string]string{ Labels: map[string]string{
"ss-label-key": "ss-label-value", "ss-label-key": "ss-label-value",
@ -51,7 +50,7 @@ func TestRecorderSpecs(t *testing.T) {
}, },
}, },
SecurityContext: &corev1.PodSecurityContext{ SecurityContext: &corev1.PodSecurityContext{
RunAsUser: ptr.To[int64](1000), RunAsUser: new(int64(1000)),
}, },
ImagePullSecrets: []corev1.LocalObjectReference{{ ImagePullSecrets: []corev1.LocalObjectReference{{
Name: "img-pull", Name: "img-pull",
@ -62,7 +61,7 @@ func TestRecorderSpecs(t *testing.T) {
Tolerations: []corev1.Toleration{{ Tolerations: []corev1.Toleration{{
Key: "key", Key: "key",
Value: "value", Value: "value",
TolerationSeconds: ptr.To[int64](60), TolerationSeconds: new(int64(60)),
}}, }},
Container: tsapi.RecorderContainer{ Container: tsapi.RecorderContainer{
Env: []tsapi.Env{{ Env: []tsapi.Env{{

@ -25,7 +25,6 @@ import (
tsoperator "tailscale.com/k8s-operator" tsoperator "tailscale.com/k8s-operator"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/ptr"
) )
const ( const (
@ -40,7 +39,7 @@ func TestRecorder(t *testing.T) {
Finalizers: []string{"tailscale.com/finalizer"}, Finalizers: []string{"tailscale.com/finalizer"},
}, },
Spec: tsapi.RecorderSpec{ Spec: tsapi.RecorderSpec{
Replicas: ptr.To[int32](3), Replicas: new(int32(3)),
}, },
} }

@ -27,7 +27,6 @@ import (
clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" clientcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"tailscale.com/kube/k8s-proxy/conf" "tailscale.com/kube/k8s-proxy/conf"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/types/ptr"
"tailscale.com/util/testenv" "tailscale.com/util/testenv"
) )
@ -178,7 +177,7 @@ func (ld *configLoader) watchConfigSecretChanges(ctx context.Context, secretName
}, },
// Re-watch regularly to avoid relying on long-lived connections. // Re-watch regularly to avoid relying on long-lived connections.
// See https://github.com/kubernetes-client/javascript/issues/596#issuecomment-786419380 // See https://github.com/kubernetes-client/javascript/issues/596#issuecomment-786419380
TimeoutSeconds: ptr.To(int64(600)), TimeoutSeconds: new(int64(600)),
FieldSelector: fmt.Sprintf("metadata.name=%s", secretName), FieldSelector: fmt.Sprintf("metadata.name=%s", secretName),
Watch: true, Watch: true,
}) })
@ -216,7 +215,7 @@ func (ld *configLoader) watchConfigSecretChanges(ctx context.Context, secretName
Kind: "Secret", Kind: "Secret",
APIVersion: "v1", APIVersion: "v1",
}, },
TimeoutSeconds: ptr.To(int64(600)), TimeoutSeconds: new(int64(600)),
FieldSelector: fmt.Sprintf("metadata.name=%s", secretName), FieldSelector: fmt.Sprintf("metadata.name=%s", secretName),
Watch: true, Watch: true,
}) })

@ -20,7 +20,6 @@ import (
ktesting "k8s.io/client-go/testing" ktesting "k8s.io/client-go/testing"
"tailscale.com/kube/k8s-proxy/conf" "tailscale.com/kube/k8s-proxy/conf"
"tailscale.com/kube/kubetypes" "tailscale.com/kube/kubetypes"
"tailscale.com/types/ptr"
) )
func TestWatchConfig(t *testing.T) { func TestWatchConfig(t *testing.T) {
@ -52,7 +51,7 @@ func TestWatchConfig(t *testing.T) {
initialConfig: `{"version": "v1alpha1", "authKey": "abc123"}`, initialConfig: `{"version": "v1alpha1", "authKey": "abc123"}`,
phases: []phase{{ phases: []phase{{
expectedConf: &conf.ConfigV1Alpha1{ expectedConf: &conf.ConfigV1Alpha1{
AuthKey: ptr.To("abc123"), AuthKey: new("abc123"),
}, },
}}, }},
}, },
@ -62,7 +61,7 @@ func TestWatchConfig(t *testing.T) {
phases: []phase{ phases: []phase{
{ {
expectedConf: &conf.ConfigV1Alpha1{ expectedConf: &conf.ConfigV1Alpha1{
AuthKey: ptr.To("abc123"), AuthKey: new("abc123"),
}, },
}, },
{ {
@ -76,13 +75,13 @@ func TestWatchConfig(t *testing.T) {
phases: []phase{ phases: []phase{
{ {
expectedConf: &conf.ConfigV1Alpha1{ expectedConf: &conf.ConfigV1Alpha1{
AuthKey: ptr.To("abc123"), AuthKey: new("abc123"),
}, },
}, },
{ {
config: `{"version": "v1alpha1", "authKey": "def456"}`, config: `{"version": "v1alpha1", "authKey": "def456"}`,
expectedConf: &conf.ConfigV1Alpha1{ expectedConf: &conf.ConfigV1Alpha1{
AuthKey: ptr.To("def456"), AuthKey: new("def456"),
}, },
}, },
}, },
@ -93,7 +92,7 @@ func TestWatchConfig(t *testing.T) {
phases: []phase{ phases: []phase{
{ {
expectedConf: &conf.ConfigV1Alpha1{ expectedConf: &conf.ConfigV1Alpha1{
AuthKey: ptr.To("abc123"), AuthKey: new("abc123"),
}, },
}, },
{ {

@ -71,7 +71,6 @@ tailscale.com/cmd/stund dependencies: (generated by github.com/tailscale/depawar
tailscale.com/types/logger from tailscale.com/tsweb+ tailscale.com/types/logger from tailscale.com/tsweb+
tailscale.com/types/opt from tailscale.com/envknob+ tailscale.com/types/opt from tailscale.com/envknob+
tailscale.com/types/persist from tailscale.com/feature tailscale.com/types/persist from tailscale.com/feature
tailscale.com/types/ptr from tailscale.com/tailcfg+
tailscale.com/types/result from tailscale.com/util/lineiter tailscale.com/types/result from tailscale.com/util/lineiter
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+

@ -24,7 +24,6 @@ import (
"tailscale.com/safesocket" "tailscale.com/safesocket"
"tailscale.com/tsconst" "tailscale.com/tsconst"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/set" "tailscale.com/util/set"
"tailscale.com/version" "tailscale.com/version"
@ -247,7 +246,7 @@ func runSet(ctx context.Context, args []string) (retErr error) {
if err != nil { if err != nil {
return fmt.Errorf("failed to set relay server port: %v", err) return fmt.Errorf("failed to set relay server port: %v", err)
} }
maskedPrefs.Prefs.RelayServerPort = ptr.To(uint16(uport)) maskedPrefs.Prefs.RelayServerPort = new(uint16(uport))
} }
if setArgs.relayServerStaticEndpoints != "" { if setArgs.relayServerStaticEndpoints != "" {

@ -11,7 +11,6 @@ import (
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
"tailscale.com/types/ptr"
) )
func TestCalcAdvertiseRoutesForSet(t *testing.T) { func TestCalcAdvertiseRoutesForSet(t *testing.T) {
@ -28,80 +27,80 @@ func TestCalcAdvertiseRoutesForSet(t *testing.T) {
}, },
{ {
name: "advertise-exit", name: "advertise-exit",
setExit: ptr.To(true), setExit: new(true),
want: tsaddr.ExitRoutes(), want: tsaddr.ExitRoutes(),
}, },
{ {
name: "advertise-exit/already-routes", name: "advertise-exit/already-routes",
was: []netip.Prefix{pfx("34.0.0.0/16")}, was: []netip.Prefix{pfx("34.0.0.0/16")},
setExit: ptr.To(true), setExit: new(true),
want: []netip.Prefix{pfx("34.0.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()}, want: []netip.Prefix{pfx("34.0.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()},
}, },
{ {
name: "advertise-exit/already-exit", name: "advertise-exit/already-exit",
was: tsaddr.ExitRoutes(), was: tsaddr.ExitRoutes(),
setExit: ptr.To(true), setExit: new(true),
want: tsaddr.ExitRoutes(), want: tsaddr.ExitRoutes(),
}, },
{ {
name: "stop-advertise-exit", name: "stop-advertise-exit",
was: tsaddr.ExitRoutes(), was: tsaddr.ExitRoutes(),
setExit: ptr.To(false), setExit: new(false),
want: nil, want: nil,
}, },
{ {
name: "stop-advertise-exit/with-routes", name: "stop-advertise-exit/with-routes",
was: []netip.Prefix{pfx("34.0.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()}, was: []netip.Prefix{pfx("34.0.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()},
setExit: ptr.To(false), setExit: new(false),
want: []netip.Prefix{pfx("34.0.0.0/16")}, want: []netip.Prefix{pfx("34.0.0.0/16")},
}, },
{ {
name: "advertise-routes", name: "advertise-routes",
setRoutes: ptr.To("10.0.0.0/24,192.168.0.0/16"), setRoutes: new("10.0.0.0/24,192.168.0.0/16"),
want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16")}, want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16")},
}, },
{ {
name: "advertise-routes/already-exit", name: "advertise-routes/already-exit",
was: tsaddr.ExitRoutes(), was: tsaddr.ExitRoutes(),
setRoutes: ptr.To("10.0.0.0/24,192.168.0.0/16"), setRoutes: new("10.0.0.0/24,192.168.0.0/16"),
want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()}, want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()},
}, },
{ {
name: "advertise-routes/already-diff-routes", name: "advertise-routes/already-diff-routes",
was: []netip.Prefix{pfx("34.0.0.0/16")}, was: []netip.Prefix{pfx("34.0.0.0/16")},
setRoutes: ptr.To("10.0.0.0/24,192.168.0.0/16"), setRoutes: new("10.0.0.0/24,192.168.0.0/16"),
want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16")}, want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16")},
}, },
{ {
name: "stop-advertise-routes", name: "stop-advertise-routes",
was: []netip.Prefix{pfx("34.0.0.0/16")}, was: []netip.Prefix{pfx("34.0.0.0/16")},
setRoutes: ptr.To(""), setRoutes: new(""),
want: nil, want: nil,
}, },
{ {
name: "stop-advertise-routes/already-exit", name: "stop-advertise-routes/already-exit",
was: []netip.Prefix{pfx("34.0.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()}, was: []netip.Prefix{pfx("34.0.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()},
setRoutes: ptr.To(""), setRoutes: new(""),
want: tsaddr.ExitRoutes(), want: tsaddr.ExitRoutes(),
}, },
{ {
name: "advertise-routes-and-exit", name: "advertise-routes-and-exit",
setExit: ptr.To(true), setExit: new(true),
setRoutes: ptr.To("10.0.0.0/24,192.168.0.0/16"), setRoutes: new("10.0.0.0/24,192.168.0.0/16"),
want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()}, want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()},
}, },
{ {
name: "advertise-routes-and-exit/already-exit", name: "advertise-routes-and-exit/already-exit",
was: tsaddr.ExitRoutes(), was: tsaddr.ExitRoutes(),
setExit: ptr.To(true), setExit: new(true),
setRoutes: ptr.To("10.0.0.0/24,192.168.0.0/16"), setRoutes: new("10.0.0.0/24,192.168.0.0/16"),
want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()}, want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()},
}, },
{ {
name: "advertise-routes-and-exit/already-routes", name: "advertise-routes-and-exit/already-routes",
was: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16")}, was: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16")},
setExit: ptr.To(true), setExit: new(true),
setRoutes: ptr.To("10.0.0.0/24,192.168.0.0/16"), setRoutes: new("10.0.0.0/24,192.168.0.0/16"),
want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()}, want: []netip.Prefix{pfx("10.0.0.0/24"), pfx("192.168.0.0/16"), tsaddr.AllIPv4(), tsaddr.AllIPv6()},
}, },
} }

@ -253,7 +253,6 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
tailscale.com/types/opt from tailscale.com/client/tailscale+ tailscale.com/types/opt from tailscale.com/client/tailscale+
tailscale.com/types/persist from tailscale.com/ipn+ tailscale.com/types/persist from tailscale.com/ipn+
tailscale.com/types/preftype from tailscale.com/cmd/tailscale/cli+ tailscale.com/types/preftype from tailscale.com/cmd/tailscale/cli+
tailscale.com/types/ptr from tailscale.com/hostinfo+
tailscale.com/types/result from tailscale.com/util/lineiter tailscale.com/types/result from tailscale.com/util/lineiter
tailscale.com/types/structs from tailscale.com/ipn+ tailscale.com/types/structs from tailscale.com/ipn+
tailscale.com/types/tkatype from tailscale.com/types/key+ tailscale.com/types/tkatype from tailscale.com/types/key+

@ -145,7 +145,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/types/opt from tailscale.com/control/controlknobs+ tailscale.com/types/opt from tailscale.com/control/controlknobs+
tailscale.com/types/persist from tailscale.com/control/controlclient+ tailscale.com/types/persist from tailscale.com/control/controlclient+
tailscale.com/types/preftype from tailscale.com/ipn+ tailscale.com/types/preftype from tailscale.com/ipn+
tailscale.com/types/ptr from tailscale.com/control/controlclient+
tailscale.com/types/result from tailscale.com/util/lineiter tailscale.com/types/result from tailscale.com/util/lineiter
tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/structs from tailscale.com/control/controlclient+
tailscale.com/types/tkatype from tailscale.com/control/controlclient+ tailscale.com/types/tkatype from tailscale.com/control/controlclient+

@ -164,7 +164,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/types/opt from tailscale.com/control/controlknobs+ tailscale.com/types/opt from tailscale.com/control/controlknobs+
tailscale.com/types/persist from tailscale.com/control/controlclient+ tailscale.com/types/persist from tailscale.com/control/controlclient+
tailscale.com/types/preftype from tailscale.com/ipn+ tailscale.com/types/preftype from tailscale.com/ipn+
tailscale.com/types/ptr from tailscale.com/control/controlclient+
tailscale.com/types/result from tailscale.com/util/lineiter tailscale.com/types/result from tailscale.com/util/lineiter
tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/structs from tailscale.com/control/controlclient+
tailscale.com/types/tkatype from tailscale.com/control/controlclient+ tailscale.com/types/tkatype from tailscale.com/control/controlclient+

@ -420,7 +420,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/types/opt from tailscale.com/control/controlknobs+ tailscale.com/types/opt from tailscale.com/control/controlknobs+
tailscale.com/types/persist from tailscale.com/control/controlclient+ tailscale.com/types/persist from tailscale.com/control/controlclient+
tailscale.com/types/preftype from tailscale.com/ipn+ tailscale.com/types/preftype from tailscale.com/ipn+
tailscale.com/types/ptr from tailscale.com/control/controlclient+
tailscale.com/types/result from tailscale.com/util/lineiter tailscale.com/types/result from tailscale.com/util/lineiter
tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/structs from tailscale.com/control/controlclient+
tailscale.com/types/tkatype from tailscale.com/tka+ tailscale.com/types/tkatype from tailscale.com/tka+

@ -328,7 +328,6 @@ tailscale.com/cmd/tsidp dependencies: (generated by github.com/tailscale/depawar
tailscale.com/types/opt from tailscale.com/cmd/tsidp+ tailscale.com/types/opt from tailscale.com/cmd/tsidp+
tailscale.com/types/persist from tailscale.com/control/controlclient+ tailscale.com/types/persist from tailscale.com/control/controlclient+
tailscale.com/types/preftype from tailscale.com/ipn+ tailscale.com/types/preftype from tailscale.com/ipn+
tailscale.com/types/ptr from tailscale.com/control/controlclient+
tailscale.com/types/result from tailscale.com/util/lineiter tailscale.com/types/result from tailscale.com/util/lineiter
tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/structs from tailscale.com/control/controlclient+
tailscale.com/types/tkatype from tailscale.com/client/local+ tailscale.com/types/tkatype from tailscale.com/client/local+

@ -8,7 +8,6 @@ import (
"github.com/google/nftables" "github.com/google/nftables"
"github.com/google/nftables/expr" "github.com/google/nftables/expr"
"tailscale.com/types/ptr"
) )
func init() { func init() {
@ -35,7 +34,7 @@ func addFirewallLinux() error {
Type: nftables.ChainTypeFilter, Type: nftables.ChainTypeFilter,
Hooknum: nftables.ChainHookInput, Hooknum: nftables.ChainHookInput,
Priority: nftables.ChainPriorityFilter, Priority: nftables.ChainPriorityFilter,
Policy: ptr.To(nftables.ChainPolicyDrop), Policy: new(nftables.ChainPolicyDrop),
} }
c.AddChain(inputChain) c.AddChain(inputChain)

@ -9,7 +9,6 @@ import (
"net/netip" "net/netip"
"golang.org/x/exp/constraints" "golang.org/x/exp/constraints"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
) )
@ -135,7 +134,7 @@ func (c *Container[T]) Clone() *Container[T] {
return &Container[T]{cloner.Clone()} return &Container[T]{cloner.Clone()}
} }
if !views.ContainsPointers[T]() { if !views.ContainsPointers[T]() {
return ptr.To(*c) return new(*c)
} }
panic(fmt.Errorf("%T contains pointers, but is not cloneable", c.Item)) panic(fmt.Errorf("%T contains pointers, but is not cloneable", c.Item))
} }

@ -10,7 +10,6 @@ import (
"net/netip" "net/netip"
"golang.org/x/exp/constraints" "golang.org/x/exp/constraints"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
) )
@ -23,13 +22,13 @@ func (src *StructWithPtrs) Clone() *StructWithPtrs {
dst := new(StructWithPtrs) dst := new(StructWithPtrs)
*dst = *src *dst = *src
if dst.Value != nil { if dst.Value != nil {
dst.Value = ptr.To(*src.Value) dst.Value = new(*src.Value)
} }
if dst.Int != nil { if dst.Int != nil {
dst.Int = ptr.To(*src.Int) dst.Int = new(*src.Int)
} }
if dst.NoView != nil { if dst.NoView != nil {
dst.NoView = ptr.To(*src.NoView) dst.NoView = new(*src.NoView)
} }
return dst return dst
} }
@ -90,7 +89,7 @@ func (src *Map) Clone() *Map {
if v == nil { if v == nil {
dst.StructPtrWithoutPtr[k] = nil dst.StructPtrWithoutPtr[k] = nil
} else { } else {
dst.StructPtrWithoutPtr[k] = ptr.To(*v) dst.StructPtrWithoutPtr[k] = new(*v)
} }
} }
} }
@ -156,7 +155,7 @@ func (src *StructWithSlices) Clone() *StructWithSlices {
if src.ValuePointers[i] == nil { if src.ValuePointers[i] == nil {
dst.ValuePointers[i] = nil dst.ValuePointers[i] = nil
} else { } else {
dst.ValuePointers[i] = ptr.To(*src.ValuePointers[i]) dst.ValuePointers[i] = new(*src.ValuePointers[i])
} }
} }
} }
@ -185,7 +184,7 @@ func (src *StructWithSlices) Clone() *StructWithSlices {
if src.Ints[i] == nil { if src.Ints[i] == nil {
dst.Ints[i] = nil dst.Ints[i] = nil
} else { } else {
dst.Ints[i] = ptr.To(*src.Ints[i]) dst.Ints[i] = new(*src.Ints[i])
} }
} }
} }
@ -248,7 +247,7 @@ func (src *GenericIntStruct[T]) Clone() *GenericIntStruct[T] {
dst := new(GenericIntStruct[T]) dst := new(GenericIntStruct[T])
*dst = *src *dst = *src
if dst.Pointer != nil { if dst.Pointer != nil {
dst.Pointer = ptr.To(*src.Pointer) dst.Pointer = new(*src.Pointer)
} }
dst.Slice = append(src.Slice[:0:0], src.Slice...) dst.Slice = append(src.Slice[:0:0], src.Slice...)
dst.Map = maps.Clone(src.Map) dst.Map = maps.Clone(src.Map)
@ -258,7 +257,7 @@ func (src *GenericIntStruct[T]) Clone() *GenericIntStruct[T] {
if src.PtrSlice[i] == nil { if src.PtrSlice[i] == nil {
dst.PtrSlice[i] = nil dst.PtrSlice[i] = nil
} else { } else {
dst.PtrSlice[i] = ptr.To(*src.PtrSlice[i]) dst.PtrSlice[i] = new(*src.PtrSlice[i])
} }
} }
} }
@ -269,7 +268,7 @@ func (src *GenericIntStruct[T]) Clone() *GenericIntStruct[T] {
if v == nil { if v == nil {
dst.PtrValueMap[k] = nil dst.PtrValueMap[k] = nil
} else { } else {
dst.PtrValueMap[k] = ptr.To(*v) dst.PtrValueMap[k] = new(*v)
} }
} }
} }
@ -305,7 +304,7 @@ func (src *GenericNoPtrsStruct[T]) Clone() *GenericNoPtrsStruct[T] {
dst := new(GenericNoPtrsStruct[T]) dst := new(GenericNoPtrsStruct[T])
*dst = *src *dst = *src
if dst.Pointer != nil { if dst.Pointer != nil {
dst.Pointer = ptr.To(*src.Pointer) dst.Pointer = new(*src.Pointer)
} }
dst.Slice = append(src.Slice[:0:0], src.Slice...) dst.Slice = append(src.Slice[:0:0], src.Slice...)
dst.Map = maps.Clone(src.Map) dst.Map = maps.Clone(src.Map)
@ -315,7 +314,7 @@ func (src *GenericNoPtrsStruct[T]) Clone() *GenericNoPtrsStruct[T] {
if src.PtrSlice[i] == nil { if src.PtrSlice[i] == nil {
dst.PtrSlice[i] = nil dst.PtrSlice[i] = nil
} else { } else {
dst.PtrSlice[i] = ptr.To(*src.PtrSlice[i]) dst.PtrSlice[i] = new(*src.PtrSlice[i])
} }
} }
} }
@ -326,7 +325,7 @@ func (src *GenericNoPtrsStruct[T]) Clone() *GenericNoPtrsStruct[T] {
if v == nil { if v == nil {
dst.PtrValueMap[k] = nil dst.PtrValueMap[k] = nil
} else { } else {
dst.PtrValueMap[k] = ptr.To(*v) dst.PtrValueMap[k] = new(*v)
} }
} }
} }
@ -375,7 +374,7 @@ func (src *GenericCloneableStruct[T, V]) Clone() *GenericCloneableStruct[T, V] {
} }
} }
if dst.Pointer != nil { if dst.Pointer != nil {
dst.Pointer = ptr.To((*src.Pointer).Clone()) dst.Pointer = new((*src.Pointer).Clone())
} }
if src.PtrSlice != nil { if src.PtrSlice != nil {
dst.PtrSlice = make([]*T, len(src.PtrSlice)) dst.PtrSlice = make([]*T, len(src.PtrSlice))
@ -383,7 +382,7 @@ func (src *GenericCloneableStruct[T, V]) Clone() *GenericCloneableStruct[T, V] {
if src.PtrSlice[i] == nil { if src.PtrSlice[i] == nil {
dst.PtrSlice[i] = nil dst.PtrSlice[i] = nil
} else { } else {
dst.PtrSlice[i] = ptr.To((*src.PtrSlice[i]).Clone()) dst.PtrSlice[i] = new((*src.PtrSlice[i]).Clone())
} }
} }
} }
@ -394,7 +393,7 @@ func (src *GenericCloneableStruct[T, V]) Clone() *GenericCloneableStruct[T, V] {
if v == nil { if v == nil {
dst.PtrValueMap[k] = nil dst.PtrValueMap[k] = nil
} else { } else {
dst.PtrValueMap[k] = ptr.To((*v).Clone()) dst.PtrValueMap[k] = new((*v).Clone())
} }
} }
} }
@ -457,7 +456,7 @@ func (src *StructWithTypeAliasFields) Clone() *StructWithTypeAliasFields {
dst.WithPtr = *src.WithPtr.Clone() dst.WithPtr = *src.WithPtr.Clone()
dst.WithPtrByPtr = src.WithPtrByPtr.Clone() dst.WithPtrByPtr = src.WithPtrByPtr.Clone()
if dst.WithoutPtrByPtr != nil { if dst.WithoutPtrByPtr != nil {
dst.WithoutPtrByPtr = ptr.To(*src.WithoutPtrByPtr) dst.WithoutPtrByPtr = new(*src.WithoutPtrByPtr)
} }
if src.SliceWithPtrs != nil { if src.SliceWithPtrs != nil {
dst.SliceWithPtrs = make([]*StructWithPtrsAlias, len(src.SliceWithPtrs)) dst.SliceWithPtrs = make([]*StructWithPtrsAlias, len(src.SliceWithPtrs))
@ -475,7 +474,7 @@ func (src *StructWithTypeAliasFields) Clone() *StructWithTypeAliasFields {
if src.SliceWithoutPtrs[i] == nil { if src.SliceWithoutPtrs[i] == nil {
dst.SliceWithoutPtrs[i] = nil dst.SliceWithoutPtrs[i] = nil
} else { } else {
dst.SliceWithoutPtrs[i] = ptr.To(*src.SliceWithoutPtrs[i]) dst.SliceWithoutPtrs[i] = new(*src.SliceWithoutPtrs[i])
} }
} }
} }
@ -495,7 +494,7 @@ func (src *StructWithTypeAliasFields) Clone() *StructWithTypeAliasFields {
if v == nil { if v == nil {
dst.MapWithoutPtrs[k] = nil dst.MapWithoutPtrs[k] = nil
} else { } else {
dst.MapWithoutPtrs[k] = ptr.To(*v) dst.MapWithoutPtrs[k] = new(*v)
} }
} }
} }

@ -51,7 +51,6 @@ import (
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/persist" "tailscale.com/types/persist"
"tailscale.com/types/ptr"
"tailscale.com/types/tkatype" "tailscale.com/types/tkatype"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/eventbus" "tailscale.com/util/eventbus"
@ -383,7 +382,7 @@ func (c *Direct) SetHostinfo(hi *tailcfg.Hostinfo) bool {
if hi == nil { if hi == nil {
panic("nil Hostinfo") panic("nil Hostinfo")
} }
hi = ptr.To(*hi) hi = new(*hi)
hi.NetInfo = nil hi.NetInfo = nil
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()

@ -28,7 +28,6 @@ import (
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/mak" "tailscale.com/util/mak"
@ -504,7 +503,7 @@ func (ms *mapSession) updatePeersStateFromResponse(resp *tailcfg.MapResponse) (s
if vp, ok := ms.peers[nodeID]; ok { if vp, ok := ms.peers[nodeID]; ok {
mut := vp.AsStruct() mut := vp.AsStruct()
if seen { if seen {
mut.LastSeen = ptr.To(clock.Now()) mut.LastSeen = new(clock.Now())
} else { } else {
mut.LastSeen = nil mut.LastSeen = nil
} }
@ -516,7 +515,7 @@ func (ms *mapSession) updatePeersStateFromResponse(resp *tailcfg.MapResponse) (s
for nodeID, online := range resp.OnlineChange { for nodeID, online := range resp.OnlineChange {
if vp, ok := ms.peers[nodeID]; ok { if vp, ok := ms.peers[nodeID]; ok {
mut := vp.AsStruct() mut := vp.AsStruct()
mut.Online = ptr.To(online) mut.Online = new(online)
ms.peers[nodeID] = mut.View() ms.peers[nodeID] = mut.View()
stats.changed++ stats.changed++
} }
@ -550,11 +549,11 @@ func (ms *mapSession) updatePeersStateFromResponse(resp *tailcfg.MapResponse) (s
patchDiscoKey.Add(1) patchDiscoKey.Add(1)
} }
if v := pc.Online; v != nil { if v := pc.Online; v != nil {
mut.Online = ptr.To(*v) mut.Online = new(*v)
patchOnline.Add(1) patchOnline.Add(1)
} }
if v := pc.LastSeen; v != nil { if v := pc.LastSeen; v != nil {
mut.LastSeen = ptr.To(*v) mut.LastSeen = new(*v)
patchLastSeen.Add(1) patchLastSeen.Add(1)
} }
if v := pc.KeyExpiry; v != nil { if v := pc.KeyExpiry; v != nil {
@ -688,11 +687,11 @@ func peerChangeDiff(was tailcfg.NodeView, n *tailcfg.Node) (_ *tailcfg.PeerChang
} }
case "Key": case "Key":
if was.Key() != n.Key { if was.Key() != n.Key {
pc().Key = ptr.To(n.Key) pc().Key = new(n.Key)
} }
case "KeyExpiry": case "KeyExpiry":
if !was.KeyExpiry().Equal(n.KeyExpiry) { if !was.KeyExpiry().Equal(n.KeyExpiry) {
pc().KeyExpiry = ptr.To(n.KeyExpiry) pc().KeyExpiry = new(n.KeyExpiry)
} }
case "KeySignature": case "KeySignature":
if !was.KeySignature().Equal(n.KeySignature) { if !was.KeySignature().Equal(n.KeySignature) {
@ -704,7 +703,7 @@ func peerChangeDiff(was tailcfg.NodeView, n *tailcfg.Node) (_ *tailcfg.PeerChang
} }
case "DiscoKey": case "DiscoKey":
if was.DiscoKey() != n.DiscoKey { if was.DiscoKey() != n.DiscoKey {
pc().DiscoKey = ptr.To(n.DiscoKey) pc().DiscoKey = new(n.DiscoKey)
} }
case "Addresses": case "Addresses":
if !views.SliceEqual(was.Addresses(), views.SliceOf(n.Addresses)) { if !views.SliceEqual(was.Addresses(), views.SliceOf(n.Addresses)) {
@ -773,11 +772,11 @@ func peerChangeDiff(was tailcfg.NodeView, n *tailcfg.Node) (_ *tailcfg.PeerChang
} }
case "Online": case "Online":
if wasOnline, ok := was.Online().GetOk(); ok && n.Online != nil && *n.Online != wasOnline { if wasOnline, ok := was.Online().GetOk(); ok && n.Online != nil && *n.Online != wasOnline {
pc().Online = ptr.To(*n.Online) pc().Online = new(*n.Online)
} }
case "LastSeen": case "LastSeen":
if wasSeen, ok := was.LastSeen().GetOk(); ok && n.LastSeen != nil && !wasSeen.Equal(*n.LastSeen) { if wasSeen, ok := was.LastSeen().GetOk(); ok && n.LastSeen != nil && !wasSeen.Equal(*n.LastSeen) {
pc().LastSeen = ptr.To(*n.LastSeen) pc().LastSeen = new(*n.LastSeen)
} }
case "MachineAuthorized": case "MachineAuthorized":
if was.MachineAuthorized() != n.MachineAuthorized { if was.MachineAuthorized() != n.MachineAuthorized {

@ -30,7 +30,6 @@ import (
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/persist" "tailscale.com/types/persist"
"tailscale.com/types/ptr"
"tailscale.com/util/eventbus/eventbustest" "tailscale.com/util/eventbus/eventbustest"
"tailscale.com/util/mak" "tailscale.com/util/mak"
"tailscale.com/util/must" "tailscale.com/util/must"
@ -250,7 +249,7 @@ func TestUpdatePeersStateFromResponse(t *testing.T) {
mapRes: &tailcfg.MapResponse{ mapRes: &tailcfg.MapResponse{
PeersChangedPatch: []*tailcfg.PeerChange{{ PeersChangedPatch: []*tailcfg.PeerChange{{
NodeID: 1, NodeID: 1,
Key: ptr.To(key.NodePublicFromRaw32(mem.B(append(make([]byte, 31), 'A')))), Key: new(key.NodePublicFromRaw32(mem.B(append(make([]byte, 31), 'A')))),
}}, }},
}, want: peers(&tailcfg.Node{ }, want: peers(&tailcfg.Node{
ID: 1, ID: 1,
@ -281,7 +280,7 @@ func TestUpdatePeersStateFromResponse(t *testing.T) {
mapRes: &tailcfg.MapResponse{ mapRes: &tailcfg.MapResponse{
PeersChangedPatch: []*tailcfg.PeerChange{{ PeersChangedPatch: []*tailcfg.PeerChange{{
NodeID: 1, NodeID: 1,
DiscoKey: ptr.To(key.DiscoPublicFromRaw32(mem.B(append(make([]byte, 31), 'A')))), DiscoKey: new(key.DiscoPublicFromRaw32(mem.B(append(make([]byte, 31), 'A')))),
}}, }},
}, },
want: peers(&tailcfg.Node{ want: peers(&tailcfg.Node{
@ -297,13 +296,13 @@ func TestUpdatePeersStateFromResponse(t *testing.T) {
mapRes: &tailcfg.MapResponse{ mapRes: &tailcfg.MapResponse{
PeersChangedPatch: []*tailcfg.PeerChange{{ PeersChangedPatch: []*tailcfg.PeerChange{{
NodeID: 1, NodeID: 1,
Online: ptr.To(true), Online: new(true),
}}, }},
}, },
want: peers(&tailcfg.Node{ want: peers(&tailcfg.Node{
ID: 1, ID: 1,
Name: "foo", Name: "foo",
Online: ptr.To(true), Online: new(true),
}), }),
wantStats: updateStats{changed: 1}, wantStats: updateStats{changed: 1},
}, },
@ -313,13 +312,13 @@ func TestUpdatePeersStateFromResponse(t *testing.T) {
mapRes: &tailcfg.MapResponse{ mapRes: &tailcfg.MapResponse{
PeersChangedPatch: []*tailcfg.PeerChange{{ PeersChangedPatch: []*tailcfg.PeerChange{{
NodeID: 1, NodeID: 1,
LastSeen: ptr.To(time.Unix(123, 0).UTC()), LastSeen: new(time.Unix(123, 0).UTC()),
}}, }},
}, },
want: peers(&tailcfg.Node{ want: peers(&tailcfg.Node{
ID: 1, ID: 1,
Name: "foo", Name: "foo",
LastSeen: ptr.To(time.Unix(123, 0).UTC()), LastSeen: new(time.Unix(123, 0).UTC()),
}), }),
wantStats: updateStats{changed: 1}, wantStats: updateStats{changed: 1},
}, },
@ -329,7 +328,7 @@ func TestUpdatePeersStateFromResponse(t *testing.T) {
mapRes: &tailcfg.MapResponse{ mapRes: &tailcfg.MapResponse{
PeersChangedPatch: []*tailcfg.PeerChange{{ PeersChangedPatch: []*tailcfg.PeerChange{{
NodeID: 1, NodeID: 1,
KeyExpiry: ptr.To(time.Unix(123, 0).UTC()), KeyExpiry: new(time.Unix(123, 0).UTC()),
}}, }},
}, },
want: peers(&tailcfg.Node{ want: peers(&tailcfg.Node{
@ -770,21 +769,21 @@ func TestPeerChangeDiff(t *testing.T) {
}, },
{ {
name: "patch-lastseen", name: "patch-lastseen",
a: &tailcfg.Node{ID: 1, LastSeen: ptr.To(time.Unix(1, 0))}, a: &tailcfg.Node{ID: 1, LastSeen: new(time.Unix(1, 0))},
b: &tailcfg.Node{ID: 1, LastSeen: ptr.To(time.Unix(2, 0))}, b: &tailcfg.Node{ID: 1, LastSeen: new(time.Unix(2, 0))},
want: &tailcfg.PeerChange{NodeID: 1, LastSeen: ptr.To(time.Unix(2, 0))}, want: &tailcfg.PeerChange{NodeID: 1, LastSeen: new(time.Unix(2, 0))},
}, },
{ {
name: "patch-online-to-true", name: "patch-online-to-true",
a: &tailcfg.Node{ID: 1, Online: ptr.To(false)}, a: &tailcfg.Node{ID: 1, Online: new(false)},
b: &tailcfg.Node{ID: 1, Online: ptr.To(true)}, b: &tailcfg.Node{ID: 1, Online: new(true)},
want: &tailcfg.PeerChange{NodeID: 1, Online: ptr.To(true)}, want: &tailcfg.PeerChange{NodeID: 1, Online: new(true)},
}, },
{ {
name: "patch-online-to-false", name: "patch-online-to-false",
a: &tailcfg.Node{ID: 1, Online: ptr.To(true)}, a: &tailcfg.Node{ID: 1, Online: new(true)},
b: &tailcfg.Node{ID: 1, Online: ptr.To(false)}, b: &tailcfg.Node{ID: 1, Online: new(false)},
want: &tailcfg.PeerChange{NodeID: 1, Online: ptr.To(false)}, want: &tailcfg.PeerChange{NodeID: 1, Online: new(false)},
}, },
{ {
name: "mix-patchable-and-not", name: "mix-patchable-and-not",
@ -818,14 +817,14 @@ func TestPeerChangeDiff(t *testing.T) {
}, },
{ {
name: "miss-change-masq-v4", name: "miss-change-masq-v4",
a: &tailcfg.Node{ID: 1, SelfNodeV4MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("100.64.0.1"))}, a: &tailcfg.Node{ID: 1, SelfNodeV4MasqAddrForThisPeer: new(netip.MustParseAddr("100.64.0.1"))},
b: &tailcfg.Node{ID: 1, SelfNodeV4MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("100.64.0.2"))}, b: &tailcfg.Node{ID: 1, SelfNodeV4MasqAddrForThisPeer: new(netip.MustParseAddr("100.64.0.2"))},
want: nil, want: nil,
}, },
{ {
name: "miss-change-masq-v6", name: "miss-change-masq-v6",
a: &tailcfg.Node{ID: 1, SelfNodeV6MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("2001::3456"))}, a: &tailcfg.Node{ID: 1, SelfNodeV6MasqAddrForThisPeer: new(netip.MustParseAddr("2001::3456"))},
b: &tailcfg.Node{ID: 1, SelfNodeV6MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("2001::3006"))}, b: &tailcfg.Node{ID: 1, SelfNodeV6MasqAddrForThisPeer: new(netip.MustParseAddr("2001::3006"))},
want: nil, want: nil,
}, },
{ {
@ -1079,7 +1078,7 @@ func TestUpgradeNode(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
var got *tailcfg.Node var got *tailcfg.Node
if tt.in != nil { if tt.in != nil {
got = ptr.To(*tt.in) // shallow clone got = new(*tt.in) // shallow clone
} }
upgradeNode(got) upgradeNode(got)
if diff := cmp.Diff(tt.want, got); diff != "" { if diff := cmp.Diff(tt.want, got); diff != "" {
@ -1122,7 +1121,7 @@ func BenchmarkMapSessionDelta(b *testing.B) {
{Proto: "peerapi-dns-proxy", Port: 1}, {Proto: "peerapi-dns-proxy", Port: 1},
}, },
}).View(), }).View(),
LastSeen: ptr.To(time.Unix(int64(i), 0)), LastSeen: new(time.Unix(int64(i), 0)),
}) })
} }
ms.HandleNonKeepAliveMapResponse(ctx, res) ms.HandleNonKeepAliveMapResponse(ctx, res)

@ -23,7 +23,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/eventbus" "tailscale.com/util/eventbus"
"tailscale.com/wgengine/magicsock" "tailscale.com/wgengine/magicsock"
@ -225,7 +224,7 @@ func (e *extension) profileStateChanged(_ ipn.LoginProfileView, prefs ipn.PrefsV
e.stopRelayServerLocked() e.stopRelayServerLocked()
e.port = nil e.port = nil
if ok { if ok {
e.port = ptr.To(newPort) e.port = new(newPort)
} }
} }
e.handleRelayServerLifetimeLocked() e.handleRelayServerLifetimeLocked()
@ -264,7 +263,7 @@ func (e *extension) serverStatus() status.ServerStatus {
if e.rs == nil { if e.rs == nil {
return st return st
} }
st.UDPPort = ptr.To(*e.port) st.UDPPort = new(*e.port)
st.Sessions = e.rs.GetSessions() st.Sessions = e.rs.GetSessions()
return st return st
} }

@ -18,15 +18,14 @@ 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/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
) )
func Test_extension_profileStateChanged(t *testing.T) { func Test_extension_profileStateChanged(t *testing.T) {
prefsWithPortOne := ipn.Prefs{RelayServerPort: ptr.To(uint16(1))} prefsWithPortOne := ipn.Prefs{RelayServerPort: new(uint16(1))}
prefsWithNilPort := ipn.Prefs{RelayServerPort: nil} prefsWithNilPort := ipn.Prefs{RelayServerPort: nil}
prefsWithPortOneRelayEndpoints := ipn.Prefs{ prefsWithPortOneRelayEndpoints := ipn.Prefs{
RelayServerPort: ptr.To(uint16(1)), RelayServerPort: new(uint16(1)),
RelayServerStaticEndpoints: []netip.AddrPort{netip.MustParseAddrPort("127.0.0.1:7777")}, RelayServerStaticEndpoints: []netip.AddrPort{netip.MustParseAddrPort("127.0.0.1:7777")},
} }
@ -51,28 +50,28 @@ func Test_extension_profileStateChanged(t *testing.T) {
{ {
name: "no changes non-nil port previously running", name: "no changes non-nil port previously running",
fields: fields{ fields: fields{
port: ptr.To(uint16(1)), port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(), rs: mockRelayServerNotZeroVal(),
}, },
args: args{ args: args{
prefs: prefsWithPortOne.View(), prefs: prefsWithPortOne.View(),
sameNode: true, sameNode: true,
}, },
wantPort: ptr.To(uint16(1)), wantPort: new(uint16(1)),
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
wantRelayServerFieldMutated: false, wantRelayServerFieldMutated: false,
}, },
{ {
name: "set addr ports unchanged port previously running", name: "set addr ports unchanged port previously running",
fields: fields{ fields: fields{
port: ptr.To(uint16(1)), port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(), rs: mockRelayServerNotZeroVal(),
}, },
args: args{ args: args{
prefs: prefsWithPortOneRelayEndpoints.View(), prefs: prefsWithPortOneRelayEndpoints.View(),
sameNode: true, sameNode: true,
}, },
wantPort: ptr.To(uint16(1)), wantPort: new(uint16(1)),
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
wantRelayServerFieldMutated: false, wantRelayServerFieldMutated: false,
wantEndpoints: prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints, wantEndpoints: prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints,
@ -87,7 +86,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
prefs: prefsWithPortOneRelayEndpoints.View(), prefs: prefsWithPortOneRelayEndpoints.View(),
sameNode: true, sameNode: true,
}, },
wantPort: ptr.To(uint16(1)), wantPort: new(uint16(1)),
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
wantRelayServerFieldMutated: true, wantRelayServerFieldMutated: true,
wantEndpoints: prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints, wantEndpoints: prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints,
@ -95,7 +94,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
{ {
name: "clear addr ports unchanged port previously running", name: "clear addr ports unchanged port previously running",
fields: fields{ fields: fields{
port: ptr.To(uint16(1)), port: new(uint16(1)),
staticEndpoints: views.SliceOf(prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints), staticEndpoints: views.SliceOf(prefsWithPortOneRelayEndpoints.RelayServerStaticEndpoints),
rs: mockRelayServerNotZeroVal(), rs: mockRelayServerNotZeroVal(),
}, },
@ -103,7 +102,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
prefs: prefsWithPortOne.View(), prefs: prefsWithPortOne.View(),
sameNode: true, sameNode: true,
}, },
wantPort: ptr.To(uint16(1)), wantPort: new(uint16(1)),
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
wantRelayServerFieldMutated: false, wantRelayServerFieldMutated: false,
wantEndpoints: nil, wantEndpoints: nil,
@ -111,7 +110,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
{ {
name: "prefs port nil", name: "prefs port nil",
fields: fields{ fields: fields{
port: ptr.To(uint16(1)), port: new(uint16(1)),
}, },
args: args{ args: args{
prefs: prefsWithNilPort.View(), prefs: prefsWithNilPort.View(),
@ -124,7 +123,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
{ {
name: "prefs port nil previously running", name: "prefs port nil previously running",
fields: fields{ fields: fields{
port: ptr.To(uint16(1)), port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(), rs: mockRelayServerNotZeroVal(),
}, },
args: args{ args: args{
@ -138,54 +137,54 @@ func Test_extension_profileStateChanged(t *testing.T) {
{ {
name: "prefs port changed", name: "prefs port changed",
fields: fields{ fields: fields{
port: ptr.To(uint16(2)), port: new(uint16(2)),
}, },
args: args{ args: args{
prefs: prefsWithPortOne.View(), prefs: prefsWithPortOne.View(),
sameNode: true, sameNode: true,
}, },
wantPort: ptr.To(uint16(1)), wantPort: new(uint16(1)),
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
wantRelayServerFieldMutated: true, wantRelayServerFieldMutated: true,
}, },
{ {
name: "prefs port changed previously running", name: "prefs port changed previously running",
fields: fields{ fields: fields{
port: ptr.To(uint16(2)), port: new(uint16(2)),
rs: mockRelayServerNotZeroVal(), rs: mockRelayServerNotZeroVal(),
}, },
args: args{ args: args{
prefs: prefsWithPortOne.View(), prefs: prefsWithPortOne.View(),
sameNode: true, sameNode: true,
}, },
wantPort: ptr.To(uint16(1)), wantPort: new(uint16(1)),
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
wantRelayServerFieldMutated: true, wantRelayServerFieldMutated: true,
}, },
{ {
name: "sameNode false", name: "sameNode false",
fields: fields{ fields: fields{
port: ptr.To(uint16(1)), port: new(uint16(1)),
}, },
args: args{ args: args{
prefs: prefsWithPortOne.View(), prefs: prefsWithPortOne.View(),
sameNode: false, sameNode: false,
}, },
wantPort: ptr.To(uint16(1)), wantPort: new(uint16(1)),
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
wantRelayServerFieldMutated: true, wantRelayServerFieldMutated: true,
}, },
{ {
name: "sameNode false previously running", name: "sameNode false previously running",
fields: fields{ fields: fields{
port: ptr.To(uint16(1)), port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(), rs: mockRelayServerNotZeroVal(),
}, },
args: args{ args: args{
prefs: prefsWithPortOne.View(), prefs: prefsWithPortOne.View(),
sameNode: false, sameNode: false,
}, },
wantPort: ptr.To(uint16(1)), wantPort: new(uint16(1)),
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
wantRelayServerFieldMutated: true, wantRelayServerFieldMutated: true,
}, },
@ -198,7 +197,7 @@ func Test_extension_profileStateChanged(t *testing.T) {
prefs: prefsWithPortOne.View(), prefs: prefsWithPortOne.View(),
sameNode: false, sameNode: false,
}, },
wantPort: ptr.To(uint16(1)), wantPort: new(uint16(1)),
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
wantRelayServerFieldMutated: true, wantRelayServerFieldMutated: true,
}, },
@ -280,7 +279,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
{ {
name: "want running", name: "want running",
shutdown: false, shutdown: false,
port: ptr.To(uint16(1)), port: new(uint16(1)),
hasNodeAttrDisableRelayServer: false, hasNodeAttrDisableRelayServer: false,
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
wantRelayServerFieldMutated: true, wantRelayServerFieldMutated: true,
@ -288,7 +287,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
{ {
name: "want running previously running", name: "want running previously running",
shutdown: false, shutdown: false,
port: ptr.To(uint16(1)), port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(), rs: mockRelayServerNotZeroVal(),
hasNodeAttrDisableRelayServer: false, hasNodeAttrDisableRelayServer: false,
wantRelayServerFieldNonNil: true, wantRelayServerFieldNonNil: true,
@ -297,7 +296,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
{ {
name: "shutdown true", name: "shutdown true",
shutdown: true, shutdown: true,
port: ptr.To(uint16(1)), port: new(uint16(1)),
hasNodeAttrDisableRelayServer: false, hasNodeAttrDisableRelayServer: false,
wantRelayServerFieldNonNil: false, wantRelayServerFieldNonNil: false,
wantRelayServerFieldMutated: false, wantRelayServerFieldMutated: false,
@ -305,7 +304,7 @@ func Test_extension_handleRelayServerLifetimeLocked(t *testing.T) {
{ {
name: "shutdown true previously running", name: "shutdown true previously running",
shutdown: true, shutdown: true,
port: ptr.To(uint16(1)), port: new(uint16(1)),
rs: mockRelayServerNotZeroVal(), rs: mockRelayServerNotZeroVal(),
hasNodeAttrDisableRelayServer: false, hasNodeAttrDisableRelayServer: false,
wantRelayServerFieldNonNil: false, wantRelayServerFieldNonNil: false,

@ -23,7 +23,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/lazy" "tailscale.com/types/lazy"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/util/cloudenv" "tailscale.com/util/cloudenv"
"tailscale.com/util/dnsname" "tailscale.com/util/dnsname"
"tailscale.com/util/lineiter" "tailscale.com/util/lineiter"
@ -93,8 +92,8 @@ func condCall[T any](fn func() T) T {
} }
var ( var (
lazyInContainer = &lazyAtomicValue[opt.Bool]{f: ptr.To(inContainer)} lazyInContainer = &lazyAtomicValue[opt.Bool]{f: new(inContainer)}
lazyGoArchVar = &lazyAtomicValue[string]{f: ptr.To(goArchVar)} lazyGoArchVar = &lazyAtomicValue[string]{f: new(goArchVar)}
) )
type lazyAtomicValue[T any] struct { type lazyAtomicValue[T any] struct {

@ -10,7 +10,6 @@ import (
"path/filepath" "path/filepath"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"tailscale.com/types/ptr"
) )
func init() { func init() {
@ -19,7 +18,7 @@ func init() {
} }
var ( var (
lazyOSVersion = &lazyAtomicValue[string]{f: ptr.To(osVersionDarwin)} lazyOSVersion = &lazyAtomicValue[string]{f: new(osVersionDarwin)}
) )
func packageTypeDarwin() string { func packageTypeDarwin() string {

@ -11,7 +11,6 @@ import (
"os/exec" "os/exec"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"tailscale.com/types/ptr"
"tailscale.com/version/distro" "tailscale.com/version/distro"
) )
@ -22,8 +21,8 @@ func init() {
} }
var ( var (
lazyVersionMeta = &lazyAtomicValue[versionMeta]{f: ptr.To(freebsdVersionMeta)} lazyVersionMeta = &lazyAtomicValue[versionMeta]{f: new(freebsdVersionMeta)}
lazyOSVersion = &lazyAtomicValue[string]{f: ptr.To(osVersionFreeBSD)} lazyOSVersion = &lazyAtomicValue[string]{f: new(osVersionFreeBSD)}
) )
func distroNameFreeBSD() string { func distroNameFreeBSD() string {

@ -11,7 +11,6 @@ import (
"strings" "strings"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"tailscale.com/types/ptr"
"tailscale.com/util/lineiter" "tailscale.com/util/lineiter"
"tailscale.com/version/distro" "tailscale.com/version/distro"
) )
@ -26,8 +25,8 @@ func init() {
} }
var ( var (
lazyVersionMeta = &lazyAtomicValue[versionMeta]{f: ptr.To(linuxVersionMeta)} lazyVersionMeta = &lazyAtomicValue[versionMeta]{f: new(linuxVersionMeta)}
lazyOSVersion = &lazyAtomicValue[string]{f: ptr.To(osVersionLinux)} lazyOSVersion = &lazyAtomicValue[string]{f: new(osVersionLinux)}
) )
type versionMeta struct { type versionMeta struct {

@ -9,14 +9,13 @@ import (
"runtime" "runtime"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"tailscale.com/types/ptr"
) )
func init() { func init() {
unameMachine = lazyUnameMachine.Get unameMachine = lazyUnameMachine.Get
} }
var lazyUnameMachine = &lazyAtomicValue[string]{f: ptr.To(unameMachineUnix)} var lazyUnameMachine = &lazyAtomicValue[string]{f: new(unameMachineUnix)}
func unameMachineUnix() string { func unameMachineUnix() string {
switch runtime.GOOS { switch runtime.GOOS {

@ -11,7 +11,6 @@ import (
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry" "golang.org/x/sys/windows/registry"
"tailscale.com/types/ptr"
"tailscale.com/util/winutil" "tailscale.com/util/winutil"
"tailscale.com/util/winutil/winenv" "tailscale.com/util/winutil/winenv"
) )
@ -23,9 +22,9 @@ func init() {
} }
var ( var (
lazyDistroName = &lazyAtomicValue[string]{f: ptr.To(distroNameWindows)} lazyDistroName = &lazyAtomicValue[string]{f: new(distroNameWindows)}
lazyOSVersion = &lazyAtomicValue[string]{f: ptr.To(osVersionWindows)} lazyOSVersion = &lazyAtomicValue[string]{f: new(osVersionWindows)}
lazyPackageType = &lazyAtomicValue[string]{f: ptr.To(packageTypeWindows)} lazyPackageType = &lazyAtomicValue[string]{f: new(packageTypeWindows)}
) )
func distroNameWindows() string { func distroNameWindows() string {

@ -14,7 +14,6 @@ import (
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/persist" "tailscale.com/types/persist"
"tailscale.com/types/preftype" "tailscale.com/types/preftype"
"tailscale.com/types/ptr"
) )
// Clone makes a deep copy of LoginProfile. // Clone makes a deep copy of LoginProfile.
@ -62,7 +61,7 @@ func (src *Prefs) Clone() *Prefs {
} }
} }
if dst.RelayServerPort != nil { if dst.RelayServerPort != nil {
dst.RelayServerPort = ptr.To(*src.RelayServerPort) dst.RelayServerPort = new(*src.RelayServerPort)
} }
dst.RelayServerStaticEndpoints = append(src.RelayServerStaticEndpoints[:0:0], src.RelayServerStaticEndpoints...) dst.RelayServerStaticEndpoints = append(src.RelayServerStaticEndpoints[:0:0], src.RelayServerStaticEndpoints...)
dst.Persist = src.Persist.Clone() dst.Persist = src.Persist.Clone()
@ -122,7 +121,7 @@ func (src *ServeConfig) Clone() *ServeConfig {
if v == nil { if v == nil {
dst.TCP[k] = nil dst.TCP[k] = nil
} else { } else {
dst.TCP[k] = ptr.To(*v) dst.TCP[k] = new(*v)
} }
} }
} }
@ -184,7 +183,7 @@ func (src *ServiceConfig) Clone() *ServiceConfig {
if v == nil { if v == nil {
dst.TCP[k] = nil dst.TCP[k] = nil
} else { } else {
dst.TCP[k] = ptr.To(*v) dst.TCP[k] = new(*v)
} }
} }
} }

@ -81,7 +81,6 @@ import (
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/persist" "tailscale.com/types/persist"
"tailscale.com/types/preftype" "tailscale.com/types/preftype"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/checkchange" "tailscale.com/util/checkchange"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
@ -1738,7 +1737,7 @@ func (b *LocalBackend) setControlClientStatusLocked(c controlclient.Client, st c
b.logf("Failed to save new controlclient state: %v", err) b.logf("Failed to save new controlclient state: %v", err)
} }
b.sendToLocked(ipn.Notify{Prefs: ptr.To(prefs.View())}, allClients) b.sendToLocked(ipn.Notify{Prefs: new(prefs.View())}, allClients)
} }
// initTKALocked is dependent on CurrentProfile.ID, which is initialized // initTKALocked is dependent on CurrentProfile.ID, which is initialized
@ -3139,13 +3138,13 @@ func (b *LocalBackend) WatchNotificationsAs(ctx context.Context, actor ipnauth.A
ini = &ipn.Notify{Version: version.Long()} ini = &ipn.Notify{Version: version.Long()}
if mask&ipn.NotifyInitialState != 0 { if mask&ipn.NotifyInitialState != 0 {
ini.SessionID = sessionID ini.SessionID = sessionID
ini.State = ptr.To(b.state) ini.State = new(b.state)
if b.state == ipn.NeedsLogin && b.authURL != "" { if b.state == ipn.NeedsLogin && b.authURL != "" {
ini.BrowseToURL = ptr.To(b.authURL) ini.BrowseToURL = new(b.authURL)
} }
} }
if mask&ipn.NotifyInitialPrefs != 0 { if mask&ipn.NotifyInitialPrefs != 0 {
ini.Prefs = ptr.To(b.sanitizedPrefsLocked()) ini.Prefs = new(b.sanitizedPrefsLocked())
} }
if mask&ipn.NotifyInitialNetMap != 0 { if mask&ipn.NotifyInitialNetMap != 0 {
ini.NetMap = cn.NetMap() ini.NetMap = cn.NetMap()
@ -3397,7 +3396,7 @@ func (b *LocalBackend) sendTo(n ipn.Notify, recipient notificationTarget) {
// sendToLocked is like [LocalBackend.sendTo], but assumes b.mu is already held. // sendToLocked is like [LocalBackend.sendTo], but assumes b.mu is already held.
func (b *LocalBackend) sendToLocked(n ipn.Notify, recipient notificationTarget) { func (b *LocalBackend) sendToLocked(n ipn.Notify, recipient notificationTarget) {
if n.Prefs != nil { if n.Prefs != nil {
n.Prefs = ptr.To(stripKeysFromPrefs(*n.Prefs)) n.Prefs = new(stripKeysFromPrefs(*n.Prefs))
} }
if n.Version == "" { if n.Version == "" {
n.Version = version.Long() n.Version = version.Long()
@ -4415,7 +4414,7 @@ func (b *LocalBackend) changeDisablesExitNodeLocked(prefs ipn.PrefsView, change
// First, apply the adjustments to a copy of the changes, // First, apply the adjustments to a copy of the changes,
// e.g., clear AutoExitNode if ExitNodeID is set. // e.g., clear AutoExitNode if ExitNodeID is set.
tmpChange := ptr.To(*change) tmpChange := new(*change)
tmpChange.Prefs = *change.Prefs.Clone() tmpChange.Prefs = *change.Prefs.Clone()
b.adjustEditPrefsLocked(prefs, tmpChange) b.adjustEditPrefsLocked(prefs, tmpChange)
@ -6185,7 +6184,7 @@ func (b *LocalBackend) resolveExitNodeLocked() (changed bool) {
b.goTracker.Go(b.doSetHostinfoFilterServices) b.goTracker.Go(b.doSetHostinfoFilterServices)
} }
b.sendToLocked(ipn.Notify{Prefs: ptr.To(prefs.View())}, allClients) b.sendToLocked(ipn.Notify{Prefs: new(prefs.View())}, allClients)
return true return true
} }

@ -61,7 +61,6 @@ import (
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/persist" "tailscale.com/types/persist"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/dnsname" "tailscale.com/util/dnsname"
"tailscale.com/util/eventbus" "tailscale.com/util/eventbus"
@ -877,7 +876,7 @@ func TestConfigureExitNode(t *testing.T) {
Prefs: ipn.Prefs{AutoExitNode: "any"}, Prefs: ipn.Prefs{AutoExitNode: "any"},
AutoExitNodeSet: true, AutoExitNodeSet: true,
}, },
useExitNodeEnabled: ptr.To(false), useExitNodeEnabled: new(false),
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
ExitNodeID: "", ExitNodeID: "",
@ -894,7 +893,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: clientNetmap, netMap: clientNetmap,
report: report, report: report,
useExitNodeEnabled: ptr.To(true), useExitNodeEnabled: new(true),
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
ExitNodeID: exitNode1.StableID(), ExitNodeID: exitNode1.StableID(),
@ -909,7 +908,7 @@ func TestConfigureExitNode(t *testing.T) {
ControlURL: controlURL, ControlURL: controlURL,
}, },
netMap: clientNetmap, netMap: clientNetmap,
exitNodeIDPolicy: ptr.To(exitNode1.StableID()), exitNodeIDPolicy: new(exitNode1.StableID()),
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
ExitNodeID: exitNode1.StableID(), ExitNodeID: exitNode1.StableID(),
@ -922,7 +921,7 @@ func TestConfigureExitNode(t *testing.T) {
ControlURL: controlURL, ControlURL: controlURL,
}, },
netMap: clientNetmap, netMap: clientNetmap,
exitNodeIDPolicy: ptr.To(exitNode1.StableID()), exitNodeIDPolicy: new(exitNode1.StableID()),
changePrefs: &ipn.MaskedPrefs{ changePrefs: &ipn.MaskedPrefs{
Prefs: ipn.Prefs{ Prefs: ipn.Prefs{
ExitNodeID: exitNode2.StableID(), // this should be ignored ExitNodeID: exitNode2.StableID(), // this should be ignored
@ -942,7 +941,7 @@ func TestConfigureExitNode(t *testing.T) {
ControlURL: controlURL, ControlURL: controlURL,
}, },
netMap: clientNetmap, netMap: clientNetmap,
exitNodeIDPolicy: ptr.To(exitNode1.StableID()), exitNodeIDPolicy: new(exitNode1.StableID()),
changePrefs: &ipn.MaskedPrefs{ changePrefs: &ipn.MaskedPrefs{
Prefs: ipn.Prefs{ Prefs: ipn.Prefs{
ExitNodeIP: exitNode2.Addresses().At(0).Addr(), // this should be ignored ExitNodeIP: exitNode2.Addresses().At(0).Addr(), // this should be ignored
@ -962,7 +961,7 @@ func TestConfigureExitNode(t *testing.T) {
ControlURL: controlURL, ControlURL: controlURL,
}, },
netMap: clientNetmap, netMap: clientNetmap,
exitNodeIDPolicy: ptr.To(exitNode1.StableID()), exitNodeIDPolicy: new(exitNode1.StableID()),
changePrefs: &ipn.MaskedPrefs{ changePrefs: &ipn.MaskedPrefs{
Prefs: ipn.Prefs{ Prefs: ipn.Prefs{
AutoExitNode: "any", // this should be ignored AutoExitNode: "any", // this should be ignored
@ -982,7 +981,7 @@ func TestConfigureExitNode(t *testing.T) {
ControlURL: controlURL, ControlURL: controlURL,
}, },
netMap: clientNetmap, netMap: clientNetmap,
exitNodeIPPolicy: ptr.To(exitNode2.Addresses().At(0).Addr()), exitNodeIPPolicy: new(exitNode2.Addresses().At(0).Addr()),
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
ExitNodeID: exitNode2.StableID(), ExitNodeID: exitNode2.StableID(),
@ -996,7 +995,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: clientNetmap, netMap: clientNetmap,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
ExitNodeID: exitNode1.StableID(), ExitNodeID: exitNode1.StableID(),
@ -1011,7 +1010,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: clientNetmap, netMap: clientNetmap,
report: nil, report: nil,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
ExitNodeID: unresolvedExitNodeID, ExitNodeID: unresolvedExitNodeID,
@ -1026,7 +1025,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: nil, netMap: nil,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
ExitNodeID: unresolvedExitNodeID, ExitNodeID: unresolvedExitNodeID,
@ -1042,7 +1041,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: nil, netMap: nil,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
exitNodeAllowedIDs: nil, // not configured, so all exit node IDs are implicitly allowed exitNodeAllowedIDs: nil, // not configured, so all exit node IDs are implicitly allowed
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
@ -1059,7 +1058,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: nil, netMap: nil,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
exitNodeAllowedIDs: []tailcfg.StableNodeID{ exitNodeAllowedIDs: []tailcfg.StableNodeID{
exitNode2.StableID(), // the current exit node ID is allowed exitNode2.StableID(), // the current exit node ID is allowed
}, },
@ -1078,7 +1077,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: nil, netMap: nil,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
exitNodeAllowedIDs: []tailcfg.StableNodeID{ exitNodeAllowedIDs: []tailcfg.StableNodeID{
exitNode1.StableID(), // a different exit node ID; the current one is not allowed exitNode1.StableID(), // a different exit node ID; the current one is not allowed
}, },
@ -1097,7 +1096,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: clientNetmap, netMap: clientNetmap,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
exitNodeAllowedIDs: []tailcfg.StableNodeID{ exitNodeAllowedIDs: []tailcfg.StableNodeID{
exitNode2.StableID(), // a different exit node ID; the current one is not allowed exitNode2.StableID(), // a different exit node ID; the current one is not allowed
}, },
@ -1116,7 +1115,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: clientNetmap, netMap: clientNetmap,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
ExitNodeID: exitNode1.StableID(), // switch to the best exit node ExitNodeID: exitNode1.StableID(), // switch to the best exit node
@ -1131,7 +1130,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: clientNetmap, netMap: clientNetmap,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:foo")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:foo")),
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
ExitNodeID: exitNode1.StableID(), // unknown exit node expressions should work as "any" ExitNodeID: exitNode1.StableID(), // unknown exit node expressions should work as "any"
@ -1164,8 +1163,8 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: clientNetmap, netMap: clientNetmap,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
useExitNodeEnabled: ptr.To(false), // should fail with an error useExitNodeEnabled: new(false), // should fail with an error
wantExitNodeToggleErr: errManagedByPolicy, wantExitNodeToggleErr: errManagedByPolicy,
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
@ -1182,7 +1181,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: clientNetmap, netMap: clientNetmap,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
exitNodeAllowOverride: true, // allow changing the exit node exitNodeAllowOverride: true, // allow changing the exit node
changePrefs: &ipn.MaskedPrefs{ changePrefs: &ipn.MaskedPrefs{
Prefs: ipn.Prefs{ Prefs: ipn.Prefs{
@ -1204,7 +1203,7 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: clientNetmap, netMap: clientNetmap,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
exitNodeAllowOverride: true, // allow changing, but not disabling, the exit node exitNodeAllowOverride: true, // allow changing, but not disabling, the exit node
changePrefs: &ipn.MaskedPrefs{ changePrefs: &ipn.MaskedPrefs{
Prefs: ipn.Prefs{ Prefs: ipn.Prefs{
@ -1228,9 +1227,9 @@ func TestConfigureExitNode(t *testing.T) {
}, },
netMap: clientNetmap, netMap: clientNetmap,
report: report, report: report,
exitNodeIDPolicy: ptr.To(tailcfg.StableNodeID("auto:any")), exitNodeIDPolicy: new(tailcfg.StableNodeID("auto:any")),
exitNodeAllowOverride: true, // allow changing, but not disabling, the exit node exitNodeAllowOverride: true, // allow changing, but not disabling, the exit node
useExitNodeEnabled: ptr.To(false), // should fail with an error useExitNodeEnabled: new(false), // should fail with an error
wantExitNodeToggleErr: errManagedByPolicy, wantExitNodeToggleErr: errManagedByPolicy,
wantPrefs: ipn.Prefs{ wantPrefs: ipn.Prefs{
ControlURL: controlURL, ControlURL: controlURL,
@ -1992,15 +1991,15 @@ func TestUpdateNetmapDelta(t *testing.T) {
}, },
{ {
NodeID: 2, NodeID: 2,
Online: ptr.To(true), Online: new(true),
}, },
{ {
NodeID: 3, NodeID: 3,
Online: ptr.To(false), Online: new(false),
}, },
{ {
NodeID: 4, NodeID: 4,
LastSeen: ptr.To(someTime), LastSeen: new(someTime),
}, },
}, },
}, someTime) }, someTime)
@ -2021,17 +2020,17 @@ func TestUpdateNetmapDelta(t *testing.T) {
{ {
ID: 2, ID: 2,
Key: makeNodeKeyFromID(2), Key: makeNodeKeyFromID(2),
Online: ptr.To(true), Online: new(true),
}, },
{ {
ID: 3, ID: 3,
Key: makeNodeKeyFromID(3), Key: makeNodeKeyFromID(3),
Online: ptr.To(false), Online: new(false),
}, },
{ {
ID: 4, ID: 4,
Key: makeNodeKeyFromID(4), Key: makeNodeKeyFromID(4),
LastSeen: ptr.To(someTime), LastSeen: new(someTime),
}, },
} }
for _, want := range wants { for _, want := range wants {
@ -3149,11 +3148,11 @@ func TestUpdateNetmapDeltaAutoExitNode(t *testing.T) {
muts: []*tailcfg.PeerChange{ muts: []*tailcfg.PeerChange{
{ {
NodeID: 1, NodeID: 1,
Online: ptr.To(true), Online: new(true),
}, },
{ {
NodeID: 2, NodeID: 2,
Online: ptr.To(false), // the selected exit node goes offline Online: new(false), // the selected exit node goes offline
}, },
}, },
exitNodeIDWant: peer1.StableID(), exitNodeIDWant: peer1.StableID(),
@ -3173,11 +3172,11 @@ func TestUpdateNetmapDeltaAutoExitNode(t *testing.T) {
muts: []*tailcfg.PeerChange{ muts: []*tailcfg.PeerChange{
{ {
NodeID: 1, NodeID: 1,
Online: ptr.To(false), // a different exit node goes offline Online: new(false), // a different exit node goes offline
}, },
{ {
NodeID: 2, NodeID: 2,
Online: ptr.To(true), Online: new(true),
}, },
}, },
exitNodeIDWant: peer2.StableID(), exitNodeIDWant: peer2.StableID(),
@ -4326,7 +4325,7 @@ func TestDriveManageShares(t *testing.T) {
b.driveSetSharesLocked(tt.existing) b.driveSetSharesLocked(tt.existing)
} }
if !tt.disabled { if !tt.disabled {
nm := ptr.To(*b.currentNode().NetMap()) nm := new(*b.currentNode().NetMap())
self := nm.SelfNode.AsStruct() self := nm.SelfNode.AsStruct()
self.CapMap = tailcfg.NodeCapMap{tailcfg.NodeAttrsTaildriveShare: nil} self.CapMap = tailcfg.NodeCapMap{tailcfg.NodeAttrsTaildriveShare: nil}
nm.SelfNode = self.View() nm.SelfNode = self.View()
@ -4476,7 +4475,7 @@ func makePeer(id tailcfg.NodeID, opts ...peerOptFunc) tailcfg.NodeView {
DiscoKey: makeDiscoKeyFromID(id), DiscoKey: makeDiscoKeyFromID(id),
StableID: tailcfg.StableNodeID(fmt.Sprintf("stable%d", id)), StableID: tailcfg.StableNodeID(fmt.Sprintf("stable%d", id)),
Name: fmt.Sprintf("peer%d", id), Name: fmt.Sprintf("peer%d", id),
Online: ptr.To(true), Online: new(true),
MachineAuthorized: true, MachineAuthorized: true,
HomeDERP: int(id), HomeDERP: int(id),
} }
@ -6399,13 +6398,13 @@ func TestConfigFileReload(t *testing.T) {
initial: &conffile.Config{ initial: &conffile.Config{
Parsed: ipn.ConfigVAlpha{ Parsed: ipn.ConfigVAlpha{
Version: "alpha0", Version: "alpha0",
Hostname: ptr.To("initial-host"), Hostname: new("initial-host"),
}, },
}, },
updated: &conffile.Config{ updated: &conffile.Config{
Parsed: ipn.ConfigVAlpha{ Parsed: ipn.ConfigVAlpha{
Version: "alpha0", Version: "alpha0",
Hostname: ptr.To("updated-host"), Hostname: new("updated-host"),
}, },
}, },
checkFn: func(t *testing.T, b *LocalBackend) { checkFn: func(t *testing.T, b *LocalBackend) {
@ -7362,28 +7361,28 @@ func TestStripKeysFromPrefs(t *testing.T) {
genNotify := map[string]func() ipn.Notify{ genNotify := map[string]func() ipn.Notify{
"Notify.Prefs.ж.Persist.PrivateNodeKey": func() ipn.Notify { "Notify.Prefs.ж.Persist.PrivateNodeKey": func() ipn.Notify {
return ipn.Notify{ return ipn.Notify{
Prefs: ptr.To((&ipn.Prefs{ Prefs: new((&ipn.Prefs{
Persist: &persist.Persist{PrivateNodeKey: key.NewNode()}, Persist: &persist.Persist{PrivateNodeKey: key.NewNode()},
}).View()), }).View()),
} }
}, },
"Notify.Prefs.ж.Persist.OldPrivateNodeKey": func() ipn.Notify { "Notify.Prefs.ж.Persist.OldPrivateNodeKey": func() ipn.Notify {
return ipn.Notify{ return ipn.Notify{
Prefs: ptr.To((&ipn.Prefs{ Prefs: new((&ipn.Prefs{
Persist: &persist.Persist{OldPrivateNodeKey: key.NewNode()}, Persist: &persist.Persist{OldPrivateNodeKey: key.NewNode()},
}).View()), }).View()),
} }
}, },
"Notify.Prefs.ж.Persist.NetworkLockKey": func() ipn.Notify { "Notify.Prefs.ж.Persist.NetworkLockKey": func() ipn.Notify {
return ipn.Notify{ return ipn.Notify{
Prefs: ptr.To((&ipn.Prefs{ Prefs: new((&ipn.Prefs{
Persist: &persist.Persist{NetworkLockKey: key.NewNLPrivate()}, Persist: &persist.Persist{NetworkLockKey: key.NewNLPrivate()},
}).View()), }).View()),
} }
}, },
"Notify.Prefs.ж.Persist.AttestationKey": func() ipn.Notify { "Notify.Prefs.ж.Persist.AttestationKey": func() ipn.Notify {
return ipn.Notify{ return ipn.Notify{
Prefs: ptr.To((&ipn.Prefs{ Prefs: new((&ipn.Prefs{
Persist: &persist.Persist{AttestationKey: new(fakeAttestationKey)}, Persist: &persist.Persist{AttestationKey: new(fakeAttestationKey)},
}).View()), }).View()),
} }

@ -11,7 +11,6 @@ import (
"time" "time"
"gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip"
"tailscale.com/types/ptr"
) )
// TCPHandlerForDst returns a TCP handler for connections to dst, or nil if // TCPHandlerForDst returns a TCP handler for connections to dst, or nil if
@ -52,7 +51,7 @@ func (b *LocalBackend) TCPHandlerForDst(src, dst netip.AddrPort) (handler func(c
// tell the difference between a long lived connection that is idle // tell the difference between a long lived connection that is idle
// vs a connection that is dead because the peer has gone away. // vs a connection that is dead because the peer has gone away.
// We pick 72h as that is typically sufficient for a long weekend. // We pick 72h as that is typically sufficient for a long weekend.
opts = append(opts, ptr.To(tcpip.KeepaliveIdleOption(72*time.Hour))) opts = append(opts, new(tcpip.KeepaliveIdleOption(72*time.Hour)))
return b.handleSSHConn, opts return b.handleSSHConn, opts
} }
// TODO(will,sonia): allow customizing web client port ? // TODO(will,sonia): allow customizing web client port ?

@ -24,7 +24,6 @@ import (
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/dnsname" "tailscale.com/util/dnsname"
"tailscale.com/util/eventbus" "tailscale.com/util/eventbus"
@ -414,7 +413,7 @@ func (nb *nodeBackend) netMapWithPeers() *netmap.NetworkMap {
if nb.netMap == nil { if nb.netMap == nil {
return nil return nil
} }
nm := ptr.To(*nb.netMap) // shallow clone nm := new(*nb.netMap) // shallow clone
nm.Peers = slicesx.MapValues(nb.peers) nm.Peers = slicesx.MapValues(nb.peers)
slices.SortFunc(nm.Peers, func(a, b tailcfg.NodeView) int { slices.SortFunc(nm.Peers, func(a, b tailcfg.NodeView) int {
return cmp.Compare(a.ID(), b.ID()) return cmp.Compare(a.ID(), b.ID())

@ -12,7 +12,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tstest" "tailscale.com/tstest"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/ptr"
"tailscale.com/util/eventbus" "tailscale.com/util/eventbus"
) )
@ -146,7 +145,7 @@ func TestNodeBackendReachability(t *testing.T) {
name: "disabled/offline", name: "disabled/offline",
cap: false, cap: false,
peer: tailcfg.Node{ peer: tailcfg.Node{
Online: ptr.To(false), Online: new(false),
}, },
want: false, want: false,
}, },
@ -154,7 +153,7 @@ func TestNodeBackendReachability(t *testing.T) {
name: "disabled/online", name: "disabled/online",
cap: false, cap: false,
peer: tailcfg.Node{ peer: tailcfg.Node{
Online: ptr.To(true), Online: new(true),
}, },
want: true, want: true,
}, },
@ -162,7 +161,7 @@ func TestNodeBackendReachability(t *testing.T) {
name: "enabled/offline", name: "enabled/offline",
cap: true, cap: true,
peer: tailcfg.Node{ peer: tailcfg.Node{
Online: ptr.To(false), Online: new(false),
}, },
want: true, want: true,
}, },
@ -170,7 +169,7 @@ func TestNodeBackendReachability(t *testing.T) {
name: "enabled/online", name: "enabled/online",
cap: true, cap: true,
peer: tailcfg.Node{ peer: tailcfg.Node{
Online: ptr.To(true), Online: new(true),
}, },
want: true, want: true,
}, },

@ -16,7 +16,6 @@ import (
"tailscale.com/ipn" "tailscale.com/ipn"
"tailscale.com/ipn/lapitest" "tailscale.com/ipn/lapitest"
"tailscale.com/tsd" "tailscale.com/tsd"
"tailscale.com/types/ptr"
"tailscale.com/util/syspolicy/pkey" "tailscale.com/util/syspolicy/pkey"
"tailscale.com/util/syspolicy/policytest" "tailscale.com/util/syspolicy/policytest"
) )
@ -49,7 +48,7 @@ func TestUserConnectDisconnectNonWindows(t *testing.T) {
// And if we send a notification, both users should receive it. // And if we send a notification, both users should receive it.
wantErrMessage := "test error" wantErrMessage := "test error"
testNotify := ipn.Notify{ErrMessage: ptr.To(wantErrMessage)} testNotify := ipn.Notify{ErrMessage: new(wantErrMessage)}
server.Backend().DebugNotify(testNotify) server.Backend().DebugNotify(testNotify)
if n, err := watcherA.Next(); err != nil { if n, err := watcherA.Next(); err != nil {
@ -274,12 +273,12 @@ func TestShutdownViaLocalAPI(t *testing.T) {
}, },
{ {
name: "AllowTailscaledRestart/False", name: "AllowTailscaledRestart/False",
allowTailscaledRestart: ptr.To(false), allowTailscaledRestart: new(false),
wantErr: errAccessDeniedByPolicy, wantErr: errAccessDeniedByPolicy,
}, },
{ {
name: "AllowTailscaledRestart/True", name: "AllowTailscaledRestart/True",
allowTailscaledRestart: ptr.To(true), allowTailscaledRestart: new(true),
wantErr: nil, // shutdown should be allowed wantErr: nil, // shutdown should be allowed
}, },
} }

@ -20,7 +20,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/tka" "tailscale.com/tka"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/dnsname" "tailscale.com/util/dnsname"
"tailscale.com/version" "tailscale.com/version"
@ -535,7 +534,7 @@ func (sb *StatusBuilder) AddPeer(peer key.NodePublic, st *PeerStatus) {
e.Expired = true e.Expired = true
} }
if t := st.KeyExpiry; t != nil { if t := st.KeyExpiry; t != nil {
e.KeyExpiry = ptr.To(*t) e.KeyExpiry = new(*t)
} }
if v := st.CapMap; v != nil { if v := st.CapMap; v != nil {
e.CapMap = v e.CapMap = v

@ -22,7 +22,6 @@ import (
"tailscale.com/ipn/ipnserver" "tailscale.com/ipn/ipnserver"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/logid" "tailscale.com/types/logid"
"tailscale.com/types/ptr"
"tailscale.com/util/mak" "tailscale.com/util/mak"
"tailscale.com/util/rands" "tailscale.com/util/rands"
) )
@ -153,7 +152,7 @@ func (s *Server) MakeTestActor(name string, clientID string) *ipnauth.TestActor
} }
// Create a shallow copy of the base actor and assign it the new client ID. // Create a shallow copy of the base actor and assign it the new client ID.
actor := ptr.To(*baseActor) actor := new(*baseActor)
actor.CID = ipnauth.ClientIDFrom(clientID) actor.CID = ipnauth.ClientIDFrom(clientID)
return actor return actor
} }

@ -43,7 +43,6 @@ import (
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/logid" "tailscale.com/types/logid"
"tailscale.com/types/ptr"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/eventbus" "tailscale.com/util/eventbus"
"tailscale.com/util/httpm" "tailscale.com/util/httpm"
@ -845,8 +844,8 @@ func InUseOtherUserIPNStream(w http.ResponseWriter, r *http.Request, err error)
} }
js, err := json.Marshal(&ipn.Notify{ js, err := json.Marshal(&ipn.Notify{
Version: version.Long(), Version: version.Long(),
State: ptr.To(ipn.InUseOtherUser), State: new(ipn.InUseOtherUser),
ErrMessage: ptr.To(err.Error()), ErrMessage: new(err.Error()),
}) })
if err != nil { if err != nil {
return false return false

@ -24,7 +24,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/reconcile"
tsapi "tailscale.com/k8s-operator/apis/v1alpha1" tsapi "tailscale.com/k8s-operator/apis/v1alpha1"
"tailscale.com/types/ptr"
"tailscale.com/util/set" "tailscale.com/util/set"
) )
@ -243,7 +242,7 @@ func (r *Reconciler) generateIngressPolicy(ctx context.Context, namespace string
ResourceVersion: policy.ResourceVersion, ResourceVersion: policy.ResourceVersion,
}, },
Spec: admr.ValidatingAdmissionPolicySpec{ Spec: admr.ValidatingAdmissionPolicySpec{
FailurePolicy: ptr.To(admr.Fail), FailurePolicy: new(admr.Fail),
MatchConstraints: &admr.MatchResources{ MatchConstraints: &admr.MatchResources{
// The operator allows ingress via Ingress resources & Service resources (that use the "tailscale" load // The operator allows ingress via Ingress resources & Service resources (that use the "tailscale" load
// balancer class), so we have two resource rules here with multiple validation expressions that attempt // balancer class), so we have two resource rules here with multiple validation expressions that attempt
@ -304,7 +303,7 @@ func (r *Reconciler) generateEgressPolicy(ctx context.Context, namespace string,
ResourceVersion: policy.ResourceVersion, ResourceVersion: policy.ResourceVersion,
}, },
Spec: admr.ValidatingAdmissionPolicySpec{ Spec: admr.ValidatingAdmissionPolicySpec{
FailurePolicy: ptr.To(admr.Fail), FailurePolicy: new(admr.Fail),
MatchConstraints: &admr.MatchResources{ MatchConstraints: &admr.MatchResources{
ResourceRules: []admr.NamedRuleWithOperations{ ResourceRules: []admr.NamedRuleWithOperations{
{ {

@ -10,7 +10,6 @@ import (
"testing" "testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"tailscale.com/types/ptr"
) )
// Test that the config file can be at the root of the object, or in a versioned sub-object. // Test that the config file can be at the root of the object, or in a versioned sub-object.
@ -23,17 +22,17 @@ func TestVersionedConfig(t *testing.T) {
}{ }{
"root_config_v1alpha1": { "root_config_v1alpha1": {
inputConfig: `{"version": "v1alpha1", "authKey": "abc123"}`, inputConfig: `{"version": "v1alpha1", "authKey": "abc123"}`,
expectedConfig: ConfigV1Alpha1{AuthKey: ptr.To("abc123")}, expectedConfig: ConfigV1Alpha1{AuthKey: new("abc123")},
}, },
"backwards_compat_v1alpha1_config": { "backwards_compat_v1alpha1_config": {
// Client doesn't know about v1beta1, so it should read in v1alpha1. // Client doesn't know about v1beta1, so it should read in v1alpha1.
inputConfig: `{"version": "v1beta1", "beta-key": "beta-value", "authKey": "def456", "v1alpha1": {"authKey": "abc123"}}`, inputConfig: `{"version": "v1beta1", "beta-key": "beta-value", "authKey": "def456", "v1alpha1": {"authKey": "abc123"}}`,
expectedConfig: ConfigV1Alpha1{AuthKey: ptr.To("abc123")}, expectedConfig: ConfigV1Alpha1{AuthKey: new("abc123")},
}, },
"unknown_key_allowed": { "unknown_key_allowed": {
// Adding new keys to the config doesn't require a version bump. // Adding new keys to the config doesn't require a version bump.
inputConfig: `{"version": "v1alpha1", "unknown-key": "unknown-value", "authKey": "abc123"}`, inputConfig: `{"version": "v1alpha1", "unknown-key": "unknown-value", "authKey": "abc123"}`,
expectedConfig: ConfigV1Alpha1{AuthKey: ptr.To("abc123")}, expectedConfig: ConfigV1Alpha1{AuthKey: new("abc123")},
}, },
"version_only_no_authkey": { "version_only_no_authkey": {
inputConfig: `{"version": "v1alpha1"}`, inputConfig: `{"version": "v1alpha1"}`,

@ -9,7 +9,6 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts" "github.com/google/go-cmp/cmp/cmpopts"
"tailscale.com/types/ptr"
) )
func TestGeneveHeader(t *testing.T) { func TestGeneveHeader(t *testing.T) {
@ -47,22 +46,22 @@ func TestVirtualNetworkID(t *testing.T) {
}, },
{ {
"Set 0", "Set 0",
ptr.To(uint32(0)), new(uint32(0)),
0, 0,
}, },
{ {
"Set 1", "Set 1",
ptr.To(uint32(1)), new(uint32(1)),
1, 1,
}, },
{ {
"Set math.MaxUint32", "Set math.MaxUint32",
ptr.To(uint32(math.MaxUint32)), new(uint32(math.MaxUint32)),
1<<24 - 1, 1<<24 - 1,
}, },
{ {
"Set max 3-byte value", "Set max 3-byte value",
ptr.To(uint32(1<<24 - 1)), new(uint32(1<<24 - 1)),
1<<24 - 1, 1<<24 - 1,
}, },
} }

@ -34,7 +34,6 @@ import (
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/netlogtype" "tailscale.com/types/netlogtype"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/eventbus" "tailscale.com/util/eventbus"
"tailscale.com/util/eventbus/eventbustest" "tailscale.com/util/eventbus/eventbustest"
@ -655,9 +654,9 @@ func TestPeerCfg_NAT(t *testing.T) {
}, },
} }
if masqIP.Is4() { if masqIP.Is4() {
p.V4MasqAddr = ptr.To(masqIP) p.V4MasqAddr = new(masqIP)
} else { } else {
p.V6MasqAddr = ptr.To(masqIP) p.V6MasqAddr = new(masqIP)
} }
p.AllowedIPs = append(p.AllowedIPs, otherAllowedIPs...) p.AllowedIPs = append(p.AllowedIPs, otherAllowedIPs...)
return p return p

@ -51,7 +51,6 @@ import (
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/logid" "tailscale.com/types/logid"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/ptr"
"tailscale.com/util/cibuild" "tailscale.com/util/cibuild"
"tailscale.com/util/lineiter" "tailscale.com/util/lineiter"
"tailscale.com/util/must" "tailscale.com/util/must"
@ -96,7 +95,7 @@ func TestMatchRule(t *testing.T) {
name: "expired", name: "expired",
rule: &tailcfg.SSHRule{ rule: &tailcfg.SSHRule{
Action: someAction, Action: someAction,
RuleExpires: ptr.To(time.Unix(100, 0)), RuleExpires: new(time.Unix(100, 0)),
}, },
ci: &sshConnInfo{}, ci: &sshConnInfo{},
wantErr: errRuleExpired, wantErr: errRuleExpired,

@ -13,7 +13,6 @@ import (
"tailscale.com/types/dnstype" "tailscale.com/types/dnstype"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/types/structs" "tailscale.com/types/structs"
"tailscale.com/types/tkatype" "tailscale.com/types/tkatype"
) )
@ -53,10 +52,10 @@ func (src *Node) Clone() *Node {
dst.Tags = append(src.Tags[:0:0], src.Tags...) dst.Tags = append(src.Tags[:0:0], src.Tags...)
dst.PrimaryRoutes = append(src.PrimaryRoutes[:0:0], src.PrimaryRoutes...) dst.PrimaryRoutes = append(src.PrimaryRoutes[:0:0], src.PrimaryRoutes...)
if dst.LastSeen != nil { if dst.LastSeen != nil {
dst.LastSeen = ptr.To(*src.LastSeen) dst.LastSeen = new(*src.LastSeen)
} }
if dst.Online != nil { if dst.Online != nil {
dst.Online = ptr.To(*src.Online) dst.Online = new(*src.Online)
} }
dst.Capabilities = append(src.Capabilities[:0:0], src.Capabilities...) dst.Capabilities = append(src.Capabilities[:0:0], src.Capabilities...)
if dst.CapMap != nil { if dst.CapMap != nil {
@ -66,10 +65,10 @@ func (src *Node) Clone() *Node {
} }
} }
if dst.SelfNodeV4MasqAddrForThisPeer != nil { if dst.SelfNodeV4MasqAddrForThisPeer != nil {
dst.SelfNodeV4MasqAddrForThisPeer = ptr.To(*src.SelfNodeV4MasqAddrForThisPeer) dst.SelfNodeV4MasqAddrForThisPeer = new(*src.SelfNodeV4MasqAddrForThisPeer)
} }
if dst.SelfNodeV6MasqAddrForThisPeer != nil { if dst.SelfNodeV6MasqAddrForThisPeer != nil {
dst.SelfNodeV6MasqAddrForThisPeer = ptr.To(*src.SelfNodeV6MasqAddrForThisPeer) dst.SelfNodeV6MasqAddrForThisPeer = new(*src.SelfNodeV6MasqAddrForThisPeer)
} }
if src.ExitNodeDNSResolvers != nil { if src.ExitNodeDNSResolvers != nil {
dst.ExitNodeDNSResolvers = make([]*dnstype.Resolver, len(src.ExitNodeDNSResolvers)) dst.ExitNodeDNSResolvers = make([]*dnstype.Resolver, len(src.ExitNodeDNSResolvers))
@ -139,10 +138,10 @@ func (src *Hostinfo) Clone() *Hostinfo {
dst.NetInfo = src.NetInfo.Clone() dst.NetInfo = src.NetInfo.Clone()
dst.SSH_HostKeys = append(src.SSH_HostKeys[:0:0], src.SSH_HostKeys...) dst.SSH_HostKeys = append(src.SSH_HostKeys[:0:0], src.SSH_HostKeys...)
if dst.Location != nil { if dst.Location != nil {
dst.Location = ptr.To(*src.Location) dst.Location = new(*src.Location)
} }
if dst.TPM != nil { if dst.TPM != nil {
dst.TPM = ptr.To(*src.TPM) dst.TPM = new(*src.TPM)
} }
return dst return dst
} }
@ -331,7 +330,7 @@ func (src *RegisterResponseAuth) Clone() *RegisterResponseAuth {
dst := new(RegisterResponseAuth) dst := new(RegisterResponseAuth)
*dst = *src *dst = *src
if dst.Oauth2Token != nil { if dst.Oauth2Token != nil {
dst.Oauth2Token = ptr.To(*src.Oauth2Token) dst.Oauth2Token = new(*src.Oauth2Token)
} }
return dst return dst
} }
@ -355,7 +354,7 @@ func (src *RegisterRequest) Clone() *RegisterRequest {
dst.Hostinfo = src.Hostinfo.Clone() dst.Hostinfo = src.Hostinfo.Clone()
dst.NodeKeySignature = append(src.NodeKeySignature[:0:0], src.NodeKeySignature...) dst.NodeKeySignature = append(src.NodeKeySignature[:0:0], src.NodeKeySignature...)
if dst.Timestamp != nil { if dst.Timestamp != nil {
dst.Timestamp = ptr.To(*src.Timestamp) dst.Timestamp = new(*src.Timestamp)
} }
dst.DeviceCert = append(src.DeviceCert[:0:0], src.DeviceCert...) dst.DeviceCert = append(src.DeviceCert[:0:0], src.DeviceCert...)
dst.Signature = append(src.Signature[:0:0], src.Signature...) dst.Signature = append(src.Signature[:0:0], src.Signature...)
@ -413,7 +412,7 @@ func (src *DERPRegion) Clone() *DERPRegion {
if src.Nodes[i] == nil { if src.Nodes[i] == nil {
dst.Nodes[i] = nil dst.Nodes[i] = nil
} else { } else {
dst.Nodes[i] = ptr.To(*src.Nodes[i]) dst.Nodes[i] = new(*src.Nodes[i])
} }
} }
} }
@ -497,7 +496,7 @@ func (src *SSHRule) Clone() *SSHRule {
dst := new(SSHRule) dst := new(SSHRule)
*dst = *src *dst = *src
if dst.RuleExpires != nil { if dst.RuleExpires != nil {
dst.RuleExpires = ptr.To(*src.RuleExpires) dst.RuleExpires = new(*src.RuleExpires)
} }
if src.Principals != nil { if src.Principals != nil {
dst.Principals = make([]*SSHPrincipal, len(src.Principals)) dst.Principals = make([]*SSHPrincipal, len(src.Principals))
@ -534,7 +533,7 @@ func (src *SSHAction) Clone() *SSHAction {
*dst = *src *dst = *src
dst.Recorders = append(src.Recorders[:0:0], src.Recorders...) dst.Recorders = append(src.Recorders[:0:0], src.Recorders...)
if dst.OnRecordingFailure != nil { if dst.OnRecordingFailure != nil {
dst.OnRecordingFailure = ptr.To(*src.OnRecordingFailure) dst.OnRecordingFailure = new(*src.OnRecordingFailure)
} }
return dst return dst
} }

@ -17,7 +17,6 @@ import (
"tailscale.com/tstest/deptest" "tailscale.com/tstest/deptest"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/util/must" "tailscale.com/util/must"
) )
@ -539,22 +538,22 @@ func TestNodeEqual(t *testing.T) {
}, },
{ {
&Node{}, &Node{},
&Node{SelfNodeV4MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("100.64.0.1"))}, &Node{SelfNodeV4MasqAddrForThisPeer: new(netip.MustParseAddr("100.64.0.1"))},
false, false,
}, },
{ {
&Node{SelfNodeV4MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("100.64.0.1"))}, &Node{SelfNodeV4MasqAddrForThisPeer: new(netip.MustParseAddr("100.64.0.1"))},
&Node{SelfNodeV4MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("100.64.0.1"))}, &Node{SelfNodeV4MasqAddrForThisPeer: new(netip.MustParseAddr("100.64.0.1"))},
true, true,
}, },
{ {
&Node{}, &Node{},
&Node{SelfNodeV6MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("2001::3456"))}, &Node{SelfNodeV6MasqAddrForThisPeer: new(netip.MustParseAddr("2001::3456"))},
false, false,
}, },
{ {
&Node{SelfNodeV6MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("2001::3456"))}, &Node{SelfNodeV6MasqAddrForThisPeer: new(netip.MustParseAddr("2001::3456"))},
&Node{SelfNodeV6MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("2001::3456"))}, &Node{SelfNodeV6MasqAddrForThisPeer: new(netip.MustParseAddr("2001::3456"))},
true, true,
}, },
{ {

@ -323,7 +323,6 @@ tailscale.com/tsnet dependencies: (generated by github.com/tailscale/depaware)
tailscale.com/types/opt from tailscale.com/control/controlknobs+ tailscale.com/types/opt from tailscale.com/control/controlknobs+
tailscale.com/types/persist from tailscale.com/control/controlclient+ tailscale.com/types/persist from tailscale.com/control/controlclient+
tailscale.com/types/preftype from tailscale.com/ipn+ tailscale.com/types/preftype from tailscale.com/ipn+
tailscale.com/types/ptr from tailscale.com/control/controlclient+
tailscale.com/types/result from tailscale.com/util/lineiter tailscale.com/types/result from tailscale.com/util/lineiter
tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/structs from tailscale.com/control/controlclient+
tailscale.com/types/tkatype from tailscale.com/client/local+ tailscale.com/types/tkatype from tailscale.com/client/local+

@ -50,7 +50,6 @@ import (
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/util/must" "tailscale.com/util/must"
"tailscale.com/util/set" "tailscale.com/util/set"
) )
@ -730,8 +729,8 @@ func TestConfigFileAuthKey(t *testing.T) {
must.Do(os.WriteFile(authKeyFile, fmt.Appendf(nil, "%s\n", authKey), 0666)) must.Do(os.WriteFile(authKeyFile, fmt.Appendf(nil, "%s\n", authKey), 0666))
must.Do(os.WriteFile(n1.configFile, must.Get(json.Marshal(ipn.ConfigVAlpha{ must.Do(os.WriteFile(n1.configFile, must.Get(json.Marshal(ipn.ConfigVAlpha{
Version: "alpha0", Version: "alpha0",
AuthKey: ptr.To("file:" + authKeyFile), AuthKey: new("file:" + authKeyFile),
ServerURL: ptr.To(n1.env.ControlServer.URL), ServerURL: new(n1.env.ControlServer.URL),
})), 0644)) })), 0644))
d1 := n1.StartDaemon() d1 := n1.StartDaemon()
@ -2232,7 +2231,7 @@ func TestC2NDebugNetmap(t *testing.T) {
// Send a delta update to n1, marking node 0 as online. // Send a delta update to n1, marking node 0 as online.
env.Control.AddRawMapResponse(nodes[1].Key, &tailcfg.MapResponse{ env.Control.AddRawMapResponse(nodes[1].Key, &tailcfg.MapResponse{
PeersChangedPatch: []*tailcfg.PeerChange{{ PeersChangedPatch: []*tailcfg.PeerChange{{
NodeID: nodes[0].ID, Online: ptr.To(true), NodeID: nodes[0].ID, Online: new(true),
}}, }},
}) })

@ -38,7 +38,6 @@ import (
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/util/httpm" "tailscale.com/util/httpm"
"tailscale.com/util/mak" "tailscale.com/util/mak"
"tailscale.com/util/must" "tailscale.com/util/must"
@ -1337,9 +1336,9 @@ func (s *Server) MapResponse(req *tailcfg.MapRequest) (res *tailcfg.MapResponse,
} }
if masqIP := nodeMasqs[p.Key]; masqIP.IsValid() { if masqIP := nodeMasqs[p.Key]; masqIP.IsValid() {
if masqIP.Is6() { if masqIP.Is6() {
p.SelfNodeV6MasqAddrForThisPeer = ptr.To(masqIP) p.SelfNodeV6MasqAddrForThisPeer = new(masqIP)
} else { } else {
p.SelfNodeV4MasqAddrForThisPeer = ptr.To(masqIP) p.SelfNodeV4MasqAddrForThisPeer = new(masqIP)
} }
} }
p.IsJailed = jailed[p.Key] p.IsJailed = jailed[p.Key]

@ -8,8 +8,6 @@ import (
"reflect" "reflect"
"testing" "testing"
"time" "time"
"tailscale.com/types/ptr"
) )
// IsZeroable is the interface for things with an IsZero method. // IsZeroable is the interface for things with an IsZero method.
@ -60,7 +58,7 @@ func CheckIsZero[T IsZeroable](t testing.TB, nonzeroValues map[reflect.Type]any)
case timeType: case timeType:
return reflect.ValueOf(time.Unix(1704067200, 0)) return reflect.ValueOf(time.Unix(1704067200, 0))
case timePtrType: case timePtrType:
return reflect.ValueOf(ptr.To(time.Unix(1704067200, 0))) return reflect.ValueOf(new(time.Unix(1704067200, 0)))
} }
switch ty.Kind() { switch ty.Kind() {

@ -10,7 +10,6 @@ import (
"github.com/go-json-experiment/json" "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext" "github.com/go-json-experiment/json/jsontext"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"tailscale.com/types/ptr"
) )
type Interface interface { type Interface interface {
@ -72,7 +71,7 @@ func TestInterfaceCoders(t *testing.T) {
wantJSON: `{"Foo":"hello"}`, wantJSON: `{"Foo":"hello"}`,
}, { }, {
label: "BarPointer", label: "BarPointer",
wantVal: InterfaceWrapper{ptr.To(Bar(5))}, wantVal: InterfaceWrapper{new(Bar(5))},
wantJSON: `{"Bar":5}`, wantJSON: `{"Bar":5}`,
}, { }, {
label: "BarValue", label: "BarValue",

@ -6,8 +6,6 @@ package lazy
import ( import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"tailscale.com/types/ptr"
) )
// DeferredInit allows one or more funcs to be deferred // DeferredInit allows one or more funcs to be deferred
@ -91,7 +89,7 @@ func (d *DeferredInit) doSlow() (err *error) {
}() }()
for _, f := range d.funcs { for _, f := range d.funcs {
if err := f(); err != nil { if err := f(); err != nil {
return ptr.To(err) return new(err)
} }
} }
return nilErrPtr return nilErrPtr

@ -7,13 +7,11 @@ package lazy
import ( import (
"sync" "sync"
"sync/atomic" "sync/atomic"
"tailscale.com/types/ptr"
) )
// nilErrPtr is a sentinel *error value for SyncValue.err to signal // nilErrPtr is a sentinel *error value for SyncValue.err to signal
// that SyncValue.v is valid. // that SyncValue.v is valid.
var nilErrPtr = ptr.To[error](nil) var nilErrPtr = new(error(nil))
// SyncValue is a lazily computed value. // SyncValue is a lazily computed value.
// //
@ -80,7 +78,7 @@ func (z *SyncValue[T]) GetErr(fill func() (T, error)) (T, error) {
// Update z.err after z.v; see field docs. // Update z.err after z.v; see field docs.
if err != nil { if err != nil {
z.err.Store(ptr.To(err)) z.err.Store(new(err))
} else { } else {
z.err.Store(nilErrPtr) z.err.Store(nilErrPtr)
} }
@ -145,7 +143,7 @@ func (z *SyncValue[T]) SetForTest(tb testing_TB, val T, err error) {
z.v = val z.v = val
if err != nil { if err != nil {
z.err.Store(ptr.To(err)) z.err.Store(new(err))
} else { } else {
z.err.Store(nilErrPtr) z.err.Store(nilErrPtr)
} }

@ -12,7 +12,6 @@ import (
"time" "time"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/ptr"
) )
// NodeMutation is the common interface for types that describe // NodeMutation is the common interface for types that describe
@ -55,7 +54,7 @@ type NodeMutationOnline struct {
} }
func (m NodeMutationOnline) Apply(n *tailcfg.Node) { func (m NodeMutationOnline) Apply(n *tailcfg.Node) {
n.Online = ptr.To(m.Online) n.Online = new(m.Online)
} }
// NodeMutationLastSeen is a NodeMutation that says a node's LastSeen // NodeMutationLastSeen is a NodeMutation that says a node's LastSeen
@ -66,14 +65,14 @@ type NodeMutationLastSeen struct {
} }
func (m NodeMutationLastSeen) Apply(n *tailcfg.Node) { func (m NodeMutationLastSeen) Apply(n *tailcfg.Node) {
n.LastSeen = ptr.To(m.LastSeen) n.LastSeen = new(m.LastSeen)
} }
var peerChangeFields = sync.OnceValue(func() []reflect.StructField { var peerChangeFields = sync.OnceValue(func() []reflect.StructField {
var fields []reflect.StructField var fields []reflect.StructField
rt := reflect.TypeFor[tailcfg.PeerChange]() rt := reflect.TypeFor[tailcfg.PeerChange]()
for i := range rt.NumField() { for field := range rt.Fields() {
fields = append(fields, rt.Field(i)) fields = append(fields, field)
} }
return fields return fields
}) })

@ -14,7 +14,6 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
) )
// tests mapResponseContainsNonPatchFields // tests mapResponseContainsNonPatchFields
@ -117,7 +116,7 @@ func TestMutationsFromMapResponse(t *testing.T) {
name: "patch-online", name: "patch-online",
mr: fromChanges(&tailcfg.PeerChange{ mr: fromChanges(&tailcfg.PeerChange{
NodeID: 1, NodeID: 1,
Online: ptr.To(true), Online: new(true),
}), }),
want: muts(NodeMutationOnline{1, true}), want: muts(NodeMutationOnline{1, true}),
}, },
@ -125,7 +124,7 @@ func TestMutationsFromMapResponse(t *testing.T) {
name: "patch-online-false", name: "patch-online-false",
mr: fromChanges(&tailcfg.PeerChange{ mr: fromChanges(&tailcfg.PeerChange{
NodeID: 1, NodeID: 1,
Online: ptr.To(false), Online: new(false),
}), }),
want: muts(NodeMutationOnline{1, false}), want: muts(NodeMutationOnline{1, false}),
}, },
@ -133,7 +132,7 @@ func TestMutationsFromMapResponse(t *testing.T) {
name: "patch-lastseen", name: "patch-lastseen",
mr: fromChanges(&tailcfg.PeerChange{ mr: fromChanges(&tailcfg.PeerChange{
NodeID: 1, NodeID: 1,
LastSeen: ptr.To(time.Unix(12345, 0)), LastSeen: new(time.Unix(12345, 0)),
}), }),
want: muts(NodeMutationLastSeen{1, time.Unix(12345, 0)}), want: muts(NodeMutationLastSeen{1, time.Unix(12345, 0)}),
}, },

@ -9,7 +9,6 @@ import (
jsonv2 "github.com/go-json-experiment/json" jsonv2 "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext" "github.com/go-json-experiment/json/jsontext"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/must" "tailscale.com/util/must"
) )
@ -47,7 +46,7 @@ func (i *Item[T]) SetManagedValue(val T) {
// It is a runtime error to call [Item.Clone] if T contains pointers // It is a runtime error to call [Item.Clone] if T contains pointers
// but does not implement [views.Cloner]. // but does not implement [views.Cloner].
func (i Item[T]) Clone() *Item[T] { func (i Item[T]) Clone() *Item[T] {
res := ptr.To(i) res := new(i)
if v, ok := i.ValueOk(); ok { if v, ok := i.ValueOk(); ok {
res.s.Value.Set(must.Get(deepClone(v))) res.s.Value.Set(must.Get(deepClone(v)))
} }

@ -12,7 +12,6 @@ import (
"github.com/go-json-experiment/json/jsontext" "github.com/go-json-experiment/json/jsontext"
"golang.org/x/exp/constraints" "golang.org/x/exp/constraints"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
) )
@ -62,7 +61,7 @@ func (ls *List[T]) View() ListView[T] {
// Clone returns a copy of l that aliases no memory with l. // Clone returns a copy of l that aliases no memory with l.
func (ls List[T]) Clone() *List[T] { func (ls List[T]) Clone() *List[T] {
res := ptr.To(ls) res := new(ls)
if v, ok := ls.s.Value.GetOk(); ok { if v, ok := ls.s.Value.GetOk(); ok {
res.s.Value.Set(append(v[:0:0], v...)) res.s.Value.Set(append(v[:0:0], v...))
} }

@ -11,7 +11,6 @@ import (
"github.com/go-json-experiment/json/jsontext" "github.com/go-json-experiment/json/jsontext"
"golang.org/x/exp/constraints" "golang.org/x/exp/constraints"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
) )
@ -44,7 +43,7 @@ func (m *Map[K, V]) View() MapView[K, V] {
// Clone returns a copy of m that aliases no memory with m. // Clone returns a copy of m that aliases no memory with m.
func (m Map[K, V]) Clone() *Map[K, V] { func (m Map[K, V]) Clone() *Map[K, V] {
res := ptr.To(m) res := new(m)
if v, ok := m.s.Value.GetOk(); ok { if v, ok := m.s.Value.GetOk(); ok {
res.s.Value.Set(maps.Clone(v)) res.s.Value.Set(maps.Clone(v))
} }

@ -7,8 +7,6 @@ package prefs
import ( import (
"net/netip" "net/netip"
"tailscale.com/types/ptr"
) )
// Clone makes a deep copy of TestPrefs. // Clone makes a deep copy of TestPrefs.
@ -67,7 +65,7 @@ func (src *TestBundle) Clone() *TestBundle {
dst := new(TestBundle) dst := new(TestBundle)
*dst = *src *dst = *src
if dst.Nested != nil { if dst.Nested != nil {
dst.Nested = ptr.To(*src.Nested) dst.Nested = new(*src.Nested)
} }
return dst return dst
} }

@ -11,7 +11,6 @@ import (
jsonv2 "github.com/go-json-experiment/json" jsonv2 "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext" "github.com/go-json-experiment/json/jsontext"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
) )
@ -45,7 +44,7 @@ func (ls *StructList[T]) SetManagedValue(val []T) {
// Clone returns a copy of l that aliases no memory with l. // Clone returns a copy of l that aliases no memory with l.
func (ls StructList[T]) Clone() *StructList[T] { func (ls StructList[T]) Clone() *StructList[T] {
res := ptr.To(ls) res := new(ls)
if v, ok := ls.s.Value.GetOk(); ok { if v, ok := ls.s.Value.GetOk(); ok {
res.s.Value.Set(deepCloneSlice(v)) res.s.Value.Set(deepCloneSlice(v))
} }

@ -9,7 +9,6 @@ import (
jsonv2 "github.com/go-json-experiment/json" jsonv2 "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext" "github.com/go-json-experiment/json/jsontext"
"tailscale.com/types/opt" "tailscale.com/types/opt"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
) )
@ -43,7 +42,7 @@ func (m *StructMap[K, V]) SetManagedValue(val map[K]V) {
// Clone returns a copy of m that aliases no memory with m. // Clone returns a copy of m that aliases no memory with m.
func (m StructMap[K, V]) Clone() *StructMap[K, V] { func (m StructMap[K, V]) Clone() *StructMap[K, V] {
res := ptr.To(m) res := new(m)
if v, ok := m.s.Value.GetOk(); ok { if v, ok := m.s.Value.GetOk(); ok {
res.s.Value.Set(deepCloneMap(v)) res.s.Value.Set(deepCloneMap(v))
} }

@ -2,9 +2,18 @@
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Package ptr contains the ptr.To function. // Package ptr contains the ptr.To function.
//
// Deprecated: Use Go 1.26's new(value) expression instead.
// See https://go.dev/doc/go1.26#language.
package ptr package ptr
// To returns a pointer to a shallow copy of v. // To returns a pointer to a shallow copy of v.
//
// Deprecated: Use Go 1.26's new(value) expression instead.
// For example, ptr.To(42) can be written as new(42).
// See https://go.dev/doc/go1.26#language.
//
//go:fix inline
func To[T any](v T) *T { func To[T any](v T) *T {
return &v return new(v)
} }

@ -19,7 +19,6 @@ import (
jsonv2 "github.com/go-json-experiment/json" jsonv2 "github.com/go-json-experiment/json"
"github.com/go-json-experiment/json/jsontext" "github.com/go-json-experiment/json/jsontext"
"go4.org/mem" "go4.org/mem"
"tailscale.com/types/ptr"
) )
// ByteSlice is a read-only accessor for types that are backed by a []byte. // ByteSlice is a read-only accessor for types that are backed by a []byte.
@ -901,7 +900,7 @@ func (p ValuePointer[T]) Clone() *T {
if p.ж == nil { if p.ж == nil {
return nil return nil
} }
return ptr.To(*p.ж) return new(*p.ж)
} }
// String implements [fmt.Stringer]. // String implements [fmt.Stringer].

@ -24,7 +24,6 @@ import (
"go4.org/netipx" "go4.org/netipx"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/ptr"
"tailscale.com/util/deephash/testtype" "tailscale.com/util/deephash/testtype"
"tailscale.com/util/hashx" "tailscale.com/util/hashx"
"tailscale.com/version" "tailscale.com/version"
@ -382,7 +381,7 @@ func TestGetTypeHasher(t *testing.T) {
}, },
{ {
name: "time_ptr", // addressable, as opposed to "time" test above name: "time_ptr", // addressable, as opposed to "time" test above
val: ptr.To(time.Unix(1234, 5678).In(time.UTC)), val: new(time.Unix(1234, 5678).In(time.UTC)),
out: u8(1) + u64(1234) + u32(5678) + u32(0), out: u8(1) + u64(1234) + u32(5678) + u32(0),
}, },
{ {
@ -412,7 +411,7 @@ func TestGetTypeHasher(t *testing.T) {
}, },
{ {
name: "array_ptr_memhash", name: "array_ptr_memhash",
val: ptr.To([4]byte{1, 2, 3, 4}), val: new([4]byte{1, 2, 3, 4}),
out: "\x01\x01\x02\x03\x04", out: "\x01\x01\x02\x03\x04",
}, },
{ {
@ -640,7 +639,7 @@ var filterRules = []tailcfg.FilterRule{
SrcIPs: []string{"*", "10.1.3.4/32", "10.0.0.0/24"}, SrcIPs: []string{"*", "10.1.3.4/32", "10.0.0.0/24"},
DstPorts: []tailcfg.NetPortRange{{ DstPorts: []tailcfg.NetPortRange{{
IP: "1.2.3.4/32", IP: "1.2.3.4/32",
Bits: ptr.To(32), Bits: new(32),
Ports: tailcfg.PortRange{First: 1, Last: 2}, Ports: tailcfg.PortRange{First: 1, Last: 2},
}}, }},
IPProto: []int{1, 2, 3, 4}, IPProto: []int{1, 2, 3, 4},
@ -823,7 +822,7 @@ func TestHashThroughView(t *testing.T) {
SSHPolicy: &sshPolicyOut{ SSHPolicy: &sshPolicyOut{
Rules: []tailcfg.SSHRuleView{ Rules: []tailcfg.SSHRuleView{
(&tailcfg.SSHRule{ (&tailcfg.SSHRule{
RuleExpires: ptr.To(time.Unix(123, 0)), RuleExpires: new(time.Unix(123, 0)),
}).View(), }).View(),
}, },
}, },

@ -20,7 +20,6 @@ import (
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/ptr"
) )
const ( const (
@ -955,7 +954,7 @@ const (
// via netfilter via nftables, as a last resort measure to detect that nftables // via netfilter via nftables, as a last resort measure to detect that nftables
// can be used. It cleans up the dummy chains after creation. // can be used. It cleans up the dummy chains after creation.
func (n *nftablesRunner) createDummyPostroutingChains() (retErr error) { func (n *nftablesRunner) createDummyPostroutingChains() (retErr error) {
polAccept := ptr.To(nftables.ChainPolicyAccept) polAccept := new(nftables.ChainPolicyAccept)
for _, table := range n.getTables() { for _, table := range n.getTables() {
nat, err := createTableIfNotExist(n.conn, table.Proto, tsDummyTableName) nat, err := createTableIfNotExist(n.conn, table.Proto, tsDummyTableName)
if err != nil { if err != nil {

@ -12,8 +12,6 @@ package pool
import ( import (
"fmt" "fmt"
"math/rand/v2" "math/rand/v2"
"tailscale.com/types/ptr"
) )
// consistencyCheck enables additional runtime checks to ensure that the pool // consistencyCheck enables additional runtime checks to ensure that the pool
@ -77,7 +75,7 @@ func (p *Pool[V]) AppendTakeAll(dst []V) []V {
func (p *Pool[V]) Add(item V) Handle[V] { func (p *Pool[V]) Add(item V) Handle[V] {
// Store the index in a pointer, so that we can pass it to both the // Store the index in a pointer, so that we can pass it to both the
// handle and store it in the itemAndIndex. // handle and store it in the itemAndIndex.
idx := ptr.To(len(p.s)) idx := new(len(p.s))
p.s = append(p.s, itemAndIndex[V]{ p.s = append(p.s, itemAndIndex[V]{
item: item, item: item,
index: idx, index: idx,

@ -5,8 +5,6 @@ package setting
import ( import (
"errors" "errors"
"tailscale.com/types/ptr"
) )
var ( var (
@ -39,7 +37,7 @@ type ErrorText string
// NewErrorText returns a [ErrorText] with the specified error message. // NewErrorText returns a [ErrorText] with the specified error message.
func NewErrorText(text string) *ErrorText { func NewErrorText(text string) *ErrorText {
return ptr.To(ErrorText(text)) return new(ErrorText(text))
} }
// MaybeErrorText returns an [ErrorText] with the text of the specified error, // MaybeErrorText returns an [ErrorText] with the text of the specified error,
@ -51,7 +49,7 @@ func MaybeErrorText(err error) *ErrorText {
if err, ok := err.(*ErrorText); ok { if err, ok := err.(*ErrorText); ok {
return err return err
} }
return ptr.To(ErrorText(err.Error())) return new(ErrorText(err.Error()))
} }
// Error implements error. // Error implements error.

@ -9,7 +9,6 @@ import (
"testing" "testing"
"tailscale.com/types/lazy" "tailscale.com/types/lazy"
"tailscale.com/types/ptr"
"tailscale.com/util/syspolicy/internal" "tailscale.com/util/syspolicy/internal"
"tailscale.com/util/syspolicy/pkey" "tailscale.com/util/syspolicy/pkey"
) )
@ -138,7 +137,7 @@ func TestSettingDefinition(t *testing.T) {
if !tt.setting.Equal(tt.setting) { if !tt.setting.Equal(tt.setting) {
t.Errorf("the setting should be equal to itself") t.Errorf("the setting should be equal to itself")
} }
if tt.setting != nil && !tt.setting.Equal(ptr.To(*tt.setting)) { if tt.setting != nil && !tt.setting.Equal(new(*tt.setting)) {
t.Errorf("the setting should be equal to its shallow copy") t.Errorf("the setting should be equal to its shallow copy")
} }
if gotKey := tt.setting.Key(); gotKey != tt.wantKey { if gotKey := tt.setting.Key(); gotKey != tt.wantKey {

@ -63,7 +63,6 @@ import (
"tailscale.com/types/netlogtype" "tailscale.com/types/netlogtype"
"tailscale.com/types/netmap" "tailscale.com/types/netmap"
"tailscale.com/types/nettype" "tailscale.com/types/nettype"
"tailscale.com/types/ptr"
"tailscale.com/types/views" "tailscale.com/types/views"
"tailscale.com/util/cibuild" "tailscale.com/util/cibuild"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
@ -2309,7 +2308,7 @@ func TestIsWireGuardOnlyPeerWithMasquerade(t *testing.T) {
IsWireGuardOnly: true, IsWireGuardOnly: true,
Addresses: []netip.Prefix{wgaip}, Addresses: []netip.Prefix{wgaip},
AllowedIPs: []netip.Prefix{wgaip}, AllowedIPs: []netip.Prefix{wgaip},
SelfNodeV4MasqAddrForThisPeer: ptr.To(masqip.Addr()), SelfNodeV4MasqAddrForThisPeer: new(masqip.Addr()),
}, },
}), }),
} }

@ -10,7 +10,6 @@ import (
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/logid" "tailscale.com/types/logid"
"tailscale.com/types/ptr"
) )
// Clone makes a deep copy of Config. // Clone makes a deep copy of Config.
@ -56,10 +55,10 @@ func (src *Peer) Clone() *Peer {
*dst = *src *dst = *src
dst.AllowedIPs = append(src.AllowedIPs[:0:0], src.AllowedIPs...) dst.AllowedIPs = append(src.AllowedIPs[:0:0], src.AllowedIPs...)
if dst.V4MasqAddr != nil { if dst.V4MasqAddr != nil {
dst.V4MasqAddr = ptr.To(*src.V4MasqAddr) dst.V4MasqAddr = new(*src.V4MasqAddr)
} }
if dst.V6MasqAddr != nil { if dst.V6MasqAddr != nil {
dst.V6MasqAddr = ptr.To(*src.V6MasqAddr) dst.V6MasqAddr = new(*src.V6MasqAddr)
} }
return dst return dst
} }

Loading…
Cancel
Save