Merge pull request #315 from ripcurld0/nat_sort
Sort swarm stacks and nodes using natural sorting
This commit is contained in:
@ -1,15 +1,27 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"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/docker/docker/api/types/swarm"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/net/context"
|
||||
"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
|
||||
@ -68,5 +80,6 @@ func runList(dockerCli command.Cli, options listOptions) error {
|
||||
Output: dockerCli.Out(),
|
||||
Format: formatter.NewNodeFormat(format, options.quiet),
|
||||
}
|
||||
sort.Sort(byHostname(nodes))
|
||||
return formatter.NodeWrite(nodesCtx, nodes, info)
|
||||
}
|
||||
|
||||
@ -9,6 +9,8 @@ import (
|
||||
"github.com/docker/cli/cli/internal/test"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/docker/docker/pkg/testutil/golden"
|
||||
"github.com/pkg/errors"
|
||||
// Import builders to get the builder function as package function
|
||||
. "github.com/docker/cli/cli/internal/test/builders"
|
||||
@ -156,3 +158,22 @@ func TestNodeListFormat(t *testing.T) {
|
||||
assert.Contains(t, buf.String(), `nodeHostname1: Leader`)
|
||||
assert.Contains(t, buf.String(), `nodeHostname2: Reachable`)
|
||||
}
|
||||
|
||||
func TestNodeListOrder(t *testing.T) {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
nodeListFunc: func() ([]swarm.Node, error) {
|
||||
return []swarm.Node{
|
||||
*Node(Hostname("node-2-foo"), Manager(Leader())),
|
||||
*Node(Hostname("node-10-foo"), Manager()),
|
||||
*Node(Hostname("node-1-foo")),
|
||||
}, nil
|
||||
|
||||
},
|
||||
})
|
||||
cmd := newListCommand(cli)
|
||||
cmd.Flags().Set("format", "{{.Hostname}}: {{.ManagerStatus}}")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := cli.OutBuffer().String()
|
||||
expected := golden.Get(t, []byte(actual), "node-list-sort.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
|
||||
3
cli/command/node/testdata/node-list-sort.golden
vendored
Normal file
3
cli/command/node/testdata/node-list-sort.golden
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
node-1-foo:
|
||||
node-2-foo: Leader
|
||||
node-10-foo: Reachable
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/net/context"
|
||||
"vbom.ml/util/sortorder"
|
||||
)
|
||||
|
||||
type listOptions struct {
|
||||
@ -60,7 +61,7 @@ type byName []*formatter.Stack
|
||||
|
||||
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 n[i].Name < n[j].Name }
|
||||
func (n byName) Less(i, j int) bool { return sortorder.NaturalLess(n[i].Name, n[j].Name) }
|
||||
|
||||
func getStacks(ctx context.Context, apiclient client.APIClient) ([]*formatter.Stack, error) {
|
||||
services, err := apiclient.ServiceList(
|
||||
|
||||
@ -98,10 +98,13 @@ func TestListWithoutFormat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestListOrder(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cmd := newListCommand(test.NewFakeCliWithOutput(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{
|
||||
usecases := []struct {
|
||||
golden string
|
||||
swarmServices []swarm.Service
|
||||
}{
|
||||
{
|
||||
golden: "stack-list-sort.golden",
|
||||
swarmServices: []swarm.Service{
|
||||
*Service(
|
||||
ServiceLabels(map[string]string{
|
||||
"com.docker.stack.namespace": "service-name-foo",
|
||||
@ -112,11 +115,40 @@ func TestListOrder(t *testing.T) {
|
||||
"com.docker.stack.namespace": "service-name-bar",
|
||||
}),
|
||||
),
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
}, buf))
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-list-sort.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
{
|
||||
golden: "stack-list-sort-natural.golden",
|
||||
swarmServices: []swarm.Service{
|
||||
*Service(
|
||||
ServiceLabels(map[string]string{
|
||||
"com.docker.stack.namespace": "service-name-1-foo",
|
||||
}),
|
||||
),
|
||||
*Service(
|
||||
ServiceLabels(map[string]string{
|
||||
"com.docker.stack.namespace": "service-name-10-foo",
|
||||
}),
|
||||
),
|
||||
*Service(
|
||||
ServiceLabels(map[string]string{
|
||||
"com.docker.stack.namespace": "service-name-2-foo",
|
||||
}),
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, uc := range usecases {
|
||||
buf := new(bytes.Buffer)
|
||||
cmd := newListCommand(test.NewFakeCliWithOutput(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return uc.swarmServices, nil
|
||||
},
|
||||
}, buf))
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), uc.golden)
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
}
|
||||
|
||||
4
cli/command/stack/testdata/stack-list-sort-natural.golden
vendored
Normal file
4
cli/command/stack/testdata/stack-list-sort-natural.golden
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
NAME SERVICES
|
||||
service-name-1-foo 1
|
||||
service-name-2-foo 1
|
||||
service-name-10-foo 1
|
||||
Reference in New Issue
Block a user