Add set contains

This commit is contained in:
Alex Dadgar
2016-10-19 13:06:28 -07:00
parent 06bf6c433b
commit c97711ef34
8 changed files with 87 additions and 0 deletions

View File

@@ -407,6 +407,7 @@ func parseConstraints(result *[]*structs.Constraint, list *ast.ObjectList) error
"version",
"regexp",
"distinct_hosts",
"set_contains",
}
if err := checkHCLKeys(o.Val, valid); err != nil {
return err
@@ -435,6 +436,13 @@ func parseConstraints(result *[]*structs.Constraint, list *ast.ObjectList) error
m["RTarget"] = constraint
}
// If "set_contains" is provided, set the operand
// to "set_contains" and the value to the "RTarget"
if constraint, ok := m[structs.ConstraintSetContains]; ok {
m["Operand"] = structs.ConstraintSetContains
m["RTarget"] = constraint
}
if value, ok := m[structs.ConstraintDistinctHosts]; ok {
enabled, err := parseBool(value)
if err != nil {

View File

@@ -282,6 +282,25 @@ func TestParse(t *testing.T) {
false,
},
{
"set-contains-constraint.hcl",
&structs.Job{
ID: "foo",
Name: "foo",
Priority: 50,
Region: "global",
Type: "service",
Constraints: []*structs.Constraint{
&structs.Constraint{
LTarget: "$meta.data",
RTarget: "foo,bar,baz",
Operand: structs.ConstraintSetContains,
},
},
},
false,
},
{
"distinctHosts-constraint.hcl",
&structs.Job{

View File

@@ -0,0 +1,6 @@
job "foo" {
constraint {
attribute = "$meta.data"
set_contains = "foo,bar,baz"
}
}

View File

@@ -2729,6 +2729,7 @@ const (
ConstraintDistinctHosts = "distinct_hosts"
ConstraintRegex = "regexp"
ConstraintVersion = "version"
ConstraintSetContains = "set_contains"
)
// Constraints are used to restrict placement options.

View File

@@ -344,6 +344,8 @@ func checkConstraint(ctx Context, operand string, lVal, rVal interface{}) bool {
return checkVersionConstraint(ctx, lVal, rVal)
case structs.ConstraintRegex:
return checkRegexpConstraint(ctx, lVal, rVal)
case structs.ConstraintSetContains:
return checkSetContainsConstraint(ctx, lVal, rVal)
default:
return false
}
@@ -451,6 +453,38 @@ func checkRegexpConstraint(ctx Context, lVal, rVal interface{}) bool {
return re.MatchString(lStr)
}
// checkSetContainsConstraint is used to see if the left hand side contains the
// string on the right hand side
func checkSetContainsConstraint(ctx Context, lVal, rVal interface{}) bool {
// Ensure left-hand is string
lStr, ok := lVal.(string)
if !ok {
return false
}
// Regexp must be a string
rStr, ok := rVal.(string)
if !ok {
return false
}
input := strings.Split(lStr, ",")
lookup := make(map[string]struct{}, len(input))
for _, in := range input {
cleaned := strings.TrimSpace(in)
lookup[cleaned] = struct{}{}
}
for _, r := range strings.Split(rStr, ",") {
cleaned := strings.TrimSpace(r)
if _, ok := lookup[cleaned]; !ok {
return false
}
}
return true
}
// FeasibilityWrapper is a FeasibleIterator which wraps both job and task group
// FeasibilityCheckers in which feasibility checking can be skipped if the
// computed node class has previously been marked as eligible or ineligible.

View File

@@ -304,6 +304,16 @@ func TestCheckConstraint(t *testing.T) {
lVal: "foo", rVal: "bar",
result: false,
},
{
op: structs.ConstraintSetContains,
lVal: "foo,bar,baz", rVal: "foo, bar ",
result: true,
},
{
op: structs.ConstraintSetContains,
lVal: "foo,bar,baz", rVal: "foo,bam",
result: false,
},
}
for _, tc := range cases {

View File

@@ -419,6 +419,12 @@ The `constraint` object supports the following keys:
the attribute. This sets the operator to "regexp" and the `value`
to the regular expression.
* `set_contains` - Specifies a set contains constraint against
the attribute. This sets the operator to "set_contains" and the `value`
to the what is specified. This will check that the given attribute contains
each of the specified elements. The attribute and the list being checked are
split using commas.
* `distinct_hosts` - `distinct_hosts` accepts a boolean value and defaults to
`false`. If set, the scheduler will not co-locate any task groups on the same
machine. This can be specified as a job constraint which applies the

View File

@@ -443,6 +443,9 @@ The `Constraint` object supports the following keys:
* `regexp` - Allows the `RTarget` to be a regular expression to be matched.
* `set_contains` - Allows the `RTarget` to be a comma separated list of values
that should be contained in the LTarget's value.
* `distinct_host` - If set, the scheduler will not co-locate any task groups on the same
machine. This can be specified as a job constraint which applies the
constraint to all task groups in the job, or as a task group constraint which