diff --git a/scheduler/filter/label.go b/scheduler/filter/label.go index c5ccf361ea..dbd3f80cb5 100644 --- a/scheduler/filter/label.go +++ b/scheduler/filter/label.go @@ -29,10 +29,19 @@ func (f *LabelFilter) Filter(config *dockerclient.ContainerConfig, nodes []*clus for k, v := range constraints { candidates := []*cluster.Node{} for _, node := range nodes { - if label, ok := node.Labels[k]; ok { - if strings.Contains(strings.ToLower(label), v) { + switch k { + case "node": + // "node" label is a special case pinning a container to a specific node. + if strings.ToLower(node.ID) == v || strings.ToLower(node.Name) == v { candidates = append(candidates, node) } + default: + // By default match the node labels. + if label, ok := node.Labels[k]; ok { + if strings.Contains(strings.ToLower(label), v) { + candidates = append(candidates, node) + } + } } } if len(candidates) == 0 { diff --git a/scheduler/filter/label_test.go b/scheduler/filter/label_test.go index aaab4c17b9..fcab6185f2 100644 --- a/scheduler/filter/label_test.go +++ b/scheduler/filter/label_test.go @@ -12,24 +12,30 @@ func TestLabeleFilter(t *testing.T) { var ( f = LabelFilter{} nodes = []*cluster.Node{ + cluster.NewNode("node-0"), cluster.NewNode("node-1"), cluster.NewNode("node-2"), - cluster.NewNode("node-3"), } result []*cluster.Node err error ) + nodes[0].ID = "node-0-id" + nodes[0].Name = "node-0-name" nodes[0].Labels = map[string]string{ "name": "node0", "group": "1", } + nodes[1].ID = "node-1-id" + nodes[1].Name = "node-1-name" nodes[1].Labels = map[string]string{ "name": "node1", "group": "1", } + nodes[2].ID = "node-2-id" + nodes[2].Name = "node-2-name" nodes[2].Labels = map[string]string{ "name": "node2", "group": "2", @@ -62,6 +68,22 @@ func TestLabeleFilter(t *testing.T) { assert.Len(t, result, 2) assert.NotContains(t, result, nodes[2]) + // Validate node pinning by id. + result, err = f.Filter(&dockerclient.ContainerConfig{ + Env: []string{"constraint:node=node-2-id"}, + }, nodes) + assert.NoError(t, err) + assert.Len(t, result, 1) + assert.Equal(t, result[0], nodes[2]) + + // Validate node pinning by name. + 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]) + // Make sure constraints are evaluated as logical ANDs. result, err = f.Filter(&dockerclient.ContainerConfig{ Env: []string{"constraint:name=node0", "constraint:group=1"},