chore: use slices.Sorted

This commit is contained in:
Julian Sommer
2026-09-30 11:44:17 +10:00
parent 04c000e7b9
commit 610ee9bab0
34 changed files with 89 additions and 196 deletions
+3 -6
View File
@@ -3,7 +3,8 @@ package cmd
import (
"context"
"fmt"
"sort"
"maps"
"slices"
"strconv"
"github.com/mulgadc/spinifex/spinifex/gateway"
@@ -166,11 +167,7 @@ func printAccountQuota(resp *gateway.AccountQuotaResponse) {
fmt.Printf("%-16s %10s %s\n", "DIMENSION", "LIMIT", "SOURCE")
fmt.Printf("%-16s %10s %s\n", "---------", "-----", "------")
names := make([]string, 0, len(resp.Limits))
for name := range resp.Limits {
names = append(names, name)
}
sort.Strings(names)
names := slices.Sorted(maps.Keys(resp.Limits))
for _, name := range names {
limit := strconv.Itoa(resp.Limits[name])
if resp.Limits[name] == handlers_quota.Unlimited {
+2 -5
View File
@@ -11,6 +11,7 @@ import (
"fmt"
"io"
"io/fs"
"maps"
"os"
"path/filepath"
"slices"
@@ -420,11 +421,7 @@ func hashStoredMsg(m *jetstream.RawStreamMsg) string {
field([]byte(m.Subject))
binary.BigEndian.PutUint64(n[:], uint64(m.Time.UnixNano()))
h.Write(n[:])
keys := make([]string, 0, len(m.Header))
for k := range m.Header {
keys = append(keys, k)
}
sort.Strings(keys)
keys := slices.Sorted(maps.Keys(m.Header))
for _, k := range keys {
field([]byte(k))
for _, v := range m.Header[k] {
+2 -5
View File
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"maps"
"os"
"slices"
"sort"
@@ -153,11 +154,7 @@ func compareNodeDigests(nodes []nodeDigest) (kvCompareResult, error) {
byName[d.Name] = append(byName[d.Name], v)
}
}
names := make([]string, 0, len(byName))
for name := range byName {
names = append(names, name)
}
sort.Strings(names)
names := slices.Sorted(maps.Keys(byName))
var res kvCompareResult
for _, name := range names {
+1 -6
View File
@@ -131,12 +131,7 @@ var modelCache sync.Map
// Services returns the supported service identifiers in stable order.
func Services() []Service {
services := make([]Service, 0, len(modelFiles))
for service := range modelFiles {
services = append(services, service)
}
slices.Sort(services)
return services
return slices.Sorted(maps.Keys(modelFiles))
}
// Load parses and indexes the embedded model for service. Each service is
+3 -7
View File
@@ -4,8 +4,9 @@ import (
"bytes"
"encoding/json"
"fmt"
"maps"
"regexp"
"sort"
"slices"
"strconv"
"strings"
"unicode/utf8"
@@ -253,12 +254,7 @@ func validateFrontmatter(owner string, page PageMetadata) error {
// key rather than by first use, so adding an operation cannot renumber a note
// that is already published.
func noteOrder(notes map[string]string) []string {
keys := make([]string, 0, len(notes))
for key := range notes {
keys = append(keys, key)
}
sort.Strings(keys)
return keys
return slices.Sorted(maps.Keys(notes))
}
// checkNotes rejects a note nothing references and a reference to a note that
+4 -10
View File
@@ -3,7 +3,9 @@ package oci
import (
"context"
"fmt"
"maps"
"net/netip"
"slices"
"sync"
)
@@ -71,22 +73,14 @@ func (f *Fake) SeedPublicIP(p PublicIP) {
func (f *Fake) PrivateIPs() []PrivateIP {
f.mu.Lock()
defer f.mu.Unlock()
out := make([]PrivateIP, 0, len(f.privateIPs))
for _, p := range f.privateIPs {
out = append(out, p)
}
return out
return slices.Collect(maps.Values(f.privateIPs))
}
// PublicIPs returns a snapshot.
func (f *Fake) PublicIPs() []PublicIP {
f.mu.Lock()
defer f.mu.Unlock()
out := make([]PublicIP, 0, len(f.publicIPs))
for _, p := range f.publicIPs {
out = append(out, p)
}
return out
return slices.Collect(maps.Values(f.publicIPs))
}
// FailOp stages err for the next call to op. Locked, so a test may stage one
+1 -5
View File
@@ -2371,11 +2371,7 @@ func (d *Daemon) nodeRunningVMs() ([]*vm.VM, error) {
if err != nil {
return nil, err
}
vms := make([]*vm.VM, 0, len(running))
for _, v := range running {
vms = append(vms, v)
}
return vms, nil
return slices.Collect(maps.Values(running)), nil
}
// connectNATS connects to NATS with infinite retry (cap 60s backoff). Tests
@@ -7,8 +7,10 @@ package gateway
import (
"crypto/tls"
"encoding/json"
"maps"
"net/http"
"net/http/httptest"
"slices"
"testing"
"github.com/mulgadc/bluebottle/pkg/iampolicy"
@@ -117,10 +119,7 @@ func TestRequestConditionKeys_EveryEmittedKeyIsUsableInAPolicy(t *testing.T) {
// The door's key set as a whole, so a key gained or lost here is a deliberate
// change made at both doors rather than a drift between them.
func TestRequestConditionKeys_MatchesTheDoorKeySet(t *testing.T) {
emitted := make([]string, 0, len(gatewayDoorKeys))
for key := range emittedKeys(t) {
emitted = append(emitted, key)
}
emitted := slices.Collect(maps.Keys(emittedKeys(t)))
assert.ElementsMatch(t, gatewayDoorKeys, emitted,
"the AWS gateway door key set changed: update predastore's mirror in "+
"internal/gate/conditionkeys_completeness_test.go and the door table in bluebottle's door_test.go")
+1
View File
@@ -118,6 +118,7 @@ var ec2ListsAsSet = map[reflect.Type][]string{
reflect.TypeFor[ec2.RevokeSecurityGroupEgressOutput](): {"UnknownIpPermissions"},
reflect.TypeFor[ec2.NetworkInterface](): {"Ipv4Prefixes", "Ipv6Prefixes"},
reflect.TypeFor[ec2.Vpc](): {"Ipv6CidrBlockAssociationSet"},
reflect.TypeFor[ec2.Subnet](): {"Tags"},
}
// marshalEC2Response renders an EC2 handler's output into the action's XML
+2 -5
View File
@@ -4,6 +4,7 @@
package gateway
import (
"maps"
"net/http"
"net/http/httptest"
"reflect"
@@ -43,11 +44,7 @@ func serveEC2(gw *GatewayConfig, body string) *httptest.ResponseRecorder {
func TestEC2Request_DryRunAnswersEveryAction(t *testing.T) {
gw := &GatewayConfig{DisableLogging: true, Region: authzRegion, IAMService: allowAllIAMService()}
actions := make([]string, 0, len(ec2Actions))
for action := range ec2Actions {
actions = append(actions, action)
}
slices.Sort(actions)
actions := slices.Sorted(maps.Keys(ec2Actions))
for _, action := range actions {
t.Run(action, func(t *testing.T) {
+4
View File
@@ -180,4 +180,8 @@ func TestEC2_NetworkListsAWSOmitsWhenEmpty(t *testing.T) {
Ipv6CidrBlockAssociationSet: []*ec2.VpcIpv6CidrBlockAssociation{},
}})
assert.Contains(t, created, "<ipv6CidrBlockAssociationSet></ipv6CidrBlockAssociationSet>")
subnet := render[ec2.CreateSubnetInput](t, "CreateSubnet", ec2.CreateSubnetOutput{Subnet: &ec2.Subnet{SubnetId: aws.String("subnet-1")}})
assert.NotContains(t, subnet, "tagSet")
assert.Contains(t, subnet, "<ipv6CidrBlockAssociationSet></ipv6CidrBlockAssociationSet>")
}
+3 -6
View File
@@ -4,7 +4,8 @@ import (
"context"
"encoding/json"
"errors"
"sort"
"maps"
"slices"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecr"
@@ -123,11 +124,7 @@ func ListTagsForResource(ctx context.Context, nc *nats.Conn, accountID string, b
if err != nil {
return nil, err
}
keys := make([]string, 0, len(meta.Tags))
for k := range meta.Tags {
keys = append(keys, k)
}
sort.Strings(keys)
keys := slices.Sorted(maps.Keys(meta.Tags))
tags := make([]*ecr.Tag, 0, len(keys))
for _, k := range keys {
tags = append(tags, &ecr.Tag{Key: aws.String(k), Value: aws.String(meta.Tags[k])})
@@ -2116,10 +2116,7 @@ func (s *InstanceServiceImpl) DescribeInstances(ctx context.Context, input *ec2.
}
})
reservations := make([]*ec2.Reservation, 0, len(reservationMap))
for _, reservation := range reservationMap {
reservations = append(reservations, reservation)
}
reservations := slices.Collect(maps.Values(reservationMap))
slog.InfoContext(ctx, "DescribeInstances completed", "count", len(reservations))
return &ec2.DescribeInstancesOutput{Reservations: reservations}, nil
@@ -2242,10 +2239,7 @@ func (s *InstanceServiceImpl) describeInstancesFromKV(ctx context.Context, input
reservationMap[resID].Instances = append(reservationMap[resID].Instances, projected)
}
reservations := make([]*ec2.Reservation, 0, len(reservationMap))
for _, reservation := range reservationMap {
reservations = append(reservations, reservation)
}
reservations := slices.Collect(maps.Values(reservationMap))
slog.InfoContext(ctx, opName+" completed", "count", len(reservations))
return &ec2.DescribeInstancesOutput{Reservations: reservations}, nil
+2 -5
View File
@@ -2,6 +2,7 @@ package handlers_eks
import (
"fmt"
"maps"
"slices"
)
@@ -111,11 +112,7 @@ func (s AddonSpec) supportsVersion(version string) bool {
// catalogSpecs returns the catalog entries sorted by name for stable output.
func catalogSpecs() []AddonSpec {
names := make([]string, 0, len(addonCatalog))
for n := range addonCatalog {
names = append(names, n)
}
slices.Sort(names)
names := slices.Sorted(maps.Keys(addonCatalog))
out := make([]AddonSpec, 0, len(names))
for _, n := range names {
out = append(out, addonCatalog[n])
+3 -6
View File
@@ -12,7 +12,9 @@ import (
"context"
"errors"
"fmt"
"maps"
"math"
"slices"
"sort"
"sync"
"time"
@@ -503,10 +505,5 @@ func Summary(report *Report) string {
}
func sortedOps(ops map[string]OpStats) []string {
names := make([]string, 0, len(ops))
for name := range ops {
names = append(names, name)
}
sort.Strings(names)
return names
return slices.Sorted(maps.Keys(ops))
}
+2 -7
View File
@@ -3,8 +3,8 @@ package loadgen
import (
"context"
"fmt"
"maps"
"slices"
"sort"
"strings"
"github.com/aws/aws-sdk-go/aws"
@@ -103,12 +103,7 @@ var DefaultOps = []string{"DescribeInstances", "DescribeVpcs", "DescribeVolumes"
// OpNames lists every operation the registry knows, for the usage text.
func OpNames() []string {
names := make([]string, 0, len(registry))
for name := range registry {
names = append(names, name)
}
sort.Strings(names)
return names
return slices.Sorted(maps.Keys(registry))
}
// ResolveOps turns names into operations, rejecting an unknown one rather than
+2 -6
View File
@@ -2,6 +2,7 @@ package resource_test
import (
"encoding/json"
"maps"
"slices"
"testing"
"time"
@@ -202,10 +203,5 @@ func TestObjectJSON_RoundTrips(t *testing.T) {
}
func sortedKeys(m map[string]json.RawMessage) []string {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
slices.Sort(keys)
return keys
return slices.Sorted(maps.Keys(m))
}
+3 -4
View File
@@ -6,10 +6,12 @@ import (
"crypto/x509"
"fmt"
"log/slog"
"maps"
"net"
"net/http"
"os"
"path/filepath"
"slices"
"strings"
"time"
@@ -443,10 +445,7 @@ func launchService(config *config.ClusterConfig) error {
// nodeIDs is the configured cluster node set, in the same namespace as the
// daemon reply header, so a fan-out's completeness can be judged by
// responder identity rather than by count.
nodeIDs := make([]string, 0, len(config.Nodes))
for nodeID := range config.Nodes {
nodeIDs = append(nodeIDs, nodeID)
}
nodeIDs := slices.Collect(maps.Keys(config.Nodes))
gw := gateway.GatewayConfig{
Debug: nodeConfig.AWSGW.Debug,
+3 -7
View File
@@ -3,7 +3,8 @@ package northstar
import (
"fmt"
"log/slog"
"sort"
"maps"
"slices"
"strings"
"time"
@@ -150,10 +151,5 @@ func ensureZone(s3cfg *nsconfig.S3Config, seed nsconfig.BaseZoneSeed) error {
// nodeNames returns the sorted node keys of the cluster, for diagnostics.
func nodeNames(cluster *config.ClusterConfig) []string {
names := make([]string, 0, len(cluster.Nodes))
for name := range cluster.Nodes {
names = append(names, name)
}
sort.Strings(names)
return names
return slices.Sorted(maps.Keys(cluster.Nodes))
}
+2 -7
View File
@@ -9,12 +9,12 @@ package systemd
import (
"errors"
"fmt"
"maps"
"os"
"os/exec"
"path/filepath"
"regexp"
"slices"
"sort"
"strconv"
"strings"
"time"
@@ -98,12 +98,7 @@ var systemctlDaemonReload = func() error {
}
func sortedUnitNames() []string {
names := make([]string, 0, len(Units))
for n := range Units {
names = append(names, n)
}
sort.Strings(names)
return names
return slices.Sorted(maps.Keys(Units))
}
// Reconcile compares each embedded unit (Units, generated from
+3 -5
View File
@@ -2,6 +2,8 @@ package utils
import (
"context"
"maps"
"slices"
"github.com/nats-io/nats.go"
"go.opentelemetry.io/otel"
@@ -22,11 +24,7 @@ type natsHeaderCarrier nats.Header
func (c natsHeaderCarrier) Get(key string) string { return nats.Header(c).Get(key) }
func (c natsHeaderCarrier) Set(key, value string) { nats.Header(c).Set(key, value) }
func (c natsHeaderCarrier) Keys() []string {
keys := make([]string, 0, len(c))
for k := range c {
keys = append(keys, k)
}
return keys
return slices.Collect(maps.Keys(c))
}
// InjectTraceContext writes ctx's span context into hdr (traceparent/tracestate).
+2 -5
View File
@@ -2,6 +2,7 @@ package vm
import (
"maps"
"slices"
"sync"
"time"
)
@@ -191,11 +192,7 @@ func (m *Manager) ForEach(fn func(*VM)) {
func (m *Manager) Snapshot() []*VM {
m.mu.Lock()
defer m.mu.Unlock()
out := make([]*VM, 0, len(m.vms))
for _, v := range m.vms {
out = append(out, v)
}
return out
return slices.Collect(maps.Values(m.vms))
}
// SnapshotMap returns a copy of the id→VM map for serialization outside the lock.
+3 -10
View File
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"maps"
"slices"
"sync"
"github.com/mulgadc/spinifex/spinifex/types"
@@ -76,11 +77,7 @@ func (f *fakeStateStore) DeleteStoppedInstance(id string) error {
func (f *fakeStateStore) ListStoppedInstances() ([]*VM, error) {
f.mu.Lock()
defer f.mu.Unlock()
out := make([]*VM, 0, len(f.stopped))
for _, v := range f.stopped {
out = append(out, v)
}
return out, nil
return slices.Collect(maps.Values(f.stopped)), nil
}
// ClaimStoppedInstance mimics the real atomic-delete claim for tests: under
@@ -107,11 +104,7 @@ func (f *fakeStateStore) WriteTerminatedInstance(id string, v *VM) error {
func (f *fakeStateStore) ListTerminatedInstances() ([]*VM, error) {
f.mu.Lock()
defer f.mu.Unlock()
out := make([]*VM, 0, len(f.terminated))
for _, v := range f.terminated {
out = append(out, v)
}
return out, nil
return slices.Collect(maps.Values(f.terminated)), nil
}
func (f *fakeStateStore) DeleteTerminatedInstance(id string) error {
+3 -10
View File
@@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"maps"
"slices"
"sync"
"github.com/mulgadc/spinifex/spinifex/kvstore"
@@ -170,11 +171,7 @@ func (s *StateStore) ListStoppedInstances() ([]*vm.VM, error) {
if s.ListStoppedErr != nil {
return nil, s.ListStoppedErr
}
out := make([]*vm.VM, 0, len(s.Stopped))
for _, v := range s.Stopped {
out = append(out, v)
}
return out, nil
return slices.Collect(maps.Values(s.Stopped)), nil
}
// ClaimStoppedInstance mimics the real atomic delete-as-claim: under the
@@ -237,11 +234,7 @@ func (s *StateStore) ListTerminatedInstances() ([]*vm.VM, error) {
if s.ListTerminatedErr != nil {
return nil, s.ListTerminatedErr
}
out := make([]*vm.VM, 0, len(s.Terminated))
for _, v := range s.Terminated {
out = append(out, v)
}
return out, nil
return slices.Collect(maps.Values(s.Terminated)), nil
}
func (s *StateStore) DeleteTerminatedInstance(id string) error {
+3 -6
View File
@@ -3,8 +3,10 @@ package ebsctl
import (
"encoding/json"
"fmt"
"maps"
"math/rand/v2"
"os"
"slices"
"sort"
"strconv"
"strings"
@@ -74,12 +76,7 @@ func unionOps(a, b *RunResult) []string {
for name := range b.Operations {
seen[name] = struct{}{}
}
out := make([]string, 0, len(seen))
for name := range seen {
out = append(out, name)
}
sort.Strings(out)
return out
return slices.Sorted(maps.Keys(seen))
}
// seriesFor picks the api or settle series from op, or nil if op is nil or
@@ -6,11 +6,12 @@ import (
"go/ast"
"go/parser"
"go/token"
"maps"
"os"
"path/filepath"
"regexp"
"runtime"
"sort"
"slices"
"strings"
"testing"
)
@@ -117,12 +118,7 @@ func lettersFromDoc(path string) ([]string, error) {
}
func sortedKeys(m map[string]struct{}) []string {
out := make([]string, 0, len(m))
for k := range m {
out = append(out, k)
}
sort.Strings(out)
return out
return slices.Sorted(maps.Keys(m))
}
// setDiff returns elements in a that are not in b (both inputs must be sorted).
+3 -7
View File
@@ -3,7 +3,8 @@
package harness
import (
"sort"
"maps"
"slices"
"sync"
"testing"
)
@@ -59,10 +60,5 @@ func (a *AccountCarousel) Get(name string) *Profile {
func (a *AccountCarousel) Names() []string {
a.mu.RLock()
defer a.mu.RUnlock()
out := make([]string, 0, len(a.profiles))
for k := range a.profiles {
out = append(out, k)
}
sort.Strings(out)
return out
return slices.Sorted(maps.Keys(a.profiles))
}
+3 -4
View File
@@ -5,8 +5,10 @@ package harness
import (
"context"
"fmt"
"maps"
"os/exec"
"regexp"
"slices"
"strconv"
"strings"
"testing"
@@ -115,10 +117,7 @@ func WaitForNewGuestDisk(t *testing.T, tgt SSHTarget, before map[string]struct{}
return nil
}
}
names := make([]string, 0, len(now))
for name := range now {
names = append(names, name)
}
names := slices.Collect(maps.Keys(now))
return fmt.Errorf("no new disk yet (visible: %s)", strings.Join(names, ","))
}, timeout, 2*time.Second)
return found
+3 -5
View File
@@ -4,6 +4,8 @@ package kvquorum
import (
"fmt"
"maps"
"slices"
"sort"
"strings"
"testing"
@@ -180,10 +182,6 @@ func peerNames(reports []kvutil.BucketReport) string {
seen[p] = struct{}{}
}
}
out := make([]string, 0, len(seen))
for p := range seen {
out = append(out, p)
}
sort.Strings(out)
out := slices.Sorted(maps.Keys(seen))
return strings.Join(out, ",")
}
+3 -5
View File
@@ -21,7 +21,9 @@ package manifestlint
import (
"bufio"
"maps"
"os"
"slices"
"sort"
"strings"
)
@@ -75,11 +77,7 @@ func WriteBaseline(path string, keys []string) error {
for _, k := range keys {
uniq[k] = true
}
out := make([]string, 0, len(uniq))
for k := range uniq {
out = append(out, k)
}
sort.Strings(out)
out := slices.Sorted(maps.Keys(uniq))
var b strings.Builder
b.WriteString("# manifest-lint baseline — pre-existing drift accepted by the ratchet.\n")
+3 -6
View File
@@ -5,9 +5,11 @@ import (
"go/ast"
"go/parser"
"go/token"
"maps"
"os"
"path/filepath"
"regexp"
"slices"
"sort"
"strconv"
"strings"
@@ -137,12 +139,7 @@ func serviceDirs(m *manifestcheck.Manifest) []string {
set[p] = true
}
}
out := make([]string, 0, len(set))
for d := range set {
out = append(out, d)
}
sort.Strings(out)
return out
return slices.Sorted(maps.Keys(set))
}
// scanSubjectsInDir walks dir recursively, parsing every non-test .go file and
+3 -5
View File
@@ -4,8 +4,10 @@ package single
import (
"fmt"
"maps"
"net"
"os/exec"
"slices"
"strconv"
"strings"
"testing"
@@ -692,11 +694,7 @@ func guestMACSet(t *testing.T, tgt harness.SSHTarget) map[string]struct{} {
// setKeys returns the keys of a string set as a slice for log/Detail output.
func setKeys(m map[string]struct{}) []string {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
return slices.Collect(maps.Keys(m))
}
// describeENI returns the single ENI record for eniID, erroring if absent.
+3 -5
View File
@@ -6,8 +6,10 @@ import (
"bytes"
"fmt"
"io"
"maps"
"net/http"
"net/url"
"slices"
"sort"
"strings"
"sync"
@@ -210,11 +212,7 @@ func (c *conformanceCollector) report(policy conformancePolicy, mode conformance
for service := range policy.promoted {
checkedServices[service] = true
}
services := make([]awsmodel.Service, 0, len(checkedServices))
for service := range checkedServices {
services = append(services, service)
}
sort.Slice(services, func(i, j int) bool { return services[i] < services[j] })
services := slices.Sorted(maps.Keys(checkedServices))
for _, service := range services {
fmt.Fprintf(&report, "CHECKED %s success=%d errors=%d unmodelled_errors=%d promoted=%t\n",
service, c.checkedByService[service], c.errorCheckedByService[service], c.errorUnmodelledByService[service], policy.isPromoted(service))
+3 -7
View File
@@ -6,8 +6,9 @@ import (
_ "embed"
"encoding/json"
"fmt"
"maps"
"os"
"sort"
"slices"
"strings"
"github.com/mulgadc/spinifex/internal/awsmodel"
@@ -89,12 +90,7 @@ func (p conformancePolicy) isRequestPromoted(service awsmodel.Service) bool {
}
func (p conformancePolicy) services() []awsmodel.Service {
services := make([]awsmodel.Service, 0, len(p.promoted))
for service := range p.promoted {
services = append(services, service)
}
sort.Slice(services, func(i, j int) bool { return services[i] < services[j] })
return services
return slices.Sorted(maps.Keys(p.promoted))
}
func conformanceModeFromEnvironment() (conformanceMode, error) {