diff --git a/api/compose_test.go b/api/compose_test.go index 85574da6cac8..68801519f073 100644 --- a/api/compose_test.go +++ b/api/compose_test.go @@ -10,7 +10,7 @@ func TestCompose(t *testing.T) { task := NewTask("task1", "exec"). SetConfig("foo", "bar"). SetMeta("foo", "bar"). - Constrain(HardConstraint("kernel.name", "=", "linux")). + Constrain(NewConstraint("kernel.name", "=", "linux")). Require(&Resources{ CPU: 1250, MemoryMB: 1024, @@ -27,7 +27,7 @@ func TestCompose(t *testing.T) { // Compose a task group grp := NewTaskGroup("grp1", 2). - Constrain(HardConstraint("kernel.name", "=", "linux")). + Constrain(NewConstraint("kernel.name", "=", "linux")). SetMeta("foo", "bar"). AddTask(task) @@ -35,7 +35,7 @@ func TestCompose(t *testing.T) { job := NewServiceJob("job1", "myjob", "region1", 2). SetMeta("foo", "bar"). AddDatacenter("dc1"). - Constrain(HardConstraint("kernel.name", "=", "linux")). + Constrain(NewConstraint("kernel.name", "=", "linux")). AddTaskGroup(grp) // Check that the composed result looks correct @@ -53,11 +53,9 @@ func TestCompose(t *testing.T) { }, Constraints: []*Constraint{ &Constraint{ - Hard: true, LTarget: "kernel.name", RTarget: "linux", Operand: "=", - Weight: 0, }, }, TaskGroups: []*TaskGroup{ @@ -66,11 +64,9 @@ func TestCompose(t *testing.T) { Count: 2, Constraints: []*Constraint{ &Constraint{ - Hard: true, LTarget: "kernel.name", RTarget: "linux", Operand: "=", - Weight: 0, }, }, Tasks: []*Task{ @@ -95,11 +91,9 @@ func TestCompose(t *testing.T) { }, Constraints: []*Constraint{ &Constraint{ - Hard: true, LTarget: "kernel.name", RTarget: "linux", Operand: "=", - Weight: 0, }, }, Config: map[string]string{ diff --git a/api/constraint.go b/api/constraint.go index 1a0f3233a1ef..ec3a37a64148 100644 --- a/api/constraint.go +++ b/api/constraint.go @@ -2,32 +2,16 @@ package api // Constraint is used to serialize a job placement constraint. type Constraint struct { - Hard bool LTarget string RTarget string Operand string - Weight int } -// HardConstraint is used to create a new hard constraint. -func HardConstraint(left, operand, right string) *Constraint { - return constraint(left, operand, right, true, 0) -} - -// SoftConstraint is used to create a new soft constraint. It -// takes an additional weight parameter to allow balancing -// multiple soft constraints amongst eachother. -func SoftConstraint(left, operand, right string, weight int) *Constraint { - return constraint(left, operand, right, false, weight) -} - -// constraint generates a new job placement constraint. -func constraint(left, operand, right string, hard bool, weight int) *Constraint { +// NewConstraint generates a new job placement constraint. +func NewConstraint(left, operand, right string) *Constraint { return &Constraint{ - Hard: hard, LTarget: left, RTarget: right, Operand: operand, - Weight: weight, } } diff --git a/api/constraint_test.go b/api/constraint_test.go index a8c7b98387e2..26b0c9fcfd8f 100644 --- a/api/constraint_test.go +++ b/api/constraint_test.go @@ -6,25 +6,11 @@ import ( ) func TestCompose_Constraints(t *testing.T) { - c := HardConstraint("kernel.name", "=", "darwin") + c := NewConstraint("kernel.name", "=", "darwin") expect := &Constraint{ - Hard: true, LTarget: "kernel.name", RTarget: "darwin", Operand: "=", - Weight: 0, - } - if !reflect.DeepEqual(c, expect) { - t.Fatalf("expect: %#v, got: %#v", expect, c) - } - - c = SoftConstraint("memory.totalbytes", ">=", "250000000", 5) - expect = &Constraint{ - Hard: false, - LTarget: "memory.totalbytes", - RTarget: "250000000", - Operand: ">=", - Weight: 5, } if !reflect.DeepEqual(c, expect) { t.Fatalf("expect: %#v, got: %#v", expect, c) diff --git a/api/jobs_test.go b/api/jobs_test.go index 59d1005d2d59..3d81204c0a7a 100644 --- a/api/jobs_test.go +++ b/api/jobs_test.go @@ -275,7 +275,7 @@ func TestJobs_Constrain(t *testing.T) { job := &Job{Constraints: nil} // Create and add a constraint - out := job.Constrain(HardConstraint("kernel.name", "=", "darwin")) + out := job.Constrain(NewConstraint("kernel.name", "=", "darwin")) if n := len(job.Constraints); n != 1 { t.Fatalf("expected 1 constraint, got: %d", n) } @@ -286,21 +286,17 @@ func TestJobs_Constrain(t *testing.T) { } // Adding another constraint preserves the original - job.Constrain(SoftConstraint("memory.totalbytes", ">=", "128000000", 2)) + job.Constrain(NewConstraint("memory.totalbytes", ">=", "128000000")) expect := []*Constraint{ &Constraint{ - Hard: true, LTarget: "kernel.name", RTarget: "darwin", Operand: "=", - Weight: 0, }, &Constraint{ - Hard: false, LTarget: "memory.totalbytes", RTarget: "128000000", Operand: ">=", - Weight: 2, }, } if !reflect.DeepEqual(job.Constraints, expect) { diff --git a/api/tasks_test.go b/api/tasks_test.go index 428d178eb2ca..877f84d5c002 100644 --- a/api/tasks_test.go +++ b/api/tasks_test.go @@ -20,7 +20,7 @@ func TestTaskGroup_Constrain(t *testing.T) { grp := NewTaskGroup("grp1", 1) // Add a constraint to the group - out := grp.Constrain(HardConstraint("kernel.name", "=", "darwin")) + out := grp.Constrain(NewConstraint("kernel.name", "=", "darwin")) if n := len(grp.Constraints); n != 1 { t.Fatalf("expected 1 constraint, got: %d", n) } @@ -31,21 +31,17 @@ func TestTaskGroup_Constrain(t *testing.T) { } // Add a second constraint - grp.Constrain(SoftConstraint("memory.totalbytes", ">=", "128000000", 2)) + grp.Constrain(NewConstraint("memory.totalbytes", ">=", "128000000")) expect := []*Constraint{ &Constraint{ - Hard: true, LTarget: "kernel.name", RTarget: "darwin", Operand: "=", - Weight: 0, }, &Constraint{ - Hard: false, LTarget: "memory.totalbytes", RTarget: "128000000", Operand: ">=", - Weight: 2, }, } if !reflect.DeepEqual(grp.Constraints, expect) { @@ -193,7 +189,7 @@ func TestTask_Constrain(t *testing.T) { task := NewTask("task1", "exec") // Add a constraint to the task - out := task.Constrain(HardConstraint("kernel.name", "=", "darwin")) + out := task.Constrain(NewConstraint("kernel.name", "=", "darwin")) if n := len(task.Constraints); n != 1 { t.Fatalf("expected 1 constraint, got: %d", n) } @@ -204,21 +200,17 @@ func TestTask_Constrain(t *testing.T) { } // Add a second constraint - task.Constrain(SoftConstraint("memory.totalbytes", ">=", "128000000", 2)) + task.Constrain(NewConstraint("memory.totalbytes", ">=", "128000000")) expect := []*Constraint{ &Constraint{ - Hard: true, LTarget: "kernel.name", RTarget: "darwin", Operand: "=", - Weight: 0, }, &Constraint{ - Hard: false, LTarget: "memory.totalbytes", RTarget: "128000000", Operand: ">=", - Weight: 2, }, } if !reflect.DeepEqual(task.Constraints, expect) { diff --git a/jobspec/parse.go b/jobspec/parse.go index 9a98da5223ea..f63ac5294a7c 100644 --- a/jobspec/parse.go +++ b/jobspec/parse.go @@ -238,11 +238,6 @@ func parseConstraints(result *[]*structs.Constraint, obj *hclobj.Object) error { m["RTarget"] = m["value"] m["Operand"] = m["operator"] - // Default constraint to being hard - if _, ok := m["hard"]; !ok { - m["hard"] = true - } - // If "version" is provided, set the operand // to "version" and the value to the "RTarget" if constraint, ok := m[structs.ConstraintVersion]; ok { diff --git a/jobspec/parse_test.go b/jobspec/parse_test.go index ccdc9989967a..f91789ddb1ed 100644 --- a/jobspec/parse_test.go +++ b/jobspec/parse_test.go @@ -33,7 +33,6 @@ func TestParse(t *testing.T) { Constraints: []*structs.Constraint{ &structs.Constraint{ - Hard: true, LTarget: "kernel.os", RTarget: "windows", Operand: "=", @@ -68,7 +67,6 @@ func TestParse(t *testing.T) { Count: 5, Constraints: []*structs.Constraint{ &structs.Constraint{ - Hard: true, LTarget: "kernel.os", RTarget: "linux", Operand: "=", @@ -114,7 +112,6 @@ func TestParse(t *testing.T) { }, Constraints: []*structs.Constraint{ &structs.Constraint{ - Hard: true, LTarget: "kernel.arch", RTarget: "amd64", Operand: "=", @@ -162,7 +159,6 @@ func TestParse(t *testing.T) { Type: "service", Constraints: []*structs.Constraint{ &structs.Constraint{ - Hard: true, LTarget: "$attr.kernel.version", RTarget: "~> 3.2", Operand: structs.ConstraintVersion, @@ -182,7 +178,6 @@ func TestParse(t *testing.T) { Type: "service", Constraints: []*structs.Constraint{ &structs.Constraint{ - Hard: true, LTarget: "$attr.kernel.version", RTarget: "[0-9.]+", Operand: structs.ConstraintRegex, @@ -202,7 +197,6 @@ func TestParse(t *testing.T) { Type: "service", Constraints: []*structs.Constraint{ &structs.Constraint{ - Hard: true, Operand: structs.ConstraintDistinctHosts, }, }, diff --git a/nomad/mock/mock.go b/nomad/mock/mock.go index 8aa3d5ba95a0..87c426dceab8 100644 --- a/nomad/mock/mock.go +++ b/nomad/mock/mock.go @@ -62,7 +62,6 @@ func Job() *structs.Job { Datacenters: []string{"dc1"}, Constraints: []*structs.Constraint{ &structs.Constraint{ - Hard: true, LTarget: "$attr.kernel.name", RTarget: "linux", Operand: "=", @@ -123,7 +122,6 @@ func SystemJob() *structs.Job { Datacenters: []string{"dc1"}, Constraints: []*structs.Constraint{ &structs.Constraint{ - Hard: true, LTarget: "$attr.kernel.name", RTarget: "linux", Operand: "=", diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index c82dc88da086..f5d20552ae3b 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -1033,15 +1033,11 @@ const ( ConstraintVersion = "version" ) -// Constraints are used to restrict placement options in the case of -// a hard constraint, and used to prefer a placement in the case of -// a soft constraint. +// Constraints are used to restrict placement options. type Constraint struct { - Hard bool // Hard or soft constraint LTarget string // Left-hand target RTarget string // Right-hand target Operand string // Constraint operand (<=, <, =, !=, >, >=), contains, near - Weight int // Soft constraints can vary the weight } func (c *Constraint) String() string { @@ -1185,8 +1181,7 @@ type AllocMetric struct { // NodesEvaluated is the number of nodes that were evaluated NodesEvaluated int - // NodesFiltered is the number of nodes filtered due to - // a hard constraint + // NodesFiltered is the number of nodes filtered due to a constraint NodesFiltered int // ClassFiltered is the number of nodes filtered by class diff --git a/scheduler/feasible.go b/scheduler/feasible.go index 782d7c8751d0..9e6782b19496 100644 --- a/scheduler/feasible.go +++ b/scheduler/feasible.go @@ -303,11 +303,6 @@ func (iter *ConstraintIterator) meetsConstraints(option *structs.Node) bool { } func (iter *ConstraintIterator) meetsConstraint(constraint *structs.Constraint, option *structs.Node) bool { - // Only enforce hard constraints, soft constraints are used for ranking - if !constraint.Hard { - return true - } - // Resolve the targets lVal, ok := resolveConstraintTarget(constraint.LTarget, option) if !ok { diff --git a/scheduler/feasible_test.go b/scheduler/feasible_test.go index b5aead21f830..84ad6d7ee34c 100644 --- a/scheduler/feasible_test.go +++ b/scheduler/feasible_test.go @@ -120,13 +120,11 @@ func TestConstraintIterator(t *testing.T) { constraints := []*structs.Constraint{ &structs.Constraint{ - Hard: true, Operand: "=", LTarget: "$node.datacenter", RTarget: "dc1", }, &structs.Constraint{ - Hard: true, Operand: "is", LTarget: "$attr.kernel.name", RTarget: "linux", diff --git a/scheduler/util_test.go b/scheduler/util_test.go index a730f28e373b..7873c55c5829 100644 --- a/scheduler/util_test.go +++ b/scheduler/util_test.go @@ -600,9 +600,9 @@ func TestEvictAndPlace_LimitGreaterThanAllocs(t *testing.T) { } func TestTaskGroupConstraints(t *testing.T) { - constr := &structs.Constraint{Hard: true} + constr := &structs.Constraint{RTarget: "bar"} constr2 := &structs.Constraint{LTarget: "foo"} - constr3 := &structs.Constraint{Weight: 10} + constr3 := &structs.Constraint{Operand: "<"} tg := &structs.TaskGroup{ Name: "web", diff --git a/website/source/docs/http/alloc.html.md b/website/source/docs/http/alloc.html.md index 6ab67cc9068e..3c224fd54018 100644 --- a/website/source/docs/http/alloc.html.md +++ b/website/source/docs/http/alloc.html.md @@ -54,11 +54,9 @@ be specified using the `?region=` query parameter. ], "Constraints": [ { - "Hard": false, "LTarget": "kernel.os", "RTarget": "windows", "Operand": "=", - "Weight": 0 } ], "TaskGroups": [ @@ -67,11 +65,9 @@ be specified using the `?region=` query parameter. "Count": 5, "Constraints": [ { - "Hard": false, "LTarget": "kernel.os", "RTarget": "linux", "Operand": "=", - "Weight": 0 } ], "Tasks": [ @@ -108,11 +104,9 @@ be specified using the `?region=` query parameter. }, "Constraints": [ { - "Hard": false, "LTarget": "kernel.arch", "RTarget": "amd64", "Operand": "=", - "Weight": 0 } ], "Resources": { diff --git a/website/source/docs/http/job.html.md b/website/source/docs/http/job.html.md index 1ccbe8dacefc..211963e6a121 100644 --- a/website/source/docs/http/job.html.md +++ b/website/source/docs/http/job.html.md @@ -47,11 +47,9 @@ region is used; another region can be specified using the `?region=` query param ], "Constraints": [ { - "Hard": true, "LTarget": "kernel.os", "RTarget": "windows", "Operand": "=", - "Weight": 0 } ], "TaskGroups": [ @@ -60,11 +58,9 @@ region is used; another region can be specified using the `?region=` query param "Count": 5, "Constraints": [ { - "Hard": true, "LTarget": "kernel.os", "RTarget": "linux", "Operand": "=", - "Weight": 0 } ], "Tasks": [ @@ -101,11 +97,9 @@ region is used; another region can be specified using the `?region=` query param }, "Constraints": [ { - "Hard": true, "LTarget": "kernel.arch", "RTarget": "amd64", "Operand": "=", - "Weight": 0 } ], "Resources": { diff --git a/website/source/docs/jobspec/index.html.md b/website/source/docs/jobspec/index.html.md index c16723e7cd47..3d05c909b3c0 100644 --- a/website/source/docs/jobspec/index.html.md +++ b/website/source/docs/jobspec/index.html.md @@ -216,9 +216,6 @@ The `constraint` object supports the following keys: * `attribute` - Specifies the attribute to examine for the constraint. See the table of attributes below. -* `hard` - Specifies if this is a hard or soft constraint. Defaults - to true. Soft constraints are not currently supported. - * `operator` - Specifies the comparison operator. Defaults to equality, and can be `=`, `==`, `is`, `!=`, `not`, `>`, `>=`, `<`, `<=`. The ordering is compared lexically.