diff --git a/scheduler/filter/constraint.go b/scheduler/filter/constraint.go index a5a4ccd197..c11edff563 100644 --- a/scheduler/filter/constraint.go +++ b/scheduler/filter/constraint.go @@ -36,6 +36,9 @@ func (f *ConstraintFilter) Filter(config *dockerclient.ContainerConfig, nodes [] } } if len(candidates) == 0 { + if constraint.isSoft { + return nodes, nil + } return nil, fmt.Errorf("unable to find a node that satisfies %s%s%s", constraint.key, OPERATORS[constraint.operator], constraint.value) } nodes = candidates diff --git a/scheduler/filter/constraint_test.go b/scheduler/filter/constraint_test.go index eade08c9d0..8a5fb8a924 100644 --- a/scheduler/filter/constraint_test.go +++ b/scheduler/filter/constraint_test.go @@ -246,3 +246,35 @@ func TestUnsupportedOperators(t *testing.T) { assert.Error(t, err) assert.Len(t, result, 0) } + +func TestFilterSoftConstraint(t *testing.T) { + var ( + f = ConstraintFilter{} + nodes = testFixtures() + result []cluster.Node + err error + ) + + result, err = f.Filter(&dockerclient.ContainerConfig{Env: []string{"constraint:node==~node-1-name"}}, nodes) + assert.NoError(t, err) + assert.Len(t, result, 1) + assert.Equal(t, result[0], nodes[1]) + + result, err = f.Filter(&dockerclient.ContainerConfig{Env: []string{`constraint:name!=~/(?i)abc*/`}}, nodes) + assert.NoError(t, err) + assert.Len(t, result, 4) + + // Check not with globber pattern + result, err = f.Filter(&dockerclient.ContainerConfig{Env: []string{"constraint:region!=~us*"}}, nodes) + assert.NoError(t, err) + assert.Len(t, result, 2) + + result, err = f.Filter(&dockerclient.ContainerConfig{Env: []string{"constraint:region!=~can*"}}, nodes) + assert.NoError(t, err) + assert.Len(t, result, 4) + + // Check matching + result, err = f.Filter(&dockerclient.ContainerConfig{Env: []string{"constraint:region==~us~"}}, nodes) + assert.Error(t, err) + assert.Len(t, result, 0) +}