mirror of https://github.com/docker/docs.git
Merge pull request #572 from vieux/improve_docker_info
add strategy and filters to docker info
This commit is contained in:
commit
c101ab7548
|
@ -268,7 +268,11 @@ func (c *Cluster) listNodes() []cluster.Node {
|
|||
|
||||
// Info is exported
|
||||
func (c *Cluster) Info() [][2]string {
|
||||
info := [][2]string{{"\bNodes", fmt.Sprintf("%d", len(c.nodes))}}
|
||||
info := [][2]string{
|
||||
{"\bStrategy", c.scheduler.Strategy()},
|
||||
{"\bFilters", c.scheduler.Filters()},
|
||||
{"\bNodes", fmt.Sprintf("%d", len(c.nodes))},
|
||||
}
|
||||
|
||||
for _, node := range c.nodes {
|
||||
info = append(info, [2]string{node.Name(), node.Addr()})
|
||||
|
|
22
flags.go
22
flags.go
|
@ -4,8 +4,11 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/docker/swarm/scheduler/filter"
|
||||
"github.com/docker/swarm/scheduler/strategy"
|
||||
)
|
||||
|
||||
func homepath(p string) string {
|
||||
|
@ -81,23 +84,24 @@ var (
|
|||
}
|
||||
flStrategy = cli.StringFlag{
|
||||
Name: "strategy",
|
||||
Usage: "placement strategy to use [spread, binpack, random]",
|
||||
Value: "spread",
|
||||
Usage: "placement strategy to use [" + strings.Join(strategy.List(), ", ") + "]",
|
||||
Value: strategy.List()[0],
|
||||
}
|
||||
|
||||
// hack for go vet
|
||||
flFilterValue = cli.StringSlice([]string{"constraint", "affinity", "health", "port", "dependency"})
|
||||
flFilterValue = cli.StringSlice(filter.List())
|
||||
// DefaultFilterNumber is exported
|
||||
DefaultFilterNumber = len(flFilterValue)
|
||||
|
||||
flFilter = cli.StringSliceFlag{
|
||||
Name: "filter, f",
|
||||
Usage: "filter to use [constraint, affinity, health, port, dependency]",
|
||||
Usage: "filter to use [" + strings.Join(filter.List(), ", ") + "]",
|
||||
Value: &flFilterValue,
|
||||
}
|
||||
flCluster = cli.StringFlag{
|
||||
Name: "cluster, c",
|
||||
Usage: "cluster to use [swarm, mesos]",
|
||||
Value: "swarm",
|
||||
}
|
||||
|
||||
// flCluster = cli.StringFlag{
|
||||
// Name: "cluster, c",
|
||||
// Usage: "cluster to use [swarm, mesos]",
|
||||
// Value: "swarm",
|
||||
// }
|
||||
)
|
||||
|
|
2
main.go
2
main.go
|
@ -105,7 +105,7 @@ func main() {
|
|||
ShortName: "m",
|
||||
Usage: "manage a docker cluster",
|
||||
Flags: []cli.Flag{
|
||||
flStore, flCluster,
|
||||
flStore,
|
||||
flStrategy, flFilter,
|
||||
flHosts, flHeartBeat, flOverCommit,
|
||||
flTLS, flTLSCaCert, flTLSCert, flTLSKey, flTLSVerify,
|
||||
|
|
|
@ -13,6 +13,11 @@ import (
|
|||
type AffinityFilter struct {
|
||||
}
|
||||
|
||||
// Name returns the name of the filter
|
||||
func (f *AffinityFilter) Name() string {
|
||||
return "affinity"
|
||||
}
|
||||
|
||||
// Filter is exported
|
||||
func (f *AffinityFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
|
||||
affinities, err := parseExprs("affinity", config.Env)
|
||||
|
|
|
@ -12,6 +12,11 @@ import (
|
|||
type ConstraintFilter struct {
|
||||
}
|
||||
|
||||
// Name returns the name of the filter
|
||||
func (f *ConstraintFilter) Name() string {
|
||||
return "constraint"
|
||||
}
|
||||
|
||||
// Filter is exported
|
||||
func (f *ConstraintFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
|
||||
constraints, err := parseExprs("constraint", config.Env)
|
||||
|
|
|
@ -12,6 +12,11 @@ import (
|
|||
type DependencyFilter struct {
|
||||
}
|
||||
|
||||
// Name returns the name of the filter
|
||||
func (f *DependencyFilter) Name() string {
|
||||
return "dependency"
|
||||
}
|
||||
|
||||
// Filter is exported
|
||||
func (f *DependencyFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
|
||||
if len(nodes) == 0 {
|
||||
|
|
|
@ -10,23 +10,25 @@ import (
|
|||
|
||||
// Filter is exported
|
||||
type Filter interface {
|
||||
Name() string
|
||||
|
||||
// Return a subset of nodes that were accepted by the filtering policy.
|
||||
Filter(*dockerclient.ContainerConfig, []cluster.Node) ([]cluster.Node, error)
|
||||
}
|
||||
|
||||
var (
|
||||
filters map[string]Filter
|
||||
filters []Filter
|
||||
// ErrNotSupported is exported
|
||||
ErrNotSupported = errors.New("filter not supported")
|
||||
)
|
||||
|
||||
func init() {
|
||||
filters = map[string]Filter{
|
||||
"affinity": &AffinityFilter{},
|
||||
"health": &HealthFilter{},
|
||||
"constraint": &ConstraintFilter{},
|
||||
"port": &PortFilter{},
|
||||
"dependency": &DependencyFilter{},
|
||||
filters = []Filter{
|
||||
&AffinityFilter{},
|
||||
&HealthFilter{},
|
||||
&ConstraintFilter{},
|
||||
&PortFilter{},
|
||||
&DependencyFilter{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,10 +37,16 @@ func New(names []string) ([]Filter, error) {
|
|||
var selectedFilters []Filter
|
||||
|
||||
for _, name := range names {
|
||||
if filter, exists := filters[name]; exists {
|
||||
log.WithField("name", name).Debug("Initializing filter")
|
||||
selectedFilters = append(selectedFilters, filter)
|
||||
} else {
|
||||
found := false
|
||||
for _, filter := range filters {
|
||||
if filter.Name() == name {
|
||||
log.WithField("name", name).Debug("Initializing filter")
|
||||
selectedFilters = append(selectedFilters, filter)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
}
|
||||
|
@ -57,3 +65,14 @@ func ApplyFilters(filters []Filter, config *dockerclient.ContainerConfig, nodes
|
|||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// List returns the names of all the available filters
|
||||
func List() []string {
|
||||
names := []string{}
|
||||
|
||||
for _, filter := range filters {
|
||||
names = append(names, filter.Name())
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
|
|
|
@ -16,6 +16,11 @@ var (
|
|||
type HealthFilter struct {
|
||||
}
|
||||
|
||||
// Name returns the name of the filter
|
||||
func (f *HealthFilter) Name() string {
|
||||
return "health"
|
||||
}
|
||||
|
||||
// Filter is exported
|
||||
func (f *HealthFilter) Filter(_ *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
|
||||
result := []cluster.Node{}
|
||||
|
|
|
@ -13,6 +13,11 @@ import (
|
|||
type PortFilter struct {
|
||||
}
|
||||
|
||||
// Name returns the name of the filter
|
||||
func (p *PortFilter) Name() string {
|
||||
return "port"
|
||||
}
|
||||
|
||||
// Filter is exported
|
||||
func (p *PortFilter) Filter(config *dockerclient.ContainerConfig, nodes []cluster.Node) ([]cluster.Node, error) {
|
||||
for _, port := range config.HostConfig.PortBindings {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package scheduler
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/swarm/cluster"
|
||||
|
@ -34,3 +35,18 @@ func (s *Scheduler) SelectNodeForContainer(nodes []cluster.Node, config *dockerc
|
|||
|
||||
return s.strategy.PlaceContainer(config, accepted)
|
||||
}
|
||||
|
||||
// Strategy returns the strategy name
|
||||
func (s *Scheduler) Strategy() string {
|
||||
return s.strategy.Name()
|
||||
}
|
||||
|
||||
// Filters returns the list of filter's name
|
||||
func (s *Scheduler) Filters() string {
|
||||
filters := []string{}
|
||||
for _, f := range s.filters {
|
||||
filters = append(filters, f.Name())
|
||||
}
|
||||
|
||||
return strings.Join(filters, ", ")
|
||||
}
|
||||
|
|
|
@ -16,6 +16,11 @@ func (p *BinpackPlacementStrategy) Initialize() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Name returns the name of the strategy
|
||||
func (p *BinpackPlacementStrategy) Name() string {
|
||||
return "binpack"
|
||||
}
|
||||
|
||||
// PlaceContainer is exported
|
||||
func (p *BinpackPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []cluster.Node) (cluster.Node, error) {
|
||||
weightedNodes, err := weighNodes(config, nodes)
|
||||
|
|
|
@ -18,6 +18,11 @@ func (p *RandomPlacementStrategy) Initialize() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Name returns the name of the strategy
|
||||
func (p *RandomPlacementStrategy) Name() string {
|
||||
return "random"
|
||||
}
|
||||
|
||||
// PlaceContainer is exported
|
||||
func (p *RandomPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []cluster.Node) (cluster.Node, error) {
|
||||
if size := len(nodes); size > 0 {
|
||||
|
|
|
@ -16,6 +16,11 @@ func (p *SpreadPlacementStrategy) Initialize() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Name returns the name of the strategy
|
||||
func (p *SpreadPlacementStrategy) Name() string {
|
||||
return "spread"
|
||||
}
|
||||
|
||||
// PlaceContainer is exported
|
||||
func (p *SpreadPlacementStrategy) PlaceContainer(config *dockerclient.ContainerConfig, nodes []cluster.Node) (cluster.Node, error) {
|
||||
weightedNodes, err := weighNodes(config, nodes)
|
||||
|
|
|
@ -10,6 +10,8 @@ import (
|
|||
|
||||
// PlacementStrategy is exported
|
||||
type PlacementStrategy interface {
|
||||
Name() string
|
||||
|
||||
Initialize() error
|
||||
// Given a container configuration and a set of nodes, select the target
|
||||
// node where the container should be scheduled.
|
||||
|
@ -17,7 +19,7 @@ type PlacementStrategy interface {
|
|||
}
|
||||
|
||||
var (
|
||||
strategies map[string]PlacementStrategy
|
||||
strategies []PlacementStrategy
|
||||
// ErrNotSupported is exported
|
||||
ErrNotSupported = errors.New("strategy not supported")
|
||||
// ErrNoResourcesAvailable is exported
|
||||
|
@ -25,21 +27,37 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
strategies = map[string]PlacementStrategy{
|
||||
"binpacking": &BinpackPlacementStrategy{}, //compat
|
||||
"binpack": &BinpackPlacementStrategy{},
|
||||
"spread": &SpreadPlacementStrategy{},
|
||||
"random": &RandomPlacementStrategy{},
|
||||
strategies = []PlacementStrategy{
|
||||
&SpreadPlacementStrategy{},
|
||||
&BinpackPlacementStrategy{},
|
||||
&RandomPlacementStrategy{},
|
||||
}
|
||||
}
|
||||
|
||||
// New is exported
|
||||
func New(name string) (PlacementStrategy, error) {
|
||||
if strategy, exists := strategies[name]; exists {
|
||||
log.WithField("name", name).Debugf("Initializing strategy")
|
||||
err := strategy.Initialize()
|
||||
return strategy, err
|
||||
if name == "binpacking" { //TODO: remove this compat
|
||||
name = "binpack"
|
||||
}
|
||||
|
||||
for _, strategy := range strategies {
|
||||
if strategy.Name() == name {
|
||||
log.WithField("name", name).Debugf("Initializing strategy")
|
||||
err := strategy.Initialize()
|
||||
return strategy, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil, ErrNotSupported
|
||||
}
|
||||
|
||||
// List returns the names of all the available strategies
|
||||
func List() []string {
|
||||
names := []string{}
|
||||
|
||||
for _, strategy := range strategies {
|
||||
names = append(names, strategy.Name())
|
||||
}
|
||||
|
||||
return names
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue