diff --git a/cli/command/config/ls.go b/cli/command/config/ls.go index dd2d89edb6..d87a3c9de4 100644 --- a/cli/command/config/ls.go +++ b/cli/command/config/ls.go @@ -9,19 +9,10 @@ import ( "github.com/docker/cli/cli/command/formatter" "github.com/docker/cli/opts" "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" "github.com/spf13/cobra" "vbom.ml/util/sortorder" ) -type byConfigName []swarm.Config - -func (r byConfigName) Len() int { return len(r) } -func (r byConfigName) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byConfigName) Less(i, j int) bool { - return sortorder.NaturalLess(r[i].Spec.Name, r[j].Spec.Name) -} - type listOptions struct { quiet bool format string @@ -67,7 +58,9 @@ func runConfigList(dockerCli command.Cli, options listOptions) error { } } - sort.Sort(byConfigName(configs)) + sort.Slice(configs, func(i, j int) bool { + return sortorder.NaturalLess(configs[i].Spec.Name, configs[j].Spec.Name) + }) configCtx := formatter.Context{ Output: dockerCli.Out(), diff --git a/cli/command/formatter/container.go b/cli/command/formatter/container.go index 028a9f6ee6..cf42555b79 100644 --- a/cli/command/formatter/container.go +++ b/cli/command/formatter/container.go @@ -269,7 +269,10 @@ func DisplayablePorts(ports []types.Port) string { var result []string var hostMappings []string var groupMapKeys []string - sort.Sort(byPortInfo(ports)) + sort.Slice(ports, func(i, j int) bool { + return comparePorts(ports[i], ports[j]) + }) + for _, port := range ports { current := port.PrivatePort portKey := port.Type @@ -322,23 +325,18 @@ func formGroup(key string, start, last uint16) string { return fmt.Sprintf("%s/%s", group, groupType) } -// byPortInfo is a temporary type used to sort types.Port by its fields -type byPortInfo []types.Port - -func (r byPortInfo) Len() int { return len(r) } -func (r byPortInfo) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byPortInfo) Less(i, j int) bool { - if r[i].PrivatePort != r[j].PrivatePort { - return r[i].PrivatePort < r[j].PrivatePort +func comparePorts(i, j types.Port) bool { + if i.PrivatePort != j.PrivatePort { + return i.PrivatePort < j.PrivatePort } - if r[i].IP != r[j].IP { - return r[i].IP < r[j].IP + if i.IP != j.IP { + return i.IP < j.IP } - if r[i].PublicPort != r[j].PublicPort { - return r[i].PublicPort < r[j].PublicPort + if i.PublicPort != j.PublicPort { + return i.PublicPort < j.PublicPort } - return r[i].Type < r[j].Type + return i.Type < j.Type } diff --git a/cli/command/formatter/service.go b/cli/command/formatter/service.go index 5dde8006d2..7e98c314c9 100644 --- a/cli/command/formatter/service.go +++ b/cli/command/formatter/service.go @@ -599,7 +599,13 @@ func (c *serviceContext) Ports() string { pr := portRange{} ports := []string{} - sort.Sort(byProtocolAndPublishedPort(c.service.Endpoint.Ports)) + servicePorts := c.service.Endpoint.Ports + sort.Slice(servicePorts, func(i, j int) bool { + if servicePorts[i].Protocol == servicePorts[j].Protocol { + return servicePorts[i].PublishedPort < servicePorts[j].PublishedPort + } + return servicePorts[i].Protocol < servicePorts[j].Protocol + }) for _, p := range c.service.Endpoint.Ports { if p.PublishMode == swarm.PortConfigPublishModeIngress { @@ -633,14 +639,3 @@ func (c *serviceContext) Ports() string { } return strings.Join(ports, ", ") } - -type byProtocolAndPublishedPort []swarm.PortConfig - -func (a byProtocolAndPublishedPort) Len() int { return len(a) } -func (a byProtocolAndPublishedPort) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byProtocolAndPublishedPort) Less(i, j int) bool { - if a[i].Protocol == a[j].Protocol { - return a[i].PublishedPort < a[j].PublishedPort - } - return a[i].Protocol < a[j].Protocol -} diff --git a/cli/command/network/list.go b/cli/command/network/list.go index 391919299e..30c1e7d122 100644 --- a/cli/command/network/list.go +++ b/cli/command/network/list.go @@ -12,12 +12,6 @@ import ( "github.com/spf13/cobra" ) -type byNetworkName []types.NetworkResource - -func (r byNetworkName) Len() int { return len(r) } -func (r byNetworkName) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byNetworkName) Less(i, j int) bool { return r[i].Name < r[j].Name } - type listOptions struct { quiet bool noTrunc bool @@ -64,7 +58,9 @@ func runList(dockerCli command.Cli, options listOptions) error { } } - sort.Sort(byNetworkName(networkResources)) + sort.Slice(networkResources, func(i, j int) bool { + return networkResources[i].Name < networkResources[j].Name + }) networksCtx := formatter.Context{ Output: dockerCli.Out(), diff --git a/cli/command/node/list.go b/cli/command/node/list.go index d35ed0ea8f..69f40ddeb6 100644 --- a/cli/command/node/list.go +++ b/cli/command/node/list.go @@ -9,19 +9,10 @@ import ( "github.com/docker/cli/cli/command/formatter" "github.com/docker/cli/opts" "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" "github.com/spf13/cobra" "vbom.ml/util/sortorder" ) -type byHostname []swarm.Node - -func (n byHostname) Len() int { return len(n) } -func (n byHostname) Swap(i, j int) { n[i], n[j] = n[j], n[i] } -func (n byHostname) Less(i, j int) bool { - return sortorder.NaturalLess(n[i].Description.Hostname, n[j].Description.Hostname) -} - type listOptions struct { quiet bool format string @@ -80,6 +71,8 @@ func runList(dockerCli command.Cli, options listOptions) error { Output: dockerCli.Out(), Format: formatter.NewNodeFormat(format, options.quiet), } - sort.Sort(byHostname(nodes)) + sort.Slice(nodes, func(i, j int) bool { + return sortorder.NaturalLess(nodes[i].Description.Hostname, nodes[j].Description.Hostname) + }) return formatter.NodeWrite(nodesCtx, nodes, info) } diff --git a/cli/command/secret/ls.go b/cli/command/secret/ls.go index a778137e48..424ac57b3f 100644 --- a/cli/command/secret/ls.go +++ b/cli/command/secret/ls.go @@ -9,19 +9,10 @@ import ( "github.com/docker/cli/cli/command/formatter" "github.com/docker/cli/opts" "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" "github.com/spf13/cobra" "vbom.ml/util/sortorder" ) -type bySecretName []swarm.Secret - -func (r bySecretName) Len() int { return len(r) } -func (r bySecretName) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r bySecretName) Less(i, j int) bool { - return sortorder.NaturalLess(r[i].Spec.Name, r[j].Spec.Name) -} - type listOptions struct { quiet bool format string @@ -66,7 +57,9 @@ func runSecretList(dockerCli command.Cli, options listOptions) error { } } - sort.Sort(bySecretName(secrets)) + sort.Slice(secrets, func(i, j int) bool { + return sortorder.NaturalLess(secrets[i].Spec.Name, secrets[j].Spec.Name) + }) secretCtx := formatter.Context{ Output: dockerCli.Out(), diff --git a/cli/command/service/list.go b/cli/command/service/list.go index db4b037694..e65a9be075 100644 --- a/cli/command/service/list.go +++ b/cli/command/service/list.go @@ -44,12 +44,6 @@ func newListCommand(dockerCli command.Cli) *cobra.Command { return cmd } -type byName []swarm.Service - -func (n byName) Len() int { return len(n) } -func (n byName) Swap(i, j int) { n[i], n[j] = n[j], n[i] } -func (n byName) Less(i, j int) bool { return sortorder.NaturalLess(n[i].Spec.Name, n[j].Spec.Name) } - func runList(dockerCli command.Cli, options listOptions) error { ctx := context.Background() client := dockerCli.Client() @@ -60,7 +54,9 @@ func runList(dockerCli command.Cli, options listOptions) error { return err } - sort.Sort(byName(services)) + sort.Slice(services, func(i, j int) bool { + return sortorder.NaturalLess(services[i].Spec.Name, services[j].Spec.Name) + }) info := map[string]formatter.ServiceListInfo{} if len(services) > 0 && !options.quiet { // only non-empty services and not quiet, should we call TaskList and NodeList api diff --git a/cli/command/service/opts.go b/cli/command/service/opts.go index 6a9591abce..834b537048 100644 --- a/cli/command/service/opts.go +++ b/cli/command/service/opts.go @@ -598,7 +598,9 @@ func (options *serviceOptions) ToService(ctx context.Context, apiClient client.N } networks[i].Target = nwID } - sort.Sort(byNetworkTarget(networks)) + sort.Slice(networks, func(i, j int) bool { + return networks[i].Target < networks[j].Target + }) resources, err := options.resources.ToResourceRequirements() if err != nil { diff --git a/cli/command/service/update.go b/cli/command/service/update.go index 3e380db23e..9076a9a4b9 100644 --- a/cli/command/service/update.go +++ b/cli/command/service/update.go @@ -753,20 +753,6 @@ func removeItems( return newSeq } -type byMountSource []mounttypes.Mount - -func (m byMountSource) Len() int { return len(m) } -func (m byMountSource) Swap(i, j int) { m[i], m[j] = m[j], m[i] } -func (m byMountSource) Less(i, j int) bool { - a, b := m[i], m[j] - - if a.Source == b.Source { - return a.Target < b.Target - } - - return a.Source < b.Source -} - func updateMounts(flags *pflag.FlagSet, mounts *[]mounttypes.Mount) error { mountsByTarget := map[string]mounttypes.Mount{} @@ -796,7 +782,15 @@ func updateMounts(flags *pflag.FlagSet, mounts *[]mounttypes.Mount) error { newMounts = append(newMounts, mount) } } - sort.Sort(byMountSource(newMounts)) + sort.Slice(newMounts, func(i, j int) bool { + a, b := newMounts[i], newMounts[j] + + if a.Source == b.Source { + return a.Target < b.Target + } + + return a.Source < b.Source + }) *mounts = newMounts return nil } @@ -886,16 +880,6 @@ func updateDNSConfig(flags *pflag.FlagSet, config **swarm.DNSConfig) error { return nil } -type byPortConfig []swarm.PortConfig - -func (r byPortConfig) Len() int { return len(r) } -func (r byPortConfig) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byPortConfig) Less(i, j int) bool { - // We convert PortConfig into `port/protocol`, e.g., `80/tcp` - // In updatePorts we already filter out with map so there is duplicate entries - return portConfigToString(&r[i]) < portConfigToString(&r[j]) -} - func portConfigToString(portConfig *swarm.PortConfig) string { protocol := portConfig.Protocol mode := portConfig.PublishMode @@ -944,7 +928,11 @@ portLoop: } // Sort the PortConfig to avoid unnecessary updates - sort.Sort(byPortConfig(newPorts)) + sort.Slice(newPorts, func(i, j int) bool { + // We convert PortConfig into `port/protocol`, e.g., `80/tcp` + // In updatePorts we already filter out with map so there is duplicate entries + return portConfigToString(&newPorts[i]) < portConfigToString(&newPorts[j]) + }) *portConfig = newPorts return nil } @@ -1142,14 +1130,6 @@ func updateHealthcheck(flags *pflag.FlagSet, containerSpec *swarm.ContainerSpec) return nil } -type byNetworkTarget []swarm.NetworkAttachmentConfig - -func (m byNetworkTarget) Len() int { return len(m) } -func (m byNetworkTarget) Swap(i, j int) { m[i], m[j] = m[j], m[i] } -func (m byNetworkTarget) Less(i, j int) bool { - return m[i].Target < m[j].Target -} - func updateNetworks(ctx context.Context, apiClient client.NetworkAPIClient, flags *pflag.FlagSet, spec *swarm.ServiceSpec) error { // spec.TaskTemplate.Networks takes precedence over the deprecated // spec.Networks field. If spec.Network is in use, we'll migrate those @@ -1198,7 +1178,9 @@ func updateNetworks(ctx context.Context, apiClient client.NetworkAPIClient, flag } } - sort.Sort(byNetworkTarget(newNetworks)) + sort.Slice(newNetworks, func(i, j int) bool { + return newNetworks[i].Target < newNetworks[j].Target + }) spec.TaskTemplate.Networks = newNetworks return nil diff --git a/cli/command/volume/list.go b/cli/command/volume/list.go index 55875e01d7..1fb446ffc7 100644 --- a/cli/command/volume/list.go +++ b/cli/command/volume/list.go @@ -8,18 +8,9 @@ import ( "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command/formatter" "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" "github.com/spf13/cobra" ) -type byVolumeName []*types.Volume - -func (r byVolumeName) Len() int { return len(r) } -func (r byVolumeName) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byVolumeName) Less(i, j int) bool { - return r[i].Name < r[j].Name -} - type listOptions struct { quiet bool format string @@ -63,7 +54,9 @@ func runList(dockerCli command.Cli, options listOptions) error { } } - sort.Sort(byVolumeName(volumes.Volumes)) + sort.Slice(volumes.Volumes, func(i, j int) bool { + return volumes.Volumes[i].Name < volumes.Volumes[j].Name + }) volumeCtx := formatter.Context{ Output: dockerCli.Out(),