Merge pull request #351 from hashicorp/f-clean-constraints

Remove weight and hard/soft fields from constraint
This commit is contained in:
Alex Dadgar 2015-10-28 10:14:06 -07:00
commit d11a7782a9
15 changed files with 16 additions and 104 deletions

View File

@ -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{

View File

@ -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,
}
}

View File

@ -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)

View File

@ -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) {

View File

@ -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) {

View File

@ -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 {

View File

@ -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,
},
},

View File

@ -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: "=",

View File

@ -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

View File

@ -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 {

View File

@ -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",

View File

@ -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",

View File

@ -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": {

View File

@ -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": {

View File

@ -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.