mirror of
https://github.com/docker/docs.git
synced 2026-10-31 10:34:26 +03:00
Merge pull request #1796 from nishanttotla/list-conflicting-constraints
Print all constraints when container can't be scheduled
This commit is contained in:
@@ -76,3 +76,16 @@ func (f *AffinityFilter) Filter(config *cluster.ContainerConfig, nodes []*node.N
|
||||
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// GetFilters returns a list of the affinities found in the container config.
|
||||
func (f *AffinityFilter) GetFilters(config *cluster.ContainerConfig) ([]string, error) {
|
||||
allAffinities := []string{}
|
||||
affinities, err := parseExprs(config.Affinities())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, affinity := range affinities {
|
||||
allAffinities = append(allAffinities, fmt.Sprintf("%s%s%s (soft=%t)", affinity.key, OPERATORS[affinity.operator], affinity.value, affinity.isSoft))
|
||||
}
|
||||
return allAffinities, nil
|
||||
}
|
||||
|
||||
@@ -51,3 +51,16 @@ func (f *ConstraintFilter) Filter(config *cluster.ContainerConfig, nodes []*node
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// GetFilters returns a list of the constraints found in the container config.
|
||||
func (f *ConstraintFilter) GetFilters(config *cluster.ContainerConfig) ([]string, error) {
|
||||
allConstraints := []string{}
|
||||
constraints, err := parseExprs(config.Constraints())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, constraint := range constraints {
|
||||
allConstraints = append(allConstraints, fmt.Sprintf("%s%s%s", constraint.key, OPERATORS[constraint.operator], constraint.value))
|
||||
}
|
||||
return allConstraints, nil
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ func (f *DependencyFilter) Filter(config *cluster.ContainerConfig, nodes []*node
|
||||
return candidates, nil
|
||||
}
|
||||
|
||||
// Get a string representation of the dependencies found in the container config.
|
||||
func (f *DependencyFilter) String(config *cluster.ContainerConfig) string {
|
||||
// GetFilters returns a list of the dependencies found in the container config.
|
||||
func (f *DependencyFilter) GetFilters(config *cluster.ContainerConfig) ([]string, error) {
|
||||
dependencies := []string{}
|
||||
for _, volume := range config.HostConfig.VolumesFrom {
|
||||
dependencies = append(dependencies, fmt.Sprintf("--volumes-from=%s", volume))
|
||||
@@ -68,6 +68,12 @@ func (f *DependencyFilter) String(config *cluster.ContainerConfig) string {
|
||||
if strings.HasPrefix(config.HostConfig.NetworkMode, "container:") {
|
||||
dependencies = append(dependencies, fmt.Sprintf("--net=%s", config.HostConfig.NetworkMode))
|
||||
}
|
||||
return dependencies, nil
|
||||
}
|
||||
|
||||
// Get a string representation of the dependencies found in the container config.
|
||||
func (f *DependencyFilter) String(config *cluster.ContainerConfig) string {
|
||||
dependencies, _ := f.GetFilters(config)
|
||||
return strings.Join(dependencies, " ")
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package filter
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/swarm/cluster"
|
||||
@@ -14,6 +15,9 @@ type Filter interface {
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -63,12 +67,31 @@ func ApplyFilters(filters []Filter, config *cluster.ContainerConfig, nodes []*no
|
||||
for _, filter := range filters {
|
||||
candidates, err = filter.Filter(config, candidates, soft)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// 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
|
||||
}
|
||||
|
||||
// List returns the names of all the available filters
|
||||
func List() []string {
|
||||
names := []string{}
|
||||
|
||||
@@ -36,3 +36,8 @@ func (f *HealthFilter) Filter(_ *cluster.ContainerConfig, nodes []*node.Node, _
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetFilters returns
|
||||
func (f *HealthFilter) GetFilters(config *cluster.ContainerConfig) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -119,6 +119,24 @@ func (p *PortFilter) compare(requested dockerclient.PortBinding, bindings map[st
|
||||
return false
|
||||
}
|
||||
|
||||
// GetFilters returns a list of the port constraints found in the container config.
|
||||
func (p *PortFilter) GetFilters(config *cluster.ContainerConfig) ([]string, error) {
|
||||
allPortConstraints := []string{}
|
||||
if config.HostConfig.NetworkMode == "host" {
|
||||
for port := range config.ExposedPorts {
|
||||
allPortConstraints = append(allPortConstraints, fmt.Sprintf("port %s (Host mode)", port))
|
||||
}
|
||||
return allPortConstraints, nil
|
||||
}
|
||||
|
||||
for _, port := range config.HostConfig.PortBindings {
|
||||
for _, binding := range port {
|
||||
allPortConstraints = append(allPortConstraints, fmt.Sprintf("port %s (Bridge mode)", binding.HostPort))
|
||||
}
|
||||
}
|
||||
return allPortConstraints, nil
|
||||
}
|
||||
|
||||
func bindsAllInterfaces(binding dockerclient.PortBinding) bool {
|
||||
return binding.HostIp == "0.0.0.0" || binding.HostIp == ""
|
||||
}
|
||||
|
||||
@@ -151,7 +151,8 @@ function teardown() {
|
||||
# Run 3 tests in parallel. One of them must fail.
|
||||
run parallel docker -H "${SWARM_HOSTS[0]}" run --label test.label=true -e affinity:test.label!=true -d busybox:latest ::: top top top
|
||||
[ "$status" -ne 0 ]
|
||||
[[ "${output}" == *'unable to find a node that satisfies test.label!=true'* ]]
|
||||
[[ "${output}" == *"Unable to find a node that satisfies the following conditions"* ]]
|
||||
[[ "${output}" == *"[test.label!=true (soft=false)]"* ]]
|
||||
|
||||
# Only 2 containers should have succeeded.
|
||||
run docker_swarm ps -q
|
||||
|
||||
@@ -17,7 +17,8 @@ function teardown() {
|
||||
|
||||
run docker_swarm build --build-arg="constraint:node==node-9" $TESTDATA/build
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" == *"Error response from daemon: unable to find a node that satisfies node==node-9"* ]]
|
||||
[[ "${lines[1]}" == *"Unable to find a node that satisfies the following conditions"* ]]
|
||||
[[ "${lines[2]}" == *"[node==node-9]"* ]]
|
||||
|
||||
run docker_swarm images -q
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
@@ -21,7 +21,8 @@ function teardown() {
|
||||
# When trying to start the 3rd one, it should be error finding port 80.
|
||||
run docker_swarm run -d --expose=80 --net=host busybox sh
|
||||
[ "$status" -ne 0 ]
|
||||
[[ "${lines[0]}" == *"unable to find a node with port 80/tcp available in the Host mode"* ]]
|
||||
[[ "${lines[0]}" == *"Unable to find a node that satisfies the following conditions"* ]]
|
||||
[[ "${lines[1]}" == *"[port 80/tcp (Host mode)]"* ]]
|
||||
|
||||
# And the number of running containers should be still 2.
|
||||
run docker_swarm ps -n 2
|
||||
@@ -40,7 +41,8 @@ function teardown() {
|
||||
# When trying to start the 3rd one, it should be error finding port 80.
|
||||
run docker_swarm run --expose=80 -p 80:80 busybox echo 3
|
||||
[ "$status" -ne 0 ]
|
||||
[[ "${lines[0]}" == *"unable to find a node with port 80 available"* ]]
|
||||
[[ "${lines[0]}" == *"Unable to find a node that satisfies the following conditions"* ]]
|
||||
[[ "${lines[1]}" == *"[port 80 (Bridge mode)]"* ]]
|
||||
|
||||
# And the number of running containers should be still 2.
|
||||
run docker_swarm ps -n 2
|
||||
|
||||
Reference in New Issue
Block a user