Skip to content

Commit

Permalink
add unlikeconstraint + unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Rob-Johnson committed Nov 20, 2015
1 parent 4e68bf9 commit 0c7f87c
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 4 deletions.
@@ -0,0 +1,37 @@
package org.apache.mesos.chronos.scheduler.jobs.constraints

import java.util.logging.Logger

import org.apache.mesos.Protos
import scala.collection.JavaConversions._

case class UnlikeConstraint(attribute: String, value: String) extends Constraint {

val regex = value.r

private[this] val log = Logger.getLogger(getClass.getName)

def matches(attributes: Seq[Protos.Attribute]): Boolean = {
attributes.find(a => a.getName == attribute).exists { a =>
a.getType match {
case Protos.Value.Type.SCALAR =>
!regex.pattern.matcher(a.getScalar.getValue.toString).matches()
case Protos.Value.Type.SET =>
!a.getSet.getItemList.exists(regex.pattern.matcher(_).matches())
case Protos.Value.Type.TEXT =>
!regex.pattern.matcher(a.getText.getValue).matches()
case Protos.Value.Type.RANGES =>
log.warning("Unlike constraint does not support attributes of type RANGES")
false
case _ =>
val t = a.getType.getNumber
log.warning(s"Unknown constraint with number $t in Unlike constraint")
false
}
}
}
}

object UnlikeConstraint {
val OPERATOR = "UNLIKE"
}
Expand Up @@ -191,6 +191,8 @@ class JobDeserializer extends JsonDeserializer[BaseJob] {
constraints.add(EqualsConstraint(c.get(0).asText, c.get(2).asText))
case LikeConstraint.OPERATOR =>
constraints.add(LikeConstraint(c.get(0).asText, c.get(2).asText))
case UnlikeConstraint.OPERATOR =>
constraints.add(UnlikeConstraint(c.get(0).asText, c.get(2).asText))
case _ =>
}
}
Expand Down
@@ -1,7 +1,7 @@
package org.apache.mesos.chronos.utils

import org.apache.mesos.chronos.scheduler.jobs.{BaseJob, DependencyBasedJob, ScheduleBasedJob}
import org.apache.mesos.chronos.scheduler.jobs.constraints.{LikeConstraint, EqualsConstraint}
import org.apache.mesos.chronos.scheduler.jobs.constraints.{LikeConstraint, EqualsConstraint, UnlikeConstraint}
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.{JsonSerializer, SerializerProvider}

Expand Down Expand Up @@ -165,6 +165,10 @@ class JobSerializer extends JsonSerializer[BaseJob] {
json.writeString(attribute)
json.writeString(LikeConstraint.OPERATOR)
json.writeString(value)
case UnlikeConstraint(attribute, value) =>
json.writeString(attribute)
json.writeString(UnlikeConstraint.OPERATOR)
json.writeString(value)
}
json.writeEndArray()
}
Expand Down
@@ -1,6 +1,6 @@
package org.apache.mesos.chronos.scheduler.api

import org.apache.mesos.chronos.scheduler.jobs.constraints.{LikeConstraint, EqualsConstraint}
import org.apache.mesos.chronos.scheduler.jobs.constraints.{LikeConstraint, EqualsConstraint, UnlikeConstraint}
import org.apache.mesos.chronos.scheduler.jobs.{DependencyBasedJob, DockerContainer, EnvironmentVariable, ScheduleBasedJob, _}
import org.apache.mesos.chronos.utils.{JobDeserializer, JobSerializer}
import com.fasterxml.jackson.databind.ObjectMapper
Expand Down Expand Up @@ -40,7 +40,8 @@ class SerDeTest extends SpecificationWithJUnit {

val constraints = Seq(
EqualsConstraint("rack", "rack-1"),
LikeConstraint("rack", "rack-[1-3]")
LikeConstraint("rack", "rack-[1-3]"),
UnlikeConstraint("host", "foo")
)

val a = new DependencyBasedJob(Set("B", "C", "D", "E"), "A", "noop", Minutes.minutes(5).toPeriod, 10L,
Expand Down Expand Up @@ -82,7 +83,8 @@ class SerDeTest extends SpecificationWithJUnit {

val constraints = Seq(
EqualsConstraint("rack", "rack-1"),
LikeConstraint("rack", "rack-[1-3]")
LikeConstraint("rack", "rack-[1-3]"),
UnlikeConstraint("host", "foo")
)

val a = new ScheduleBasedJob("FOO/BAR/BAM", "A", "noop", Minutes.minutes(5).toPeriod, 10L, 20L,
Expand Down
@@ -0,0 +1,47 @@
package org.apache.mesos.chronos.scheduler.jobs.constraints

import java.util.regex.PatternSyntaxException

import org.specs2.mutable.SpecificationWithJUnit

class UnlikeConstraintSpec extends SpecificationWithJUnit
with ConstraintSpecHelper {
"matches attributes of type text" in {
val attributes = List(createTextAttribute("dc", "north"), createTextAttribute("rack", "rack-4"))
val constraint = UnlikeConstraint("rack", "rack-[1-3]")

constraint.matches(attributes) must_== true

val attributes2 = List(createTextAttribute("dc", "north"))
val constraint2 = UnlikeConstraint("dc", "north|south")

constraint2.matches(attributes2) must_== false
}

"matches attributes of type scalar" in {
val attributes = List(createScalarAttribute("number", 1))
val constraint = UnlikeConstraint("number", """\d\.\d""")

constraint.matches(attributes) must_== false

val attributes2 = List(createScalarAttribute("number", 1))
val constraint2 = UnlikeConstraint("number", """100.\d""")
constraint2.matches(attributes) must_== true

}

"matches attributes of type set" in {
val attributes = List(createSetAttribute("dc", Array("north")))
val constraint = UnlikeConstraint("dc", "^n.*")

constraint.matches(attributes) must_== false

val attributes2 = List(createSetAttribute("dc", Array("south")))

constraint.matches(attributes2) must_== true
}

"fails in case of an invalid regular expression" in {
UnlikeConstraint("invalid-regex", "[[[") must throwA[PatternSyntaxException]
}
}

0 comments on commit 0c7f87c

Please sign in to comment.