Docker Swarm manage
命令的filter
选项用来指定scheduler
选择Docker Engine
的过滤项,其变量定义如下(cli/flags.go
):
// hack for go vet
flFilterValue = cli.StringSlice(filter.List())
// DefaultFilterNumber is exported
DefaultFilterNumber = len(flFilterValue)
flFilter = cli.StringSliceFlag{
Name: "filter, f",
Usage: "filter to use [" + strings.Join(filter.List(), ", ") + "]",
Value: &flFilterValue,
}
获得filter
值的代码如下(cli/manage.go
):
// see https://github.com/codegangsta/cli/issues/160
names := c.StringSlice("filter")
if c.IsSet("filter") || c.IsSet("f") {
names = names[DefaultFilterNumber:]
}
fs, err := filter.New(names)
if err != nil {
log.Fatal(err)
}
默认情况下,获得所有的filter
(scheduler/filter/filter.go
):
func init() {
filters = []Filter{
&HealthFilter{},
&PortFilter{},
&SlotsFilter{},
&DependencyFilter{},
&AffinityFilter{},
&ConstraintFilter{},
}
}
而Filter
是一个interface
(scheduler/filter/filter.go
):
// Filter is exported
type Filter interface {
Name() string
// Return a subset of nodes that were accepted by the filtering policy.
Filter(*cluster.ContainerConfig, []*node.Node, bool) ([]*node.Node, error)
// Return a list of constraints/filters provided
GetFilters(*cluster.ContainerConfig) ([]string, error)
}
其中Filter
方法用来过滤符合条件的Docker Engine
,而GetFilters
则返回一个描述过滤条件的字符串。
在scheduler/filter/filter.go
中,ApplyFilters
用来过滤Docker Engine
;listAllFilters
返回所有的过滤条件:
// ApplyFilters applies a set of filters in batch.
func ApplyFilters(filters []Filter, config *cluster.ContainerConfig, nodes []*node.Node, soft bool) ([]*node.Node, error) {
var (
err error
candidates = nodes
)
for _, filter := range filters {
candidates, err = filter.Filter(config, candidates, soft)
if err != nil {
// special case for when no healthy nodes are found
if filter.Name() == "health" {
return nil, err
}
return nil, fmt.Errorf("Unable to find a node that satisfies the following conditions %s", listAllFilters(filters, config, filter.Name()))
}
}
return candidates, nil
}
// listAllFilters creates a string containing all applied filters
func listAllFilters(filters []Filter, config *cluster.ContainerConfig, lastFilter string) string {
allFilters := ""
for _, filter := range filters {
list, err := filter.GetFilters(config)
if err == nil && len(list) > 0 {
allFilters = fmt.Sprintf("%s\n%v", allFilters, list)
}
if filter.Name() == lastFilter {
return allFilters
}
}
return allFilters
}