diff --git a/README.md b/README.md index a96cc80934..905727d14f 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,8 @@ Some of *SwarmKit*'s main features are: | node.id | node's ID | `node.id == 2ivku8v2gvtg4`| | node.hostname | node's hostname | `node.hostname != node-2`| | node.role | node's manager or worker role | `node.role == manager`| + | node.platform.os | node's operating system | `node.platform.os == linux`| + | node.platform.arch | node's architecture | `node.platform.arch == x86_64`| | node.labels | node's labels added by cluster admins | `node.labels.security == high`| | engine.labels | Docker Engine's labels | `engine.labels.operatingsystem == ubuntu 14.04`| diff --git a/manager/constraint/constraint.go b/manager/constraint/constraint.go index acd4245c61..ae636cb109 100644 --- a/manager/constraint/constraint.go +++ b/manager/constraint/constraint.go @@ -125,6 +125,26 @@ func NodeMatches(constraints []Constraint, n *api.Node) bool { if !constraint.Match(n.Spec.Role.String()) { return false } + case strings.EqualFold(constraint.key, "node.platform.os"): + if n.Description == nil || n.Description.Platform == nil { + if !constraint.Match("") { + return false + } + continue + } + if !constraint.Match(n.Description.Platform.OS) { + return false + } + case strings.EqualFold(constraint.key, "node.platform.arch"): + if n.Description == nil || n.Description.Platform == nil { + if !constraint.Match("") { + return false + } + continue + } + if !constraint.Match(n.Description.Platform.Architecture) { + return false + } // node labels constraint in form like 'node.labels.key==value' case len(constraint.key) > len(nodeLabelPrefix) && strings.EqualFold(constraint.key[:len(nodeLabelPrefix)], nodeLabelPrefix): diff --git a/manager/scheduler/constraint_test.go b/manager/scheduler/constraint_test.go index 1c5429ae36..9d3babdb12 100644 --- a/manager/scheduler/constraint_test.go +++ b/manager/scheduler/constraint_test.go @@ -158,6 +158,41 @@ func TestNodeRole(t *testing.T) { assert.False(t, f.Check(ni)) } +func TestNodePlatform(t *testing.T) { + setupEnv() + f := ConstraintFilter{} + task1.Spec.Placement = &api.Placement{ + Constraints: []string{"node.platform.os == linux"}, + } + require.True(t, f.SetTask(task1)) + //node info doesn't have platform yet + assert.False(t, f.Check(ni)) + + ni.Node.Description.Platform = &api.Platform{ + Architecture: "x86_64", + OS: "linux", + } + assert.True(t, f.Check(ni)) + + ni.Node.Description.Platform = &api.Platform{ + Architecture: "x86_64", + OS: "windows", + } + assert.False(t, f.Check(ni)) + + task1.Spec.Placement = &api.Placement{ + Constraints: []string{"node.platform.arch == amd64"}, + } + require.True(t, f.SetTask(task1)) + assert.False(t, f.Check(ni)) + + task1.Spec.Placement = &api.Placement{ + Constraints: []string{"node.platform.arch != amd64"}, + } + require.True(t, f.SetTask(task1)) + assert.True(t, f.Check(ni)) +} + func TestNodeLabel(t *testing.T) { setupEnv() f := ConstraintFilter{}