Compare commits

...

2 Commits

Author SHA1 Message Date
ehsan-salamati c0b5d71316
Merge 94b0eb83ec into 88f1e99e8e 2024-10-11 07:27:03 +02:00
Ehsan Salamati 94b0eb83ec Fixes duplicate entries in docker node ps when multi nodes are passed. For example, 'docker ps node node1 node2'.
Signed-off-by: Ehsan Salamati <ehsan.salamati@instacart.com>
2024-08-02 10:24:43 -04:00
4 changed files with 82 additions and 23 deletions

View File

@ -13,6 +13,7 @@ type fakeClient struct {
client.Client client.Client
infoFunc func() (system.Info, error) infoFunc func() (system.Info, error)
nodeInspectFunc func() (swarm.Node, []byte, error) nodeInspectFunc func() (swarm.Node, []byte, error)
nodeInspectFuncWithArgs func(string) (swarm.Node, []byte, error)
nodeListFunc func() ([]swarm.Node, error) nodeListFunc func() ([]swarm.Node, error)
nodeRemoveFunc func() error nodeRemoveFunc func() error
nodeUpdateFunc func(nodeID string, version swarm.Version, node swarm.NodeSpec) error nodeUpdateFunc func(nodeID string, version swarm.Version, node swarm.NodeSpec) error
@ -21,10 +22,15 @@ type fakeClient struct {
serviceInspectFunc func(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error) serviceInspectFunc func(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error)
} }
func (cli *fakeClient) NodeInspectWithRaw(context.Context, string) (swarm.Node, []byte, error) { func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, nodeRef string) (swarm.Node, []byte, error) {
if cli.nodeInspectFunc != nil { if cli.nodeInspectFunc != nil {
return cli.nodeInspectFunc() return cli.nodeInspectFunc()
} }
if cli.nodeInspectFuncWithArgs != nil {
return cli.nodeInspectFuncWithArgs(nodeRef)
}
return swarm.Node{}, []byte{}, nil return swarm.Node{}, []byte{}, nil
} }

View File

@ -74,7 +74,7 @@ func runPs(ctx context.Context, dockerCli command.Cli, options psOptions) error
continue continue
} }
filter := options.filter.Value() filter := options.filter.Value().Clone()
filter.Add("node", node.ID) filter.Add("node", node.ID)
nodeTasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter}) nodeTasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter})

View File

@ -73,6 +73,7 @@ func TestNodePs(t *testing.T) {
flags map[string]string flags map[string]string
infoFunc func() (system.Info, error) infoFunc func() (system.Info, error)
nodeInspectFunc func() (swarm.Node, []byte, error) nodeInspectFunc func() (swarm.Node, []byte, error)
nodeInspectFuncWithArgs func(string) (swarm.Node, []byte, error)
taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error) taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error)
taskInspectFunc func(taskID string) (swarm.Task, []byte, error) taskInspectFunc func(taskID string) (swarm.Task, []byte, error)
serviceInspectFunc func(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error) serviceInspectFunc func(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error)
@ -132,6 +133,51 @@ func TestNodePs(t *testing.T) {
}, []byte{}, nil }, []byte{}, nil
}, },
}, },
{
name: "multiple-nodes-no-duplicates",
args: []string{"nodeID1", "nodeID2"},
nodeInspectFuncWithArgs: func(nodeRef string) (swarm.Node, []byte, error) {
switch nodeRef {
case "nodeID1":
return *builders.Node(builders.NodeID("nodeID1")), []byte{}, nil
case "nodeID2":
return *builders.Node(builders.NodeID("nodeID2")), []byte{}, nil
default:
return swarm.Node{}, []byte{}, errors.Errorf("unexpected nodeRef %q", nodeRef)
}
},
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
nodeFilter := options.Filters.Get("node")[0]
switch nodeFilter {
case "nodeID1":
return []swarm.Task{
*builders.Task(builders.TaskID("taskID1"), builders.TaskServiceID("service1"), builders.TaskNodeID("nodeID1"),
builders.WithStatus(builders.Timestamp(time.Now().Add(-2*time.Hour)), builders.TaskState(swarm.TaskStateRunning))),
*builders.Task(builders.TaskID("taskID2"), builders.TaskServiceID("service2"), builders.TaskNodeID("nodeID1"),
builders.WithStatus(builders.Timestamp(time.Now().Add(-3*time.Hour)), builders.TaskState(swarm.TaskStateRunning))),
}, nil
case "nodeID2":
return []swarm.Task{
*builders.Task(builders.TaskID("taskID3"), builders.TaskServiceID("service3"), builders.TaskNodeID("nodeID2"),
builders.WithStatus(builders.Timestamp(time.Now().Add(-2*time.Hour)), builders.TaskState(swarm.TaskStateRunning))),
*builders.Task(builders.TaskID("taskID4"), builders.TaskServiceID("service4"), builders.TaskNodeID("nodeID2"),
builders.WithStatus(builders.Timestamp(time.Now().Add(-3*time.Hour)), builders.TaskState(swarm.TaskStateRunning))),
}, nil
default:
return []swarm.Task{}, nil
}
},
serviceInspectFunc: func(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error) {
return swarm.Service{
ID: serviceID,
Spec: swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: serviceID,
},
},
}, []byte{}, nil
},
},
} }
for _, tc := range testCases { for _, tc := range testCases {
tc := tc tc := tc
@ -139,10 +185,12 @@ func TestNodePs(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{ cli := test.NewFakeCli(&fakeClient{
infoFunc: tc.infoFunc, infoFunc: tc.infoFunc,
nodeInspectFunc: tc.nodeInspectFunc, nodeInspectFunc: tc.nodeInspectFunc,
nodeInspectFuncWithArgs: tc.nodeInspectFuncWithArgs,
taskInspectFunc: tc.taskInspectFunc, taskInspectFunc: tc.taskInspectFunc,
taskListFunc: tc.taskListFunc, taskListFunc: tc.taskListFunc,
serviceInspectFunc: tc.serviceInspectFunc, serviceInspectFunc: tc.serviceInspectFunc,
}) })
cmd := newPsCommand(cli) cmd := newPsCommand(cli)
cmd.SetArgs(tc.args) cmd.SetArgs(tc.args)
for key, value := range tc.flags { for key, value := range tc.flags {

View File

@ -0,0 +1,5 @@
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
taskID1 service1.1 myimage:mytag defaultNodeName Ready Running 2 hours ago
taskID2 service2.1 myimage:mytag defaultNodeName Ready Running 3 hours ago
taskID3 service3.1 myimage:mytag defaultNodeName Ready Running 2 hours ago
taskID4 service4.1 myimage:mytag defaultNodeName Ready Running 3 hours ago