Use strongly typed errors to set HTTP status codes. Error interfaces are defined in the api/errors package and errors returned from controllers are checked against these interfaces. Errors can be wraeped in a pkg/errors.Causer, as long as somewhere in the line of causes one of the interfaces is implemented. The special error interfaces take precedence over Causer, meaning if both Causer and one of the new error interfaces are implemented, the Causer is not traversed. Signed-off-by: Brian Goff <cpuguy83@gmail.com> Upstream-commit: ebcb7d6b406fe50ea9a237c73004d75884184c33 Component: engine
104 lines
2.4 KiB
Go
104 lines
2.4 KiB
Go
package cluster
|
|
|
|
import (
|
|
apitypes "github.com/docker/docker/api/types"
|
|
types "github.com/docker/docker/api/types/swarm"
|
|
"github.com/docker/docker/daemon/cluster/convert"
|
|
swarmapi "github.com/docker/swarmkit/api"
|
|
"golang.org/x/net/context"
|
|
)
|
|
|
|
// GetNodes returns a list of all nodes known to a cluster.
|
|
func (c *Cluster) GetNodes(options apitypes.NodeListOptions) ([]types.Node, error) {
|
|
c.mu.RLock()
|
|
defer c.mu.RUnlock()
|
|
|
|
state := c.currentNodeState()
|
|
if !state.IsActiveManager() {
|
|
return nil, c.errNoManager(state)
|
|
}
|
|
|
|
filters, err := newListNodesFilters(options.Filters)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ctx, cancel := c.getRequestContext()
|
|
defer cancel()
|
|
|
|
r, err := state.controlClient.ListNodes(
|
|
ctx,
|
|
&swarmapi.ListNodesRequest{Filters: filters})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
nodes := make([]types.Node, 0, len(r.Nodes))
|
|
|
|
for _, node := range r.Nodes {
|
|
nodes = append(nodes, convert.NodeFromGRPC(*node))
|
|
}
|
|
return nodes, nil
|
|
}
|
|
|
|
// GetNode returns a node based on an ID.
|
|
func (c *Cluster) GetNode(input string) (types.Node, error) {
|
|
var node *swarmapi.Node
|
|
|
|
if err := c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
|
|
n, err := getNode(ctx, state.controlClient, input)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
node = n
|
|
return nil
|
|
}); err != nil {
|
|
return types.Node{}, err
|
|
}
|
|
|
|
return convert.NodeFromGRPC(*node), nil
|
|
}
|
|
|
|
// UpdateNode updates existing nodes properties.
|
|
func (c *Cluster) UpdateNode(input string, version uint64, spec types.NodeSpec) error {
|
|
return c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
|
|
nodeSpec, err := convert.NodeSpecToGRPC(spec)
|
|
if err != nil {
|
|
return convertError{err}
|
|
}
|
|
|
|
ctx, cancel := c.getRequestContext()
|
|
defer cancel()
|
|
|
|
currentNode, err := getNode(ctx, state.controlClient, input)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = state.controlClient.UpdateNode(
|
|
ctx,
|
|
&swarmapi.UpdateNodeRequest{
|
|
NodeID: currentNode.ID,
|
|
Spec: &nodeSpec,
|
|
NodeVersion: &swarmapi.Version{
|
|
Index: version,
|
|
},
|
|
},
|
|
)
|
|
return err
|
|
})
|
|
}
|
|
|
|
// RemoveNode removes a node from a cluster
|
|
func (c *Cluster) RemoveNode(input string, force bool) error {
|
|
return c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
|
|
node, err := getNode(ctx, state.controlClient, input)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = state.controlClient.RemoveNode(ctx, &swarmapi.RemoveNodeRequest{NodeID: node.ID, Force: force})
|
|
return err
|
|
})
|
|
}
|