diff --git a/jobspec/parse.go b/jobspec/parse.go index 18d1a4ff3..9a98da522 100644 --- a/jobspec/parse.go +++ b/jobspec/parse.go @@ -245,19 +245,19 @@ func parseConstraints(result *[]*structs.Constraint, obj *hclobj.Object) error { // If "version" is provided, set the operand // to "version" and the value to the "RTarget" - if constraint, ok := m["version"]; ok { - m["Operand"] = "version" + if constraint, ok := m[structs.ConstraintVersion]; ok { + m["Operand"] = structs.ConstraintVersion m["RTarget"] = constraint } // If "regexp" is provided, set the operand // to "regexp" and the value to the "RTarget" - if constraint, ok := m["regexp"]; ok { - m["Operand"] = "regexp" + if constraint, ok := m[structs.ConstraintRegex]; ok { + m["Operand"] = structs.ConstraintRegex m["RTarget"] = constraint } - if value, ok := m["distinctHosts"]; ok { + if value, ok := m[structs.ConstraintDistinctHosts]; ok { enabled, err := strconv.ParseBool(value.(string)) if err != nil { return err @@ -268,7 +268,7 @@ func parseConstraints(result *[]*structs.Constraint, obj *hclobj.Object) error { continue } - m["Operand"] = "distinctHosts" + m["Operand"] = structs.ConstraintDistinctHosts } // Build the constraint diff --git a/jobspec/parse_test.go b/jobspec/parse_test.go index 07cb7c914..ccdc99899 100644 --- a/jobspec/parse_test.go +++ b/jobspec/parse_test.go @@ -165,7 +165,7 @@ func TestParse(t *testing.T) { Hard: true, LTarget: "$attr.kernel.version", RTarget: "~> 3.2", - Operand: "version", + Operand: structs.ConstraintVersion, }, }, }, @@ -185,7 +185,7 @@ func TestParse(t *testing.T) { Hard: true, LTarget: "$attr.kernel.version", RTarget: "[0-9.]+", - Operand: "regexp", + Operand: structs.ConstraintRegex, }, }, }, @@ -203,7 +203,7 @@ func TestParse(t *testing.T) { Constraints: []*structs.Constraint{ &structs.Constraint{ Hard: true, - Operand: "distinctHosts", + Operand: structs.ConstraintDistinctHosts, }, }, }, diff --git a/jobspec/test-fixtures/distinctHosts-constraint.hcl b/jobspec/test-fixtures/distinctHosts-constraint.hcl index 7780c4b8c..cf6bc7bfc 100644 --- a/jobspec/test-fixtures/distinctHosts-constraint.hcl +++ b/jobspec/test-fixtures/distinctHosts-constraint.hcl @@ -1,5 +1,5 @@ job "foo" { constraint { - distinctHosts = "true" + distinct_hosts = "true" } } diff --git a/nomad/structs/structs.go b/nomad/structs/structs.go index 8d58a9857..c82dc88da 100644 --- a/nomad/structs/structs.go +++ b/nomad/structs/structs.go @@ -1027,6 +1027,12 @@ func (t *Task) Validate() error { return mErr.ErrorOrNil() } +const ( + ConstraintDistinctHosts = "distinct_hosts" + ConstraintRegex = "regexp" + 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. @@ -1050,11 +1056,11 @@ func (c *Constraint) Validate() error { // Perform additional validation based on operand switch c.Operand { - case "regexp": + case ConstraintRegex: if _, err := regexp.Compile(c.RTarget); err != nil { mErr.Errors = append(mErr.Errors, fmt.Errorf("Regular expression failed to compile: %v", err)) } - case "version": + case ConstraintVersion: if _, err := version.NewConstraint(c.RTarget); err != nil { mErr.Errors = append(mErr.Errors, fmt.Errorf("Version constraint is invalid: %v", err)) } diff --git a/nomad/structs/structs_test.go b/nomad/structs/structs_test.go index 6df231a67..cabf83dfa 100644 --- a/nomad/structs/structs_test.go +++ b/nomad/structs/structs_test.go @@ -144,7 +144,7 @@ func TestConstraint_Validate(t *testing.T) { } // Perform additional regexp validation - c.Operand = "regexp" + c.Operand = ConstraintRegex c.RTarget = "(foo" err = c.Validate() mErr = err.(*multierror.Error) @@ -153,7 +153,7 @@ func TestConstraint_Validate(t *testing.T) { } // Perform version validation - c.Operand = "version" + c.Operand = ConstraintVersion c.RTarget = "~> foo" err = c.Validate() mErr = err.(*multierror.Error) diff --git a/scheduler/feasible.go b/scheduler/feasible.go index 7a96b6644..cbd87f036 100644 --- a/scheduler/feasible.go +++ b/scheduler/feasible.go @@ -152,7 +152,7 @@ func (iter *DriverIterator) hasDrivers(option *structs.Node) bool { // DynamicConstraintIterator is a FeasibleIterator which returns nodes that // match constraints that are not static such as Node attributes but are -// effected by alloc placements. Examples are distinctHosts and tenancy constraints. +// effected by alloc placements. Examples are distinct_hosts and tenancy constraints. // This is used to filter on job and task group constraints. type DynamicConstraintIterator struct { ctx Context @@ -160,7 +160,7 @@ type DynamicConstraintIterator struct { tg *structs.TaskGroup job *structs.Job - // Store whether the Job or TaskGroup has a distinctHosts constraints so + // Store whether the Job or TaskGroup has a distinct_hosts constraints so // they don't have to be calculated every time Next() is called. tgDistinctHosts bool jobDistinctHosts bool @@ -192,7 +192,7 @@ func (iter *DynamicConstraintIterator) hasDistinctHostsConstraint(constraints [] } for _, con := range constraints { - if con.Operand == "distinctHosts" { + if con.Operand == structs.ConstraintDistinctHosts { return true } } @@ -214,13 +214,13 @@ func (iter *DynamicConstraintIterator) Next() *structs.Node { // Get the next option from the source option := iter.source.Next() - // Hot-path if the option is nil or there are no distinctHosts constraints. + // Hot-path if the option is nil or there are no distinct_hosts constraints. if option == nil || (!iter.jobDistinctHosts && !iter.tgDistinctHosts) { return option } if !iter.satisfiesDistinctHosts(option, iter.jobDistinctHosts) { - iter.ctx.Metrics().FilterNode(option, "distinctHosts") + iter.ctx.Metrics().FilterNode(option, structs.ConstraintDistinctHosts) continue } @@ -228,7 +228,7 @@ func (iter *DynamicConstraintIterator) Next() *structs.Node { } } -// satisfiesDistinctHosts checks if the node satisfies a distinctHosts +// satisfiesDistinctHosts checks if the node satisfies a distinct_hosts // constraint either specified at the job level or the TaskGroup level. func (iter *DynamicConstraintIterator) satisfiesDistinctHosts(option *structs.Node, job bool) bool { // Get the proposed allocations @@ -244,7 +244,7 @@ func (iter *DynamicConstraintIterator) satisfiesDistinctHosts(option *structs.No jobCollision := alloc.JobID == iter.job.ID taskCollision := alloc.TaskGroup == iter.tg.Name - // If the job has a distinctHosts constraint we only need an alloc + // If the job has a distinct_hosts constraint we only need an alloc // collision on the JobID but if the constraint is on the TaskGroup then // we need both a job and TaskGroup collision. jobInvalid := job && jobCollision @@ -370,7 +370,7 @@ func resolveConstraintTarget(target string, node *structs.Node) (interface{}, bo func checkConstraint(ctx Context, operand string, lVal, rVal interface{}) bool { // Check for constraints not handled by this iterator. switch operand { - case "distinctHosts": + case structs.ConstraintDistinctHosts: return true default: break @@ -383,9 +383,9 @@ func checkConstraint(ctx Context, operand string, lVal, rVal interface{}) bool { return !reflect.DeepEqual(lVal, rVal) case "<", "<=", ">", ">=": return checkLexicalOrder(operand, lVal, rVal) - case "version": + case structs.ConstraintVersion: return checkVersionConstraint(ctx, lVal, rVal) - case "regexp": + case structs.ConstraintRegex: return checkRegexpConstraint(ctx, lVal, rVal) default: return false diff --git a/scheduler/feasible_test.go b/scheduler/feasible_test.go index 74eb99f03..a898baa96 100644 --- a/scheduler/feasible_test.go +++ b/scheduler/feasible_test.go @@ -248,12 +248,12 @@ func TestCheckConstraint(t *testing.T) { result: true, }, { - op: "version", + op: structs.ConstraintVersion, lVal: "1.2.3", rVal: "~> 1.0", result: true, }, { - op: "regexp", + op: structs.ConstraintRegex, lVal: "foobarbaz", rVal: "[\\w]+", result: true, }, @@ -392,13 +392,13 @@ func TestDynamicConstraint_JobDistinctHosts(t *testing.T) { } static := NewStaticIterator(ctx, nodes) - // Create a job with a distinctHosts constraint and two task groups. + // Create a job with a distinct_hosts constraint and two task groups. tg1 := &structs.TaskGroup{Name: "bar"} tg2 := &structs.TaskGroup{Name: "baz"} job := &structs.Job{ ID: "foo", - Constraints: []*structs.Constraint{{Operand: "distinctHosts"}}, + Constraints: []*structs.Constraint{{Operand: structs.ConstraintDistinctHosts}}, TaskGroups: []*structs.TaskGroup{tg1, tg2}, } @@ -428,13 +428,13 @@ func TestDynamicConstraint_JobDistinctHosts_Infeasible(t *testing.T) { } static := NewStaticIterator(ctx, nodes) - // Create a job with a distinctHosts constraint and two task groups. + // Create a job with a distinct_hosts constraint and two task groups. tg1 := &structs.TaskGroup{Name: "bar"} tg2 := &structs.TaskGroup{Name: "baz"} job := &structs.Job{ ID: "foo", - Constraints: []*structs.Constraint{{Operand: "distinctHosts"}}, + Constraints: []*structs.Constraint{{Operand: structs.ConstraintDistinctHosts}}, TaskGroups: []*structs.TaskGroup{tg1, tg2}, } @@ -484,14 +484,14 @@ func TestDynamicConstraint_JobDistinctHosts_InfeasibleCount(t *testing.T) { } static := NewStaticIterator(ctx, nodes) - // Create a job with a distinctHosts constraint and three task groups. + // Create a job with a distinct_hosts constraint and three task groups. tg1 := &structs.TaskGroup{Name: "bar"} tg2 := &structs.TaskGroup{Name: "baz"} tg3 := &structs.TaskGroup{Name: "bam"} job := &structs.Job{ ID: "foo", - Constraints: []*structs.Constraint{{Operand: "distinctHosts"}}, + Constraints: []*structs.Constraint{{Operand: structs.ConstraintDistinctHosts}}, TaskGroups: []*structs.TaskGroup{tg1, tg2, tg3}, } @@ -514,11 +514,11 @@ func TestDynamicConstraint_TaskGroupDistinctHosts(t *testing.T) { } static := NewStaticIterator(ctx, nodes) - // Create a task group with a distinctHosts constraint. + // Create a task group with a distinct_hosts constraint. taskGroup := &structs.TaskGroup{ Name: "example", Constraints: []*structs.Constraint{ - {Operand: "distinctHosts"}, + {Operand: structs.ConstraintDistinctHosts}, }, } diff --git a/website/source/docs/jobspec/index.html.md b/website/source/docs/jobspec/index.html.md index 1cde52456..c16723e7c 100644 --- a/website/source/docs/jobspec/index.html.md +++ b/website/source/docs/jobspec/index.html.md @@ -237,13 +237,13 @@ The `constraint` object supports the following keys: the attribute. This sets the operator to "regexp" and the `value` to the regular expression. -* `distinctHosts` - `distinctHosts` accepts a boolean `true`. The default is +* `distinct_hosts` - `distinct_hosts` accepts a boolean `true`. The default is `false`. - When `distinctHosts` is `true` at the Job level, each instance of all Task + When `distinct_hosts` is `true` at the Job level, each instance of all Task Groups specified in the job is placed on a separate host. - When `distinctHosts` is `true` at the Task Group level with count > 1, each + When `distinct_hosts` is `true` at the Task Group level with count > 1, each instance of a Task Group is placed on a separate host. Different task groups in the same job _may_ be co-scheduled.