diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 4b05f11f..1bf92c68 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -6,8 +6,7 @@ body: - type: checkboxes attributes: label: Is this a support request? - description: - This issue tracker is for bugs and feature requests only. If you need + description: This issue tracker is for bugs and feature requests only. If you need help, please use ask in our Discord community options: - label: This is not a support request @@ -15,8 +14,7 @@ body: - type: checkboxes attributes: label: Is there an existing issue for this? - description: - Please search to see if an issue already exists for the bug you + description: Please search to see if an issue already exists for the bug you encountered. options: - label: I have searched the existing issues diff --git a/.golangci.yaml b/.golangci.yaml index 5ebd698a..c6d8ff01 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -45,6 +45,16 @@ linters: Import "github.com/juanfont/headscale/hscontrol/util/zlog/zf" and use constants like zf.NodeID, zf.UserName, etc. Add new constants to hscontrol/util/zlog/zf/fields.go if needed. + # Forbid ptr.To - use Go 1.26 new(expr) instead + - pattern: 'ptr\.To\(' + msg: >- + ptr.To is forbidden. Use Go 1.26's new(expr) syntax instead. + Example: ptr.To(value) → new(value) + # Forbid tsaddr.SortPrefixes - use slices.SortFunc with netip.Prefix.Compare + - pattern: 'tsaddr\.SortPrefixes' + msg: >- + tsaddr.SortPrefixes is forbidden. Use Go 1.26's netip.Prefix.Compare instead. + Example: slices.SortFunc(prefixes, netip.Prefix.Compare) analyze-types: true gocritic: disabled-checks: diff --git a/.goreleaser.yml b/.goreleaser.yml index f77dfe38..a3622995 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -2,7 +2,7 @@ version: 2 before: hooks: - - go mod tidy -compat=1.25 + - go mod tidy -compat=1.26 - go mod vendor release: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ed869775..b05f2566 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,26 +43,12 @@ repos: entry: prettier --write --list-different language: system exclude: ^docs/ - types_or: - [ - javascript, - jsx, - ts, - tsx, - yaml, - json, - toml, - html, - css, - scss, - sass, - markdown, - ] + types_or: [javascript, jsx, ts, tsx, yaml, json, toml, html, css, scss, sass, markdown] # golangci-lint for Go code quality - id: golangci-lint name: golangci-lint - entry: nix develop --command golangci-lint run --new-from-rev=HEAD~1 --timeout=5m --fix + entry: golangci-lint run --new-from-rev=HEAD~1 --timeout=5m --fix language: system types: [go] pass_filenames: false diff --git a/Dockerfile.derper b/Dockerfile.derper index 395d9586..85376299 100644 --- a/Dockerfile.derper +++ b/Dockerfile.derper @@ -1,6 +1,6 @@ # For testing purposes only -FROM golang:alpine AS build-env +FROM golang:1.26rc2-alpine AS build-env WORKDIR /go/src diff --git a/Dockerfile.integration b/Dockerfile.integration index 341067e5..b810aa0a 100644 --- a/Dockerfile.integration +++ b/Dockerfile.integration @@ -2,7 +2,7 @@ # and are in no way endorsed by Headscale's maintainers as an # official nor supported release or distribution. -FROM docker.io/golang:1.25-trixie AS builder +FROM docker.io/golang:1.26rc2-trixie AS builder ARG VERSION=dev ENV GOPATH /go WORKDIR /go/src/headscale diff --git a/Dockerfile.tailscale-HEAD b/Dockerfile.tailscale-HEAD index 96edf72c..90816f5b 100644 --- a/Dockerfile.tailscale-HEAD +++ b/Dockerfile.tailscale-HEAD @@ -4,7 +4,7 @@ # This Dockerfile is more or less lifted from tailscale/tailscale # to ensure a similar build process when testing the HEAD of tailscale. -FROM golang:1.25-alpine AS build-env +FROM golang:1.26rc2-alpine AS build-env WORKDIR /go/src diff --git a/cmd/headscale/cli/serve.go b/cmd/headscale/cli/serve.go index e777b029..777739f9 100644 --- a/cmd/headscale/cli/serve.go +++ b/cmd/headscale/cli/serve.go @@ -23,8 +23,7 @@ var serveCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { app, err := newHeadscaleServerWithConfig() if err != nil { - var squibbleErr squibble.ValidationError - if errors.As(err, &squibbleErr) { + if squibbleErr, ok := errors.AsType[squibble.ValidationError](err); ok { fmt.Printf("SQLite schema failed to validate:\n") fmt.Println(squibbleErr.Diff) } diff --git a/cmd/hi/run.go b/cmd/hi/run.go index 132feb89..f21adb91 100644 --- a/cmd/hi/run.go +++ b/cmd/hi/run.go @@ -76,7 +76,7 @@ func detectGoVersion() string { content, err := os.ReadFile(goModPath) if err != nil { - return "1.25" + return "1.26rc2" } lines := splitLines(string(content)) @@ -91,7 +91,7 @@ func detectGoVersion() string { } } - return "1.25" + return "1.26rc2" } // splitLines splits a string into lines without using strings.Split. diff --git a/flake.nix b/flake.nix index 7e6214a9..65ad0497 100644 --- a/flake.nix +++ b/flake.nix @@ -26,7 +26,7 @@ overlays.default = _: prev: let pkgs = nixpkgs.legacyPackages.${prev.stdenv.hostPlatform.system}; - buildGo = pkgs.buildGo125Module; + buildGo = pkgs.buildGo126Module; vendorHash = "sha256-9BvphYDAxzwooyVokI3l+q1wRuRsWn/qM+NpWUgqJH0="; in { @@ -94,14 +94,46 @@ subPackages = [ "." ]; }; - # Upstream does not override buildGoModule properly, - # importing a specific module, so comment out for now. - # golangci-lint = prev.golangci-lint.override { - # buildGoModule = buildGo; - # }; - # golangci-lint-langserver = prev.golangci-lint.override { - # buildGoModule = buildGo; - # }; + # Build golangci-lint with Go 1.26 (upstream uses hardcoded Go version) + golangci-lint = buildGo rec { + pname = "golangci-lint"; + version = "2.8.0"; + + src = pkgs.fetchFromGitHub { + owner = "golangci"; + repo = "golangci-lint"; + rev = "v${version}"; + hash = "sha256-w6MAOirj8rPHYbKrW4gJeemXCS64fNtteV6IioqIQTQ="; + }; + + vendorHash = "sha256-/Vqo/yrmGh6XipELQ9NDtlMEO2a654XykmvnMs0BdrI="; + + subPackages = [ "cmd/golangci-lint" ]; + + nativeBuildInputs = [ pkgs.installShellFiles ]; + + ldflags = [ + "-s" + "-w" + "-X main.version=${version}" + "-X main.commit=v${version}" + "-X main.date=1970-01-01T00:00:00Z" + ]; + + postInstall = '' + for shell in bash zsh fish; do + HOME=$TMPDIR $out/bin/golangci-lint completion $shell > golangci-lint.$shell + installShellCompletion golangci-lint.$shell + done + ''; + + meta = { + description = "Fast linters runner for Go"; + homepage = "https://golangci-lint.run/"; + changelog = "https://github.com/golangci/golangci-lint/blob/v${version}/CHANGELOG.md"; + mainProgram = "golangci-lint"; + }; + }; # The package uses buildGo125Module, not the convention. # goreleaser = prev.goreleaser.override { @@ -132,7 +164,7 @@ overlays = [ self.overlays.default ]; inherit system; }; - buildDeps = with pkgs; [ git go_1_25 gnumake ]; + buildDeps = with pkgs; [ git go_1_26 gnumake ]; devDeps = with pkgs; buildDeps ++ [ diff --git a/go.mod b/go.mod index fec079bc..f42c7dca 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/juanfont/headscale -go 1.25.5 +go 1.26rc2 require ( github.com/arl/statsviz v0.8.0 diff --git a/hscontrol/auth.go b/hscontrol/auth.go index 1aa40c7b..fdc63461 100644 --- a/hscontrol/auth.go +++ b/hscontrol/auth.go @@ -16,7 +16,6 @@ import ( "gorm.io/gorm" "tailscale.com/tailcfg" "tailscale.com/types/key" - "tailscale.com/types/ptr" ) type AuthProvider interface { @@ -113,8 +112,7 @@ func (h *Headscale) handleRegister( resp, err := h.handleRegisterWithAuthKey(req, machineKey) if err != nil { // Preserve HTTPError types so they can be handled properly by the HTTP layer - var httpErr HTTPError - if errors.As(err, &httpErr) { + if httpErr, ok := errors.AsType[HTTPError](err); ok { return nil, httpErr } @@ -315,7 +313,7 @@ func (h *Headscale) reqToNewRegisterResponse( MachineKey: machineKey, NodeKey: req.NodeKey, Hostinfo: hostinfo, - LastSeen: ptr.To(time.Now()), + LastSeen: new(time.Now()), }, ) @@ -344,8 +342,7 @@ func (h *Headscale) handleRegisterWithAuthKey( return nil, NewHTTPError(http.StatusUnauthorized, "invalid pre auth key", nil) } - var perr types.PAKError - if errors.As(err, &perr) { + if perr, ok := errors.AsType[types.PAKError](err); ok { return nil, NewHTTPError(http.StatusUnauthorized, perr.Error(), nil) } @@ -443,7 +440,7 @@ func (h *Headscale) handleRegisterInteractive( MachineKey: machineKey, NodeKey: req.NodeKey, Hostinfo: hostinfo, - LastSeen: ptr.To(time.Now()), + LastSeen: new(time.Now()), }, ) diff --git a/hscontrol/db/db.go b/hscontrol/db/db.go index 0fc6bb68..c518502e 100644 --- a/hscontrol/db/db.go +++ b/hscontrol/db/db.go @@ -24,7 +24,6 @@ import ( "gorm.io/gorm" "gorm.io/gorm/logger" "gorm.io/gorm/schema" - "tailscale.com/net/tsaddr" "zgo.at/zcache/v2" ) @@ -172,7 +171,7 @@ AND auth_key_id NOT IN ( } for nodeID, routes := range nodeRoutes { - tsaddr.SortPrefixes(routes) + slices.SortFunc(routes, netip.Prefix.Compare) routes = slices.Compact(routes) data, _ := json.Marshal(routes) diff --git a/hscontrol/db/ip_test.go b/hscontrol/db/ip_test.go index 35798426..cf450e38 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 { @@ -491,8 +490,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 { @@ -500,17 +499,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.go b/hscontrol/db/node.go index 91276f50..98b73551 100644 --- a/hscontrol/db/node.go +++ b/hscontrol/db/node.go @@ -21,7 +21,6 @@ import ( "gorm.io/gorm" "tailscale.com/net/tsaddr" "tailscale.com/types/key" - "tailscale.com/types/ptr" ) const ( @@ -694,7 +693,7 @@ func (hsdb *HSDatabase) CreateNodeForTest(user *types.User, hostname ...string) Hostname: nodeName, UserID: &user.ID, RegisterMethod: util.RegisterMethodAuthKey, - AuthKeyID: ptr.To(pak.ID), + AuthKeyID: new(pak.ID), } err = hsdb.DB.Save(node).Error diff --git a/hscontrol/db/node_test.go b/hscontrol/db/node_test.go index a151baff..5991d494 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) @@ -444,7 +443,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 @@ -461,7 +460,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 @@ -660,7 +659,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{ @@ -670,7 +669,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 @@ -763,8 +762,8 @@ func TestNodeNaming(t *testing.T) { return 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) + _, _ = 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 }) diff --git a/hscontrol/db/preauth_keys_test.go b/hscontrol/db/preauth_keys_test.go index 7c5dcbd7..2f28d449 100644 --- a/hscontrol/db/preauth_keys_test.go +++ b/hscontrol/db/preauth_keys_test.go @@ -11,7 +11,6 @@ import ( "github.com/juanfont/headscale/hscontrol/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "tailscale.com/types/ptr" ) func TestCreatePreAuthKey(t *testing.T) { @@ -24,7 +23,7 @@ func TestCreatePreAuthKey(t *testing.T) { test: func(t *testing.T, db *HSDatabase) { t.Helper() - _, err := db.CreatePreAuthKey(ptr.To(types.UserID(12345)), true, false, nil, nil) + _, err := db.CreatePreAuthKey(new(types.UserID(12345)), true, false, nil, nil) assert.Error(t, err) }, }, @@ -127,7 +126,7 @@ func TestCannotDeleteAssignedPreAuthKey(t *testing.T) { Hostname: "testest", UserID: &user.ID, RegisterMethod: util.RegisterMethodAuthKey, - AuthKeyID: ptr.To(key.ID), + AuthKeyID: new(key.ID), } db.DB.Save(&node) 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/grpcv1.go b/hscontrol/grpcv1.go index 882d5ba6..073c6677 100644 --- a/hscontrol/grpcv1.go +++ b/hscontrol/grpcv1.go @@ -387,7 +387,7 @@ func (api headscaleV1APIServer) SetApprovedRoutes( newApproved = append(newApproved, prefix) } } - tsaddr.SortPrefixes(newApproved) + slices.SortFunc(newApproved, netip.Prefix.Compare) newApproved = slices.Compact(newApproved) node, nodeChange, err := api.h.state.SetApprovedRoutes(types.NodeID(request.GetNodeId()), newApproved) diff --git a/hscontrol/handlers.go b/hscontrol/handlers.go index 72891344..7c45f1ec 100644 --- a/hscontrol/handlers.go +++ b/hscontrol/handlers.go @@ -36,8 +36,7 @@ const ( // httpError logs an error and sends an HTTP error response with the given. func httpError(w http.ResponseWriter, err error) { - var herr HTTPError - if errors.As(err, &herr) { + if herr, ok := errors.AsType[HTTPError](err); ok { http.Error(w, herr.Msg, herr.Code) log.Error().Err(herr.Err).Int("code", herr.Code).Msgf("user msg: %s", herr.Msg) } else { diff --git a/hscontrol/mapper/batcher_lockfree.go b/hscontrol/mapper/batcher_lockfree.go index 1be722d4..10c84b50 100644 --- a/hscontrol/mapper/batcher_lockfree.go +++ b/hscontrol/mapper/batcher_lockfree.go @@ -16,7 +16,6 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) // LockFreeBatcher errors. @@ -151,7 +150,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 nlog.Debug().Caller().Msg("node disconnected from batcher, 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/mapper_test.go b/hscontrol/mapper/mapper_test.go index 368e1829..3349a155 100644 --- a/hscontrol/mapper/mapper_test.go +++ b/hscontrol/mapper/mapper_test.go @@ -10,7 +10,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 { @@ -47,7 +46,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/mapper/tail_test.go b/hscontrol/mapper/tail_test.go index 70572f5a..81c64115 100644 --- a/hscontrol/mapper/tail_test.go +++ b/hscontrol/mapper/tail_test.go @@ -13,7 +13,6 @@ import ( "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" - "tailscale.com/types/ptr" ) func TestTailNode(t *testing.T) { @@ -98,7 +97,7 @@ func TestTailNode(t *testing.T) { IPv4: iap("100.64.0.1"), Hostname: "mini", GivenName: "mini", - UserID: ptr.To(uint(0)), + UserID: new(uint(0)), User: &types.User{ Name: "mini", }, @@ -140,8 +139,8 @@ func TestTailNode(t *testing.T) { Addresses: []netip.Prefix{netip.MustParsePrefix("100.64.0.1/32")}, AllowedIPs: []netip.Prefix{ tsaddr.AllIPv4(), - netip.MustParsePrefix("192.168.0.0/24"), netip.MustParsePrefix("100.64.0.1/32"), + netip.MustParsePrefix("192.168.0.0/24"), tsaddr.AllIPv6(), }, PrimaryRoutes: []netip.Prefix{ diff --git a/hscontrol/noise.go b/hscontrol/noise.go index 1e974408..2880f33a 100644 --- a/hscontrol/noise.go +++ b/hscontrol/noise.go @@ -265,8 +265,7 @@ func (ns *noiseServer) NoiseRegistrationHandler( resp, err = ns.headscale.handleRegister(req.Context(), regReq, ns.conn.Peer()) if err != nil { - var httpErr HTTPError - if errors.As(err, &httpErr) { + if httpErr, ok := errors.AsType[HTTPError](err); ok { resp = &tailcfg.RegisterResponse{ Error: httpErr.Msg, } diff --git a/hscontrol/policy/policy.go b/hscontrol/policy/policy.go index e598349e..53cc241e 100644 --- a/hscontrol/policy/policy.go +++ b/hscontrol/policy/policy.go @@ -9,7 +9,6 @@ import ( "github.com/juanfont/headscale/hscontrol/util" "github.com/rs/zerolog/log" "github.com/samber/lo" - "tailscale.com/net/tsaddr" "tailscale.com/types/views" ) @@ -111,7 +110,7 @@ func ApproveRoutesWithPolicy(pm PolicyManager, nv types.NodeView, currentApprove } // Sort and deduplicate - tsaddr.SortPrefixes(newApproved) + slices.SortFunc(newApproved, netip.Prefix.Compare) newApproved = slices.Compact(newApproved) newApproved = lo.Filter(newApproved, func(route netip.Prefix, index int) bool { return route.IsValid() @@ -120,7 +119,7 @@ func ApproveRoutesWithPolicy(pm PolicyManager, nv types.NodeView, currentApprove // Sort the current approved for comparison sortedCurrent := make([]netip.Prefix, len(currentApproved)) copy(sortedCurrent, currentApproved) - tsaddr.SortPrefixes(sortedCurrent) + slices.SortFunc(sortedCurrent, netip.Prefix.Compare) // Only update if the routes actually changed if !slices.Equal(sortedCurrent, newApproved) { diff --git a/hscontrol/policy/policy_autoapprove_test.go b/hscontrol/policy/policy_autoapprove_test.go index a9b36f75..68266645 100644 --- a/hscontrol/policy/policy_autoapprove_test.go +++ b/hscontrol/policy/policy_autoapprove_test.go @@ -3,6 +3,7 @@ package policy import ( "fmt" "net/netip" + "slices" "testing" policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2" @@ -11,9 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/gorm" - "tailscale.com/net/tsaddr" "tailscale.com/types/key" - "tailscale.com/types/ptr" "tailscale.com/types/views" ) @@ -33,10 +32,10 @@ func TestApproveRoutesWithPolicy_NeverRemovesApprovedRoutes(t *testing.T) { MachineKey: key.NewMachine().Public(), NodeKey: key.NewNode().Public(), Hostname: "test-node", - UserID: ptr.To(user1.ID), - User: ptr.To(user1), + UserID: new(user1.ID), + User: new(user1), RegisterMethod: util.RegisterMethodAuthKey, - IPv4: ptr.To(netip.MustParseAddr("100.64.0.1")), + IPv4: new(netip.MustParseAddr("100.64.0.1")), Tags: []string{"tag:test"}, } @@ -45,10 +44,10 @@ func TestApproveRoutesWithPolicy_NeverRemovesApprovedRoutes(t *testing.T) { MachineKey: key.NewMachine().Public(), NodeKey: key.NewNode().Public(), Hostname: "other-node", - UserID: ptr.To(user2.ID), - User: ptr.To(user2), + UserID: new(user2.ID), + User: new(user2), RegisterMethod: util.RegisterMethodAuthKey, - IPv4: ptr.To(netip.MustParseAddr("100.64.0.2")), + IPv4: new(netip.MustParseAddr("100.64.0.2")), } // Create a policy that auto-approves specific routes @@ -195,7 +194,7 @@ func TestApproveRoutesWithPolicy_NeverRemovesApprovedRoutes(t *testing.T) { assert.Equal(t, tt.wantChanged, gotChanged, "changed flag mismatch: %s", tt.description) // Sort for comparison since ApproveRoutesWithPolicy sorts the results - tsaddr.SortPrefixes(tt.wantApproved) + slices.SortFunc(tt.wantApproved, netip.Prefix.Compare) assert.Equal(t, tt.wantApproved, gotApproved, "approved routes mismatch: %s", tt.description) // Verify that all previously approved routes are still present @@ -305,10 +304,10 @@ func TestApproveRoutesWithPolicy_NilAndEmptyCases(t *testing.T) { MachineKey: key.NewMachine().Public(), NodeKey: key.NewNode().Public(), Hostname: "testnode", - UserID: ptr.To(user.ID), - User: ptr.To(user), + UserID: new(user.ID), + User: new(user), RegisterMethod: util.RegisterMethodAuthKey, - IPv4: ptr.To(netip.MustParseAddr("100.64.0.1")), + IPv4: new(netip.MustParseAddr("100.64.0.1")), ApprovedRoutes: tt.currentApproved, } nodes := types.Nodes{&node} @@ -334,7 +333,7 @@ func TestApproveRoutesWithPolicy_NilAndEmptyCases(t *testing.T) { if tt.wantApproved == nil { assert.Nil(t, gotApproved, "expected nil approved routes") } else { - tsaddr.SortPrefixes(tt.wantApproved) + slices.SortFunc(tt.wantApproved, netip.Prefix.Compare) assert.Equal(t, tt.wantApproved, gotApproved, "approved routes mismatch") } }) diff --git a/hscontrol/policy/policy_route_approval_test.go b/hscontrol/policy/policy_route_approval_test.go index 70aa6a21..816a121d 100644 --- a/hscontrol/policy/policy_route_approval_test.go +++ b/hscontrol/policy/policy_route_approval_test.go @@ -13,7 +13,6 @@ import ( "gorm.io/gorm" "tailscale.com/tailcfg" "tailscale.com/types/key" - "tailscale.com/types/ptr" ) func TestApproveRoutesWithPolicy_NeverRemovesRoutes(t *testing.T) { @@ -92,8 +91,8 @@ func TestApproveRoutesWithPolicy_NeverRemovesRoutes(t *testing.T) { announcedRoutes: []netip.Prefix{}, // No routes announced anymore nodeUser: "test", wantApproved: []netip.Prefix{ - netip.MustParsePrefix("172.16.0.0/16"), netip.MustParsePrefix("10.0.0.0/24"), + netip.MustParsePrefix("172.16.0.0/16"), netip.MustParsePrefix("192.168.0.0/24"), }, wantChanged: false, @@ -124,8 +123,8 @@ func TestApproveRoutesWithPolicy_NeverRemovesRoutes(t *testing.T) { nodeUser: "test", nodeTags: []string{"tag:approved"}, wantApproved: []netip.Prefix{ - netip.MustParsePrefix("172.16.0.0/16"), // New tag-approved netip.MustParsePrefix("10.0.0.0/24"), // Previous approval preserved + netip.MustParsePrefix("172.16.0.0/16"), // New tag-approved }, wantChanged: true, }, @@ -168,13 +167,13 @@ func TestApproveRoutesWithPolicy_NeverRemovesRoutes(t *testing.T) { MachineKey: key.NewMachine().Public(), NodeKey: key.NewNode().Public(), Hostname: tt.nodeHostname, - UserID: ptr.To(user.ID), - User: ptr.To(user), + UserID: new(user.ID), + User: new(user), RegisterMethod: util.RegisterMethodAuthKey, Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: tt.announcedRoutes, }, - IPv4: ptr.To(netip.MustParseAddr("100.64.0.1")), + IPv4: new(netip.MustParseAddr("100.64.0.1")), ApprovedRoutes: tt.currentApproved, Tags: tt.nodeTags, } @@ -294,13 +293,13 @@ func TestApproveRoutesWithPolicy_EdgeCases(t *testing.T) { MachineKey: key.NewMachine().Public(), NodeKey: key.NewNode().Public(), Hostname: "testnode", - UserID: ptr.To(user.ID), - User: ptr.To(user), + UserID: new(user.ID), + User: new(user), RegisterMethod: util.RegisterMethodAuthKey, Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: tt.announcedRoutes, }, - IPv4: ptr.To(netip.MustParseAddr("100.64.0.1")), + IPv4: new(netip.MustParseAddr("100.64.0.1")), ApprovedRoutes: tt.currentApproved, } nodes := types.Nodes{&node} @@ -343,13 +342,13 @@ func TestApproveRoutesWithPolicy_NilPolicyManagerCase(t *testing.T) { MachineKey: key.NewMachine().Public(), NodeKey: key.NewNode().Public(), Hostname: "testnode", - UserID: ptr.To(user.ID), - User: ptr.To(user), + UserID: new(user.ID), + User: new(user), RegisterMethod: util.RegisterMethodAuthKey, Hostinfo: &tailcfg.Hostinfo{ RoutableIPs: announcedRoutes, }, - IPv4: ptr.To(netip.MustParseAddr("100.64.0.1")), + IPv4: new(netip.MustParseAddr("100.64.0.1")), ApprovedRoutes: currentApproved, } diff --git a/hscontrol/policy/policy_test.go b/hscontrol/policy/policy_test.go index 486fdec7..9c97e39c 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 { @@ -1084,21 +1083,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"}, } @@ -1106,8 +1105,8 @@ func TestSSHPolicyRules(t *testing.T) { nodeTaggedServer := types.Node{ Hostname: "tagged-server", IPv4: ap("100.64.0.5"), - UserID: ptr.To(uint(1)), - User: ptr.To(users[0]), + UserID: new(uint(1)), + User: new(users[0]), Tags: []string{"tag:server"}, } diff --git a/hscontrol/policy/policyutil/reduce_test.go b/hscontrol/policy/policyutil/reduce_test.go index ced422c4..aa02ac07 100644 --- a/hscontrol/policy/policyutil/reduce_test.go +++ b/hscontrol/policy/policyutil/reduce_test.go @@ -17,7 +17,6 @@ import ( "gorm.io/gorm" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" "tailscale.com/util/must" ) @@ -145,13 +144,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{}, @@ -192,7 +191,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"), @@ -203,7 +202,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{ @@ -274,19 +273,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(), }, @@ -335,7 +334,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(), }, @@ -344,12 +343,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{ @@ -442,7 +441,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(), }, @@ -451,12 +450,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{ @@ -549,7 +548,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")}, }, @@ -558,12 +557,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{ @@ -634,7 +633,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")}, }, @@ -643,12 +642,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{ @@ -711,7 +710,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")}, }, @@ -721,7 +720,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{ @@ -778,13 +777,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 7393b3b2..3d070a25 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 44490f29..cdf7c131 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. @@ -411,15 +410,15 @@ func TestCompileSSHPolicy_UserMapping(t *testing.T) { nodeTaggedServer := types.Node{ Hostname: "tagged-server", 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]), Tags: []string{"tag:server"}, } nodeTaggedDB := types.Node{ Hostname: "tagged-db", 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]), Tags: []string{"tag:database"}, } // Add untagged node for user2 - this will be the SSH source @@ -427,8 +426,8 @@ func TestCompileSSHPolicy_UserMapping(t *testing.T) { nodeUser2Untagged := types.Node{ Hostname: "user2-device", IPv4: createAddr("100.64.0.3"), - UserID: ptr.To(users[1].ID), - User: ptr.To(users[1]), + UserID: new(users[1].ID), + User: new(users[1]), } nodes := types.Nodes{&nodeTaggedServer, &nodeTaggedDB, &nodeUser2Untagged} @@ -658,15 +657,15 @@ func TestCompileSSHPolicy_CheckAction(t *testing.T) { nodeTaggedServer := types.Node{ Hostname: "tagged-server", 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]), Tags: []string{"tag:server"}, } 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{&nodeTaggedServer, &nodeUser2} @@ -723,15 +722,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} @@ -848,19 +847,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 @@ -983,11 +982,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 @@ -1005,8 +1004,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 @@ -1101,11 +1100,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 @@ -1128,10 +1127,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 @@ -1252,10 +1251,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{ @@ -1320,11 +1319,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{ @@ -1389,13 +1388,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{ @@ -1470,10 +1469,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{ @@ -1526,11 +1525,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{ @@ -1585,10 +1584,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{ @@ -1647,10 +1646,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{ @@ -1722,11 +1721,11 @@ func TestAutogroupSelfWithNonExistentUserInGroup(t *testing.T) { nodes := types.Nodes{ // superadmin's device - {ID: 1, User: ptr.To(users[0]), IPv4: ap("100.64.0.1"), Hostname: "superadmin-device"}, + {ID: 1, User: new(users[0]), IPv4: ap("100.64.0.1"), Hostname: "superadmin-device"}, // admin's device - {ID: 2, User: ptr.To(users[1]), IPv4: ap("100.64.0.2"), Hostname: "admin-device"}, + {ID: 2, User: new(users[1]), IPv4: ap("100.64.0.2"), Hostname: "admin-device"}, // direction's device - {ID: 3, User: ptr.To(users[2]), IPv4: ap("100.64.0.3"), Hostname: "direction-device"}, + {ID: 3, User: new(users[2]), IPv4: ap("100.64.0.3"), Hostname: "direction-device"}, // tagged servers {ID: 4, IPv4: ap("100.64.0.10"), Hostname: "common-server", Tags: []string{"tag:common"}}, {ID: 5, IPv4: ap("100.64.0.11"), Hostname: "tech-server", Tags: []string{"tag:tech"}}, diff --git a/hscontrol/policy/v2/policy_test.go b/hscontrol/policy/v2/policy_test.go index 2b2258a2..aa8e03ca 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) *types.Node { @@ -20,8 +19,8 @@ func node(name, ipv4, ipv6 string, user types.User) *types.Node { Hostname: name, IPv4: ap(ipv4), IPv6: ap(ipv6), - User: ptr.To(user), - UserID: ptr.To(user.ID), + User: new(user), + UserID: new(user.ID), } } @@ -463,8 +462,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{}, } @@ -474,8 +473,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{}, } @@ -543,8 +542,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{}, } @@ -553,8 +552,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{}, } @@ -653,8 +652,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"}, } @@ -664,8 +663,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} @@ -692,8 +691,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! } @@ -755,8 +754,8 @@ func TestAutogroupSelfWithAdminOverride(t *testing.T) { Hostname: "admin-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{}, } @@ -766,8 +765,8 @@ func TestAutogroupSelfWithAdminOverride(t *testing.T) { Hostname: "user1-server", 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:server"}, Hostinfo: &tailcfg.Hostinfo{}, } @@ -838,8 +837,8 @@ func TestAutogroupSelfSymmetricVisibility(t *testing.T) { Hostname: "device-a", 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{}, } @@ -849,8 +848,8 @@ func TestAutogroupSelfSymmetricVisibility(t *testing.T) { Hostname: "device-b", 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:web"}, Hostinfo: &tailcfg.Hostinfo{}, } @@ -928,8 +927,8 @@ func TestAutogroupSelfDoesNotBreakOtherUsersAccess(t *testing.T) { superadminDevice := &types.Node{ ID: 1, Hostname: "superadmin-laptop", - User: ptr.To(users[0]), - UserID: ptr.To(users[0].ID), + User: new(users[0]), + UserID: new(users[0].ID), IPv4: ap("100.64.0.1"), Hostinfo: &tailcfg.Hostinfo{}, } @@ -937,8 +936,8 @@ func TestAutogroupSelfDoesNotBreakOtherUsersAccess(t *testing.T) { adminDevice := &types.Node{ ID: 2, Hostname: "admin-laptop", - User: ptr.To(users[1]), - UserID: ptr.To(users[1].ID), + User: new(users[1]), + UserID: new(users[1].ID), IPv4: ap("100.64.0.2"), Hostinfo: &tailcfg.Hostinfo{}, } @@ -946,8 +945,8 @@ func TestAutogroupSelfDoesNotBreakOtherUsersAccess(t *testing.T) { directionDevice := &types.Node{ ID: 3, Hostname: "direction-laptop", - User: ptr.To(users[2]), - UserID: ptr.To(users[2].ID), + User: new(users[2]), + UserID: new(users[2].ID), IPv4: ap("100.64.0.3"), Hostinfo: &tailcfg.Hostinfo{}, } @@ -955,8 +954,8 @@ func TestAutogroupSelfDoesNotBreakOtherUsersAccess(t *testing.T) { commonServer := &types.Node{ ID: 4, Hostname: "common-server", - User: ptr.To(users[3]), - UserID: ptr.To(users[3].ID), + User: new(users[3]), + UserID: new(users[3].ID), IPv4: ap("100.64.0.4"), Tags: []string{"tag:common"}, Hostinfo: &tailcfg.Hostinfo{}, @@ -965,8 +964,8 @@ func TestAutogroupSelfDoesNotBreakOtherUsersAccess(t *testing.T) { techServer := &types.Node{ ID: 5, Hostname: "tech-server", - User: ptr.To(users[3]), - UserID: ptr.To(users[3].ID), + User: new(users[3]), + UserID: new(users[3].ID), IPv4: ap("100.64.0.5"), Tags: []string{"tag:tech"}, Hostinfo: &tailcfg.Hostinfo{}, @@ -975,8 +974,8 @@ func TestAutogroupSelfDoesNotBreakOtherUsersAccess(t *testing.T) { privilegedServer := &types.Node{ ID: 6, Hostname: "privileged-server", - User: ptr.To(users[3]), - UserID: ptr.To(users[3].ID), + User: new(users[3]), + UserID: new(users[3].ID), IPv4: ap("100.64.0.6"), Tags: []string{"tag:privileged"}, Hostinfo: &tailcfg.Hostinfo{}, @@ -1088,8 +1087,8 @@ func TestEmptyFilterNodesStillVisible(t *testing.T) { adminDevice := &types.Node{ ID: 1, Hostname: "admin-laptop", - User: ptr.To(users[0]), - UserID: ptr.To(users[0].ID), + User: new(users[0]), + UserID: new(users[0].ID), IPv4: ap("100.64.0.1"), Hostinfo: &tailcfg.Hostinfo{}, } @@ -1099,8 +1098,8 @@ func TestEmptyFilterNodesStillVisible(t *testing.T) { taggedServer := &types.Node{ ID: 2, Hostname: "server", - User: ptr.To(users[1]), - UserID: ptr.To(users[1].ID), + User: new(users[1]), + UserID: new(users[1].ID), IPv4: ap("100.64.0.2"), Tags: []string{"tag:server"}, Hostinfo: &tailcfg.Hostinfo{}, @@ -1157,8 +1156,8 @@ func TestAutogroupSelfCombinedWithTags(t *testing.T) { adminLaptop := &types.Node{ ID: 1, Hostname: "admin-laptop", - User: ptr.To(users[0]), - UserID: ptr.To(users[0].ID), + User: new(users[0]), + UserID: new(users[0].ID), IPv4: ap("100.64.0.1"), Hostinfo: &tailcfg.Hostinfo{}, } @@ -1166,8 +1165,8 @@ func TestAutogroupSelfCombinedWithTags(t *testing.T) { adminPhone := &types.Node{ ID: 2, Hostname: "admin-phone", - User: ptr.To(users[0]), - UserID: ptr.To(users[0].ID), + User: new(users[0]), + UserID: new(users[0].ID), IPv4: ap("100.64.0.2"), Hostinfo: &tailcfg.Hostinfo{}, } @@ -1176,8 +1175,8 @@ func TestAutogroupSelfCombinedWithTags(t *testing.T) { webServer := &types.Node{ ID: 3, Hostname: "web-server", - User: ptr.To(users[1]), - UserID: ptr.To(users[1].ID), + User: new(users[1]), + UserID: new(users[1].ID), IPv4: ap("100.64.0.3"), Tags: []string{"tag:web"}, Hostinfo: &tailcfg.Hostinfo{}, @@ -1252,8 +1251,8 @@ func TestIssue2990SameUserTaggedDevice(t *testing.T) { node1 := &types.Node{ ID: 1, Hostname: "node1", - User: ptr.To(users[0]), - UserID: ptr.To(users[0].ID), + User: new(users[0]), + UserID: new(users[0].ID), IPv4: ap("100.64.0.1"), IPv6: ap("fd7a:115c:a1e0::1"), Hostinfo: &tailcfg.Hostinfo{}, @@ -1263,8 +1262,8 @@ func TestIssue2990SameUserTaggedDevice(t *testing.T) { node2 := &types.Node{ ID: 2, Hostname: "node2", - User: ptr.To(users[0]), - UserID: ptr.To(users[0].ID), + User: new(users[0]), + UserID: new(users[0].ID), IPv4: ap("100.64.0.2"), IPv6: ap("fd7a:115c:a1e0::2"), Tags: []string{"tag:admin"}, diff --git a/hscontrol/policy/v2/types.go b/hscontrol/policy/v2/types.go index c9d6b7d5..8785bed0 100644 --- a/hscontrol/policy/v2/types.go +++ b/hscontrol/policy/v2/types.go @@ -16,7 +16,6 @@ import ( "go4.org/netipx" "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" "tailscale.com/types/views" "tailscale.com/util/multierr" "tailscale.com/util/slicesx" @@ -762,17 +761,17 @@ func parseAlias(vs string) (Alias, error) { case isWildcard(vs): return Wildcard, nil case isUser(vs): - return ptr.To(Username(vs)), nil + return new(Username(vs)), nil case isGroup(vs): - return ptr.To(Group(vs)), nil + return new(Group(vs)), nil case isTag(vs): - return ptr.To(Tag(vs)), nil + return new(Tag(vs)), nil case isAutoGroup(vs): - return ptr.To(AutoGroup(vs)), nil + return new(AutoGroup(vs)), nil } if isHost(vs) { - return ptr.To(Host(vs)), nil + return new(Host(vs)), nil } return nil, fmt.Errorf("%w: %q", ErrInvalidAlias, vs) @@ -933,11 +932,11 @@ func (aa AutoApprovers) MarshalJSON() ([]byte, error) { func parseAutoApprover(s string) (AutoApprover, error) { switch { case isUser(s): - return ptr.To(Username(s)), nil + return new(Username(s)), nil case isGroup(s): - return ptr.To(Group(s)), nil + return new(Group(s)), nil case isTag(s): - return ptr.To(Tag(s)), nil + return new(Tag(s)), nil } return nil, fmt.Errorf("%w: %q", ErrInvalidAutoApprover, s) @@ -1027,11 +1026,11 @@ func (o Owners) MarshalJSON() ([]byte, error) { func parseOwner(s string) (Owner, error) { switch { case isUser(s): - return ptr.To(Username(s)), nil + return new(Username(s)), nil case isGroup(s): - return ptr.To(Group(s)), nil + return new(Group(s)), nil case isTag(s): - return ptr.To(Tag(s)), nil + return new(Tag(s)), nil } return nil, fmt.Errorf("%w: %q", ErrInvalidOwner, s) @@ -2299,8 +2298,7 @@ func unmarshalPolicy(b []byte) (*Policy, error) { ast.Standardize() if err = json.Unmarshal(ast.Pack(), &policy, policyJSONOpts...); err != nil { //nolint:noinlineerr - var serr *json.SemanticError - if errors.As(err, &serr) && errors.Is(serr.Err, json.ErrUnknownName) { + if serr, ok := errors.AsType[*json.SemanticError](err); ok && errors.Is(serr.Err, json.ErrUnknownName) { ptr := serr.JSONPointer name := ptr.LastToken() diff --git a/hscontrol/policy/v2/types_test.go b/hscontrol/policy/v2/types_test.go index 16105ecb..6e25af95 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}}, }, }, @@ -254,11 +253,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}}, }, }, @@ -547,7 +546,7 @@ func TestUnmarshalPolicy(t *testing.T) { }, Destinations: []AliasWithPorts{ { - Alias: ptr.To(AutoGroup("autogroup:internet")), + Alias: new(AutoGroup("autogroup:internet")), Ports: []tailcfg.PortRange{tailcfg.PortRangeAny}, }, }, @@ -684,8 +683,8 @@ func TestUnmarshalPolicy(t *testing.T) { `, want: &Policy{ TagOwners: TagOwners{ - Tag("tag:web"): Owners{ptr.To(Username("admin@example.com"))}, - Tag("tag:server"): Owners{ptr.To(Username("admin@example.com"))}, + Tag("tag:web"): Owners{new(Username("admin@example.com"))}, + Tag("tag:server"): Owners{new(Username("admin@example.com"))}, }, SSHs: []SSH{ { @@ -1157,7 +1156,7 @@ func TestUnmarshalPolicy(t *testing.T) { }, Destinations: []AliasWithPorts{ { - Alias: ptr.To(AutoGroup("autogroup:internet")), + Alias: new(AutoGroup("autogroup:internet")), Ports: []tailcfg.PortRange{tailcfg.PortRangeAny}, }, }, @@ -1494,7 +1493,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{ { @@ -1505,7 +1504,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}}, }, }, @@ -1829,14 +1828,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) { @@ -1882,31 +1881,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"), }, }, @@ -1914,31 +1913,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"), }, }, @@ -1956,7 +1955,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 @@ -1992,7 +1991,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{ @@ -2015,7 +2014,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{ @@ -2050,14 +2049,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"), }, }, @@ -2075,10 +2074,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"), }, }, @@ -2106,47 +2105,47 @@ func TestResolvePolicy(t *testing.T) { }, { name: "autogroup-member-comprehensive", - toResolve: ptr.To(AutoGroupMember), + toResolve: new(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{ @@ -2156,54 +2155,54 @@ func TestResolvePolicy(t *testing.T) { }, { name: "autogroup-tagged", - toResolve: ptr.To(AutoGroupTagged), + toResolve: new(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{ @@ -2214,37 +2213,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", }, } @@ -2323,7 +2322,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@"))}, }, }, }, @@ -2338,8 +2337,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@"))}, }, }, }, @@ -2354,7 +2353,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{}, @@ -2369,7 +2368,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"))}, }, }, }, @@ -2384,20 +2383,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"))}, }, }, }, @@ -2415,10 +2414,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{ @@ -2639,7 +2638,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@"))}, }, }, }, @@ -2652,8 +2651,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@"))}, }, }, }, @@ -2665,7 +2664,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], @@ -2680,7 +2679,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"))}, }, }, }, @@ -2696,10 +2695,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], @@ -2711,7 +2710,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@"))}, }, }, }, @@ -2769,7 +2768,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{ @@ -2781,7 +2780,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{ @@ -2796,7 +2795,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{ @@ -2808,8 +2807,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{ @@ -2871,7 +2870,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], @@ -2882,7 +2881,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], @@ -2896,7 +2895,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], @@ -2910,7 +2909,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], @@ -2922,7 +2921,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], @@ -2933,7 +2932,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 @@ -2944,8 +2943,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 @@ -2965,7 +2964,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], @@ -2978,13 +2977,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 @@ -2993,13 +2992,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 @@ -3011,13 +3010,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 @@ -3029,13 +3028,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 @@ -3044,7 +3043,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{ @@ -3061,14 +3060,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, @@ -3081,14 +3080,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, @@ -3134,14 +3133,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, }, { @@ -3152,7 +3151,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, }, { @@ -3163,7 +3162,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, }, { @@ -3172,7 +3171,7 @@ func TestUserMatchesOwner(t *testing.T) { Groups: Groups{}, }, user: users[0], - owner: ptr.To(Group("group:undefined")), + owner: new(Group("group:undefined")), want: false, }, { @@ -3517,20 +3516,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", @@ -3538,83 +3537,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/routes/primary.go b/hscontrol/routes/primary.go index 3a1db3dd..a1bcbdc7 100644 --- a/hscontrol/routes/primary.go +++ b/hscontrol/routes/primary.go @@ -240,7 +240,7 @@ func (pr *PrimaryRoutes) PrimaryRoutes(id types.NodeID) []netip.Prefix { } } - tsaddr.SortPrefixes(routes) + slices.SortFunc(routes, netip.Prefix.Compare) return routes } @@ -300,7 +300,7 @@ func (pr *PrimaryRoutes) DebugJSON() DebugRoutes { // Populate available routes for nodeID, routes := range pr.routes { prefixes := routes.Slice() - tsaddr.SortPrefixes(prefixes) + slices.SortFunc(prefixes, netip.Prefix.Compare) debug.AvailableRoutes[nodeID] = prefixes } diff --git a/hscontrol/state/ephemeral_test.go b/hscontrol/state/ephemeral_test.go index 65e7738c..5c755687 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 @@ -55,7 +54,7 @@ func TestEphemeralNodeDeleteWithConcurrentUpdate(t *testing.T) { 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 @@ -114,7 +113,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 @@ -165,7 +164,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") @@ -234,7 +233,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 @@ -310,7 +309,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} }) @@ -380,7 +379,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 @@ -435,7 +434,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/node_store_test.go b/hscontrol/state/node_store_test.go index 736c3cfa..a8b02d8d 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) { @@ -175,7 +174,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, @@ -883,7 +882,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/state/state.go b/hscontrol/state/state.go index 16ea06d3..65ebf905 100644 --- a/hscontrol/state/state.go +++ b/hscontrol/state/state.go @@ -27,10 +27,8 @@ import ( "github.com/rs/zerolog/log" "golang.org/x/sync/errgroup" "gorm.io/gorm" - "tailscale.com/net/tsaddr" "tailscale.com/tailcfg" "tailscale.com/types/key" - "tailscale.com/types/ptr" "tailscale.com/types/views" zcache "zgo.at/zcache/v2" ) @@ -135,7 +133,7 @@ func NewState(cfg *types.Config) (*State, error) { // On startup, all nodes should be marked as offline until they reconnect // This ensures we don't have stale online status from previous runs for _, node := range nodes { - node.IsOnline = ptr.To(false) + node.IsOnline = new(false) } users, err := db.ListUsers() @@ -479,7 +477,7 @@ func (s *State) Connect(id types.NodeID) []change.Change { // the NodeStore already reflects the correct online status for full map generation. // now := time.Now() node, ok := s.nodeStore.UpdateNode(id, func(n *types.Node) { - n.IsOnline = ptr.To(true) + n.IsOnline = new(true) // n.LastSeen = ptr.To(now) }) if !ok { @@ -507,9 +505,9 @@ func (s *State) Disconnect(id types.NodeID) ([]change.Change, error) { now := time.Now() node, ok := s.nodeStore.UpdateNode(id, func(n *types.Node) { - n.LastSeen = ptr.To(now) + n.LastSeen = new(now) // NodeStore is the source of truth for all node state including online status. - n.IsOnline = ptr.To(false) + n.IsOnline = new(false) }) if !ok { @@ -805,7 +803,7 @@ func (s *State) BackfillNodeIPs() ([]string, error) { // Preserve online status and NetInfo when refreshing from database existingNode, exists := s.nodeStore.GetNode(node.ID) if exists && existingNode.Valid() { - node.IsOnline = ptr.To(existingNode.IsOnline().Get()) + node.IsOnline = new(existingNode.IsOnline().Get()) // TODO(kradalby): We should ensure we use the same hostinfo and node merge semantics // when a node re-registers as we do when it sends a map request (UpdateNodeFromMapRequest). @@ -1183,8 +1181,8 @@ func (s *State) applyAuthNodeUpdate(params authNodeUpdateParams) (types.NodeView ) node.Endpoints = params.RegEntry.Node.Endpoints - node.IsOnline = ptr.To(false) - node.LastSeen = ptr.To(time.Now()) + node.IsOnline = new(false) + node.LastSeen = new(time.Now()) // Set RegisterMethod - for conversion this is the new method, // for reauth we preserve the existing one from regEntry @@ -1286,7 +1284,7 @@ func (s *State) createAndSaveNewNode(params newNodeParams) (types.NodeView, erro DiscoKey: params.DiscoKey, Hostinfo: params.Hostinfo, Endpoints: params.Endpoints, - LastSeen: ptr.To(time.Now()), + LastSeen: new(time.Now()), RegisterMethod: params.RegisterMethod, Expiry: params.Expiry, } @@ -1822,8 +1820,8 @@ func (s *State) HandleNodeFromPreAuthKey( // Only update AuthKey reference node.AuthKey = pak node.AuthKeyID = &pak.ID - node.IsOnline = ptr.To(false) - node.LastSeen = ptr.To(time.Now()) + node.IsOnline = new(false) + node.LastSeen = new(time.Now()) // Tagged nodes keep their existing expiry (disabled). // User-owned nodes update expiry from the client request. @@ -2281,8 +2279,8 @@ func routesChanged(oldNode types.NodeView, newHI *tailcfg.Hostinfo) bool { newRoutes = []netip.Prefix{} } - tsaddr.SortPrefixes(oldRoutes) - tsaddr.SortPrefixes(newRoutes) + slices.SortFunc(oldRoutes, netip.Prefix.Compare) + slices.SortFunc(newRoutes, netip.Prefix.Compare) return !slices.Equal(oldRoutes, newRoutes) } diff --git a/hscontrol/types/change/change.go b/hscontrol/types/change/change.go index a76fb7c4..cd7e99d7 100644 --- a/hscontrol/types/change/change.go +++ b/hscontrol/types/change/change.go @@ -333,7 +333,7 @@ func NodeOnline(nodeID types.NodeID) Change { PeerPatches: []*tailcfg.PeerChange{ { NodeID: nodeID.NodeID(), - Online: ptrTo(true), + Online: new(true), }, }, } @@ -346,7 +346,7 @@ func NodeOffline(nodeID types.NodeID) Change { PeerPatches: []*tailcfg.PeerChange{ { NodeID: nodeID.NodeID(), - Online: ptrTo(false), + Online: new(false), }, }, } @@ -367,7 +367,7 @@ func KeyExpiry(nodeID types.NodeID, expiry *time.Time) Change { // ptrTo returns a pointer to the given value. func ptrTo[T any](v T) *T { - return &v + return new(v) } // High-level change constructors diff --git a/hscontrol/types/change/change_test.go b/hscontrol/types/change/change_test.go index 9f181dd6..dc2dd0af 100644 --- a/hscontrol/types/change/change_test.go +++ b/hscontrol/types/change/change_test.go @@ -16,8 +16,8 @@ func TestChange_FieldSync(t *testing.T) { typ := reflect.TypeFor[Change]() boolCount := 0 - for i := range typ.NumField() { - if typ.Field(i).Type.Kind() == reflect.Bool { + for field := range typ.Fields() { + if field.Type.Kind() == reflect.Bool { boolCount++ } } diff --git a/hscontrol/types/config.go b/hscontrol/types/config.go index b030c384..b7440f8b 100644 --- a/hscontrol/types/config.go +++ b/hscontrol/types/config.go @@ -407,8 +407,7 @@ func LoadConfig(path string, isFile bool) error { err := viper.ReadInConfig() if err != nil { - var configFileNotFoundError viper.ConfigFileNotFoundError - if errors.As(err, &configFileNotFoundError) { + if _, ok := errors.AsType[viper.ConfigFileNotFoundError](err); ok { log.Warn().Msg("no config file found, using defaults") return nil } diff --git a/hscontrol/types/node.go b/hscontrol/types/node.go index c699d6df..e705a33a 100644 --- a/hscontrol/types/node.go +++ b/hscontrol/types/node.go @@ -1104,7 +1104,7 @@ func (nv NodeView) TailNode( primaryRoutes := primaryRouteFunc(nv.ID()) allowedIPs := slices.Concat(nv.Prefixes(), primaryRoutes, nv.ExitRoutes()) - tsaddr.SortPrefixes(allowedIPs) + slices.SortFunc(allowedIPs, netip.Prefix.Compare) capMap := tailcfg.NodeCapMap{ tailcfg.CapabilityAdmin: []tailcfg.RawMessage{}, 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/preauth_key_test.go b/hscontrol/types/preauth_key_test.go index 7bd1d552..1b280149 100644 --- a/hscontrol/types/preauth_key_test.go +++ b/hscontrol/types/preauth_key_test.go @@ -110,9 +110,7 @@ func TestCanUsePreAuthKey(t *testing.T) { if err == nil { t.Errorf("expected error but got none") } else { - var httpErr PAKError - - ok := errors.As(err, &httpErr) + httpErr, ok := errors.AsType[PAKError](err) if !ok { t.Errorf("expected HTTPError but got %T", err) } else { diff --git a/hscontrol/util/test.go b/hscontrol/util/test.go index b7be5825..d37f3315 100644 --- a/hscontrol/util/test.go +++ b/hscontrol/util/test.go @@ -10,7 +10,7 @@ import ( ) var PrefixComparer = cmp.Comparer(func(x, y netip.Prefix) bool { - return x == y + return x.Compare(y) == 0 }) var IPComparer = cmp.Comparer(func(x, y netip.Addr) bool { diff --git a/integration/acl_test.go b/integration/acl_test.go index 4f4c3eed..1027dbf0 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), }, }, { @@ -1957,9 +1956,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/auth_key_test.go b/integration/auth_key_test.go index 862b7d32..74482e19 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) { @@ -634,7 +633,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/helpers.go b/integration/helpers.go index fa96bcac..3bc1db55 100644 --- a/integration/helpers.go +++ b/integration/helpers.go @@ -27,7 +27,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) const ( @@ -906,32 +905,32 @@ func wildcard() policyv2.Alias { // usernamep returns a pointer to a Username as an Alias for policy v2 configurations. // Used in ACL rules to reference specific users in network access policies. func usernamep(name string) policyv2.Alias { - return ptr.To(policyv2.Username(name)) + return new(policyv2.Username(name)) } // hostp returns a pointer to a Host as an Alias for policy v2 configurations. // Used in ACL rules to reference specific hosts in network access policies. func hostp(name string) policyv2.Alias { - return ptr.To(policyv2.Host(name)) + return new(policyv2.Host(name)) } // groupp returns a pointer to a Group as an Alias for policy v2 configurations. // Used in ACL rules to reference user groups in network access policies. func groupp(name string) policyv2.Alias { - return ptr.To(policyv2.Group(name)) + return new(policyv2.Group(name)) } // tagp returns a pointer to a Tag as an Alias for policy v2 configurations. // Used in ACL rules to reference node tags in network access policies. func tagp(name string) policyv2.Alias { - return ptr.To(policyv2.Tag(name)) + return new(policyv2.Tag(name)) } // prefixp returns a pointer to a Prefix from a CIDR string for policy v2 configurations. // Converts CIDR notation to policy prefix format for network range specifications. func prefixp(cidr string) policyv2.Alias { prefix := netip.MustParsePrefix(cidr) - return ptr.To(policyv2.Prefix(prefix)) + return new(policyv2.Prefix(prefix)) } // aliasWithPorts creates an AliasWithPorts structure from an alias and port ranges. @@ -947,7 +946,7 @@ func aliasWithPorts(alias policyv2.Alias, ports ...tailcfg.PortRange) policyv2.A // usernameOwner returns a Username as an Owner for use in TagOwners policies. // Specifies which users can assign and manage specific tags in ACL configurations. func usernameOwner(name string) policyv2.Owner { - return ptr.To(policyv2.Username(name)) + return new(policyv2.Username(name)) } // groupOwner returns a Group as an Owner for use in TagOwners policies. @@ -955,25 +954,25 @@ func usernameOwner(name string) policyv2.Owner { // //nolint:unused func groupOwner(name string) policyv2.Owner { - return ptr.To(policyv2.Group(name)) + return new(policyv2.Group(name)) } // usernameApprover returns a Username as an AutoApprover for subnet route policies. // Specifies which users can automatically approve subnet route advertisements. func usernameApprover(name string) policyv2.AutoApprover { - return ptr.To(policyv2.Username(name)) + return new(policyv2.Username(name)) } // groupApprover returns a Group as an AutoApprover for subnet route policies. // Specifies which groups can automatically approve subnet route advertisements. func groupApprover(name string) policyv2.AutoApprover { - return ptr.To(policyv2.Group(name)) + return new(policyv2.Group(name)) } // tagApprover returns a Tag as an AutoApprover for subnet route policies. // Specifies which tagged nodes can automatically approve subnet route advertisements. func tagApprover(name string) policyv2.AutoApprover { - return ptr.To(policyv2.Tag(name)) + return new(policyv2.Tag(name)) } // oidcMockUser creates a MockUser for OIDC authentication testing. diff --git a/integration/ssh_test.go b/integration/ssh_test.go index 993ac418..45bc2dc7 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 { @@ -85,8 +84,8 @@ func TestSSHOneUserToAll(t *testing.T) { // Use autogroup:member and autogroup:tagged instead of wildcard // since wildcard (*) is no longer supported for SSH destinations Destinations: policyv2.SSHDstAliases{ - ptr.To(policyv2.AutoGroupMember), - ptr.To(policyv2.AutoGroupTagged), + new(policyv2.AutoGroupMember), + new(policyv2.AutoGroupTagged), }, Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")}, }, @@ -160,7 +159,7 @@ func TestSSHMultipleUsersAllToAll(t *testing.T) { // Username destinations (e.g., "user1@") now require the source // to be that exact same user only. For group-to-group SSH access, // use autogroup:self instead. - Destinations: policyv2.SSHDstAliases{ptr.To(policyv2.AutoGroupSelf)}, + Destinations: policyv2.SSHDstAliases{new(policyv2.AutoGroupSelf)}, Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")}, }, }, @@ -285,7 +284,7 @@ func TestSSHIsBlockedInACL(t *testing.T) { { Action: "accept", Sources: policyv2.SSHSrcAliases{groupp("group:integration-test")}, - Destinations: policyv2.SSHDstAliases{ptr.To(policyv2.AutoGroupSelf)}, + Destinations: policyv2.SSHDstAliases{new(policyv2.AutoGroupSelf)}, Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")}, }, }, @@ -340,13 +339,13 @@ func TestSSHUserOnlyIsolation(t *testing.T) { { Action: "accept", Sources: policyv2.SSHSrcAliases{groupp("group:ssh1")}, - Destinations: policyv2.SSHDstAliases{ptr.To(policyv2.AutoGroupSelf)}, + Destinations: policyv2.SSHDstAliases{new(policyv2.AutoGroupSelf)}, Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")}, }, { Action: "accept", Sources: policyv2.SSHSrcAliases{groupp("group:ssh2")}, - Destinations: policyv2.SSHDstAliases{ptr.To(policyv2.AutoGroupSelf)}, + Destinations: policyv2.SSHDstAliases{new(policyv2.AutoGroupSelf)}, Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")}, }, }, @@ -522,10 +521,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")}, }, diff --git a/integration/tags_test.go b/integration/tags_test.go index f9cd394b..b4fe678b 100644 --- a/integration/tags_test.go +++ b/integration/tags_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "tailscale.com/tailcfg" - "tailscale.com/types/ptr" ) const tagTestUser = "taguser" @@ -30,9 +29,9 @@ const tagTestUser = "taguser" func tagsTestPolicy() *policyv2.Policy { return &policyv2.Policy{ TagOwners: policyv2.TagOwners{ - "tag:valid-owned": policyv2.Owners{ptr.To(policyv2.Username(tagTestUser + "@"))}, - "tag:second": policyv2.Owners{ptr.To(policyv2.Username(tagTestUser + "@"))}, - "tag:valid-unowned": policyv2.Owners{ptr.To(policyv2.Username("other-user@"))}, + "tag:valid-owned": policyv2.Owners{new(policyv2.Username(tagTestUser + "@"))}, + "tag:second": policyv2.Owners{new(policyv2.Username(tagTestUser + "@"))}, + "tag:valid-unowned": policyv2.Owners{new(policyv2.Username("other-user@"))}, // Note: tag:nonexistent deliberately NOT defined }, ACLs: []policyv2.ACL{