1package cluster
2
3import (
4	apitypes "github.com/docker/docker/api/types"
5	types "github.com/docker/docker/api/types/swarm"
6	"github.com/docker/docker/daemon/cluster/convert"
7	swarmapi "github.com/docker/swarmkit/api"
8	"golang.org/x/net/context"
9)
10
11// GetNodes returns a list of all nodes known to a cluster.
12func (c *Cluster) GetNodes(options apitypes.NodeListOptions) ([]types.Node, error) {
13	c.mu.RLock()
14	defer c.mu.RUnlock()
15
16	state := c.currentNodeState()
17	if !state.IsActiveManager() {
18		return nil, c.errNoManager(state)
19	}
20
21	filters, err := newListNodesFilters(options.Filters)
22	if err != nil {
23		return nil, err
24	}
25
26	ctx, cancel := c.getRequestContext()
27	defer cancel()
28
29	r, err := state.controlClient.ListNodes(
30		ctx,
31		&swarmapi.ListNodesRequest{Filters: filters})
32	if err != nil {
33		return nil, err
34	}
35
36	nodes := make([]types.Node, 0, len(r.Nodes))
37
38	for _, node := range r.Nodes {
39		nodes = append(nodes, convert.NodeFromGRPC(*node))
40	}
41	return nodes, nil
42}
43
44// GetNode returns a node based on an ID.
45func (c *Cluster) GetNode(input string) (types.Node, error) {
46	var node *swarmapi.Node
47
48	if err := c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
49		n, err := getNode(ctx, state.controlClient, input)
50		if err != nil {
51			return err
52		}
53		node = n
54		return nil
55	}); err != nil {
56		return types.Node{}, err
57	}
58
59	return convert.NodeFromGRPC(*node), nil
60}
61
62// UpdateNode updates existing nodes properties.
63func (c *Cluster) UpdateNode(input string, version uint64, spec types.NodeSpec) error {
64	return c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
65		nodeSpec, err := convert.NodeSpecToGRPC(spec)
66		if err != nil {
67			return convertError{err}
68		}
69
70		ctx, cancel := c.getRequestContext()
71		defer cancel()
72
73		currentNode, err := getNode(ctx, state.controlClient, input)
74		if err != nil {
75			return err
76		}
77
78		_, err = state.controlClient.UpdateNode(
79			ctx,
80			&swarmapi.UpdateNodeRequest{
81				NodeID: currentNode.ID,
82				Spec:   &nodeSpec,
83				NodeVersion: &swarmapi.Version{
84					Index: version,
85				},
86			},
87		)
88		return err
89	})
90}
91
92// RemoveNode removes a node from a cluster
93func (c *Cluster) RemoveNode(input string, force bool) error {
94	return c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
95		node, err := getNode(ctx, state.controlClient, input)
96		if err != nil {
97			return err
98		}
99
100		_, err = state.controlClient.RemoveNode(ctx, &swarmapi.RemoveNodeRequest{NodeID: node.ID, Force: force})
101		return err
102	})
103}
104