From 3675b6550401c52e48235cbdf24e7d8f3da02a45 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 20 Jan 2026 14:23:21 +0000 Subject: [PATCH] all: use new() builtin and slices utilities Modernize code to use Go 1.26 features: 1. Replace ptr.To with the new() builtin: Before: ptr.To(value) After: new(value) 2. Replace append clone pattern with slices.Clone: Before: copy := append([]T{}, slice...) After: copy := slices.Clone(slice) 3. Replace manual contains loops with slices.Contains: Before: for _, v := range slice { if v == target { return true } } After: slices.Contains(slice, target) The ptr.To function from tailscale.com/types/ptr is no longer needed as Go 1.26's enhanced new() builtin accepts a value argument and returns a pointer to a copy of that value. Note: Auto-generated files (types_clone.go) are not modified as they are generated by tailscale.com/cmd/cloner. --- hscontrol/db/ip_test.go | 11 +- hscontrol/db/node_test.go | 17 +- hscontrol/db/text_serialiser.go | 8 +- hscontrol/db/users_test.go | 3 +- hscontrol/mapper/batcher_lockfree.go | 3 +- hscontrol/mapper/batcher_test.go | 5 +- hscontrol/mapper/mapper_test.go | 3 +- hscontrol/policy/policy_test.go | 13 +- hscontrol/policy/policyutil/reduce_test.go | 47 ++- hscontrol/policy/route_approval_test.go | 17 +- hscontrol/policy/v2/filter_test.go | 115 ++++---- hscontrol/policy/v2/policy_test.go | 33 +-- hscontrol/policy/v2/types_test.go | 321 ++++++++++----------- hscontrol/state/ephemeral_test.go | 15 +- hscontrol/state/maprequest_test.go | 3 +- hscontrol/state/node_store_test.go | 5 +- hscontrol/types/node_tags_test.go | 13 +- hscontrol/types/users.go | 2 +- integration/acl_test.go | 17 +- integration/api_auth_test.go | 6 +- integration/auth_key_test.go | 3 +- integration/ssh_test.go | 5 +- 22 files changed, 324 insertions(+), 341 deletions(-) diff --git a/hscontrol/db/ip_test.go b/hscontrol/db/ip_test.go index 7ba335e8..73895876 100644 --- a/hscontrol/db/ip_test.go +++ b/hscontrol/db/ip_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "tailscale.com/net/tsaddr" - "tailscale.com/types/ptr" ) var mpp = func(pref string) *netip.Prefix { @@ -488,8 +487,8 @@ func TestIPAllocatorNextNoReservedIPs(t *testing.T) { alloc, err := NewIPAllocator( db, - ptr.To(tsaddr.CGNATRange()), - ptr.To(tsaddr.TailscaleULARange()), + new(tsaddr.CGNATRange()), + new(tsaddr.TailscaleULARange()), types.IPAllocationStrategySequential, ) if err != nil { @@ -497,17 +496,17 @@ func TestIPAllocatorNextNoReservedIPs(t *testing.T) { } // Validate that we do not give out 100.100.100.100 - nextQuad100, err := alloc.next(na("100.100.100.99"), ptr.To(tsaddr.CGNATRange())) + nextQuad100, err := alloc.next(na("100.100.100.99"), new(tsaddr.CGNATRange())) require.NoError(t, err) assert.Equal(t, na("100.100.100.101"), *nextQuad100) // Validate that we do not give out fd7a:115c:a1e0::53 - nextQuad100v6, err := alloc.next(na("fd7a:115c:a1e0::52"), ptr.To(tsaddr.TailscaleULARange())) + nextQuad100v6, err := alloc.next(na("fd7a:115c:a1e0::52"), new(tsaddr.TailscaleULARange())) require.NoError(t, err) assert.Equal(t, na("fd7a:115c:a1e0::54"), *nextQuad100v6) // Validate that we do not give out fd7a:115c:a1e0::53 - nextChrome, err := alloc.next(na("100.115.91.255"), ptr.To(tsaddr.CGNATRange())) + nextChrome, err := alloc.next(na("100.115.91.255"), new(tsaddr.CGNATRange())) t.Logf("chrome: %s", nextChrome.String()) require.NoError(t, err) assert.Equal(t, na("100.115.94.0"), *nextChrome) diff --git a/hscontrol/db/node_test.go b/hscontrol/db/node_test.go index 7e00f9ca..e82cdb62 100644 --- a/hscontrol/db/node_test.go +++ b/hscontrol/db/node_test.go @@ -22,7 +22,6 @@ import ( "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" - "tailscale.com/types/ptr" ) func TestGetNode(t *testing.T) { @@ -115,7 +114,7 @@ func TestExpireNode(t *testing.T) { Hostname: "testnode", UserID: &user.ID, RegisterMethod: util.RegisterMethodAuthKey, - AuthKeyID: ptr.To(pak.ID), + AuthKeyID: new(pak.ID), Expiry: &time.Time{}, } db.DB.Save(node) @@ -159,7 +158,7 @@ func TestSetTags(t *testing.T) { Hostname: "testnode", UserID: &user.ID, RegisterMethod: util.RegisterMethodAuthKey, - AuthKeyID: ptr.To(pak.ID), + AuthKeyID: new(pak.ID), } trx := db.DB.Save(node) @@ -443,7 +442,7 @@ func TestAutoApproveRoutes(t *testing.T) { Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: tt.routes, }, - IPv4: ptr.To(netip.MustParseAddr("100.64.0.1")), + IPv4: new(netip.MustParseAddr("100.64.0.1")), } err = adb.DB.Save(&node).Error @@ -460,7 +459,7 @@ func TestAutoApproveRoutes(t *testing.T) { RoutableIPs: tt.routes, }, Tags: []string{"tag:exit"}, - IPv4: ptr.To(netip.MustParseAddr("100.64.0.2")), + IPv4: new(netip.MustParseAddr("100.64.0.2")), } err = adb.DB.Save(&nodeTagged).Error @@ -649,7 +648,7 @@ func TestListEphemeralNodes(t *testing.T) { Hostname: "test", UserID: &user.ID, RegisterMethod: util.RegisterMethodAuthKey, - AuthKeyID: ptr.To(pak.ID), + AuthKeyID: new(pak.ID), } nodeEph := types.Node{ @@ -659,7 +658,7 @@ func TestListEphemeralNodes(t *testing.T) { Hostname: "ephemeral", UserID: &user.ID, RegisterMethod: util.RegisterMethodAuthKey, - AuthKeyID: ptr.To(pakEph.ID), + AuthKeyID: new(pakEph.ID), } err = db.DB.Save(&node).Error @@ -750,8 +749,8 @@ func TestNodeNaming(t *testing.T) { if err != nil { return err } - _, err = RegisterNodeForTest(tx, nodeInvalidHostname, ptr.To(mpp("100.64.0.66/32").Addr()), nil) - _, err = RegisterNodeForTest(tx, nodeShortHostname, ptr.To(mpp("100.64.0.67/32").Addr()), nil) + _, err = RegisterNodeForTest(tx, nodeInvalidHostname, new(mpp("100.64.0.66/32").Addr()), nil) + _, err = RegisterNodeForTest(tx, nodeShortHostname, new(mpp("100.64.0.67/32").Addr()), nil) return err }) require.NoError(t, err) diff --git a/hscontrol/db/text_serialiser.go b/hscontrol/db/text_serialiser.go index 6172e7e0..46bd154f 100644 --- a/hscontrol/db/text_serialiser.go +++ b/hscontrol/db/text_serialiser.go @@ -17,7 +17,7 @@ func isTextUnmarshaler(rv reflect.Value) bool { } func maybeInstantiatePtr(rv reflect.Value) { - if rv.Kind() == reflect.Ptr && rv.IsNil() { + if rv.Kind() == reflect.Pointer && rv.IsNil() { np := reflect.New(rv.Type().Elem()) rv.Set(np) } @@ -36,7 +36,7 @@ func (TextSerialiser) Scan(ctx context.Context, field *schema.Field, dst reflect // If the field is a pointer, we need to dereference it to get the actual type // so we do not end with a second pointer. - if fieldValue.Elem().Kind() == reflect.Ptr { + if fieldValue.Elem().Kind() == reflect.Pointer { fieldValue = fieldValue.Elem() } @@ -65,7 +65,7 @@ func (TextSerialiser) Scan(ctx context.Context, field *schema.Field, dst reflect // If it is not a pointer, we need to assign the value to the // field. dstField := field.ReflectValueOf(ctx, dst) - if dstField.Kind() == reflect.Ptr { + if dstField.Kind() == reflect.Pointer { dstField.Set(fieldValue) } else { dstField.Set(fieldValue.Elem()) @@ -86,7 +86,7 @@ func (TextSerialiser) Value(ctx context.Context, field *schema.Field, dst reflec // If the value is nil, we return nil, however, go nil values are not // always comparable, particularly when reflection is involved: // https://dev.to/arxeiss/in-go-nil-is-not-equal-to-nil-sometimes-jn8 - if v == nil || (reflect.ValueOf(v).Kind() == reflect.Ptr && reflect.ValueOf(v).IsNil()) { + if v == nil || (reflect.ValueOf(v).Kind() == reflect.Pointer && reflect.ValueOf(v).IsNil()) { return nil, nil } b, err := v.MarshalText() diff --git a/hscontrol/db/users_test.go b/hscontrol/db/users_test.go index a3fd49b3..bbb8e4d4 100644 --- a/hscontrol/db/users_test.go +++ b/hscontrol/db/users_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/gorm" - "tailscale.com/types/ptr" ) func TestCreateAndDestroyUser(t *testing.T) { @@ -79,7 +78,7 @@ func TestDestroyUserErrors(t *testing.T) { Hostname: "testnode", UserID: &user.ID, RegisterMethod: util.RegisterMethodAuthKey, - AuthKeyID: ptr.To(pak.ID), + AuthKeyID: new(pak.ID), } trx := db.DB.Save(&node) require.NoError(t, trx.Error) diff --git a/hscontrol/mapper/batcher_lockfree.go b/hscontrol/mapper/batcher_lockfree.go index e00512b6..1d9c2c32 100644 --- a/hscontrol/mapper/batcher_lockfree.go +++ b/hscontrol/mapper/batcher_lockfree.go @@ -13,7 +13,6 @@ import ( "github.com/puzpuzpuz/xsync/v4" "github.com/rs/zerolog/log" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) var errConnectionClosed = errors.New("connection channel already closed") @@ -136,7 +135,7 @@ func (b *LockFreeBatcher) RemoveNode(id types.NodeID, c chan<- *tailcfg.MapRespo // No active connections - keep the node entry alive for rapid reconnections // The node will get a fresh full map when it reconnects log.Debug().Caller().Uint64("node.id", id.Uint64()).Msg("Node disconnected from batcher because all connections removed, keeping entry for rapid reconnection") - b.connected.Store(id, ptr.To(time.Now())) + b.connected.Store(id, new(time.Now())) return false } diff --git a/hscontrol/mapper/batcher_test.go b/hscontrol/mapper/batcher_test.go index 70d5e377..00053892 100644 --- a/hscontrol/mapper/batcher_test.go +++ b/hscontrol/mapper/batcher_test.go @@ -5,6 +5,7 @@ import ( "fmt" "net/netip" "runtime" + "slices" "strings" "sync" "sync/atomic" @@ -327,7 +328,7 @@ func (ut *updateTracker) getStats(nodeID types.NodeID) UpdateStats { // Return a copy to avoid race conditions return UpdateStats{ TotalUpdates: stats.TotalUpdates, - UpdateSizes: append([]int{}, stats.UpdateSizes...), + UpdateSizes: slices.Clone(stats.UpdateSizes), LastUpdate: stats.LastUpdate, } } @@ -344,7 +345,7 @@ func (ut *updateTracker) getAllStats() map[types.NodeID]UpdateStats { for nodeID, stats := range ut.stats { result[nodeID] = UpdateStats{ TotalUpdates: stats.TotalUpdates, - UpdateSizes: append([]int{}, stats.UpdateSizes...), + UpdateSizes: slices.Clone(stats.UpdateSizes), LastUpdate: stats.LastUpdate, } } diff --git a/hscontrol/mapper/mapper_test.go b/hscontrol/mapper/mapper_test.go index 1bafd135..a503c08c 100644 --- a/hscontrol/mapper/mapper_test.go +++ b/hscontrol/mapper/mapper_test.go @@ -14,7 +14,6 @@ import ( "github.com/juanfont/headscale/hscontrol/types" "tailscale.com/tailcfg" "tailscale.com/types/dnstype" - "tailscale.com/types/ptr" ) var iap = func(ipStr string) *netip.Addr { @@ -51,7 +50,7 @@ func TestDNSConfigMapResponse(t *testing.T) { mach := func(hostname, username string, userid uint) *types.Node { return &types.Node{ Hostname: hostname, - UserID: ptr.To(userid), + UserID: new(userid), User: &types.User{ Name: username, }, diff --git a/hscontrol/policy/policy_test.go b/hscontrol/policy/policy_test.go index 87142dd9..eb3d85b6 100644 --- a/hscontrol/policy/policy_test.go +++ b/hscontrol/policy/policy_test.go @@ -14,7 +14,6 @@ import ( "github.com/stretchr/testify/require" "gorm.io/gorm" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) var ap = func(ipStr string) *netip.Addr { @@ -1074,21 +1073,21 @@ func TestSSHPolicyRules(t *testing.T) { nodeUser1 := types.Node{ Hostname: "user1-device", IPv4: ap("100.64.0.1"), - UserID: ptr.To(uint(1)), - User: ptr.To(users[0]), + UserID: new(uint(1)), + User: new(users[0]), } nodeUser2 := types.Node{ Hostname: "user2-device", IPv4: ap("100.64.0.2"), - UserID: ptr.To(uint(2)), - User: ptr.To(users[1]), + UserID: new(uint(2)), + User: new(users[1]), } taggedClient := types.Node{ Hostname: "tagged-client", IPv4: ap("100.64.0.4"), - UserID: ptr.To(uint(2)), - User: ptr.To(users[1]), + UserID: new(uint(2)), + User: new(users[1]), Tags: []string{"tag:client"}, } diff --git a/hscontrol/policy/policyutil/reduce_test.go b/hscontrol/policy/policyutil/reduce_test.go index 35f5b472..bd975d23 100644 --- a/hscontrol/policy/policyutil/reduce_test.go +++ b/hscontrol/policy/policyutil/reduce_test.go @@ -16,7 +16,6 @@ import ( "gorm.io/gorm" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" "tailscale.com/util/must" ) @@ -144,13 +143,13 @@ func TestReduceFilterRules(t *testing.T) { node: &types.Node{ IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0:ab12:4843:2222:6273:2221"), - User: ptr.To(users[0]), + User: new(users[0]), }, peers: types.Nodes{ &types.Node{ IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0:ab12:4843:2222:6273:2222"), - User: ptr.To(users[0]), + User: new(users[0]), }, }, want: []tailcfg.FilterRule{}, @@ -191,7 +190,7 @@ func TestReduceFilterRules(t *testing.T) { node: &types.Node{ IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[1]), + User: new(users[1]), Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: []netip.Prefix{ netip.MustParsePrefix("10.33.0.0/16"), @@ -202,7 +201,7 @@ func TestReduceFilterRules(t *testing.T) { &types.Node{ IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), - User: ptr.To(users[1]), + User: new(users[1]), }, }, want: []tailcfg.FilterRule{ @@ -283,19 +282,19 @@ func TestReduceFilterRules(t *testing.T) { node: &types.Node{ IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[1]), + User: new(users[1]), }, peers: types.Nodes{ &types.Node{ IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), - User: ptr.To(users[2]), + User: new(users[2]), }, // "internal" exit node &types.Node{ IPv4: ap("100.64.0.100"), IPv6: ap("fd7a:115c:a1e0::100"), - User: ptr.To(users[3]), + User: new(users[3]), Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: tsaddr.ExitRoutes(), }, @@ -344,7 +343,7 @@ func TestReduceFilterRules(t *testing.T) { node: &types.Node{ IPv4: ap("100.64.0.100"), IPv6: ap("fd7a:115c:a1e0::100"), - User: ptr.To(users[3]), + User: new(users[3]), Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: tsaddr.ExitRoutes(), }, @@ -353,12 +352,12 @@ func TestReduceFilterRules(t *testing.T) { &types.Node{ IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), - User: ptr.To(users[2]), + User: new(users[2]), }, &types.Node{ IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[1]), + User: new(users[1]), }, }, want: []tailcfg.FilterRule{ @@ -453,7 +452,7 @@ func TestReduceFilterRules(t *testing.T) { node: &types.Node{ IPv4: ap("100.64.0.100"), IPv6: ap("fd7a:115c:a1e0::100"), - User: ptr.To(users[3]), + User: new(users[3]), Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: tsaddr.ExitRoutes(), }, @@ -462,12 +461,12 @@ func TestReduceFilterRules(t *testing.T) { &types.Node{ IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), - User: ptr.To(users[2]), + User: new(users[2]), }, &types.Node{ IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[1]), + User: new(users[1]), }, }, want: []tailcfg.FilterRule{ @@ -565,7 +564,7 @@ func TestReduceFilterRules(t *testing.T) { node: &types.Node{ IPv4: ap("100.64.0.100"), IPv6: ap("fd7a:115c:a1e0::100"), - User: ptr.To(users[3]), + User: new(users[3]), Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: []netip.Prefix{netip.MustParsePrefix("8.0.0.0/16"), netip.MustParsePrefix("16.0.0.0/16")}, }, @@ -574,12 +573,12 @@ func TestReduceFilterRules(t *testing.T) { &types.Node{ IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), - User: ptr.To(users[2]), + User: new(users[2]), }, &types.Node{ IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[1]), + User: new(users[1]), }, }, want: []tailcfg.FilterRule{ @@ -655,7 +654,7 @@ func TestReduceFilterRules(t *testing.T) { node: &types.Node{ IPv4: ap("100.64.0.100"), IPv6: ap("fd7a:115c:a1e0::100"), - User: ptr.To(users[3]), + User: new(users[3]), Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: []netip.Prefix{netip.MustParsePrefix("8.0.0.0/8"), netip.MustParsePrefix("16.0.0.0/8")}, }, @@ -664,12 +663,12 @@ func TestReduceFilterRules(t *testing.T) { &types.Node{ IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), - User: ptr.To(users[2]), + User: new(users[2]), }, &types.Node{ IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[1]), + User: new(users[1]), }, }, want: []tailcfg.FilterRule{ @@ -737,7 +736,7 @@ func TestReduceFilterRules(t *testing.T) { node: &types.Node{ IPv4: ap("100.64.0.100"), IPv6: ap("fd7a:115c:a1e0::100"), - User: ptr.To(users[3]), + User: new(users[3]), Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: []netip.Prefix{netip.MustParsePrefix("172.16.0.0/24")}, }, @@ -747,7 +746,7 @@ func TestReduceFilterRules(t *testing.T) { &types.Node{ IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[1]), + User: new(users[1]), }, }, want: []tailcfg.FilterRule{ @@ -804,13 +803,13 @@ func TestReduceFilterRules(t *testing.T) { node: &types.Node{ IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), - User: ptr.To(users[3]), + User: new(users[3]), }, peers: types.Nodes{ &types.Node{ IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[1]), + User: new(users[1]), Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: []netip.Prefix{p("172.16.0.0/24"), p("10.10.11.0/24"), p("10.10.12.0/24")}, }, diff --git a/hscontrol/policy/route_approval_test.go b/hscontrol/policy/route_approval_test.go index 39b15cee..5aa5e28c 100644 --- a/hscontrol/policy/route_approval_test.go +++ b/hscontrol/policy/route_approval_test.go @@ -10,7 +10,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/gorm" - "tailscale.com/types/ptr" ) func TestNodeCanApproveRoute(t *testing.T) { @@ -25,24 +24,24 @@ func TestNodeCanApproveRoute(t *testing.T) { ID: 1, Hostname: "user1-device", IPv4: ap("100.64.0.1"), - UserID: ptr.To(uint(1)), - User: ptr.To(users[0]), + UserID: new(uint(1)), + User: new(users[0]), } exitNode := types.Node{ ID: 2, Hostname: "user2-device", IPv4: ap("100.64.0.2"), - UserID: ptr.To(uint(2)), - User: ptr.To(users[1]), + UserID: new(uint(2)), + User: new(users[1]), } taggedNode := types.Node{ ID: 3, Hostname: "tagged-server", IPv4: ap("100.64.0.3"), - UserID: ptr.To(uint(3)), - User: ptr.To(users[2]), + UserID: new(uint(3)), + User: new(users[2]), Tags: []string{"tag:router"}, } @@ -50,8 +49,8 @@ func TestNodeCanApproveRoute(t *testing.T) { ID: 4, Hostname: "multi-tag-node", IPv4: ap("100.64.0.4"), - UserID: ptr.To(uint(2)), - User: ptr.To(users[1]), + UserID: new(uint(2)), + User: new(users[1]), Tags: []string{"tag:router", "tag:server"}, } diff --git a/hscontrol/policy/v2/filter_test.go b/hscontrol/policy/v2/filter_test.go index 46f544c9..d798b5f7 100644 --- a/hscontrol/policy/v2/filter_test.go +++ b/hscontrol/policy/v2/filter_test.go @@ -15,7 +15,6 @@ import ( "github.com/stretchr/testify/require" "gorm.io/gorm" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) // aliasWithPorts creates an AliasWithPorts structure from an alias and ports. @@ -410,14 +409,14 @@ func TestCompileSSHPolicy_UserMapping(t *testing.T) { nodeUser1 := types.Node{ Hostname: "user1-device", IPv4: createAddr("100.64.0.1"), - UserID: ptr.To(users[0].ID), - User: ptr.To(users[0]), + UserID: new(users[0].ID), + User: new(users[0]), } nodeUser2 := types.Node{ Hostname: "user2-device", IPv4: createAddr("100.64.0.2"), - UserID: ptr.To(users[1].ID), - User: ptr.To(users[1]), + UserID: new(users[1].ID), + User: new(users[1]), } nodes := types.Nodes{&nodeUser1, &nodeUser2} @@ -622,14 +621,14 @@ func TestCompileSSHPolicy_CheckAction(t *testing.T) { nodeUser1 := types.Node{ Hostname: "user1-device", IPv4: createAddr("100.64.0.1"), - UserID: ptr.To(users[0].ID), - User: ptr.To(users[0]), + UserID: new(users[0].ID), + User: new(users[0]), } nodeUser2 := types.Node{ Hostname: "user2-device", IPv4: createAddr("100.64.0.2"), - UserID: ptr.To(users[1].ID), - User: ptr.To(users[1]), + UserID: new(users[1].ID), + User: new(users[1]), } nodes := types.Nodes{&nodeUser1, &nodeUser2} @@ -683,15 +682,15 @@ func TestSSHIntegrationReproduction(t *testing.T) { node1 := &types.Node{ Hostname: "user1-node", IPv4: createAddr("100.64.0.1"), - UserID: ptr.To(users[0].ID), - User: ptr.To(users[0]), + UserID: new(users[0].ID), + User: new(users[0]), } node2 := &types.Node{ Hostname: "user2-node", IPv4: createAddr("100.64.0.2"), - UserID: ptr.To(users[1].ID), - User: ptr.To(users[1]), + UserID: new(users[1].ID), + User: new(users[1]), } nodes := types.Nodes{node1, node2} @@ -806,19 +805,19 @@ func TestCompileFilterRulesForNodeWithAutogroupSelf(t *testing.T) { nodes := types.Nodes{ { - User: ptr.To(users[0]), + User: new(users[0]), IPv4: ap("100.64.0.1"), }, { - User: ptr.To(users[0]), + User: new(users[0]), IPv4: ap("100.64.0.2"), }, { - User: ptr.To(users[1]), + User: new(users[1]), IPv4: ap("100.64.0.3"), }, { - User: ptr.To(users[1]), + User: new(users[1]), IPv4: ap("100.64.0.4"), }, // Tagged device for user1 @@ -938,11 +937,11 @@ func TestTagUserMutualExclusivity(t *testing.T) { nodes := types.Nodes{ // User-owned nodes { - User: ptr.To(users[0]), + User: new(users[0]), IPv4: ap("100.64.0.1"), }, { - User: ptr.To(users[1]), + User: new(users[1]), IPv4: ap("100.64.0.2"), }, // Tagged nodes @@ -960,8 +959,8 @@ func TestTagUserMutualExclusivity(t *testing.T) { policy := &Policy{ TagOwners: TagOwners{ - Tag("tag:server"): Owners{ptr.To(Username("user1@"))}, - Tag("tag:database"): Owners{ptr.To(Username("user2@"))}, + Tag("tag:server"): Owners{new(Username("user1@"))}, + Tag("tag:database"): Owners{new(Username("user2@"))}, }, ACLs: []ACL{ // Rule 1: user1 (user-owned) should NOT be able to reach tagged nodes @@ -1056,11 +1055,11 @@ func TestAutogroupTagged(t *testing.T) { nodes := types.Nodes{ // User-owned nodes (not tagged) { - User: ptr.To(users[0]), + User: new(users[0]), IPv4: ap("100.64.0.1"), }, { - User: ptr.To(users[1]), + User: new(users[1]), IPv4: ap("100.64.0.2"), }, // Tagged nodes @@ -1083,10 +1082,10 @@ func TestAutogroupTagged(t *testing.T) { policy := &Policy{ TagOwners: TagOwners{ - Tag("tag:server"): Owners{ptr.To(Username("user1@"))}, - Tag("tag:database"): Owners{ptr.To(Username("user2@"))}, - Tag("tag:web"): Owners{ptr.To(Username("user1@"))}, - Tag("tag:prod"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:server"): Owners{new(Username("user1@"))}, + Tag("tag:database"): Owners{new(Username("user2@"))}, + Tag("tag:web"): Owners{new(Username("user1@"))}, + Tag("tag:prod"): Owners{new(Username("user1@"))}, }, ACLs: []ACL{ // Rule: autogroup:tagged can reach user-owned nodes @@ -1206,10 +1205,10 @@ func TestAutogroupSelfWithSpecificUserSource(t *testing.T) { } nodes := types.Nodes{ - {User: ptr.To(users[0]), IPv4: ap("100.64.0.1")}, - {User: ptr.To(users[0]), IPv4: ap("100.64.0.2")}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.3")}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.4")}, + {User: new(users[0]), IPv4: ap("100.64.0.1")}, + {User: new(users[0]), IPv4: ap("100.64.0.2")}, + {User: new(users[1]), IPv4: ap("100.64.0.3")}, + {User: new(users[1]), IPv4: ap("100.64.0.4")}, } policy := &Policy{ @@ -1273,11 +1272,11 @@ func TestAutogroupSelfWithGroupSource(t *testing.T) { } nodes := types.Nodes{ - {User: ptr.To(users[0]), IPv4: ap("100.64.0.1")}, - {User: ptr.To(users[0]), IPv4: ap("100.64.0.2")}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.3")}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.4")}, - {User: ptr.To(users[2]), IPv4: ap("100.64.0.5")}, + {User: new(users[0]), IPv4: ap("100.64.0.1")}, + {User: new(users[0]), IPv4: ap("100.64.0.2")}, + {User: new(users[1]), IPv4: ap("100.64.0.3")}, + {User: new(users[1]), IPv4: ap("100.64.0.4")}, + {User: new(users[2]), IPv4: ap("100.64.0.5")}, } policy := &Policy{ @@ -1342,13 +1341,13 @@ func TestSSHWithAutogroupSelfInDestination(t *testing.T) { nodes := types.Nodes{ // User1's nodes - {User: ptr.To(users[0]), IPv4: ap("100.64.0.1"), Hostname: "user1-node1"}, - {User: ptr.To(users[0]), IPv4: ap("100.64.0.2"), Hostname: "user1-node2"}, + {User: new(users[0]), IPv4: ap("100.64.0.1"), Hostname: "user1-node1"}, + {User: new(users[0]), IPv4: ap("100.64.0.2"), Hostname: "user1-node2"}, // User2's nodes - {User: ptr.To(users[1]), IPv4: ap("100.64.0.3"), Hostname: "user2-node1"}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.4"), Hostname: "user2-node2"}, + {User: new(users[1]), IPv4: ap("100.64.0.3"), Hostname: "user2-node1"}, + {User: new(users[1]), IPv4: ap("100.64.0.4"), Hostname: "user2-node2"}, // Tagged node for user1 (should be excluded) - {User: ptr.To(users[0]), IPv4: ap("100.64.0.5"), Hostname: "user1-tagged", Tags: []string{"tag:server"}}, + {User: new(users[0]), IPv4: ap("100.64.0.5"), Hostname: "user1-tagged", Tags: []string{"tag:server"}}, } policy := &Policy{ @@ -1420,10 +1419,10 @@ func TestSSHWithAutogroupSelfAndSpecificUser(t *testing.T) { } nodes := types.Nodes{ - {User: ptr.To(users[0]), IPv4: ap("100.64.0.1")}, - {User: ptr.To(users[0]), IPv4: ap("100.64.0.2")}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.3")}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.4")}, + {User: new(users[0]), IPv4: ap("100.64.0.1")}, + {User: new(users[0]), IPv4: ap("100.64.0.2")}, + {User: new(users[1]), IPv4: ap("100.64.0.3")}, + {User: new(users[1]), IPv4: ap("100.64.0.4")}, } policy := &Policy{ @@ -1474,11 +1473,11 @@ func TestSSHWithAutogroupSelfAndGroup(t *testing.T) { } nodes := types.Nodes{ - {User: ptr.To(users[0]), IPv4: ap("100.64.0.1")}, - {User: ptr.To(users[0]), IPv4: ap("100.64.0.2")}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.3")}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.4")}, - {User: ptr.To(users[2]), IPv4: ap("100.64.0.5")}, + {User: new(users[0]), IPv4: ap("100.64.0.1")}, + {User: new(users[0]), IPv4: ap("100.64.0.2")}, + {User: new(users[1]), IPv4: ap("100.64.0.3")}, + {User: new(users[1]), IPv4: ap("100.64.0.4")}, + {User: new(users[2]), IPv4: ap("100.64.0.5")}, } policy := &Policy{ @@ -1531,10 +1530,10 @@ func TestSSHWithAutogroupSelfExcludesTaggedDevices(t *testing.T) { } nodes := types.Nodes{ - {User: ptr.To(users[0]), IPv4: ap("100.64.0.1"), Hostname: "untagged1"}, - {User: ptr.To(users[0]), IPv4: ap("100.64.0.2"), Hostname: "untagged2"}, - {User: ptr.To(users[0]), IPv4: ap("100.64.0.3"), Hostname: "tagged1", Tags: []string{"tag:server"}}, - {User: ptr.To(users[0]), IPv4: ap("100.64.0.4"), Hostname: "tagged2", Tags: []string{"tag:web"}}, + {User: new(users[0]), IPv4: ap("100.64.0.1"), Hostname: "untagged1"}, + {User: new(users[0]), IPv4: ap("100.64.0.2"), Hostname: "untagged2"}, + {User: new(users[0]), IPv4: ap("100.64.0.3"), Hostname: "tagged1", Tags: []string{"tag:server"}}, + {User: new(users[0]), IPv4: ap("100.64.0.4"), Hostname: "tagged2", Tags: []string{"tag:web"}}, } policy := &Policy{ @@ -1591,10 +1590,10 @@ func TestSSHWithAutogroupSelfAndMixedDestinations(t *testing.T) { } nodes := types.Nodes{ - {User: ptr.To(users[0]), IPv4: ap("100.64.0.1"), Hostname: "user1-device"}, - {User: ptr.To(users[0]), IPv4: ap("100.64.0.2"), Hostname: "user1-device2"}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.3"), Hostname: "user2-device"}, - {User: ptr.To(users[1]), IPv4: ap("100.64.0.4"), Hostname: "user2-router", Tags: []string{"tag:router"}}, + {User: new(users[0]), IPv4: ap("100.64.0.1"), Hostname: "user1-device"}, + {User: new(users[0]), IPv4: ap("100.64.0.2"), Hostname: "user1-device2"}, + {User: new(users[1]), IPv4: ap("100.64.0.3"), Hostname: "user2-device"}, + {User: new(users[1]), IPv4: ap("100.64.0.4"), Hostname: "user2-router", Tags: []string{"tag:router"}}, } policy := &Policy{ diff --git a/hscontrol/policy/v2/policy_test.go b/hscontrol/policy/v2/policy_test.go index 26b0d141..80c08eed 100644 --- a/hscontrol/policy/v2/policy_test.go +++ b/hscontrol/policy/v2/policy_test.go @@ -11,7 +11,6 @@ import ( "github.com/stretchr/testify/require" "gorm.io/gorm" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) func node(name, ipv4, ipv6 string, user types.User, hostinfo *tailcfg.Hostinfo) *types.Node { @@ -20,8 +19,8 @@ func node(name, ipv4, ipv6 string, user types.User, hostinfo *tailcfg.Hostinfo) Hostname: name, IPv4: ap(ipv4), IPv6: ap(ipv6), - User: ptr.To(user), - UserID: ptr.To(user.ID), + User: new(user), + UserID: new(user.ID), Hostinfo: hostinfo, } } @@ -457,8 +456,8 @@ func TestAutogroupSelfWithOtherRules(t *testing.T) { Hostname: "test-1-device", IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[0]), - UserID: ptr.To(users[0].ID), + User: new(users[0]), + UserID: new(users[0].ID), Hostinfo: &tailcfg.Hostinfo{}, } @@ -468,8 +467,8 @@ func TestAutogroupSelfWithOtherRules(t *testing.T) { Hostname: "test-2-router", IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), - User: ptr.To(users[1]), - UserID: ptr.To(users[1].ID), + User: new(users[1]), + UserID: new(users[1].ID), Tags: []string{"tag:node-router"}, Hostinfo: &tailcfg.Hostinfo{}, } @@ -537,8 +536,8 @@ func TestAutogroupSelfPolicyUpdateTriggersMapResponse(t *testing.T) { Hostname: "test-1-device", IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[0]), - UserID: ptr.To(users[0].ID), + User: new(users[0]), + UserID: new(users[0].ID), Hostinfo: &tailcfg.Hostinfo{}, } @@ -547,8 +546,8 @@ func TestAutogroupSelfPolicyUpdateTriggersMapResponse(t *testing.T) { Hostname: "test-2-device", IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), - User: ptr.To(users[1]), - UserID: ptr.To(users[1].ID), + User: new(users[1]), + UserID: new(users[1].ID), Hostinfo: &tailcfg.Hostinfo{}, } @@ -647,8 +646,8 @@ func TestTagPropagationToPeerMap(t *testing.T) { Hostname: "user1-node", IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[0]), - UserID: ptr.To(users[0].ID), + User: new(users[0]), + UserID: new(users[0].ID), Tags: []string{"tag:web", "tag:internal"}, } @@ -658,8 +657,8 @@ func TestTagPropagationToPeerMap(t *testing.T) { Hostname: "user2-node", IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), - User: ptr.To(users[1]), - UserID: ptr.To(users[1].ID), + User: new(users[1]), + UserID: new(users[1].ID), } initialNodes := types.Nodes{user1Node, user2Node} @@ -686,8 +685,8 @@ func TestTagPropagationToPeerMap(t *testing.T) { Hostname: "user1-node", IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), - User: ptr.To(users[0]), - UserID: ptr.To(users[0].ID), + User: new(users[0]), + UserID: new(users[0].ID), Tags: []string{"tag:internal"}, // tag:web removed! } diff --git a/hscontrol/policy/v2/types_test.go b/hscontrol/policy/v2/types_test.go index 664f76b7..8f4f7a85 100644 --- a/hscontrol/policy/v2/types_test.go +++ b/hscontrol/policy/v2/types_test.go @@ -19,7 +19,6 @@ import ( "gorm.io/gorm" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) // TestUnmarshalPolicy tests the unmarshalling of JSON into Policy objects and the marshalling @@ -53,11 +52,11 @@ func TestMarshalJSON(t *testing.T) { Action: "accept", Protocol: "tcp", Sources: Aliases{ - ptr.To(Username("user@example.com")), + new(Username("user@example.com")), }, Destinations: []AliasWithPorts{ { - Alias: ptr.To(Username("other@example.com")), + Alias: new(Username("other@example.com")), Ports: []tailcfg.PortRange{{First: 80, Last: 80}}, }, }, @@ -253,11 +252,11 @@ func TestUnmarshalPolicy(t *testing.T) { Action: "accept", Protocol: "tcp", Sources: Aliases{ - ptr.To(Username("testuser@headscale.net")), + new(Username("testuser@headscale.net")), }, Destinations: []AliasWithPorts{ { - Alias: ptr.To(Username("otheruser@headscale.net")), + Alias: new(Username("otheruser@headscale.net")), Ports: []tailcfg.PortRange{{First: 80, Last: 80}}, }, }, @@ -546,7 +545,7 @@ func TestUnmarshalPolicy(t *testing.T) { }, Destinations: []AliasWithPorts{ { - Alias: ptr.To(AutoGroup("autogroup:internet")), + Alias: new(AutoGroup("autogroup:internet")), Ports: []tailcfg.PortRange{tailcfg.PortRangeAny}, }, }, @@ -682,7 +681,7 @@ func TestUnmarshalPolicy(t *testing.T) { `, want: &Policy{ TagOwners: TagOwners{ - Tag("tag:web"): Owners{ptr.To(Username("admin@example.com"))}, + Tag("tag:web"): Owners{new(Username("admin@example.com"))}, }, SSHs: []SSH{ { @@ -691,7 +690,7 @@ func TestUnmarshalPolicy(t *testing.T) { tp("tag:web"), }, Destinations: SSHDstAliases{ - ptr.To(Username("admin@example.com")), + new(Username("admin@example.com")), }, Users: []SSHUser{ SSHUser("*"), @@ -733,7 +732,7 @@ func TestUnmarshalPolicy(t *testing.T) { gp("group:admins"), }, Destinations: SSHDstAliases{ - ptr.To(Username("admin@example.com")), + new(Username("admin@example.com")), }, Users: []SSHUser{ SSHUser("root"), @@ -1154,7 +1153,7 @@ func TestUnmarshalPolicy(t *testing.T) { }, Destinations: []AliasWithPorts{ { - Alias: ptr.To(AutoGroup("autogroup:internet")), + Alias: new(AutoGroup("autogroup:internet")), Ports: []tailcfg.PortRange{tailcfg.PortRangeAny}, }, }, @@ -1491,7 +1490,7 @@ func TestUnmarshalPolicy(t *testing.T) { want: &Policy{ TagOwners: TagOwners{ Tag("tag:bigbrother"): {}, - Tag("tag:smallbrother"): {ptr.To(Tag("tag:bigbrother"))}, + Tag("tag:smallbrother"): {new(Tag("tag:bigbrother"))}, }, ACLs: []ACL{ { @@ -1502,7 +1501,7 @@ func TestUnmarshalPolicy(t *testing.T) { }, Destinations: []AliasWithPorts{ { - Alias: ptr.To(Tag("tag:smallbrother")), + Alias: new(Tag("tag:smallbrother")), Ports: []tailcfg.PortRange{{First: 9000, Last: 9000}}, }, }, @@ -1583,14 +1582,14 @@ func TestUnmarshalPolicy(t *testing.T) { } } -func gp(s string) *Group { return ptr.To(Group(s)) } -func up(s string) *Username { return ptr.To(Username(s)) } -func hp(s string) *Host { return ptr.To(Host(s)) } -func tp(s string) *Tag { return ptr.To(Tag(s)) } -func agp(s string) *AutoGroup { return ptr.To(AutoGroup(s)) } +func gp(s string) *Group { return new(Group(s)) } +func up(s string) *Username { return new(Username(s)) } +func hp(s string) *Host { return new(Host(s)) } +func tp(s string) *Tag { return new(Tag(s)) } +func agp(s string) *AutoGroup { return new(AutoGroup(s)) } func mp(pref string) netip.Prefix { return netip.MustParsePrefix(pref) } -func ap(addr string) *netip.Addr { return ptr.To(netip.MustParseAddr(addr)) } -func pp(pref string) *Prefix { return ptr.To(Prefix(mp(pref))) } +func ap(addr string) *netip.Addr { return new(netip.MustParseAddr(addr)) } +func pp(pref string) *Prefix { return new(Prefix(mp(pref))) } func p(pref string) Prefix { return Prefix(mp(pref)) } func TestResolvePolicy(t *testing.T) { @@ -1636,31 +1635,31 @@ func TestResolvePolicy(t *testing.T) { }, { name: "username", - toResolve: ptr.To(Username("testuser@")), + toResolve: new(Username("testuser@")), nodes: types.Nodes{ // Not matching other user { - User: ptr.To(notme), + User: new(notme), IPv4: ap("100.100.101.1"), }, // Not matching forced tags { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"tag:anything"}, IPv4: ap("100.100.101.2"), }, // not matching because it's tagged (tags copied from AuthKey) { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"alsotagged"}, IPv4: ap("100.100.101.3"), }, { - User: ptr.To(testuser), + User: new(testuser), IPv4: ap("100.100.101.103"), }, { - User: ptr.To(testuser), + User: new(testuser), IPv4: ap("100.100.101.104"), }, }, @@ -1668,31 +1667,31 @@ func TestResolvePolicy(t *testing.T) { }, { name: "group", - toResolve: ptr.To(Group("group:testgroup")), + toResolve: new(Group("group:testgroup")), nodes: types.Nodes{ // Not matching other user { - User: ptr.To(notme), + User: new(notme), IPv4: ap("100.100.101.4"), }, // Not matching forced tags { - User: ptr.To(groupuser), + User: new(groupuser), Tags: []string{"tag:anything"}, IPv4: ap("100.100.101.5"), }, // not matching because it's tagged (tags copied from AuthKey) { - User: ptr.To(groupuser), + User: new(groupuser), Tags: []string{"tag:alsotagged"}, IPv4: ap("100.100.101.6"), }, { - User: ptr.To(groupuser), + User: new(groupuser), IPv4: ap("100.100.101.203"), }, { - User: ptr.To(groupuser), + User: new(groupuser), IPv4: ap("100.100.101.204"), }, }, @@ -1710,7 +1709,7 @@ func TestResolvePolicy(t *testing.T) { nodes: types.Nodes{ // Not matching other user { - User: ptr.To(notme), + User: new(notme), IPv4: ap("100.100.101.9"), }, // Not matching forced tags @@ -1746,7 +1745,7 @@ func TestResolvePolicy(t *testing.T) { pol: &Policy{ TagOwners: TagOwners{ Tag("tag:bigbrother"): {}, - Tag("tag:smallbrother"): {ptr.To(Tag("tag:bigbrother"))}, + Tag("tag:smallbrother"): {new(Tag("tag:bigbrother"))}, }, }, nodes: types.Nodes{ @@ -1769,7 +1768,7 @@ func TestResolvePolicy(t *testing.T) { pol: &Policy{ TagOwners: TagOwners{ Tag("tag:bigbrother"): {}, - Tag("tag:smallbrother"): {ptr.To(Tag("tag:bigbrother"))}, + Tag("tag:smallbrother"): {new(Tag("tag:bigbrother"))}, }, }, nodes: types.Nodes{ @@ -1804,14 +1803,14 @@ func TestResolvePolicy(t *testing.T) { }, { name: "multiple-groups", - toResolve: ptr.To(Group("group:testgroup")), + toResolve: new(Group("group:testgroup")), nodes: types.Nodes{ { - User: ptr.To(groupuser1), + User: new(groupuser1), IPv4: ap("100.100.101.203"), }, { - User: ptr.To(groupuser2), + User: new(groupuser2), IPv4: ap("100.100.101.204"), }, }, @@ -1829,10 +1828,10 @@ func TestResolvePolicy(t *testing.T) { }, { name: "invalid-username", - toResolve: ptr.To(Username("invaliduser@")), + toResolve: new(Username("invaliduser@")), nodes: types.Nodes{ { - User: ptr.To(testuser), + User: new(testuser), IPv4: ap("100.100.101.103"), }, }, @@ -1860,47 +1859,47 @@ func TestResolvePolicy(t *testing.T) { }, { name: "autogroup-member-comprehensive", - toResolve: ptr.To(AutoGroup(AutoGroupMember)), + toResolve: new(AutoGroup(AutoGroupMember)), nodes: types.Nodes{ // Node with no tags (should be included - is a member) { - User: ptr.To(testuser), + User: new(testuser), IPv4: ap("100.100.101.1"), }, // Node with single tag (should be excluded - tagged nodes are not members) { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"tag:test"}, IPv4: ap("100.100.101.2"), }, // Node with multiple tags, all defined in policy (should be excluded) { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"tag:test", "tag:other"}, IPv4: ap("100.100.101.3"), }, // Node with tag not defined in policy (should be excluded - still tagged) { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"tag:undefined"}, IPv4: ap("100.100.101.4"), }, // Node with mixed tags - some defined, some not (should be excluded) { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"tag:test", "tag:undefined"}, IPv4: ap("100.100.101.5"), }, // Another untagged node from different user (should be included) { - User: ptr.To(testuser2), + User: new(testuser2), IPv4: ap("100.100.101.6"), }, }, pol: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("testuser@"))}, - Tag("tag:other"): Owners{ptr.To(Username("testuser@"))}, + Tag("tag:test"): Owners{new(Username("testuser@"))}, + Tag("tag:other"): Owners{new(Username("testuser@"))}, }, }, want: []netip.Prefix{ @@ -1910,54 +1909,54 @@ func TestResolvePolicy(t *testing.T) { }, { name: "autogroup-tagged", - toResolve: ptr.To(AutoGroup(AutoGroupTagged)), + toResolve: new(AutoGroup(AutoGroupTagged)), nodes: types.Nodes{ // Node with no tags (should be excluded - not tagged) { - User: ptr.To(testuser), + User: new(testuser), IPv4: ap("100.100.101.1"), }, // Node with single tag defined in policy (should be included) { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"tag:test"}, IPv4: ap("100.100.101.2"), }, // Node with multiple tags, all defined in policy (should be included) { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"tag:test", "tag:other"}, IPv4: ap("100.100.101.3"), }, // Node with tag not defined in policy (should be included - still tagged) { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"tag:undefined"}, IPv4: ap("100.100.101.4"), }, // Node with mixed tags - some defined, some not (should be included) { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"tag:test", "tag:undefined"}, IPv4: ap("100.100.101.5"), }, // Another untagged node from different user (should be excluded) { - User: ptr.To(testuser2), + User: new(testuser2), IPv4: ap("100.100.101.6"), }, // Tagged node from different user (should be included) { - User: ptr.To(testuser2), + User: new(testuser2), Tags: []string{"tag:server"}, IPv4: ap("100.100.101.7"), }, }, pol: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("testuser@"))}, - Tag("tag:other"): Owners{ptr.To(Username("testuser@"))}, - Tag("tag:server"): Owners{ptr.To(Username("testuser2@"))}, + Tag("tag:test"): Owners{new(Username("testuser@"))}, + Tag("tag:other"): Owners{new(Username("testuser@"))}, + Tag("tag:server"): Owners{new(Username("testuser2@"))}, }, }, want: []netip.Prefix{ @@ -1968,37 +1967,37 @@ func TestResolvePolicy(t *testing.T) { }, { name: "autogroup-self", - toResolve: ptr.To(AutoGroupSelf), + toResolve: new(AutoGroupSelf), nodes: types.Nodes{ { - User: ptr.To(testuser), + User: new(testuser), IPv4: ap("100.100.101.1"), }, { - User: ptr.To(testuser2), + User: new(testuser2), IPv4: ap("100.100.101.2"), }, { - User: ptr.To(testuser), + User: new(testuser), Tags: []string{"tag:test"}, IPv4: ap("100.100.101.3"), }, { - User: ptr.To(testuser2), + User: new(testuser2), Tags: []string{"tag:test"}, IPv4: ap("100.100.101.4"), }, }, pol: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("testuser@"))}, + Tag("tag:test"): Owners{new(Username("testuser@"))}, }, }, wantErr: "autogroup:self requires per-node resolution", }, { name: "autogroup-invalid", - toResolve: ptr.To(AutoGroup("autogroup:invalid")), + toResolve: new(AutoGroup("autogroup:invalid")), wantErr: "unknown autogroup", }, } @@ -2076,7 +2075,7 @@ func TestResolveAutoApprovers(t *testing.T) { policy: &Policy{ AutoApprovers: AutoApproverPolicy{ Routes: map[netip.Prefix]AutoApprovers{ - mp("10.0.0.0/24"): {ptr.To(Username("user1@"))}, + mp("10.0.0.0/24"): {new(Username("user1@"))}, }, }, }, @@ -2091,8 +2090,8 @@ func TestResolveAutoApprovers(t *testing.T) { policy: &Policy{ AutoApprovers: AutoApproverPolicy{ Routes: map[netip.Prefix]AutoApprovers{ - mp("10.0.0.0/24"): {ptr.To(Username("user1@"))}, - mp("10.0.1.0/24"): {ptr.To(Username("user2@"))}, + mp("10.0.0.0/24"): {new(Username("user1@"))}, + mp("10.0.1.0/24"): {new(Username("user2@"))}, }, }, }, @@ -2107,7 +2106,7 @@ func TestResolveAutoApprovers(t *testing.T) { name: "exit-node", policy: &Policy{ AutoApprovers: AutoApproverPolicy{ - ExitNode: AutoApprovers{ptr.To(Username("user1@"))}, + ExitNode: AutoApprovers{new(Username("user1@"))}, }, }, want: map[netip.Prefix]*netipx.IPSet{}, @@ -2122,7 +2121,7 @@ func TestResolveAutoApprovers(t *testing.T) { }, AutoApprovers: AutoApproverPolicy{ Routes: map[netip.Prefix]AutoApprovers{ - mp("10.0.0.0/24"): {ptr.To(Group("group:testgroup"))}, + mp("10.0.0.0/24"): {new(Group("group:testgroup"))}, }, }, }, @@ -2137,20 +2136,20 @@ func TestResolveAutoApprovers(t *testing.T) { policy: &Policy{ TagOwners: TagOwners{ "tag:testtag": Owners{ - ptr.To(Username("user1@")), - ptr.To(Username("user2@")), + new(Username("user1@")), + new(Username("user2@")), }, "tag:exittest": Owners{ - ptr.To(Group("group:exitgroup")), + new(Group("group:exitgroup")), }, }, Groups: Groups{ "group:exitgroup": Usernames{"user2@"}, }, AutoApprovers: AutoApproverPolicy{ - ExitNode: AutoApprovers{ptr.To(Tag("tag:exittest"))}, + ExitNode: AutoApprovers{new(Tag("tag:exittest"))}, Routes: map[netip.Prefix]AutoApprovers{ - mp("10.0.1.0/24"): {ptr.To(Tag("tag:testtag"))}, + mp("10.0.1.0/24"): {new(Tag("tag:testtag"))}, }, }, }, @@ -2168,10 +2167,10 @@ func TestResolveAutoApprovers(t *testing.T) { }, AutoApprovers: AutoApproverPolicy{ Routes: map[netip.Prefix]AutoApprovers{ - mp("10.0.0.0/24"): {ptr.To(Group("group:testgroup"))}, - mp("10.0.1.0/24"): {ptr.To(Username("user3@"))}, + mp("10.0.0.0/24"): {new(Group("group:testgroup"))}, + mp("10.0.1.0/24"): {new(Username("user3@"))}, }, - ExitNode: AutoApprovers{ptr.To(Username("user1@"))}, + ExitNode: AutoApprovers{new(Username("user1@"))}, }, }, want: map[netip.Prefix]*netipx.IPSet{ @@ -2388,7 +2387,7 @@ func TestNodeCanApproveRoute(t *testing.T) { policy: &Policy{ AutoApprovers: AutoApproverPolicy{ Routes: map[netip.Prefix]AutoApprovers{ - mp("10.0.0.0/24"): {ptr.To(Username("user1@"))}, + mp("10.0.0.0/24"): {new(Username("user1@"))}, }, }, }, @@ -2401,8 +2400,8 @@ func TestNodeCanApproveRoute(t *testing.T) { policy: &Policy{ AutoApprovers: AutoApproverPolicy{ Routes: map[netip.Prefix]AutoApprovers{ - mp("10.0.0.0/24"): {ptr.To(Username("user1@"))}, - mp("10.0.1.0/24"): {ptr.To(Username("user2@"))}, + mp("10.0.0.0/24"): {new(Username("user1@"))}, + mp("10.0.1.0/24"): {new(Username("user2@"))}, }, }, }, @@ -2414,7 +2413,7 @@ func TestNodeCanApproveRoute(t *testing.T) { name: "exit-node-approval", policy: &Policy{ AutoApprovers: AutoApproverPolicy{ - ExitNode: AutoApprovers{ptr.To(Username("user1@"))}, + ExitNode: AutoApprovers{new(Username("user1@"))}, }, }, node: nodes[0], @@ -2429,7 +2428,7 @@ func TestNodeCanApproveRoute(t *testing.T) { }, AutoApprovers: AutoApproverPolicy{ Routes: map[netip.Prefix]AutoApprovers{ - mp("10.0.0.0/24"): {ptr.To(Group("group:testgroup"))}, + mp("10.0.0.0/24"): {new(Group("group:testgroup"))}, }, }, }, @@ -2445,10 +2444,10 @@ func TestNodeCanApproveRoute(t *testing.T) { }, AutoApprovers: AutoApproverPolicy{ Routes: map[netip.Prefix]AutoApprovers{ - mp("10.0.0.0/24"): {ptr.To(Group("group:testgroup"))}, - mp("10.0.1.0/24"): {ptr.To(Username("user3@"))}, + mp("10.0.0.0/24"): {new(Group("group:testgroup"))}, + mp("10.0.1.0/24"): {new(Username("user3@"))}, }, - ExitNode: AutoApprovers{ptr.To(Username("user1@"))}, + ExitNode: AutoApprovers{new(Username("user1@"))}, }, }, node: nodes[0], @@ -2460,7 +2459,7 @@ func TestNodeCanApproveRoute(t *testing.T) { policy: &Policy{ AutoApprovers: AutoApproverPolicy{ Routes: map[netip.Prefix]AutoApprovers{ - mp("10.0.0.0/24"): {ptr.To(Username("user2@"))}, + mp("10.0.0.0/24"): {new(Username("user2@"))}, }, }, }, @@ -2518,7 +2517,7 @@ func TestResolveTagOwners(t *testing.T) { name: "single-tag-owner", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:test"): Owners{new(Username("user1@"))}, }, }, want: map[Tag]*netipx.IPSet{ @@ -2530,7 +2529,7 @@ func TestResolveTagOwners(t *testing.T) { name: "multiple-tag-owners", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("user1@")), ptr.To(Username("user2@"))}, + Tag("tag:test"): Owners{new(Username("user1@")), new(Username("user2@"))}, }, }, want: map[Tag]*netipx.IPSet{ @@ -2545,7 +2544,7 @@ func TestResolveTagOwners(t *testing.T) { "group:testgroup": Usernames{"user1@", "user2@"}, }, TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Group("group:testgroup"))}, + Tag("tag:test"): Owners{new(Group("group:testgroup"))}, }, }, want: map[Tag]*netipx.IPSet{ @@ -2557,8 +2556,8 @@ func TestResolveTagOwners(t *testing.T) { name: "tag-owns-tag", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:bigbrother"): Owners{ptr.To(Username("user1@"))}, - Tag("tag:smallbrother"): Owners{ptr.To(Tag("tag:bigbrother"))}, + Tag("tag:bigbrother"): Owners{new(Username("user1@"))}, + Tag("tag:smallbrother"): Owners{new(Tag("tag:bigbrother"))}, }, }, want: map[Tag]*netipx.IPSet{ @@ -2619,7 +2618,7 @@ func TestNodeCanHaveTag(t *testing.T) { name: "single-tag-owner", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:test"): Owners{new(Username("user1@"))}, }, }, node: nodes[0], @@ -2630,7 +2629,7 @@ func TestNodeCanHaveTag(t *testing.T) { name: "multiple-tag-owners", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("user1@")), ptr.To(Username("user2@"))}, + Tag("tag:test"): Owners{new(Username("user1@")), new(Username("user2@"))}, }, }, node: nodes[1], @@ -2644,7 +2643,7 @@ func TestNodeCanHaveTag(t *testing.T) { "group:testgroup": Usernames{"user1@", "user2@"}, }, TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Group("group:testgroup"))}, + Tag("tag:test"): Owners{new(Group("group:testgroup"))}, }, }, node: nodes[1], @@ -2658,7 +2657,7 @@ func TestNodeCanHaveTag(t *testing.T) { "group:testgroup": Usernames{"invalid"}, }, TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Group("group:testgroup"))}, + Tag("tag:test"): Owners{new(Group("group:testgroup"))}, }, }, node: nodes[0], @@ -2670,7 +2669,7 @@ func TestNodeCanHaveTag(t *testing.T) { name: "node-cannot-have-tag", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("user2@"))}, + Tag("tag:test"): Owners{new(Username("user2@"))}, }, }, node: nodes[0], @@ -2681,7 +2680,7 @@ func TestNodeCanHaveTag(t *testing.T) { name: "node-with-unauthorized-tag-different-user", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:prod"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:prod"): Owners{new(Username("user1@"))}, }, }, node: nodes[2], // user3's node @@ -2692,8 +2691,8 @@ func TestNodeCanHaveTag(t *testing.T) { name: "node-with-multiple-tags-one-unauthorized", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:web"): Owners{ptr.To(Username("user1@"))}, - Tag("tag:database"): Owners{ptr.To(Username("user2@"))}, + Tag("tag:web"): Owners{new(Username("user1@"))}, + Tag("tag:database"): Owners{new(Username("user2@"))}, }, }, node: nodes[0], // user1's node @@ -2713,7 +2712,7 @@ func TestNodeCanHaveTag(t *testing.T) { name: "tag-not-in-tagowners", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:prod"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:prod"): Owners{new(Username("user1@"))}, }, }, node: nodes[0], @@ -2726,13 +2725,13 @@ func TestNodeCanHaveTag(t *testing.T) { name: "node-without-ip-user-owns-tag", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:test"): Owners{new(Username("user1@"))}, }, }, node: &types.Node{ // No IPv4 or IPv6 - simulates new node registration User: &users[0], - UserID: ptr.To(users[0].ID), + UserID: new(users[0].ID), }, tag: "tag:test", want: true, // Should succeed via user-based fallback @@ -2741,13 +2740,13 @@ func TestNodeCanHaveTag(t *testing.T) { name: "node-without-ip-user-does-not-own-tag", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("user2@"))}, + Tag("tag:test"): Owners{new(Username("user2@"))}, }, }, node: &types.Node{ // No IPv4 or IPv6 - simulates new node registration User: &users[0], // user1, but tag owned by user2 - UserID: ptr.To(users[0].ID), + UserID: new(users[0].ID), }, tag: "tag:test", want: false, // user1 does not own tag:test @@ -2759,13 +2758,13 @@ func TestNodeCanHaveTag(t *testing.T) { "group:admins": Usernames{"user1@", "user2@"}, }, TagOwners: TagOwners{ - Tag("tag:admin"): Owners{ptr.To(Group("group:admins"))}, + Tag("tag:admin"): Owners{new(Group("group:admins"))}, }, }, node: &types.Node{ // No IPv4 or IPv6 - simulates new node registration User: &users[1], // user2 is in group:admins - UserID: ptr.To(users[1].ID), + UserID: new(users[1].ID), }, tag: "tag:admin", want: true, // Should succeed via group membership @@ -2777,13 +2776,13 @@ func TestNodeCanHaveTag(t *testing.T) { "group:admins": Usernames{"user1@"}, }, TagOwners: TagOwners{ - Tag("tag:admin"): Owners{ptr.To(Group("group:admins"))}, + Tag("tag:admin"): Owners{new(Group("group:admins"))}, }, }, node: &types.Node{ // No IPv4 or IPv6 - simulates new node registration User: &users[1], // user2 is NOT in group:admins - UserID: ptr.To(users[1].ID), + UserID: new(users[1].ID), }, tag: "tag:admin", want: false, // user2 is not in group:admins @@ -2792,7 +2791,7 @@ func TestNodeCanHaveTag(t *testing.T) { name: "node-without-ip-no-user", policy: &Policy{ TagOwners: TagOwners{ - Tag("tag:test"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:test"): Owners{new(Username("user1@"))}, }, }, node: &types.Node{ @@ -2809,14 +2808,14 @@ func TestNodeCanHaveTag(t *testing.T) { }, TagOwners: TagOwners{ Tag("tag:server"): Owners{ - ptr.To(Username("user1@")), - ptr.To(Group("group:ops")), + new(Username("user1@")), + new(Group("group:ops")), }, }, }, node: &types.Node{ User: &users[0], // user1 directly owns the tag - UserID: ptr.To(users[0].ID), + UserID: new(users[0].ID), }, tag: "tag:server", want: true, @@ -2829,14 +2828,14 @@ func TestNodeCanHaveTag(t *testing.T) { }, TagOwners: TagOwners{ Tag("tag:server"): Owners{ - ptr.To(Username("user1@")), - ptr.To(Group("group:ops")), + new(Username("user1@")), + new(Group("group:ops")), }, }, }, node: &types.Node{ User: &users[2], // user3 is in group:ops - UserID: ptr.To(users[2].ID), + UserID: new(users[2].ID), }, tag: "tag:server", want: true, @@ -2881,14 +2880,14 @@ func TestUserMatchesOwner(t *testing.T) { name: "username-match", policy: &Policy{}, user: users[0], - owner: ptr.To(Username("user1@")), + owner: new(Username("user1@")), want: true, }, { name: "username-no-match", policy: &Policy{}, user: users[0], - owner: ptr.To(Username("user2@")), + owner: new(Username("user2@")), want: false, }, { @@ -2899,7 +2898,7 @@ func TestUserMatchesOwner(t *testing.T) { }, }, user: users[1], // user2 is in group:admins - owner: ptr.To(Group("group:admins")), + owner: new(Group("group:admins")), want: true, }, { @@ -2910,7 +2909,7 @@ func TestUserMatchesOwner(t *testing.T) { }, }, user: users[1], // user2 is NOT in group:admins - owner: ptr.To(Group("group:admins")), + owner: new(Group("group:admins")), want: false, }, { @@ -2919,7 +2918,7 @@ func TestUserMatchesOwner(t *testing.T) { Groups: Groups{}, }, user: users[0], - owner: ptr.To(Group("group:undefined")), + owner: new(Group("group:undefined")), want: false, }, { @@ -3261,20 +3260,20 @@ func TestFlattenTagOwners(t *testing.T) { { name: "tag-owns-tag", input: TagOwners{ - Tag("tag:bigbrother"): Owners{ptr.To(Group("group:user1"))}, - Tag("tag:smallbrother"): Owners{ptr.To(Tag("tag:bigbrother"))}, + Tag("tag:bigbrother"): Owners{new(Group("group:user1"))}, + Tag("tag:smallbrother"): Owners{new(Tag("tag:bigbrother"))}, }, want: TagOwners{ - Tag("tag:bigbrother"): Owners{ptr.To(Group("group:user1"))}, - Tag("tag:smallbrother"): Owners{ptr.To(Group("group:user1"))}, + Tag("tag:bigbrother"): Owners{new(Group("group:user1"))}, + Tag("tag:smallbrother"): Owners{new(Group("group:user1"))}, }, wantErr: "", }, { name: "circular-reference", input: TagOwners{ - Tag("tag:a"): Owners{ptr.To(Tag("tag:b"))}, - Tag("tag:b"): Owners{ptr.To(Tag("tag:a"))}, + Tag("tag:a"): Owners{new(Tag("tag:b"))}, + Tag("tag:b"): Owners{new(Tag("tag:a"))}, }, want: nil, wantErr: "circular reference detected: tag:a -> tag:b", @@ -3282,83 +3281,83 @@ func TestFlattenTagOwners(t *testing.T) { { name: "mixed-owners", input: TagOwners{ - Tag("tag:x"): Owners{ptr.To(Username("user1@")), ptr.To(Tag("tag:y"))}, - Tag("tag:y"): Owners{ptr.To(Username("user2@"))}, + Tag("tag:x"): Owners{new(Username("user1@")), new(Tag("tag:y"))}, + Tag("tag:y"): Owners{new(Username("user2@"))}, }, want: TagOwners{ - Tag("tag:x"): Owners{ptr.To(Username("user1@")), ptr.To(Username("user2@"))}, - Tag("tag:y"): Owners{ptr.To(Username("user2@"))}, + Tag("tag:x"): Owners{new(Username("user1@")), new(Username("user2@"))}, + Tag("tag:y"): Owners{new(Username("user2@"))}, }, wantErr: "", }, { name: "mixed-dupe-owners", input: TagOwners{ - Tag("tag:x"): Owners{ptr.To(Username("user1@")), ptr.To(Tag("tag:y"))}, - Tag("tag:y"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:x"): Owners{new(Username("user1@")), new(Tag("tag:y"))}, + Tag("tag:y"): Owners{new(Username("user1@"))}, }, want: TagOwners{ - Tag("tag:x"): Owners{ptr.To(Username("user1@"))}, - Tag("tag:y"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:x"): Owners{new(Username("user1@"))}, + Tag("tag:y"): Owners{new(Username("user1@"))}, }, wantErr: "", }, { name: "no-tag-owners", input: TagOwners{ - Tag("tag:solo"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:solo"): Owners{new(Username("user1@"))}, }, want: TagOwners{ - Tag("tag:solo"): Owners{ptr.To(Username("user1@"))}, + Tag("tag:solo"): Owners{new(Username("user1@"))}, }, wantErr: "", }, { name: "tag-long-owner-chain", input: TagOwners{ - Tag("tag:a"): Owners{ptr.To(Group("group:user1"))}, - Tag("tag:b"): Owners{ptr.To(Tag("tag:a"))}, - Tag("tag:c"): Owners{ptr.To(Tag("tag:b"))}, - Tag("tag:d"): Owners{ptr.To(Tag("tag:c"))}, - Tag("tag:e"): Owners{ptr.To(Tag("tag:d"))}, - Tag("tag:f"): Owners{ptr.To(Tag("tag:e"))}, - Tag("tag:g"): Owners{ptr.To(Tag("tag:f"))}, + Tag("tag:a"): Owners{new(Group("group:user1"))}, + Tag("tag:b"): Owners{new(Tag("tag:a"))}, + Tag("tag:c"): Owners{new(Tag("tag:b"))}, + Tag("tag:d"): Owners{new(Tag("tag:c"))}, + Tag("tag:e"): Owners{new(Tag("tag:d"))}, + Tag("tag:f"): Owners{new(Tag("tag:e"))}, + Tag("tag:g"): Owners{new(Tag("tag:f"))}, }, want: TagOwners{ - Tag("tag:a"): Owners{ptr.To(Group("group:user1"))}, - Tag("tag:b"): Owners{ptr.To(Group("group:user1"))}, - Tag("tag:c"): Owners{ptr.To(Group("group:user1"))}, - Tag("tag:d"): Owners{ptr.To(Group("group:user1"))}, - Tag("tag:e"): Owners{ptr.To(Group("group:user1"))}, - Tag("tag:f"): Owners{ptr.To(Group("group:user1"))}, - Tag("tag:g"): Owners{ptr.To(Group("group:user1"))}, + Tag("tag:a"): Owners{new(Group("group:user1"))}, + Tag("tag:b"): Owners{new(Group("group:user1"))}, + Tag("tag:c"): Owners{new(Group("group:user1"))}, + Tag("tag:d"): Owners{new(Group("group:user1"))}, + Tag("tag:e"): Owners{new(Group("group:user1"))}, + Tag("tag:f"): Owners{new(Group("group:user1"))}, + Tag("tag:g"): Owners{new(Group("group:user1"))}, }, wantErr: "", }, { name: "tag-long-circular-chain", input: TagOwners{ - Tag("tag:a"): Owners{ptr.To(Tag("tag:g"))}, - Tag("tag:b"): Owners{ptr.To(Tag("tag:a"))}, - Tag("tag:c"): Owners{ptr.To(Tag("tag:b"))}, - Tag("tag:d"): Owners{ptr.To(Tag("tag:c"))}, - Tag("tag:e"): Owners{ptr.To(Tag("tag:d"))}, - Tag("tag:f"): Owners{ptr.To(Tag("tag:e"))}, - Tag("tag:g"): Owners{ptr.To(Tag("tag:f"))}, + Tag("tag:a"): Owners{new(Tag("tag:g"))}, + Tag("tag:b"): Owners{new(Tag("tag:a"))}, + Tag("tag:c"): Owners{new(Tag("tag:b"))}, + Tag("tag:d"): Owners{new(Tag("tag:c"))}, + Tag("tag:e"): Owners{new(Tag("tag:d"))}, + Tag("tag:f"): Owners{new(Tag("tag:e"))}, + Tag("tag:g"): Owners{new(Tag("tag:f"))}, }, wantErr: "circular reference detected: tag:a -> tag:b -> tag:c -> tag:d -> tag:e -> tag:f -> tag:g", }, { name: "undefined-tag-reference", input: TagOwners{ - Tag("tag:a"): Owners{ptr.To(Tag("tag:nonexistent"))}, + Tag("tag:a"): Owners{new(Tag("tag:nonexistent"))}, }, wantErr: `tag "tag:a" references undefined tag "tag:nonexistent"`, }, { name: "tag-with-empty-owners-is-valid", input: TagOwners{ - Tag("tag:a"): Owners{ptr.To(Tag("tag:b"))}, + Tag("tag:a"): Owners{new(Tag("tag:b"))}, Tag("tag:b"): Owners{}, // empty owners but exists }, want: TagOwners{ diff --git a/hscontrol/state/ephemeral_test.go b/hscontrol/state/ephemeral_test.go index 632af13c..9f713b3d 100644 --- a/hscontrol/state/ephemeral_test.go +++ b/hscontrol/state/ephemeral_test.go @@ -8,7 +8,6 @@ import ( "github.com/juanfont/headscale/hscontrol/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "tailscale.com/types/ptr" ) // TestEphemeralNodeDeleteWithConcurrentUpdate tests the race condition where UpdateNode and DeleteNode @@ -50,7 +49,7 @@ func TestEphemeralNodeDeleteWithConcurrentUpdate(t *testing.T) { // Goroutine 1: UpdateNode (simulates UpdateNodeFromMapRequest) go func() { updatedNode, updateOk = store.UpdateNode(node.ID, func(n *types.Node) { - n.LastSeen = ptr.To(time.Now()) + n.LastSeen = new(time.Now()) }) done <- true }() @@ -106,7 +105,7 @@ func TestUpdateNodeReturnsInvalidWhenDeletedInSameBatch(t *testing.T) { // Start UpdateNode in goroutine - it will queue and wait for batch go func() { node, ok := store.UpdateNode(node.ID, func(n *types.Node) { - n.LastSeen = ptr.To(time.Now()) + n.LastSeen = new(time.Now()) }) resultChan <- struct { node types.NodeView @@ -156,7 +155,7 @@ func TestPersistNodeToDBPreventsRaceCondition(t *testing.T) { // Simulate UpdateNode being called updatedNode, ok := store.UpdateNode(node.ID, func(n *types.Node) { - n.LastSeen = ptr.To(time.Now()) + n.LastSeen = new(time.Now()) }) require.True(t, ok, "UpdateNode should succeed") require.True(t, updatedNode.Valid(), "UpdateNode should return valid node") @@ -221,7 +220,7 @@ func TestEphemeralNodeLogoutRaceCondition(t *testing.T) { // Goroutine 1: UpdateNode (simulates UpdateNodeFromMapRequest) go func() { updatedNode, updateOk = store.UpdateNode(ephemeralNode.ID, func(n *types.Node) { - n.LastSeen = ptr.To(time.Now()) + n.LastSeen = new(time.Now()) }) done <- true }() @@ -294,7 +293,7 @@ func TestUpdateNodeFromMapRequestEphemeralLogoutSequence(t *testing.T) { go func() { node, ok := store.UpdateNode(ephemeralNode.ID, func(n *types.Node) { - n.LastSeen = ptr.To(time.Now()) + n.LastSeen = new(time.Now()) endpoint := netip.MustParseAddrPort("10.0.0.1:41641") n.Endpoints = []netip.AddrPort{endpoint} }) @@ -363,7 +362,7 @@ func TestUpdateNodeDeletedInSameBatchReturnsInvalid(t *testing.T) { go func() { updatedNode, ok := store.UpdateNode(node.ID, func(n *types.Node) { - n.LastSeen = ptr.To(time.Now()) + n.LastSeen = new(time.Now()) }) updateDone <- struct { node types.NodeView @@ -417,7 +416,7 @@ func TestPersistNodeToDBChecksNodeStoreBeforePersist(t *testing.T) { // UpdateNode returns a node updatedNode, ok := store.UpdateNode(ephemeralNode.ID, func(n *types.Node) { - n.LastSeen = ptr.To(time.Now()) + n.LastSeen = new(time.Now()) }) require.True(t, ok, "UpdateNode should succeed") require.True(t, updatedNode.Valid(), "updated node should be valid") diff --git a/hscontrol/state/maprequest_test.go b/hscontrol/state/maprequest_test.go index 99f781d4..0fa81318 100644 --- a/hscontrol/state/maprequest_test.go +++ b/hscontrol/state/maprequest_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/require" "tailscale.com/tailcfg" "tailscale.com/types/key" - "tailscale.com/types/ptr" ) func TestNetInfoFromMapRequest(t *testing.T) { @@ -149,7 +148,7 @@ func createTestNodeSimple(id types.NodeID) *types.Node { node := &types.Node{ ID: id, Hostname: "test-node", - UserID: ptr.To(uint(id)), + UserID: new(uint(id)), User: &user, MachineKey: machineKey.Public(), NodeKey: nodeKey.Public(), diff --git a/hscontrol/state/node_store_test.go b/hscontrol/state/node_store_test.go index 3d6184ba..745850cc 100644 --- a/hscontrol/state/node_store_test.go +++ b/hscontrol/state/node_store_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "tailscale.com/types/key" - "tailscale.com/types/ptr" ) func TestSnapshotFromNodes(t *testing.T) { @@ -174,7 +173,7 @@ func createTestNode(nodeID types.NodeID, userID uint, username, hostname string) DiscoKey: discoKey.Public(), Hostname: hostname, GivenName: hostname, - UserID: ptr.To(userID), + UserID: new(userID), User: &types.User{ Name: username, DisplayName: username, @@ -856,7 +855,7 @@ func createConcurrentTestNode(id types.NodeID, hostname string) types.Node { Hostname: hostname, MachineKey: machineKey.Public(), NodeKey: nodeKey.Public(), - UserID: ptr.To(uint(1)), + UserID: new(uint(1)), User: &types.User{ Name: "concurrent-test-user", }, diff --git a/hscontrol/types/node_tags_test.go b/hscontrol/types/node_tags_test.go index 72598b3c..97e01b2a 100644 --- a/hscontrol/types/node_tags_test.go +++ b/hscontrol/types/node_tags_test.go @@ -6,7 +6,6 @@ import ( "github.com/juanfont/headscale/hscontrol/util" "github.com/stretchr/testify/assert" "gorm.io/gorm" - "tailscale.com/types/ptr" ) // TestNodeIsTagged tests the IsTagged() method for determining if a node is tagged. @@ -69,7 +68,7 @@ func TestNodeIsTagged(t *testing.T) { { name: "node with user and no tags - not tagged", node: Node{ - UserID: ptr.To(uint(42)), + UserID: new(uint(42)), Tags: []string{}, }, want: false, @@ -112,7 +111,7 @@ func TestNodeViewIsTagged(t *testing.T) { { name: "user-owned node", node: Node{ - UserID: ptr.To(uint(1)), + UserID: new(uint(1)), }, want: false, }, @@ -223,7 +222,7 @@ func TestNodeTagsImmutableAfterRegistration(t *testing.T) { // Test that a user-owned node is not tagged userNode := Node{ ID: 2, - UserID: ptr.To(uint(42)), + UserID: new(uint(42)), Tags: []string{}, RegisterMethod: util.RegisterMethodOIDC, } @@ -243,7 +242,7 @@ func TestNodeOwnershipModel(t *testing.T) { name: "tagged node has tags, UserID is informational", node: Node{ ID: 1, - UserID: ptr.To(uint(5)), // "created by" user 5 + UserID: new(uint(5)), // "created by" user 5 Tags: []string{"tag:server"}, }, wantIsTagged: true, @@ -253,7 +252,7 @@ func TestNodeOwnershipModel(t *testing.T) { name: "user-owned node has no tags", node: Node{ ID: 2, - UserID: ptr.To(uint(5)), + UserID: new(uint(5)), Tags: []string{}, }, wantIsTagged: false, @@ -265,7 +264,7 @@ func TestNodeOwnershipModel(t *testing.T) { name: "node with only authkey tags - not tagged (tags should be copied)", node: Node{ ID: 3, - UserID: ptr.To(uint(5)), // "created by" user 5 + UserID: new(uint(5)), // "created by" user 5 AuthKey: &PreAuthKey{ Tags: []string{"tag:database"}, }, diff --git a/hscontrol/types/users.go b/hscontrol/types/users.go index ec40492b..27aff519 100644 --- a/hscontrol/types/users.go +++ b/hscontrol/types/users.go @@ -93,7 +93,7 @@ func (u *User) StringID() string { } // TypedID returns a pointer to the user's ID as a UserID type. -// This is a convenience method to avoid ugly casting like ptr.To(types.UserID(user.ID)). +// This is a convenience method to avoid ugly casting like new(types.UserID(user.ID)). func (u *User) TypedID() *UserID { uid := UserID(u.ID) return &uid diff --git a/integration/acl_test.go b/integration/acl_test.go index c746f900..7a33240b 100644 --- a/integration/acl_test.go +++ b/integration/acl_test.go @@ -20,7 +20,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) var veryLargeDestination = []policyv2.AliasWithPorts{ @@ -1284,9 +1283,9 @@ func TestACLAutogroupMember(t *testing.T) { ACLs: []policyv2.ACL{ { Action: "accept", - Sources: []policyv2.Alias{ptr.To(policyv2.AutoGroupMember)}, + Sources: []policyv2.Alias{new(policyv2.AutoGroupMember)}, Destinations: []policyv2.AliasWithPorts{ - aliasWithPorts(ptr.To(policyv2.AutoGroupMember), tailcfg.PortRangeAny), + aliasWithPorts(new(policyv2.AutoGroupMember), tailcfg.PortRangeAny), }, }, }, @@ -1372,9 +1371,9 @@ func TestACLAutogroupTagged(t *testing.T) { ACLs: []policyv2.ACL{ { Action: "accept", - Sources: []policyv2.Alias{ptr.To(policyv2.AutoGroupTagged)}, + Sources: []policyv2.Alias{new(policyv2.AutoGroupTagged)}, Destinations: []policyv2.AliasWithPorts{ - aliasWithPorts(ptr.To(policyv2.AutoGroupTagged), tailcfg.PortRangeAny), + aliasWithPorts(new(policyv2.AutoGroupTagged), tailcfg.PortRangeAny), }, }, }, @@ -1657,9 +1656,9 @@ func TestACLAutogroupSelf(t *testing.T) { ACLs: []policyv2.ACL{ { Action: "accept", - Sources: []policyv2.Alias{ptr.To(policyv2.AutoGroupMember)}, + Sources: []policyv2.Alias{new(policyv2.AutoGroupMember)}, Destinations: []policyv2.AliasWithPorts{ - aliasWithPorts(ptr.To(policyv2.AutoGroupSelf), tailcfg.PortRangeAny), + aliasWithPorts(new(policyv2.AutoGroupSelf), tailcfg.PortRangeAny), }, }, { @@ -1956,9 +1955,9 @@ func TestACLPolicyPropagationOverTime(t *testing.T) { ACLs: []policyv2.ACL{ { Action: "accept", - Sources: []policyv2.Alias{ptr.To(policyv2.AutoGroupMember)}, + Sources: []policyv2.Alias{new(policyv2.AutoGroupMember)}, Destinations: []policyv2.AliasWithPorts{ - aliasWithPorts(ptr.To(policyv2.AutoGroupSelf), tailcfg.PortRangeAny), + aliasWithPorts(new(policyv2.AutoGroupSelf), tailcfg.PortRangeAny), }, }, }, diff --git a/integration/api_auth_test.go b/integration/api_auth_test.go index df5f2455..223e4c8b 100644 --- a/integration/api_auth_test.go +++ b/integration/api_auth_test.go @@ -356,13 +356,13 @@ func TestAPIAuthenticationBypassCurl(t *testing.T) { lines := strings.Split(curlOutput, "\n") var httpCode string - var responseBody string + var responseBody strings.Builder for _, line := range lines { if after, ok := strings.CutPrefix(line, "HTTP_CODE:"); ok { httpCode = after } else { - responseBody += line + responseBody.WriteString(line) } } @@ -372,7 +372,7 @@ func TestAPIAuthenticationBypassCurl(t *testing.T) { // Should contain user data var response v1.ListUsersResponse - err = protojson.Unmarshal([]byte(responseBody), &response) + err = protojson.Unmarshal([]byte(responseBody.String()), &response) assert.NoError(t, err, "Response should be valid protobuf JSON") users := response.GetUsers() assert.Len(t, users, 2, "Should have 2 users") diff --git a/integration/auth_key_test.go b/integration/auth_key_test.go index ba6a195b..9cf352bb 100644 --- a/integration/auth_key_test.go +++ b/integration/auth_key_test.go @@ -17,7 +17,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) func TestAuthKeyLogoutAndReloginSameUser(t *testing.T) { @@ -608,7 +607,7 @@ func TestAuthKeyLogoutAndReloginRoutesPreserved(t *testing.T) { }, AutoApprovers: policyv2.AutoApproverPolicy{ Routes: map[netip.Prefix]policyv2.AutoApprovers{ - netip.MustParsePrefix(advertiseRoute): {ptr.To(policyv2.Username(user + "@test.no"))}, + netip.MustParsePrefix(advertiseRoute): {new(policyv2.Username(user + "@test.no"))}, }, }, }, diff --git a/integration/ssh_test.go b/integration/ssh_test.go index 1ca291c0..04365eae 100644 --- a/integration/ssh_test.go +++ b/integration/ssh_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) func isSSHNoAccessStdError(stderr string) bool { @@ -482,10 +481,10 @@ func TestSSHAutogroupSelf(t *testing.T) { { Action: "accept", Sources: policyv2.SSHSrcAliases{ - ptr.To(policyv2.AutoGroupMember), + new(policyv2.AutoGroupMember), }, Destinations: policyv2.SSHDstAliases{ - ptr.To(policyv2.AutoGroupSelf), + new(policyv2.AutoGroupSelf), }, Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")}, },