mirror of
https://github.com/juanfont/headscale.git
synced 2026-01-23 02:24:10 +00:00
all: modernize sorting with slices package
Replace deprecated sort package functions with their modern slices package equivalents: - sort.Slice -> slices.SortFunc - sort.SliceStable -> slices.SortStableFunc - sort.Sort -> slices.Sort - sort.Strings -> slices.Sort Also removes the now-unused sort.Interface implementation (Len, Less, Swap methods) from types.NodeIDs since slices.Sort works directly with ordered types.
This commit is contained in:
parent
f9b3265158
commit
094faf7a6a
12 changed files with 98 additions and 111 deletions
|
|
@ -1,12 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
|
@ -371,8 +372,8 @@ func (sc *StatsCollector) GetSummary() []ContainerStatsSummary {
|
|||
}
|
||||
|
||||
// Sort by container name for consistent output
|
||||
sort.Slice(summaries, func(i, j int) bool {
|
||||
return summaries[i].ContainerName < summaries[j].ContainerName
|
||||
slices.SortFunc(summaries, func(a, b ContainerStatsSummary) int {
|
||||
return cmp.Compare(a.ContainerName, b.ContainerName)
|
||||
})
|
||||
|
||||
return summaries
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"regexp"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
|
@ -20,7 +20,6 @@ import (
|
|||
"gorm.io/gorm"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/ptr"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -60,7 +59,7 @@ func ListPeers(tx *gorm.DB, nodeID types.NodeID, peerIDs ...types.NodeID) (types
|
|||
return types.Nodes{}, err
|
||||
}
|
||||
|
||||
sort.Slice(nodes, func(i, j int) bool { return nodes[i].ID < nodes[j].ID })
|
||||
slices.SortFunc(nodes, func(a, b *types.Node) int { return cmp.Compare(a.ID, b.ID) })
|
||||
|
||||
return nodes, nil
|
||||
}
|
||||
|
|
@ -668,7 +667,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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
package mapper
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"errors"
|
||||
"net/netip"
|
||||
"sort"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/juanfont/headscale/hscontrol/policy"
|
||||
|
|
@ -261,8 +262,8 @@ func (b *MapResponseBuilder) buildTailPeers(peers views.Slice[types.NodeView]) (
|
|||
}
|
||||
|
||||
// Peers is always returned sorted by Node.ID.
|
||||
sort.SliceStable(tailPeers, func(x, y int) bool {
|
||||
return tailPeers[x].ID < tailPeers[y].ID
|
||||
slices.SortStableFunc(tailPeers, func(a, b *tailcfg.Node) int {
|
||||
return cmp.Compare(a.ID, b.ID)
|
||||
})
|
||||
|
||||
return tailPeers, nil
|
||||
|
|
|
|||
|
|
@ -956,14 +956,7 @@ func (pm *PolicyManager) invalidateGlobalPolicyCache(newNodes views.Slice[types.
|
|||
// It will return a Owners list where all the Tag types have been resolved to their underlying Owners.
|
||||
func flattenTags(tagOwners TagOwners, tag Tag, visiting map[Tag]bool, chain []Tag) (Owners, error) {
|
||||
if visiting[tag] {
|
||||
cycleStart := 0
|
||||
|
||||
for i, t := range chain {
|
||||
if t == tag {
|
||||
cycleStart = i
|
||||
break
|
||||
}
|
||||
}
|
||||
cycleStart := slices.Index(chain, tag)
|
||||
|
||||
cycleTags := make([]string, len(chain[cycleStart:]))
|
||||
for i, t := range chain[cycleStart:] {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -366,8 +366,10 @@ func KeyExpiry(nodeID types.NodeID, expiry *time.Time) Change {
|
|||
}
|
||||
|
||||
// ptrTo returns a pointer to the given value.
|
||||
//
|
||||
//go:fix inline
|
||||
func ptrTo[T any](v T) *T {
|
||||
return &v
|
||||
return new(v)
|
||||
}
|
||||
|
||||
// High-level change constructors
|
||||
|
|
|
|||
|
|
@ -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++
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"maps"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"sort"
|
||||
"slices"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
gocmp "github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||
policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2"
|
||||
|
|
@ -111,11 +112,11 @@ func TestOIDCAuthenticationPingAll(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
sort.Slice(listUsers, func(i, j int) bool {
|
||||
return listUsers[i].GetId() < listUsers[j].GetId()
|
||||
slices.SortFunc(listUsers, func(a, b *v1.User) int {
|
||||
return cmp.Compare(a.GetId(), b.GetId())
|
||||
})
|
||||
|
||||
if diff := cmp.Diff(want, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
if diff := gocmp.Diff(want, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
t.Fatalf("unexpected users: %s", diff)
|
||||
}
|
||||
}
|
||||
|
|
@ -388,11 +389,11 @@ func TestOIDC024UserCreation(t *testing.T) {
|
|||
listUsers, err := headscale.ListUsers()
|
||||
require.NoError(t, err)
|
||||
|
||||
sort.Slice(listUsers, func(i, j int) bool {
|
||||
return listUsers[i].GetId() < listUsers[j].GetId()
|
||||
slices.SortFunc(listUsers, func(a, b *v1.User) int {
|
||||
return cmp.Compare(a.GetId(), b.GetId())
|
||||
})
|
||||
|
||||
if diff := cmp.Diff(want, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
if diff := gocmp.Diff(want, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
t.Errorf("unexpected users: %s", diff)
|
||||
}
|
||||
})
|
||||
|
|
@ -517,11 +518,11 @@ func TestOIDCReloginSameNodeNewUser(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
sort.Slice(listUsers, func(i, j int) bool {
|
||||
return listUsers[i].GetId() < listUsers[j].GetId()
|
||||
slices.SortFunc(listUsers, func(a, b *v1.User) int {
|
||||
return cmp.Compare(a.GetId(), b.GetId())
|
||||
})
|
||||
|
||||
if diff := cmp.Diff(wantUsers, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
if diff := gocmp.Diff(wantUsers, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
ct.Errorf("User validation failed after first login - unexpected users: %s", diff)
|
||||
}
|
||||
}, 30*time.Second, 1*time.Second, "validating user1 creation after initial OIDC login")
|
||||
|
|
@ -599,11 +600,11 @@ func TestOIDCReloginSameNodeNewUser(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
sort.Slice(listUsers, func(i, j int) bool {
|
||||
return listUsers[i].GetId() < listUsers[j].GetId()
|
||||
slices.SortFunc(listUsers, func(a, b *v1.User) int {
|
||||
return cmp.Compare(a.GetId(), b.GetId())
|
||||
})
|
||||
|
||||
if diff := cmp.Diff(wantUsers, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
if diff := gocmp.Diff(wantUsers, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
ct.Errorf("User validation failed after user2 login - expected both user1 and user2: %s", diff)
|
||||
}
|
||||
}, 30*time.Second, 1*time.Second, "validating both user1 and user2 exist after second OIDC login")
|
||||
|
|
@ -763,11 +764,11 @@ func TestOIDCReloginSameNodeNewUser(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
sort.Slice(listUsers, func(i, j int) bool {
|
||||
return listUsers[i].GetId() < listUsers[j].GetId()
|
||||
slices.SortFunc(listUsers, func(a, b *v1.User) int {
|
||||
return cmp.Compare(a.GetId(), b.GetId())
|
||||
})
|
||||
|
||||
if diff := cmp.Diff(wantUsers, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
if diff := gocmp.Diff(wantUsers, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
ct.Errorf("Final user validation failed - both users should persist after relogin cycle: %s", diff)
|
||||
}
|
||||
}, 30*time.Second, 1*time.Second, "validating user persistence after complete relogin cycle (user1->user2->user1)")
|
||||
|
|
@ -935,13 +936,11 @@ func TestOIDCFollowUpUrl(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
sort.Slice(
|
||||
listUsers, func(i, j int) bool {
|
||||
return listUsers[i].GetId() < listUsers[j].GetId()
|
||||
},
|
||||
)
|
||||
slices.SortFunc(listUsers, func(a, b *v1.User) int {
|
||||
return cmp.Compare(a.GetId(), b.GetId())
|
||||
})
|
||||
|
||||
if diff := cmp.Diff(
|
||||
if diff := gocmp.Diff(
|
||||
wantUsers,
|
||||
listUsers,
|
||||
cmpopts.IgnoreUnexported(v1.User{}),
|
||||
|
|
@ -1046,13 +1045,11 @@ func TestOIDCMultipleOpenedLoginUrls(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
sort.Slice(
|
||||
listUsers, func(i, j int) bool {
|
||||
return listUsers[i].GetId() < listUsers[j].GetId()
|
||||
},
|
||||
)
|
||||
slices.SortFunc(listUsers, func(a, b *v1.User) int {
|
||||
return cmp.Compare(a.GetId(), b.GetId())
|
||||
})
|
||||
|
||||
if diff := cmp.Diff(
|
||||
if diff := gocmp.Diff(
|
||||
wantUsers,
|
||||
listUsers,
|
||||
cmpopts.IgnoreUnexported(v1.User{}),
|
||||
|
|
@ -1155,11 +1152,11 @@ func TestOIDCReloginSameNodeSameUser(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
sort.Slice(listUsers, func(i, j int) bool {
|
||||
return listUsers[i].GetId() < listUsers[j].GetId()
|
||||
slices.SortFunc(listUsers, func(a, b *v1.User) int {
|
||||
return cmp.Compare(a.GetId(), b.GetId())
|
||||
})
|
||||
|
||||
if diff := cmp.Diff(wantUsers, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
if diff := gocmp.Diff(wantUsers, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
ct.Errorf("User validation failed after first login - unexpected users: %s", diff)
|
||||
}
|
||||
}, 30*time.Second, 1*time.Second, "validating user1 creation after initial OIDC login")
|
||||
|
|
@ -1249,11 +1246,11 @@ func TestOIDCReloginSameNodeSameUser(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
sort.Slice(listUsers, func(i, j int) bool {
|
||||
return listUsers[i].GetId() < listUsers[j].GetId()
|
||||
slices.SortFunc(listUsers, func(a, b *v1.User) int {
|
||||
return cmp.Compare(a.GetId(), b.GetId())
|
||||
})
|
||||
|
||||
if diff := cmp.Diff(wantUsers, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
if diff := gocmp.Diff(wantUsers, listUsers, cmpopts.IgnoreUnexported(v1.User{}), cmpopts.IgnoreFields(v1.User{}, "CreatedAt")); diff != "" {
|
||||
ct.Errorf("Final user validation failed - user1 should persist after same-user relogin: %s", diff)
|
||||
}
|
||||
}, 30*time.Second, 1*time.Second, "validating user1 persistence after same-user OIDC relogin cycle")
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ import (
|
|||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/ptr"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -839,32 +838,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.
|
||||
|
|
@ -880,31 +879,31 @@ 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.
|
||||
// Specifies which groups can assign and manage specific tags in ACL configurations.
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -1232,8 +1232,8 @@ func (t *HeadscaleInContainer) ListNodes(
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(ret, func(i, j int) bool {
|
||||
return cmp.Compare(ret[i].GetId(), ret[j].GetId()) == -1
|
||||
slices.SortFunc(ret, func(a, b *v1.Node) int {
|
||||
return cmp.Compare(a.GetId(), b.GetId())
|
||||
})
|
||||
|
||||
return ret, nil
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"maps"
|
||||
"net/netip"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
|
@ -287,11 +286,10 @@ func TestHASubnetRouterFailover(t *testing.T) {
|
|||
t.Logf("webservice: %s, %s", webip.String(), weburl)
|
||||
|
||||
// Sort nodes by ID
|
||||
sort.SliceStable(allClients, func(i, j int) bool {
|
||||
statusI := allClients[i].MustStatus()
|
||||
statusJ := allClients[j].MustStatus()
|
||||
|
||||
return statusI.Self.ID < statusJ.Self.ID
|
||||
slices.SortStableFunc(allClients, func(a, b TailscaleClient) int {
|
||||
statusA := a.MustStatus()
|
||||
statusB := b.MustStatus()
|
||||
return cmp.Compare(statusA.Self.ID, statusB.Self.ID)
|
||||
})
|
||||
|
||||
// This is ok because the scenario makes users in order, so the three first
|
||||
|
|
@ -1359,10 +1357,10 @@ func TestSubnetRouteACL(t *testing.T) {
|
|||
}
|
||||
|
||||
// Sort nodes by ID
|
||||
sort.SliceStable(allClients, func(i, j int) bool {
|
||||
statusI := allClients[i].MustStatus()
|
||||
statusJ := allClients[j].MustStatus()
|
||||
return statusI.Self.ID < statusJ.Self.ID
|
||||
slices.SortStableFunc(allClients, func(a, b TailscaleClient) int {
|
||||
statusA := a.MustStatus()
|
||||
statusB := b.MustStatus()
|
||||
return cmp.Compare(statusA.Self.ID, statusB.Self.ID)
|
||||
})
|
||||
|
||||
subRouter1 := allClients[0]
|
||||
|
|
@ -2403,11 +2401,10 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
t.Logf("webservice: %s, %s", webip.String(), weburl)
|
||||
|
||||
// Sort nodes by ID
|
||||
sort.SliceStable(allClients, func(i, j int) bool {
|
||||
statusI := allClients[i].MustStatus()
|
||||
statusJ := allClients[j].MustStatus()
|
||||
|
||||
return statusI.Self.ID < statusJ.Self.ID
|
||||
slices.SortStableFunc(allClients, func(a, b TailscaleClient) int {
|
||||
statusA := a.MustStatus()
|
||||
statusB := b.MustStatus()
|
||||
return cmp.Compare(statusA.Self.ID, statusB.Self.ID)
|
||||
})
|
||||
|
||||
// This is ok because the scenario makes users in order, so the three first
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package integration
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"slices"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -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{
|
||||
|
|
@ -51,11 +50,11 @@ func tagsEqual(actual, expected []string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
sortedActual := append([]string{}, actual...)
|
||||
sortedExpected := append([]string{}, expected...)
|
||||
sortedActual := slices.Clone(actual)
|
||||
sortedExpected := slices.Clone(expected)
|
||||
|
||||
sort.Strings(sortedActual)
|
||||
sort.Strings(sortedExpected)
|
||||
slices.Sort(sortedActual)
|
||||
slices.Sort(sortedExpected)
|
||||
|
||||
for i := range sortedActual {
|
||||
if sortedActual[i] != sortedExpected[i] {
|
||||
|
|
@ -69,11 +68,11 @@ func tagsEqual(actual, expected []string) bool {
|
|||
// assertNodeHasTagsWithCollect asserts that a node has exactly the expected tags (order-independent).
|
||||
func assertNodeHasTagsWithCollect(c *assert.CollectT, node *v1.Node, expectedTags []string) {
|
||||
actualTags := node.GetTags()
|
||||
sortedActual := append([]string{}, actualTags...)
|
||||
sortedExpected := append([]string{}, expectedTags...)
|
||||
sortedActual := slices.Clone(actualTags)
|
||||
sortedExpected := slices.Clone(expectedTags)
|
||||
|
||||
sort.Strings(sortedActual)
|
||||
sort.Strings(sortedExpected)
|
||||
slices.Sort(sortedActual)
|
||||
slices.Sort(sortedExpected)
|
||||
assert.Equal(c, sortedExpected, sortedActual, "Node %s tags mismatch", node.GetName())
|
||||
}
|
||||
|
||||
|
|
@ -102,11 +101,11 @@ func assertNodeSelfHasTagsWithCollect(c *assert.CollectT, client TailscaleClient
|
|||
}
|
||||
}
|
||||
|
||||
sortedActual := append([]string{}, actualTagsSlice...)
|
||||
sortedExpected := append([]string{}, expectedTags...)
|
||||
sortedActual := slices.Clone(actualTagsSlice)
|
||||
sortedExpected := slices.Clone(expectedTags)
|
||||
|
||||
sort.Strings(sortedActual)
|
||||
sort.Strings(sortedExpected)
|
||||
slices.Sort(sortedActual)
|
||||
slices.Sort(sortedExpected)
|
||||
assert.Equal(c, sortedExpected, sortedActual, "Client %s self tags mismatch", client.Hostname())
|
||||
}
|
||||
|
||||
|
|
@ -2507,11 +2506,11 @@ func assertNetmapSelfHasTagsWithCollect(c *assert.CollectT, client TailscaleClie
|
|||
}
|
||||
}
|
||||
|
||||
sortedActual := append([]string{}, actualTagsSlice...)
|
||||
sortedExpected := append([]string{}, expectedTags...)
|
||||
sortedActual := slices.Clone(actualTagsSlice)
|
||||
sortedExpected := slices.Clone(expectedTags)
|
||||
|
||||
sort.Strings(sortedActual)
|
||||
sort.Strings(sortedExpected)
|
||||
slices.Sort(sortedActual)
|
||||
slices.Sort(sortedExpected)
|
||||
assert.Equal(c, sortedExpected, sortedActual, "Client %s netmap self tags mismatch", client.Hostname())
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue