diff --git a/cmd/talosctl/cmd/mgmt/cluster/create.go b/cmd/talosctl/cmd/mgmt/cluster/create.go index 135dbf80f..92f608331 100644 --- a/cmd/talosctl/cmd/mgmt/cluster/create.go +++ b/cmd/talosctl/cmd/mgmt/cluster/create.go @@ -837,7 +837,7 @@ func create(ctx context.Context) error { types := []machine.Type{machine.TypeControlPlane, machine.TypeWorker} if withInitNode { - types = append([]machine.Type{machine.TypeInit}, types...) + types = slices.Insert(types, 0, machine.TypeInit) } if err = configBundle.Write(".", encoder.CommentsAll, types...); err != nil { diff --git a/cmd/talosctl/cmd/mgmt/cluster/show.go b/cmd/talosctl/cmd/mgmt/cluster/show.go index 2d2dfcf8e..cfc088af7 100644 --- a/cmd/talosctl/cmd/mgmt/cluster/show.go +++ b/cmd/talosctl/cmd/mgmt/cluster/show.go @@ -5,11 +5,12 @@ package cluster import ( + "cmp" "context" "fmt" "net/netip" "os" - "sort" + "slices" "strings" "text/tabwriter" @@ -76,7 +77,7 @@ func showCluster(cluster provision.Cluster) error { fmt.Fprintf(w, "NAME\tTYPE\tIP\tCPU\tRAM\tDISK\n") nodes := cluster.Info().Nodes - sort.Slice(nodes, func(i, j int) bool { return nodes[i].Name < nodes[j].Name }) + slices.SortFunc(nodes, func(a, b provision.NodeInfo) int { return cmp.Compare(a.Name, b.Name) }) for _, node := range nodes { cpus := "-" diff --git a/cmd/talosctl/cmd/talos/config.go b/cmd/talosctl/cmd/talos/config.go index 4a6d6a378..5e0cbcdf9 100644 --- a/cmd/talosctl/cmd/talos/config.go +++ b/cmd/talosctl/cmd/talos/config.go @@ -14,7 +14,7 @@ import ( "errors" "fmt" "os" - "sort" + "slices" "strings" "text/tabwriter" "text/template" @@ -279,7 +279,7 @@ var configRemoveCmd = &cobra.Command{ } func sortInPlace(slc []string) []string { - sort.Slice(slc, func(i, j int) bool { return slc[i] < slc[j] }) + slices.Sort(slc) return slc } @@ -326,7 +326,7 @@ var configGetContextsCmd = &cobra.Command{ } keys := maps.Keys(c.Contexts) - sort.Strings(keys) + slices.Sort(keys) w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0) fmt.Fprintln(w, "CURRENT\tNAME\tENDPOINTS\tNODES") @@ -587,7 +587,7 @@ func CompleteConfigContext(*cobra.Command, []string, string) ([]string, cobra.Sh } contextnames := maps.Keys(c.Contexts) - sort.Strings(contextnames) + slices.Sort(contextnames) return contextnames, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/talosctl/cmd/talos/containers.go b/cmd/talosctl/cmd/talos/containers.go index 37e094644..40a125bb7 100644 --- a/cmd/talosctl/cmd/talos/containers.go +++ b/cmd/talosctl/cmd/talos/containers.go @@ -8,7 +8,7 @@ import ( "context" "fmt" "os" - "sort" + "slices" "strings" "text/tabwriter" @@ -68,10 +68,7 @@ func containerRender(remotePeer *peer.Peer, resp *machineapi.ContainersResponse) defaultNode := client.AddrFromPeer(remotePeer) for _, msg := range resp.Messages { - sort.Slice(msg.Containers, - func(i, j int) bool { - return strings.Compare(msg.Containers[i].Id, msg.Containers[j].Id) < 0 - }) + slices.SortFunc(msg.Containers, func(a, b *machineapi.ContainerInfo) int { return strings.Compare(a.Id, b.Id) }) for _, p := range msg.Containers { display := p.Id diff --git a/cmd/talosctl/cmd/talos/diskusage.go b/cmd/talosctl/cmd/talos/diskusage.go index 5a05f2000..e51360994 100644 --- a/cmd/talosctl/cmd/talos/diskusage.go +++ b/cmd/talosctl/cmd/talos/diskusage.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "os" + "slices" "strconv" "text/tabwriter" @@ -109,7 +110,7 @@ var duCmd = &cobra.Command{ if multipleNodes { pattern = "%s\t%s\t%s\n" - args = append([]any{node}, args...) + args = slices.Insert(args, 0, any(node)) } fmt.Fprintf(w, pattern, args...) diff --git a/cmd/talosctl/cmd/talos/etcd.go b/cmd/talosctl/cmd/talos/etcd.go index d00c36c91..de1fc10ce 100644 --- a/cmd/talosctl/cmd/talos/etcd.go +++ b/cmd/talosctl/cmd/talos/etcd.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "os" + "slices" "strings" "text/tabwriter" @@ -72,7 +73,7 @@ func displayAlarms(messages []alarmMessage) error { alarm.GetAlarm().String(), } if node != "" { - args = append([]any{node}, args...) + args = slices.Insert(args, 0, any(node)) } fmt.Fprintf(w, pattern, args...) @@ -241,7 +242,7 @@ var etcdMemberListCmd = &cobra.Command{ member.IsLearner, } if node != "" { - args = append([]any{node}, args...) + args = slices.Insert(args, 0, any(node)) } fmt.Fprintf(w, pattern, args...) @@ -305,7 +306,7 @@ var etcdStatusCmd = &cobra.Command{ strings.Join(message.GetMemberStatus().GetErrors(), ", "), } if node != "" { - args = append([]any{node}, args...) + args = slices.Insert(args, 0, any(node)) } fmt.Fprintf(w, pattern, args...) diff --git a/cmd/talosctl/cmd/talos/health.go b/cmd/talosctl/cmd/talos/health.go index 695b52458..346fb975f 100644 --- a/cmd/talosctl/cmd/talos/health.go +++ b/cmd/talosctl/cmd/talos/health.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "os" + "slices" "time" "github.com/cosi-project/runtime/pkg/safe" @@ -62,11 +63,7 @@ func (cl *clusterNodes) InitNodeInfos() error { nodesByType[machine.TypeWorker] = workerNodeInfos cl.nodesByType = nodesByType - nodes := make([]cluster.NodeInfo, 0, len(initNodeInfos)+len(controlPlaneNodeInfos)+len(workerNodeInfos)) - nodes = append(nodes, initNodeInfos...) - nodes = append(nodes, controlPlaneNodeInfos...) - nodes = append(nodes, workerNodeInfos...) - cl.nodes = nodes + cl.nodes = slices.Concat(initNodeInfos, controlPlaneNodeInfos, workerNodeInfos) return nil } diff --git a/cmd/talosctl/cmd/talos/reset.go b/cmd/talosctl/cmd/talos/reset.go index f72340e89..f45cb9a54 100644 --- a/cmd/talosctl/cmd/talos/reset.go +++ b/cmd/talosctl/cmd/talos/reset.go @@ -8,7 +8,7 @@ import ( "context" "errors" "fmt" - "sort" + "slices" "strings" "github.com/siderolabs/gen/maps" @@ -63,7 +63,7 @@ func (m *WipeMode) Set(value string) error { // Type implements Flag interface. func (m *WipeMode) Type() string { options := maps.Keys(wipeOptions) - sort.Strings(options) + slices.Sort(options) return strings.Join(options, ", ") } diff --git a/cmd/talosctl/cmd/talos/stats.go b/cmd/talosctl/cmd/talos/stats.go index ef6b7837a..4c2d2cb7d 100644 --- a/cmd/talosctl/cmd/talos/stats.go +++ b/cmd/talosctl/cmd/talos/stats.go @@ -8,7 +8,7 @@ import ( "context" "fmt" "os" - "sort" + "slices" "strings" "text/tabwriter" @@ -68,10 +68,7 @@ func statsRender(remotePeer *peer.Peer, resp *machineapi.StatsResponse) error { defaultNode := client.AddrFromPeer(remotePeer) for _, msg := range resp.Messages { - sort.Slice(msg.Stats, - func(i, j int) bool { - return strings.Compare(msg.Stats[i].Id, msg.Stats[j].Id) < 0 - }) + slices.SortFunc(msg.Stats, func(a, b *machineapi.Stat) int { return strings.Compare(a.Id, b.Id) }) for _, s := range msg.Stats { display := s.Id diff --git a/cmd/talosctl/cmd/talos/upgrade.go b/cmd/talosctl/cmd/talos/upgrade.go index 745d433c6..3720de5de 100644 --- a/cmd/talosctl/cmd/talos/upgrade.go +++ b/cmd/talosctl/cmd/talos/upgrade.go @@ -5,11 +5,12 @@ package talos import ( + "cmp" "context" "errors" "fmt" "os" - "sort" + "slices" "strings" "text/tabwriter" "time" @@ -146,8 +147,8 @@ func upgradeGetActorID(ctx context.Context, c *client.Client, opts []client.Upgr func init() { rebootModes := maps.Keys(machine.UpgradeRequest_RebootMode_value) - sort.Slice(rebootModes, func(i, j int) bool { - return machine.UpgradeRequest_RebootMode_value[rebootModes[i]] < machine.UpgradeRequest_RebootMode_value[rebootModes[j]] + slices.SortFunc(rebootModes, func(a, b string) int { + return cmp.Compare(machine.UpgradeRequest_RebootMode_value[a], machine.UpgradeRequest_RebootMode_value[b]) }) rebootModes = xslices.Map(rebootModes, strings.ToLower) diff --git a/cmd/talosctl/pkg/talos/helpers/mode.go b/cmd/talosctl/pkg/talos/helpers/mode.go index 39368494b..78d75336c 100644 --- a/cmd/talosctl/pkg/talos/helpers/mode.go +++ b/cmd/talosctl/pkg/talos/helpers/mode.go @@ -7,7 +7,7 @@ package helpers import ( "fmt" "os" - "sort" + "slices" "strings" "github.com/siderolabs/gen/maps" @@ -61,7 +61,7 @@ func (m *Mode) Set(value string) error { // Type implements Flag interface. func (m *Mode) Type() string { options := maps.Keys(m.options) - sort.Strings(options) + slices.Sort(options) return strings.Join(options, ", ") } diff --git a/hack/module-sig-verify/main.go b/hack/module-sig-verify/main.go index 3f3d3df54..3f81dae08 100644 --- a/hack/module-sig-verify/main.go +++ b/hack/module-sig-verify/main.go @@ -82,12 +82,6 @@ func main() { } } -type noOPCloser struct { - io.ReadSeeker -} - -func (noOPCloser) Close() error { return nil } - func parseModuleInput(module string) (io.ReadSeekCloser, error) { if module == "-" { moduleData, err := io.ReadAll(os.Stdin) @@ -95,7 +89,13 @@ func parseModuleInput(module string) (io.ReadSeekCloser, error) { return nil, fmt.Errorf("failed to read module from stdin: %w", err) } - return noOPCloser{bytes.NewReader(moduleData)}, nil + return struct { + io.ReadSeeker + io.Closer + }{ + bytes.NewReader(moduleData), + io.NopCloser(nil), + }, nil } moduleData, err := os.Open(module) diff --git a/internal/app/apid/pkg/backend/apid.go b/internal/app/apid/pkg/backend/apid.go index 80857ca09..9ae8d7c61 100644 --- a/internal/app/apid/pkg/backend/apid.go +++ b/internal/app/apid/pkg/backend/apid.go @@ -8,6 +8,7 @@ import ( "context" "crypto/tls" "fmt" + "slices" "sync" "time" @@ -212,9 +213,8 @@ func (a *APID) AppendInfo(streaming bool, resp []byte) ([]byte, error) { protowire.AppendVarint(nil, (metadataField<<3)|metadataType), uint64(len(resp)+len(payload)), ) - resp = append(prefix, resp...) - return append(resp, payload...), err + return slices.Concat(prefix, resp, payload), err } // BuildError is called to convert error from upstream into response field. diff --git a/internal/app/machined/internal/server/v1alpha1/v1alpha1_cluster.go b/internal/app/machined/internal/server/v1alpha1/v1alpha1_cluster.go index 44f6c4112..a2985b826 100644 --- a/internal/app/machined/internal/server/v1alpha1/v1alpha1_cluster.go +++ b/internal/app/machined/internal/server/v1alpha1/v1alpha1_cluster.go @@ -140,7 +140,7 @@ func buildClusterInfo(ctx context.Context, } return &clusterState{ - nodeInfos: append(slices.Clone(controlPlaneNodeInfos), workerNodeInfos...), + nodeInfos: slices.Concat(controlPlaneNodeInfos, workerNodeInfos), nodeInfosByType: map[machine.Type][]cluster.NodeInfo{ machine.TypeControlPlane: controlPlaneNodeInfos, machine.TypeWorker: workerNodeInfos, diff --git a/internal/app/machined/pkg/adapters/network/nftables_rule.go b/internal/app/machined/pkg/adapters/network/nftables_rule.go index c79d754e2..4031acd22 100644 --- a/internal/app/machined/pkg/adapters/network/nftables_rule.go +++ b/internal/app/machined/pkg/adapters/network/nftables_rule.go @@ -676,36 +676,16 @@ func (a nftablesRule) Compile() (*NfTablesCompiled, error) { result.Rules = [][]expr.Any{append(rulePre, rulePost...)} case rule4 != nil && rule6 == nil: result.Rules = [][]expr.Any{ - append(rulePre, - append( - append(matchV4, rule4...), - rulePost..., - )..., - ), + slices.Concat(rulePre, matchV4, rule4, rulePost), } case rule4 == nil && rule6 != nil: result.Rules = [][]expr.Any{ - append(rulePre, - append( - append(matchV6, rule6...), - rulePost..., - )..., - ), + slices.Concat(rulePre, matchV6, rule6, rulePost), } case rule4 != nil && rule6 != nil: result.Rules = [][]expr.Any{ - append(slices.Clone(rulePre), - append( - append(matchV4, rule4...), - rulePost..., - )..., - ), - append(slices.Clone(rulePre), - append( - append(matchV6, rule6...), - rulePost..., - )..., - ), + slices.Concat(rulePre, matchV4, rule4, rulePost), + slices.Concat(rulePre, matchV6, rule6, rulePost), } } diff --git a/internal/app/machined/pkg/controllers/cluster/endpoint.go b/internal/app/machined/pkg/controllers/cluster/endpoint.go index a2e44637e..1cb9b566c 100644 --- a/internal/app/machined/pkg/controllers/cluster/endpoint.go +++ b/internal/app/machined/pkg/controllers/cluster/endpoint.go @@ -9,7 +9,6 @@ import ( "fmt" "net/netip" "slices" - "sort" "github.com/cosi-project/runtime/pkg/controller" "github.com/cosi-project/runtime/pkg/safe" @@ -75,7 +74,7 @@ func (ctrl *EndpointController) Run(ctx context.Context, r controller.Runtime, l endpoints = append(endpoints, memberSpec.Addresses...) } - sort.Slice(endpoints, func(i, j int) bool { return endpoints[i].Compare(endpoints[j]) < 0 }) + slices.SortFunc(endpoints, func(a, b netip.Addr) int { return a.Compare(b) }) if err := safe.WriterModify( ctx, diff --git a/internal/app/machined/pkg/controllers/ctest/assert.go b/internal/app/machined/pkg/controllers/ctest/assert.go index 7b1b4ccef..86032df14 100644 --- a/internal/app/machined/pkg/controllers/ctest/assert.go +++ b/internal/app/machined/pkg/controllers/ctest/assert.go @@ -6,7 +6,7 @@ package ctest import ( "fmt" - "sort" + "slices" "strings" "github.com/siderolabs/go-retry/retry" @@ -46,7 +46,7 @@ func (agg *assertionAggregator) Error() error { lines = append(lines, " * "+errorString) } - sort.Strings(lines) + slices.Sort(lines) return fmt.Errorf("%s", strings.Join(lines, "\n")) } diff --git a/internal/app/machined/pkg/controllers/etcd/spec.go b/internal/app/machined/pkg/controllers/etcd/spec.go index ed3079be9..78ae1a7ec 100644 --- a/internal/app/machined/pkg/controllers/etcd/spec.go +++ b/internal/app/machined/pkg/controllers/etcd/spec.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "net/netip" + "slices" "github.com/cosi-project/runtime/pkg/controller" "github.com/cosi-project/runtime/pkg/resource" @@ -144,13 +145,15 @@ func (ctrl *SpecController) Run(ctx context.Context, r controller.Runtime, _ *za advertiseValidSubnets = []string{"0.0.0.0/0", "::/0"} } - advertisedCIDRs := make([]string, 0, len(advertiseValidSubnets)+len(etcdConfig.TypedSpec().AdvertiseExcludeSubnets)) - advertisedCIDRs = append(advertisedCIDRs, advertiseValidSubnets...) - advertisedCIDRs = append(advertisedCIDRs, xslices.Map(etcdConfig.TypedSpec().AdvertiseExcludeSubnets, func(cidr string) string { return "!" + cidr })...) + advertisedCIDRs := slices.Concat( + advertiseValidSubnets, + xslices.Map(etcdConfig.TypedSpec().AdvertiseExcludeSubnets, func(cidr string) string { return "!" + cidr }), + ) - listenCIDRs := make([]string, 0, len(etcdConfig.TypedSpec().ListenValidSubnets)+len(etcdConfig.TypedSpec().ListenExcludeSubnets)) - listenCIDRs = append(listenCIDRs, etcdConfig.TypedSpec().ListenValidSubnets...) - listenCIDRs = append(listenCIDRs, xslices.Map(etcdConfig.TypedSpec().ListenExcludeSubnets, func(cidr string) string { return "!" + cidr })...) + listenCIDRs := slices.Concat( + etcdConfig.TypedSpec().ListenValidSubnets, + xslices.Map(etcdConfig.TypedSpec().ListenExcludeSubnets, func(cidr string) string { return "!" + cidr }), + ) defaultListenAddress := netip.AddrFrom4([4]byte{0, 0, 0, 0}) loopbackAddress := netip.AddrFrom4([4]byte{127, 0, 0, 1}) diff --git a/internal/app/machined/pkg/controllers/files/cri_config_parts.go b/internal/app/machined/pkg/controllers/files/cri_config_parts.go index 3abbd9e2a..b0734a3ab 100644 --- a/internal/app/machined/pkg/controllers/files/cri_config_parts.go +++ b/internal/app/machined/pkg/controllers/files/cri_config_parts.go @@ -8,7 +8,7 @@ import ( "context" "fmt" "path/filepath" - "sort" + "slices" "github.com/cosi-project/runtime/pkg/controller" "github.com/cosi-project/runtime/pkg/safe" @@ -70,7 +70,7 @@ func (ctrl *CRIConfigPartsController) Run(ctx context.Context, r controller.Runt return err } - sort.Strings(parts) + slices.Sort(parts) out, err := toml.Merge(parts) if err != nil { diff --git a/internal/app/machined/pkg/controllers/k8s/address_filter.go b/internal/app/machined/pkg/controllers/k8s/address_filter.go index d8723c0d8..06abca34b 100644 --- a/internal/app/machined/pkg/controllers/k8s/address_filter.go +++ b/internal/app/machined/pkg/controllers/k8s/address_filter.go @@ -97,7 +97,7 @@ func (ctrl *AddressFilterController) Run(ctx context.Context, r controller.Runti } if err = safe.WriterModify(ctx, r, network.NewNodeAddressFilter(network.NamespaceName, k8s.NodeAddressFilterNoK8s), func(r *network.NodeAddressFilter) error { - r.TypedSpec().ExcludeSubnets = append(slices.Clone(podCIDRs), serviceCIDRs...) + r.TypedSpec().ExcludeSubnets = slices.Concat(podCIDRs, serviceCIDRs) return nil }); err != nil { @@ -105,7 +105,7 @@ func (ctrl *AddressFilterController) Run(ctx context.Context, r controller.Runti } if err = safe.WriterModify(ctx, r, network.NewNodeAddressFilter(network.NamespaceName, k8s.NodeAddressFilterOnlyK8s), func(r *network.NodeAddressFilter) error { - r.TypedSpec().IncludeSubnets = append(slices.Clone(podCIDRs), serviceCIDRs...) + r.TypedSpec().IncludeSubnets = slices.Concat(podCIDRs, serviceCIDRs) return nil }); err != nil { diff --git a/internal/app/machined/pkg/controllers/k8s/nodeip.go b/internal/app/machined/pkg/controllers/k8s/nodeip.go index 20c905073..36ef22971 100644 --- a/internal/app/machined/pkg/controllers/k8s/nodeip.go +++ b/internal/app/machined/pkg/controllers/k8s/nodeip.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "net/netip" + "slices" "github.com/cosi-project/runtime/pkg/controller" "github.com/cosi-project/runtime/pkg/resource" @@ -99,10 +100,10 @@ func (ctrl *NodeIPController) Run(ctx context.Context, r controller.Runtime, log } addrs := nodeAddrs.TypedSpec().IPs() - - cidrs := make([]string, 0, len(cfgSpec.ValidSubnets)+len(cfgSpec.ExcludeSubnets)) - cidrs = append(cidrs, cfgSpec.ValidSubnets...) - cidrs = append(cidrs, xslices.Map(cfgSpec.ExcludeSubnets, func(cidr string) string { return "!" + cidr })...) + cidrs := slices.Concat( + cfgSpec.ValidSubnets, + xslices.Map(cfgSpec.ExcludeSubnets, func(cidr string) string { return "!" + cidr }), + ) ips, err := net.FilterIPs(addrs, cidrs) if err != nil { diff --git a/internal/app/machined/pkg/controllers/kubeaccess/serviceaccount/crd_controller.go b/internal/app/machined/pkg/controllers/kubeaccess/serviceaccount/crd_controller.go index babdca5fd..b352cd80c 100644 --- a/internal/app/machined/pkg/controllers/kubeaccess/serviceaccount/crd_controller.go +++ b/internal/app/machined/pkg/controllers/kubeaccess/serviceaccount/crd_controller.go @@ -13,7 +13,6 @@ import ( "errors" "fmt" "slices" - "sort" "sync" "time" @@ -584,8 +583,8 @@ func (t *CRDController) needsUpdate(secret *corev1.Secret, desiredRoles []string actualRoles := certificate.Subject.Organization - sort.Strings(actualRoles) - sort.Strings(desiredRoles) + slices.Sort(actualRoles) + slices.Sort(desiredRoles) if !slices.Equal(actualRoles, desiredRoles) { t.logger.Debug("roles in certificate do not match desired roles", diff --git a/internal/app/machined/pkg/controllers/kubespan/kubespan_test.go b/internal/app/machined/pkg/controllers/kubespan/kubespan_test.go index 5898d1a66..4ce0f3f30 100644 --- a/internal/app/machined/pkg/controllers/kubespan/kubespan_test.go +++ b/internal/app/machined/pkg/controllers/kubespan/kubespan_test.go @@ -7,7 +7,6 @@ package kubespan_test import ( "context" "slices" - "sort" "sync" "time" @@ -64,7 +63,7 @@ func (suite *KubeSpanSuite) assertResourceIDs(md resource.Metadata, expectedIDs actualIDs := xslices.Map(l.Items, func(r resource.Resource) string { return r.Metadata().ID() }) - sort.Strings(expectedIDs) + slices.Sort(expectedIDs) if !slices.Equal(actualIDs, expectedIDs) { return retry.ExpectedErrorf("ids do no match expected %v != actual %v", expectedIDs, actualIDs) diff --git a/internal/app/machined/pkg/controllers/network/address_config_test.go b/internal/app/machined/pkg/controllers/network/address_config_test.go index 50af71f8d..43a777d9d 100644 --- a/internal/app/machined/pkg/controllers/network/address_config_test.go +++ b/internal/app/machined/pkg/controllers/network/address_config_test.go @@ -5,11 +5,12 @@ package network_test import ( + "cmp" "context" "fmt" "net" "net/url" - "sort" + "slices" "sync" "testing" "time" @@ -126,7 +127,7 @@ func (suite *AddressConfigSuite) TestCmdlineNoNetmask() { ifaces, _ := net.Interfaces() //nolint:errcheck // ignoring error here as ifaces will be empty - sort.Slice(ifaces, func(i, j int) bool { return ifaces[i].Name < ifaces[j].Name }) + slices.SortFunc(ifaces, func(a, b net.Interface) int { return cmp.Compare(a.Name, b.Name) }) ifaceName := "" diff --git a/internal/app/machined/pkg/controllers/network/cmdline.go b/internal/app/machined/pkg/controllers/network/cmdline.go index b6fd5f9a2..02d572ce9 100644 --- a/internal/app/machined/pkg/controllers/network/cmdline.go +++ b/internal/app/machined/pkg/controllers/network/cmdline.go @@ -5,11 +5,12 @@ package network import ( + "cmp" "errors" "fmt" "net" "net/netip" - "sort" + "slices" "strconv" "strings" @@ -230,7 +231,7 @@ func ParseCmdlineNetwork(cmdline *procfs.Cmdline) (CmdlineNetworking, error) { if linkConfig.LinkName == "" { ifaces, _ := net.Interfaces() //nolint:errcheck // ignoring error here as ifaces will be empty - sort.Slice(ifaces, func(i, j int) bool { return ifaces[i].Name < ifaces[j].Name }) + slices.SortFunc(ifaces, func(a, b net.Interface) int { return cmp.Compare(a.Name, b.Name) }) for _, iface := range ifaces { if iface.Flags&net.FlagLoopback != 0 { diff --git a/internal/app/machined/pkg/controllers/network/cmdline_test.go b/internal/app/machined/pkg/controllers/network/cmdline_test.go index dafcbc194..f2c04a315 100644 --- a/internal/app/machined/pkg/controllers/network/cmdline_test.go +++ b/internal/app/machined/pkg/controllers/network/cmdline_test.go @@ -5,10 +5,11 @@ package network_test import ( + "cmp" "fmt" "net" "net/netip" - "sort" + "slices" "testing" "github.com/siderolabs/go-procfs/procfs" @@ -26,7 +27,7 @@ type CmdlineSuite struct { func (suite *CmdlineSuite) TestParse() { ifaces, _ := net.Interfaces() //nolint:errcheck // ignoring error here as ifaces will be empty - sort.Slice(ifaces, func(i, j int) bool { return ifaces[i].Name < ifaces[j].Name }) + slices.SortFunc(ifaces, func(a, b net.Interface) int { return cmp.Compare(a.Name, b.Name) }) defaultIfaceName := "" diff --git a/internal/app/machined/pkg/controllers/network/link_merge.go b/internal/app/machined/pkg/controllers/network/link_merge.go index 53a85c43b..ff660f161 100644 --- a/internal/app/machined/pkg/controllers/network/link_merge.go +++ b/internal/app/machined/pkg/controllers/network/link_merge.go @@ -6,9 +6,9 @@ package network import ( + "cmp" "context" "fmt" - "sort" "github.com/cosi-project/runtime/pkg/controller" "github.com/cosi-project/runtime/pkg/resource" @@ -65,32 +65,24 @@ func (ctrl *LinkMergeController) Run(ctx context.Context, r controller.Runtime, } // list source network configuration resources - list, err := r.List(ctx, resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, "", resource.VersionUndefined)) + list, err := safe.ReaderList[*network.LinkSpec](ctx, r, resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, "", resource.VersionUndefined)) if err != nil { return fmt.Errorf("error listing source network routes: %w", err) } // sort by link name, configuration layer - sort.Slice(list.Items, func(i, j int) bool { - left := list.Items[i].(*network.LinkSpec) //nolint:forcetypeassert - right := list.Items[j].(*network.LinkSpec) //nolint:forcetypeassert - - if left.TypedSpec().Name < right.TypedSpec().Name { - return false + list.SortFunc(func(left, right *network.LinkSpec) int { + if res := cmp.Compare(left.TypedSpec().Name, right.TypedSpec().Name); res != 0 { + return res } - if left.TypedSpec().Name == right.TypedSpec().Name { - return left.TypedSpec().ConfigLayer < right.TypedSpec().ConfigLayer - } - - return true + return cmp.Compare(left.TypedSpec().ConfigLayer, right.TypedSpec().ConfigLayer) }) // build final link definition merging multiple layers - links := map[string]*network.LinkSpecSpec{} + links := make(map[string]*network.LinkSpecSpec, list.Len()) - for _, res := range list.Items { - link := res.(*network.LinkSpec) //nolint:forcetypeassert + for link := range list.All() { id := network.LinkID(link.TypedSpec().Name) existing, ok := links[id] @@ -124,12 +116,12 @@ func (ctrl *LinkMergeController) Run(ctx context.Context, r controller.Runtime, } // list link for cleanup - list, err = r.List(ctx, resource.NewMetadata(network.NamespaceName, network.LinkSpecType, "", resource.VersionUndefined)) + list, err = safe.ReaderList[*network.LinkSpec](ctx, r, resource.NewMetadata(network.NamespaceName, network.LinkSpecType, "", resource.VersionUndefined)) if err != nil { return fmt.Errorf("error listing resources: %w", err) } - for _, res := range list.Items { + for res := range list.All() { if _, ok := links[res.Metadata().ID()]; !ok { var okToDestroy bool diff --git a/internal/app/machined/pkg/controllers/network/nftables_chain_config.go b/internal/app/machined/pkg/controllers/network/nftables_chain_config.go index cc10e9099..8f45f5172 100644 --- a/internal/app/machined/pkg/controllers/network/nftables_chain_config.go +++ b/internal/app/machined/pkg/controllers/network/nftables_chain_config.go @@ -192,13 +192,13 @@ func (ctrl *NfTablesChainConfigController) Run(ctx context.Context, r controller network.NfTablesRule{ MatchSourceAddress: &network.NfTablesAddressMatch{ IncludeSubnets: xslices.Map( - append(slices.Clone(cfg.Config().Cluster().Network().PodCIDRs()), cfg.Config().Cluster().Network().ServiceCIDRs()...), + slices.Concat(cfg.Config().Cluster().Network().PodCIDRs(), cfg.Config().Cluster().Network().ServiceCIDRs()), netip.MustParsePrefix, ), }, MatchDestinationAddress: &network.NfTablesAddressMatch{ IncludeSubnets: xslices.Map( - append(slices.Clone(cfg.Config().Cluster().Network().PodCIDRs()), cfg.Config().Cluster().Network().ServiceCIDRs()...), + slices.Concat(cfg.Config().Cluster().Network().PodCIDRs(), cfg.Config().Cluster().Network().ServiceCIDRs()), netip.MustParsePrefix, ), }, diff --git a/internal/app/machined/pkg/controllers/network/node_address.go b/internal/app/machined/pkg/controllers/network/node_address.go index 4a3c4e21e..e4bbe9ed4 100644 --- a/internal/app/machined/pkg/controllers/network/node_address.go +++ b/internal/app/machined/pkg/controllers/network/node_address.go @@ -320,16 +320,16 @@ func updateAccumulativeAddresses(ctx context.Context, r controller.Runtime, id r for _, ip := range accumulative { // find insert position using binary search - i := sort.Search(len(spec.Addresses), func(j int) bool { - return !spec.Addresses[j].Addr().Less(ip.Addr()) + pos, _ := slices.BinarySearchFunc(spec.Addresses, ip.Addr(), func(prefix netip.Prefix, addr netip.Addr) int { + return prefix.Addr().Compare(ip.Addr()) }) - if i < len(spec.Addresses) && spec.Addresses[i].Addr().Compare(ip.Addr()) == 0 { + if pos < len(spec.Addresses) && spec.Addresses[pos].Addr().Compare(ip.Addr()) == 0 { continue } // insert at position i - spec.Addresses = slices.Insert(spec.Addresses, i, ip) + spec.Addresses = slices.Insert(spec.Addresses, pos, ip) } return nil diff --git a/internal/app/machined/pkg/controllers/network/node_address_test.go b/internal/app/machined/pkg/controllers/network/node_address_test.go index 97f595f45..bc0435acb 100644 --- a/internal/app/machined/pkg/controllers/network/node_address_test.go +++ b/internal/app/machined/pkg/controllers/network/node_address_test.go @@ -7,7 +7,7 @@ package network_test import ( "net/netip" - "sort" + "slices" "strings" "testing" "time" @@ -51,9 +51,10 @@ func (suite *NodeAddressSuite) TestDefaults() { suite.T().Logf("id %q val %s", r.Metadata().ID(), addrs) asrt.True( - sort.SliceIsSorted( - addrs, func(i, j int) bool { - return addrs[i].Addr().Compare(addrs[j].Addr()) < 0 + slices.IsSortedFunc( + addrs, + func(a, b netip.Prefix) int { + return a.Addr().Compare(b.Addr()) }, ), "addresses %s", addrs, ) diff --git a/internal/app/machined/pkg/controllers/runtime/cri_image_gc_test.go b/internal/app/machined/pkg/controllers/runtime/cri_image_gc_test.go index 9ff1c182c..c9f3a4468 100644 --- a/internal/app/machined/pkg/controllers/runtime/cri_image_gc_test.go +++ b/internal/app/machined/pkg/controllers/runtime/cri_image_gc_test.go @@ -7,7 +7,6 @@ package runtime_test import ( "context" "slices" - "sort" "sync" "testing" "time" @@ -288,8 +287,8 @@ func TestBuildExpectedImageNames(t *testing.T) { expectedImageNames := maps.Keys(expectedImages) - sort.Strings(test.expectedImageNames) - sort.Strings(expectedImageNames) + slices.Sort(test.expectedImageNames) + slices.Sort(expectedImageNames) assert.Equal(t, test.expectedImageNames, expectedImageNames) }) diff --git a/internal/app/machined/pkg/runtime/drainer.go b/internal/app/machined/pkg/runtime/drainer.go index c9d79f4e0..0f7cc8888 100644 --- a/internal/app/machined/pkg/runtime/drainer.go +++ b/internal/app/machined/pkg/runtime/drainer.go @@ -7,6 +7,7 @@ package runtime import ( "context" "errors" + "slices" "sync" ) @@ -98,7 +99,7 @@ func (s *DrainSubscription) Cancel() { for i, sub := range s.drainer.subscriptions { if sub == s { - s.drainer.subscriptions = append(s.drainer.subscriptions[:i], s.drainer.subscriptions[i+1:]...) + s.drainer.subscriptions = slices.Delete(s.drainer.subscriptions, i, i+1) break } diff --git a/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/metadata.go b/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/metadata.go index d0b9776f9..d0ccb00cf 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/metadata.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud/metadata.go @@ -14,7 +14,7 @@ import ( "net/url" "os" "path/filepath" - "sort" + "slices" "strings" "github.com/cosi-project/runtime/pkg/safe" @@ -577,7 +577,7 @@ func (n *Nocloud) applyNetworkConfigV2(config *NetworkConfig, st state.State, ne } ethernetNames := maps.Keys(config.Ethernets) - sort.Strings(ethernetNames) + slices.Sort(ethernetNames) for _, name := range ethernetNames { eth := config.Ethernets[name] diff --git a/internal/app/machined/pkg/system/system.go b/internal/app/machined/pkg/system/system.go index 41fcd2d19..659f4747d 100644 --- a/internal/app/machined/pkg/system/system.go +++ b/internal/app/machined/pkg/system/system.go @@ -5,11 +5,12 @@ package system import ( + "cmp" "context" "errors" "fmt" "log" - "sort" + "slices" "strings" "sync" "time" @@ -386,7 +387,7 @@ func (s *singleton) List() (result []*ServiceRunner) { // TODO: results should be sorted properly with topological sort on dependencies // but, we don't have dependencies yet, so sort by service id for now to get stable order - sort.Slice(result, func(i, j int) bool { return result[i].id < result[j].id }) + slices.SortFunc(result, func(a, b *ServiceRunner) int { return cmp.Compare(a.id, b.id) }) return } diff --git a/internal/integration/api/reset.go b/internal/integration/api/reset.go index e12d7a820..ffb7f92e9 100644 --- a/internal/integration/api/reset.go +++ b/internal/integration/api/reset.go @@ -8,7 +8,7 @@ package api import ( "context" - "sort" + "slices" "testing" "time" @@ -73,7 +73,7 @@ func (suite *ResetSuite) TestResetNodeByNode() { nodes := suite.DiscoverNodeInternalIPs(suite.ctx) suite.Require().NotEmpty(nodes) - sort.Strings(nodes) + slices.Sort(nodes) for _, node := range nodes { suite.ResetNode(suite.ctx, node, &machineapi.ResetRequest{ diff --git a/internal/integration/base/cluster.go b/internal/integration/base/cluster.go index 65c20dddf..64d2736a5 100644 --- a/internal/integration/base/cluster.go +++ b/internal/integration/base/cluster.go @@ -30,7 +30,7 @@ func newNodeInfo(masterNodes, workerNodes []string) (*infoWrapper, error) { } return &infoWrapper{ - nodeInfos: append(slices.Clone(controlPlaneNodeInfos), workerNodeInfos...), + nodeInfos: slices.Concat(controlPlaneNodeInfos, workerNodeInfos), nodeInfosByType: map[machine.Type][]cluster.NodeInfo{ machine.TypeControlPlane: controlPlaneNodeInfos, machine.TypeWorker: workerNodeInfos, diff --git a/internal/integration/base/flags.go b/internal/integration/base/flags.go index dcbda66e3..f719cbbcf 100644 --- a/internal/integration/base/flags.go +++ b/internal/integration/base/flags.go @@ -6,7 +6,12 @@ package base -import "strings" +import ( + "slices" + "strings" + + "github.com/siderolabs/gen/xiter/xstrings" +) // StringList implements flag.Value for list of strings. type StringList []string @@ -18,7 +23,7 @@ func (l *StringList) String() string { // Set implements flag.Value. func (l *StringList) Set(value string) error { - *l = append(*l, strings.Split(value, ",")...) + *l = slices.AppendSeq(*l, xstrings.SplitSeq(value, ",")) return nil } diff --git a/internal/pkg/dashboard/components/footer.go b/internal/pkg/dashboard/components/footer.go index 2dafefcf0..e4d5f8dc6 100644 --- a/internal/pkg/dashboard/components/footer.go +++ b/internal/pkg/dashboard/components/footer.go @@ -6,7 +6,7 @@ package components import ( "fmt" - "sort" + "slices" "strings" "github.com/gdamore/tcell/v2" @@ -109,7 +109,7 @@ func (widget *Footer) nodesText() string { func (widget *Footer) screensText() string { screenKeys := maps.Keys(widget.screenKeyToName) - sort.Strings(screenKeys) + slices.Sort(screenKeys) screenTexts := make([]string, 0, len(widget.screenKeyToName)) diff --git a/internal/pkg/dashboard/components/networkinfo.go b/internal/pkg/dashboard/components/networkinfo.go index 784c187b6..d28b7a6cc 100644 --- a/internal/pkg/dashboard/components/networkinfo.go +++ b/internal/pkg/dashboard/components/networkinfo.go @@ -6,7 +6,7 @@ package components import ( "net/netip" - "sort" + "slices" "strings" "github.com/cosi-project/runtime/pkg/resource" @@ -197,11 +197,9 @@ func (widget *NetworkInfo) setAddresses(data resourcedata.Data, nodeAddress *net return notAvailable } - strs := xslices.Map(res.TypedSpec().Addresses, func(prefix netip.Prefix) string { - return prefix.String() - }) + strs := xslices.Map(res.TypedSpec().Addresses, netip.Prefix.String) - sort.Strings(strs) + slices.Sort(strs) return strings.Join(strs, ", ") } @@ -238,8 +236,8 @@ func (widget *NetworkInfo) gateway(statuses []*network.RouteStatus) string { return notAvailable } - sort.Strings(gatewaysV4) - sort.Strings(gatewaysV6) + slices.Sort(gatewaysV4) + slices.Sort(gatewaysV6) return strings.Join(append(gatewaysV4, gatewaysV6...), ", ") } diff --git a/internal/pkg/dashboard/networkconfig.go b/internal/pkg/dashboard/networkconfig.go index 40ca32bf4..a237cdb80 100644 --- a/internal/pkg/dashboard/networkconfig.go +++ b/internal/pkg/dashboard/networkconfig.go @@ -7,7 +7,7 @@ package dashboard import ( "context" "fmt" - "sort" + "slices" "strings" "github.com/gdamore/tcell/v2" @@ -348,7 +348,7 @@ func (widget *NetworkConfigGrid) updateNodeData(data resourcedata.Data) { links := maps.Keys(nodeData.linkSet) - sort.Strings(links) + slices.Sort(links) allLinks := append([]string{interfaceNone}, links...) diff --git a/internal/pkg/encryption/encryption.go b/internal/pkg/encryption/encryption.go index 47e51f90d..e83d59646 100644 --- a/internal/pkg/encryption/encryption.go +++ b/internal/pkg/encryption/encryption.go @@ -6,11 +6,12 @@ package encryption import ( + "cmp" "context" "encoding/json" "errors" "fmt" - "sort" + "slices" "strconv" "time" @@ -66,7 +67,7 @@ func NewHandler(encryptionConfig block.EncryptionSpec, volumeID string, getSyste } //nolint:scopelint - sort.Slice(keyHandlers, func(i, j int) bool { return keyHandlers[i].Slot() < keyHandlers[j].Slot() }) + slices.SortFunc(keyHandlers, func(a, b keys.Handler) int { return cmp.Compare(a.Slot(), b.Slot()) }) provider := luks.New( cipher, diff --git a/internal/pkg/extensions/list.go b/internal/pkg/extensions/list.go index 897be05d7..61c117a16 100644 --- a/internal/pkg/extensions/list.go +++ b/internal/pkg/extensions/list.go @@ -5,10 +5,11 @@ package extensions import ( + "cmp" "fmt" "os" "path/filepath" - "sort" + "slices" "github.com/siderolabs/talos/pkg/machinery/extensions" ) @@ -28,7 +29,7 @@ func List(rootPath string) ([]*Extension, error) { return nil, nil } - sort.Slice(items, func(i, j int) bool { return items[i].Name() < items[j].Name() }) + slices.SortFunc(items, func(a, b os.DirEntry) int { return cmp.Compare(a.Name(), b.Name()) }) result := make([]*Extension, 0, len(items)) diff --git a/internal/pkg/meta/internal/adv/talos/talos_test.go b/internal/pkg/meta/internal/adv/talos/talos_test.go index 8a1235691..8efd2a0b4 100644 --- a/internal/pkg/meta/internal/adv/talos/talos_test.go +++ b/internal/pkg/meta/internal/adv/talos/talos_test.go @@ -7,7 +7,6 @@ package talos_test import ( "bytes" "slices" - "sort" "testing" "github.com/stretchr/testify/assert" @@ -86,7 +85,7 @@ func TestMarshalUnmarshal(t *testing.T) { assert.Equal(t, val3, val) tags := a.ListTags() - sort.Slice(tags, func(i, j int) bool { return tags[i] < tags[j] }) + slices.Sort(tags) assert.Equal(t, []uint8{adv.Reserved1, adv.Reserved2, adv.Reserved3}, tags) } } diff --git a/pkg/archiver/archiver_test.go b/pkg/archiver/archiver_test.go index 136864618..efed8036f 100644 --- a/pkg/archiver/archiver_test.go +++ b/pkg/archiver/archiver_test.go @@ -8,6 +8,7 @@ import ( "bytes" "os" "path/filepath" + "slices" "github.com/stretchr/testify/suite" ) @@ -74,8 +75,10 @@ func (suite *CommonSuite) SetupSuite() { var contents []byte if file.Size > 0 { - contents = bytes.Repeat(file.Contents, file.Size/len(file.Contents)) - contents = append(contents, file.Contents[:file.Size-file.Size/len(file.Contents)*len(file.Contents)]...) + contents = slices.Concat( + bytes.Repeat(file.Contents, file.Size/len(file.Contents)), + file.Contents[:file.Size-file.Size/len(file.Contents)*len(file.Contents)], + ) } else { contents = file.Contents } diff --git a/pkg/argsbuilder/argsbuilder_args.go b/pkg/argsbuilder/argsbuilder_args.go index 136fc138d..d8ca283f0 100644 --- a/pkg/argsbuilder/argsbuilder_args.go +++ b/pkg/argsbuilder/argsbuilder_args.go @@ -6,7 +6,7 @@ package argsbuilder import ( "fmt" - "sort" + "slices" "strings" "github.com/siderolabs/gen/maps" @@ -92,7 +92,7 @@ func (a Args) Set(k, v Key) ArgsBuilder { // Args implements the ArgsBuilder interface. func (a Args) Args() []string { keys := maps.Keys(a) - sort.Strings(keys) + slices.Sort(keys) args := make([]string, 0, len(a)) diff --git a/pkg/cluster/bootstrap.go b/pkg/cluster/bootstrap.go index b053240e4..ed499ea98 100644 --- a/pkg/cluster/bootstrap.go +++ b/pkg/cluster/bootstrap.go @@ -9,7 +9,7 @@ import ( "errors" "fmt" "io" - "sort" + "slices" "strings" "time" @@ -45,9 +45,7 @@ func (s *APIBootstrapper) Bootstrap(ctx context.Context, out io.Writer) error { return errors.New("no control plane nodes to bootstrap") } - sort.Slice(controlPlaneNodes, func(i, j int) bool { - return controlPlaneNodes[i].IPs[0].String() < controlPlaneNodes[j].IPs[0].String() - }) + slices.SortFunc(controlPlaneNodes, func(a, b NodeInfo) int { return strings.Compare(a.IPs[0].String(), b.IPs[0].String()) }) nodeIP := controlPlaneNodes[0].IPs[0] nodeCtx := client.WithNodes(ctx, nodeIP.String()) diff --git a/pkg/cluster/check/etcd.go b/pkg/cluster/check/etcd.go index b3c5d8f53..6f89d6c32 100644 --- a/pkg/cluster/check/etcd.go +++ b/pkg/cluster/check/etcd.go @@ -5,11 +5,12 @@ package check import ( + "cmp" "context" "errors" "fmt" "net/url" - "sort" + "slices" "github.com/siderolabs/gen/maps" "github.com/siderolabs/gen/xslices" @@ -55,8 +56,8 @@ func EtcdConsistentAssertion(ctx context.Context, cl ClusterInfo) error { return errors.New("no messages returned") } - sort.Slice(messages, func(i, j int) bool { - return messages[i].GetMetadata().GetHostname() < messages[j].GetMetadata().GetHostname() + slices.SortFunc(messages, func(a, b *machineapi.EtcdMembers) int { + return cmp.Compare(a.GetMetadata().GetHostname(), b.GetMetadata().GetHostname()) }) for i, message := range messages { diff --git a/pkg/cluster/check/service.go b/pkg/cluster/check/service.go index 37a3dac40..ee304cebf 100644 --- a/pkg/cluster/check/service.go +++ b/pkg/cluster/check/service.go @@ -6,10 +6,11 @@ package check import ( + "cmp" "context" "errors" "fmt" - "sort" + "slices" "github.com/hashicorp/go-multierror" @@ -111,8 +112,8 @@ func ServiceHealthAssertion(ctx context.Context, cl ClusterInfo, service string, var multiErr *multierror.Error // sort service info list so that errors returned are consistent - sort.Slice(servicesInfo, func(i, j int) bool { - return servicesInfo[i].Metadata.GetHostname() < servicesInfo[j].Metadata.GetHostname() + slices.SortFunc(servicesInfo, func(a, b client.ServiceInfo) int { + return cmp.Compare(a.Metadata.GetHostname(), b.Metadata.GetHostname()) }) for _, serviceInfo := range servicesInfo { diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index cd984353c..f40bc2082 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -10,7 +10,7 @@ import ( "fmt" "io" "net/netip" - "sort" + "slices" "github.com/siderolabs/gen/maps" "github.com/siderolabs/gen/xslices" @@ -123,7 +123,7 @@ func NodesMatch(expected, actual []NodeInfo) error { if len(actualNodes) > 0 { unexpectedIPs := xslices.FlatMap(maps.Keys(actualNodes), func(n *NodeInfo) []netip.Addr { return n.IPs }) - sort.Slice(unexpectedIPs, func(i, j int) bool { return unexpectedIPs[i].Less(unexpectedIPs[j]) }) + slices.SortFunc(unexpectedIPs, func(a, b netip.Addr) int { return a.Compare(b) }) return fmt.Errorf("unexpected nodes with IPs %q", unexpectedIPs) } diff --git a/pkg/cluster/kubernetes/kubelet.go b/pkg/cluster/kubernetes/kubelet.go index 55c3cf118..915c36b3c 100644 --- a/pkg/cluster/kubernetes/kubelet.go +++ b/pkg/cluster/kubernetes/kubelet.go @@ -15,6 +15,7 @@ import ( "github.com/cosi-project/runtime/pkg/resource" "github.com/cosi-project/runtime/pkg/safe" "github.com/cosi-project/runtime/pkg/state" + "github.com/siderolabs/gen/xiter" "github.com/siderolabs/go-retry/retry" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -37,7 +38,7 @@ func upgradeKubelet(ctx context.Context, cluster UpgradeProvider, options Upgrad options.Log("updating kubelet to version %q", options.Path.ToVersion()) - for _, node := range append(slices.Clone(options.controlPlaneNodes), options.workerNodes...) { + for node := range xiter.Concat(slices.Values(options.controlPlaneNodes), slices.Values(options.workerNodes)) { if err := upgradeKubeletOnNode(ctx, cluster, options, node); err != nil { return fmt.Errorf("error updating node %q: %w", node, err) } diff --git a/pkg/cluster/kubernetes/talos_managed.go b/pkg/cluster/kubernetes/talos_managed.go index f81a9b161..545988c73 100644 --- a/pkg/cluster/kubernetes/talos_managed.go +++ b/pkg/cluster/kubernetes/talos_managed.go @@ -8,12 +8,14 @@ import ( "context" "errors" "fmt" + "slices" "strings" "time" "github.com/cosi-project/runtime/pkg/resource" "github.com/cosi-project/runtime/pkg/state" "github.com/siderolabs/gen/channel" + "github.com/siderolabs/gen/xiter" "github.com/siderolabs/go-kubernetes/kubernetes/manifests" "github.com/siderolabs/go-kubernetes/kubernetes/upgrade" "google.golang.org/grpc/codes" @@ -148,7 +150,7 @@ func prePullImages(ctx context.Context, talosClient *client.Client, options Upgr imageRef := fmt.Sprintf("%s:v%s", options.KubeletImage, options.Path.ToVersion()) - for _, node := range append(append([]string(nil), options.controlPlaneNodes...), options.workerNodes...) { + for node := range xiter.Concat(slices.Values(options.controlPlaneNodes), slices.Values(options.workerNodes)) { options.Log(" > %q: pre-pulling %s", node, imageRef) err := talosClient.ImagePull(client.WithNode(ctx, node), common.ContainerdNamespace_NS_SYSTEM, imageRef) diff --git a/pkg/grpc/middleware/log/log.go b/pkg/grpc/middleware/log/log.go index 1fb287cf0..5d7889bdd 100644 --- a/pkg/grpc/middleware/log/log.go +++ b/pkg/grpc/middleware/log/log.go @@ -8,7 +8,7 @@ package log import ( "context" "log" - "sort" + "slices" "strings" "time" @@ -38,7 +38,7 @@ var sensitiveFields = map[string]struct{}{ func ExtractMetadata(ctx context.Context) string { md, _ := metadata.FromIncomingContext(ctx) keys := maps.Keys(md) - sort.Strings(keys) + slices.Sort(keys) pairs := make([]string, 0, len(keys)) diff --git a/pkg/imager/filemap/filemap.go b/pkg/imager/filemap/filemap.go index ff045dd57..2326c5569 100644 --- a/pkg/imager/filemap/filemap.go +++ b/pkg/imager/filemap/filemap.go @@ -7,10 +7,11 @@ package filemap import ( "archive/tar" + "cmp" "io" "os" "path/filepath" - "sort" + "slices" v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/tarball" @@ -105,9 +106,7 @@ func build(filemap []File) io.ReadCloser { // // A filemap is a path -> file content map representing a file system. func Layer(filemap []File) (v1.Layer, error) { - sort.Slice(filemap, func(i, j int) bool { - return filemap[i].ImagePath < filemap[j].ImagePath - }) + slices.SortFunc(filemap, func(a, b File) int { return cmp.Compare(a.ImagePath, b.ImagePath) }) // Return a new copy of the buffer each time it's opened. return tarball.LayerFromOpener(func() (io.ReadCloser, error) { diff --git a/pkg/machinery/config/container/container.go b/pkg/machinery/config/container/container.go index 55e8eb5e6..3144a5d0c 100644 --- a/pkg/machinery/config/container/container.go +++ b/pkg/machinery/config/container/container.go @@ -10,6 +10,7 @@ import ( "context" "errors" "fmt" + "slices" "strings" "github.com/cosi-project/runtime/pkg/state" @@ -122,7 +123,7 @@ func (container *Container) PatchV1Alpha1(patcher func(*v1alpha1.Config) error) return !ok }) - return New(append([]config.Document{cfg}, otherDocs...)...) + return New(slices.Insert(otherDocs, 0, config.Document(cfg))...) } // Readonly implements config.Container interface. diff --git a/pkg/machinery/config/encoder/encoder.go b/pkg/machinery/config/encoder/encoder.go index 8e379b682..e4829e015 100644 --- a/pkg/machinery/config/encoder/encoder.go +++ b/pkg/machinery/config/encoder/encoder.go @@ -5,9 +5,10 @@ package encoder import ( + "cmp" "encoding" "reflect" - "sort" + "slices" "strings" yaml "gopkg.in/yaml.v3" @@ -287,9 +288,7 @@ func toYamlNode(in any, options *Options) (*yaml.Node, error) { node.Kind = yaml.MappingNode keys := v.MapKeys() // always interate keys in alphabetical order to preserve the same output for maps - sort.Slice(keys, func(i, j int) bool { - return keys[i].String() < keys[j].String() - }) + slices.SortFunc(keys, func(a, b reflect.Value) int { return cmp.Compare(a.String(), b.String()) }) for _, k := range keys { element := v.MapIndex(k) diff --git a/pkg/machinery/config/merge/merge_test.go b/pkg/machinery/config/merge/merge_test.go index 0a4e185fe..113f3cbd4 100644 --- a/pkg/machinery/config/merge/merge_test.go +++ b/pkg/machinery/config/merge/merge_test.go @@ -6,7 +6,7 @@ package merge_test import ( "fmt" - "sort" + "slices" "testing" "github.com/siderolabs/go-pointer" @@ -40,7 +40,7 @@ func (s *CustomSlice) Merge(other any) error { } *s = append(*s, otherSlice...) - sort.Strings(*s) + slices.Sort(*s) return nil } diff --git a/pkg/machinery/formatters/formatters.go b/pkg/machinery/formatters/formatters.go index dc30c0197..808137e61 100644 --- a/pkg/machinery/formatters/formatters.go +++ b/pkg/machinery/formatters/formatters.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "math" + "slices" "strings" "text/tabwriter" "time" @@ -58,7 +59,7 @@ func RenderMounts(resp *machine.MountsResponse, output io.Writer, remotePeer *pe if defaultNode != "" { format = "%s\t" + format - args = append([]any{node}, args...) + args = slices.Insert(args, 0, any(node)) } fmt.Fprintf(w, format, args...) diff --git a/pkg/machinery/resources/k8s/endpoint.go b/pkg/machinery/resources/k8s/endpoint.go index 9fe0c2dcb..051e3ead6 100644 --- a/pkg/machinery/resources/k8s/endpoint.go +++ b/pkg/machinery/resources/k8s/endpoint.go @@ -6,7 +6,7 @@ package k8s import ( "net/netip" - "sort" + "slices" "github.com/cosi-project/runtime/pkg/resource" "github.com/cosi-project/runtime/pkg/resource/meta" @@ -71,13 +71,14 @@ type EndpointList []netip.Addr // Merge endpoints from multiple Endpoint resources into a single list. func (l EndpointList) Merge(endpoint *Endpoint) EndpointList { for _, ip := range endpoint.TypedSpec().Addresses { - idx := sort.Search(len(l), func(i int) bool { return !l[i].Less(ip) }) - + idx, _ := slices.BinarySearchFunc(l, ip, func(a netip.Addr, target netip.Addr) int { + return a.Compare(target) + }) if idx < len(l) && l[idx].Compare(ip) == 0 { continue } - l = append(l[:idx], append([]netip.Addr{ip}, l[idx:]...)...) + l = slices.Insert(l, idx, ip) } return l diff --git a/pkg/machinery/resources/secrets/cert_sans.go b/pkg/machinery/resources/secrets/cert_sans.go index 08f8727e3..14d3c505f 100644 --- a/pkg/machinery/resources/secrets/cert_sans.go +++ b/pkg/machinery/resources/secrets/cert_sans.go @@ -7,7 +7,7 @@ package secrets import ( "net" "net/netip" - "sort" + "slices" "github.com/cosi-project/runtime/pkg/resource" "github.com/cosi-project/runtime/pkg/resource/meta" @@ -126,8 +126,8 @@ func (spec *CertSANSpec) StdIPs() []net.IP { // Sort the CertSANs. func (spec *CertSANSpec) Sort() { - sort.Strings(spec.DNSNames) - sort.Slice(spec.IPs, func(i, j int) bool { return spec.IPs[i].Compare(spec.IPs[j]) < 0 }) + slices.Sort(spec.DNSNames) + slices.SortFunc(spec.IPs, func(a, b netip.Addr) int { return a.Compare(b) }) } func init() { diff --git a/pkg/machinery/role/role.go b/pkg/machinery/role/role.go index 89d7fe713..4789cd848 100644 --- a/pkg/machinery/role/role.go +++ b/pkg/machinery/role/role.go @@ -5,7 +5,7 @@ package role import ( - "sort" + "slices" "strings" "github.com/siderolabs/gen/maps" @@ -93,7 +93,7 @@ func Parse(str []string) (Set, []string) { // Strings returns a set as a slice of strings. func (s Set) Strings() []string { res := maps.KeysFunc(s.roles, func(r Role) string { return string(r) }) - sort.Strings(res) + slices.Sort(res) return res } diff --git a/pkg/provision/providers/qemu/preflight.go b/pkg/provision/providers/qemu/preflight.go index d71fe895e..4c6fddac9 100644 --- a/pkg/provision/providers/qemu/preflight.go +++ b/pkg/provision/providers/qemu/preflight.go @@ -12,6 +12,7 @@ import ( "os/exec" "path/filepath" "runtime" + "slices" "strings" "github.com/coreos/go-iptables/iptables" @@ -52,7 +53,7 @@ type preflightCheckContext struct { arch Arch } -func (check *preflightCheckContext) verifyRoot(ctx context.Context) error { +func (check *preflightCheckContext) verifyRoot(context.Context) error { if os.Geteuid() != 0 { return errors.New("error: please run as root user (CNI requirement), we recommend running with `sudo -E`") } @@ -60,7 +61,7 @@ func (check *preflightCheckContext) verifyRoot(ctx context.Context) error { return nil } -func (check *preflightCheckContext) checkKVM(ctx context.Context) error { +func (check *preflightCheckContext) checkKVM(context.Context) error { f, err := os.OpenFile("/dev/kvm", os.O_RDWR, 0) if err != nil { return fmt.Errorf("error opening /dev/kvm, please make sure KVM support is enabled in Linux kernel: %w", err) @@ -69,7 +70,7 @@ func (check *preflightCheckContext) checkKVM(ctx context.Context) error { return f.Close() } -func (check *preflightCheckContext) qemuExecutable(ctx context.Context) error { +func (check *preflightCheckContext) qemuExecutable(context.Context) error { if check.arch.QemuExecutable() == "" { return fmt.Errorf("QEMU executable (qemu-system-%s or qemu-kvm) not found, please install QEMU with package manager", check.arch.QemuArch()) } @@ -77,7 +78,7 @@ func (check *preflightCheckContext) qemuExecutable(ctx context.Context) error { return nil } -func (check *preflightCheckContext) checkFlashImages(ctx context.Context) error { +func (check *preflightCheckContext) checkFlashImages(context.Context) error { for _, flashImage := range check.arch.PFlash(check.options.UEFIEnabled, check.options.ExtraUEFISearchPaths) { if len(flashImage.SourcePaths) == 0 { continue @@ -103,7 +104,7 @@ func (check *preflightCheckContext) checkFlashImages(ctx context.Context) error return nil } -func (check *preflightCheckContext) swtpmExecutable(ctx context.Context) error { +func (check *preflightCheckContext) swtpmExecutable(context.Context) error { if check.options.TPM2Enabled { if _, err := exec.LookPath("swtpm"); err != nil { return fmt.Errorf("swtpm not found in PATH, please install swtpm-tools with the package manager: %w", err) @@ -113,8 +114,8 @@ func (check *preflightCheckContext) swtpmExecutable(ctx context.Context) error { return nil } -func (check *preflightCheckContext) cniDirectories(ctx context.Context) error { - cniDirs := append([]string{}, check.request.Network.CNI.BinPath...) +func (check *preflightCheckContext) cniDirectories(context.Context) error { + cniDirs := slices.Clone(check.request.Network.CNI.BinPath) cniDirs = append(cniDirs, check.request.Network.CNI.CacheDir, check.request.Network.CNI.ConfDir) for _, cniDir := range cniDirs { diff --git a/pkg/provision/providers/vm/node.go b/pkg/provision/providers/vm/node.go index ff70aba88..c7e5528f7 100644 --- a/pkg/provision/providers/vm/node.go +++ b/pkg/provision/providers/vm/node.go @@ -6,6 +6,7 @@ package vm import ( "fmt" + "slices" multierror "github.com/hashicorp/go-multierror" @@ -16,8 +17,7 @@ import ( func (p *Provisioner) DestroyNodes(cluster provision.ClusterInfo, options *provision.Options) error { errCh := make(chan error) - nodes := append([]provision.NodeInfo{}, cluster.Nodes...) - nodes = append(nodes, cluster.ExtraNodes...) + nodes := slices.Concat(cluster.Nodes, cluster.ExtraNodes) for _, node := range nodes { go func(node provision.NodeInfo) {