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