diff --git a/changelog.md b/changelog.md
index f9b7df3e9..3044f06eb 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,8 @@
+## Changes from 2.5.0 to 2.5.1
+
+### Correctly handle `TASK_STARTING` status updates.
+
+
## Changes from 2.4.0 to 2.5.0
### Highlights of this Release
@@ -24,7 +29,7 @@ Check the [REST API documentation](https://mesos.github.io/chronos/docs/api.html
#### Changed the default framework name
The framework name doesn't include the version number anymore.
-#### New API endpoints
+#### New API endpoints
The new `/scheduler/leader` endpoint makes it possible to get the current leader.
It is now possible to mark a job as successful via the `/scheduler/job/success` API endpoint.
diff --git a/docs/docs/api.md b/docs/docs/api.md
index aa049a8c1..77adedee7 100644
--- a/docs/docs/api.md
+++ b/docs/docs/api.md
@@ -17,6 +17,8 @@ All examples in this section assume that you've found a running leader at `chron
- [Adding a Scheduled Job](#adding-a-scheduled-job)
- [Adding a Dependent Job](#adding-a-dependent-job)
- [Adding a Docker Job](#adding-a-docker-job)
+- [Adding a Containerized Job](#adding-a-containerized-job)
+- [Using External Volumes](#using-external-volumes)
- [Updating Task Progress](#updating-task-progress)
- [Describing the Dependency Graph](#describing-the-dependency-graph)
- [Asynchronous Jobs](#asynchronous-jobs)
@@ -26,6 +28,7 @@ All examples in this section assume that you've found a running leader at `chron
- [Constraints](#constraints)
+
## Leaders
When you have multiple Chronos nodes running, only one of them will be elected as the leader.
@@ -278,6 +281,99 @@ There is also support for passing in arbitrary docker config options.
}
```
+## Adding a Containerized Job
+
+A containerized job takes the same format as a scheduled job or a dependency job and runs on a Mesos container.
+To configure it, an additional `container` argument is required, which contains a type (required), an image (required), a network name (optional), mounted volumes (optional) and whether Mesos should always pull the latest image before executing or not (optional).
+
+```json
+{
+ "container": {
+ "type": "MESOS",
+ "forcePullImage": true,
+ "image": "debian",
+ "networkInfos": [
+ {
+ "name": "mynet"
+ }
+ ],
+ "volumes": [
+ {
+ "containerPath": "/var/log/",
+ "hostPath": "/logs/",
+ "mode": "RW"
+ }
+ }
+ ]
+ }
+}
+```
+## Using External Volumes
+
+Docker and Mesos Containerized jobs can use external volumes, typically volumes mounted using docker volume plugins.
+To configure it, do not add a `hostPath` argument, instead add an `external` argument, which contain a `name`, `provider`, and `options` (optional).
+
+```json
+"volumes": [
+ {
+ "mode": "RW",
+ "containerPath": "/tmp",
+ "external": {
+ "name": "test",
+ "provider": "local-persist",
+ "options": [
+ {
+ "key": "mountpoint",
+ "value": "/tmp/test"
+ }
+ ]
+ }
+ }
+]
+```
+
+Here is a more elaborate example with a Mesos container, a network name, a mounted and an external volumes.
+```json
+{
+ "container": {
+ "type": "MESOS",
+ "forcePullImage": true,
+ "image": "debian",
+ "networkInfos": [
+ {
+ "name": "mynet",
+ "labels": [
+ {
+ "key": "service",
+ "value": "test"
+ }
+ ]
+ }
+ ],
+ "volumes": [
+ {
+ "containerPath": "/var/log/",
+ "hostPath": "/logs/",
+ "mode": "RW"
+ },
+ {
+ "mode": "RW",
+ "containerPath": "/tmp",
+ "external": {
+ "name": "test",
+ "provider": "local-persist",
+ "options": [
+ {
+ "key": "mountpoint",
+ "value": "/tmp/test"
+ }
+ ]
+ }
+ }
+ ]
+ }
+}
+```
## Updating Task Progress
Task progress can be updated by providing the number of additional elements processed. This will increment the existing count of elements processed.
diff --git a/pom.xml b/pom.xml
index 77b8d2f72..bf97a3306 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
org.apache.mesos
chronos
- 2.5.0
+ 2.5.2
2012
diff --git a/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Containers.scala b/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Containers.scala
index 0373fff67..a5bd6d2bc 100644
--- a/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Containers.scala
+++ b/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Containers.scala
@@ -12,21 +12,58 @@ object VolumeMode extends Enumeration {
object NetworkMode extends Enumeration {
type NetworkMode = Value
- // Bridged and Host
- val BRIDGE, HOST = Value
+ // Bridged, Host and USER
+ val BRIDGE, HOST, USER = Value
+}
+
+object ContainerType extends Enumeration {
+ type ContainerType = Value
+
+ // Docker, Mesos
+ val DOCKER, MESOS = Value
+}
+
+
+object ProtocolType extends Enumeration {
+ type ProtocolType = Value
+
+ val IPv4, IPv6 = Value
}
import org.apache.mesos.chronos.scheduler.jobs.NetworkMode._
import org.apache.mesos.chronos.scheduler.jobs.VolumeMode._
+import org.apache.mesos.chronos.scheduler.jobs.ContainerType._
+import org.apache.mesos.chronos.scheduler.jobs.ProtocolType._
+
+case class ExternalVolume(
+ @JsonProperty name: String,
+ @JsonProperty provider: String,
+ @JsonProperty options: Seq[Parameter])
case class Volume(
@JsonProperty hostPath: Option[String],
@JsonProperty containerPath: String,
- @JsonProperty mode: Option[VolumeMode])
+ @JsonProperty mode: Option[VolumeMode],
+ @JsonProperty external: Option[ExternalVolume])
+
+case class PortMapping(
+ @JsonProperty hostPort: Int,
+ @JsonProperty containerPort: Int,
+ @JsonProperty protocol: Option[String])
+
+case class Network(
+ @JsonProperty name: String,
+ @JsonProperty protocol: Option[ProtocolType],
+ @JsonProperty labels: Seq[Label],
+ @JsonProperty portMappings: Seq[PortMapping])
-case class DockerContainer(
+case class Container(
@JsonProperty image: String,
+ @JsonProperty `type`: ContainerType = ContainerType.DOCKER,
@JsonProperty volumes: Seq[Volume],
@JsonProperty parameters: Seq[Parameter],
@JsonProperty network: NetworkMode = NetworkMode.HOST,
+ // DEPRECATED, "networkName" will be removed in a future version.
+ @JsonProperty networkName: Option[String],
+ @JsonProperty networkInfos: Seq[Network],
@JsonProperty forcePullImage: Boolean = false)
diff --git a/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Jobs.scala b/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Jobs.scala
index 2c1238d99..1045ae02c 100644
--- a/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Jobs.scala
+++ b/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Jobs.scala
@@ -72,7 +72,7 @@ trait BaseJob {
def runAsUser: String = ""
- def container: DockerContainer = null
+ def container: Container = null
def environmentVariables: Seq[EnvironmentVariable] = List()
@@ -114,7 +114,7 @@ case class ScheduleBasedJob(
@JsonProperty override val fetch: Seq[Fetch] = List(),
@JsonProperty override val highPriority: Boolean = false,
@JsonProperty override val runAsUser: String = "",
- @JsonProperty override val container: DockerContainer = null,
+ @JsonProperty override val container: Container = null,
@JsonProperty scheduleTimeZone: String = "",
@JsonProperty override val environmentVariables: Seq[EnvironmentVariable] = List(),
@JsonProperty override val shell: Boolean = true,
@@ -152,7 +152,7 @@ case class DependencyBasedJob(
@JsonProperty override val fetch: Seq[Fetch] = List(),
@JsonProperty override val highPriority: Boolean = false,
@JsonProperty override val runAsUser: String = "",
- @JsonProperty override val container: DockerContainer = null,
+ @JsonProperty override val container: Container = null,
@JsonProperty override val environmentVariables: Seq[EnvironmentVariable] = List(),
@JsonProperty override val shell: Boolean = true,
@JsonProperty override val arguments: Seq[String] = List(),
diff --git a/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Label.scala b/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Label.scala
new file mode 100644
index 000000000..0a3483ae9
--- /dev/null
+++ b/src/main/scala/org/apache/mesos/chronos/scheduler/jobs/Label.scala
@@ -0,0 +1,25 @@
+package org.apache.mesos.chronos.scheduler.jobs
+
+import org.apache.mesos.{Protos => mesos}
+
+/**
+ * Represents an environment variable definition for the job
+ */
+case class Label(
+ key: String,
+ value: String) {
+
+ def toProto(): mesos.Label =
+ mesos.Label.newBuilder
+ .setKey(key)
+ .setValue(value)
+ .build
+}
+
+object Label {
+ def apply(proto: mesos.Label): Label =
+ Label(
+ proto.getKey,
+ proto.getValue
+ )
+}
diff --git a/src/main/scala/org/apache/mesos/chronos/scheduler/mesos/MesosJobFramework.scala b/src/main/scala/org/apache/mesos/chronos/scheduler/mesos/MesosJobFramework.scala
index 9bf392a97..d357ea576 100644
--- a/src/main/scala/org/apache/mesos/chronos/scheduler/mesos/MesosJobFramework.scala
+++ b/src/main/scala/org/apache/mesos/chronos/scheduler/mesos/MesosJobFramework.scala
@@ -205,10 +205,7 @@ class MesosJobFramework @Inject()(
val (jobName, _, _, _) = TaskUtils.parseTaskId(taskStatus.getTaskId.getValue)
taskStatus.getState match {
- case TaskState.TASK_RUNNING =>
- scheduler.handleStartedTask(taskStatus)
- updateRunningTask(jobName, taskStatus)
- case TaskState.TASK_STAGING =>
+ case TaskState.TASK_RUNNING | TaskState.TASK_STAGING | TaskState.TASK_STARTING =>
scheduler.handleStartedTask(taskStatus)
updateRunningTask(jobName, taskStatus)
case _ =>
diff --git a/src/main/scala/org/apache/mesos/chronos/scheduler/mesos/MesosTaskBuilder.scala b/src/main/scala/org/apache/mesos/chronos/scheduler/mesos/MesosTaskBuilder.scala
index 80d9a1bc2..4fb76628d 100644
--- a/src/main/scala/org/apache/mesos/chronos/scheduler/mesos/MesosTaskBuilder.scala
+++ b/src/main/scala/org/apache/mesos/chronos/scheduler/mesos/MesosTaskBuilder.scala
@@ -11,6 +11,8 @@ import com.google.protobuf.ByteString
import org.apache.mesos.Protos.ContainerInfo.DockerInfo
import org.apache.mesos.Protos.Environment.Variable
import org.apache.mesos.Protos._
+import org.apache.mesos.chronos.scheduler.config.SchedulerConfiguration
+import org.apache.mesos.chronos.scheduler.jobs.{BaseJob, ContainerType, Fetch, TaskUtils}
import scala.collection.JavaConverters._
import scala.collection.Map
@@ -173,16 +175,63 @@ class MesosTaskBuilder @Inject()(val conf: SchedulerConfiguration) {
v.mode.map { m =>
volumeBuilder.setMode(Volume.Mode.valueOf(m.toString.toUpperCase))
}
+ v.external.foreach { e =>
+ volumeBuilder.setSource(Volume.Source.newBuilder()
+ .setType(Volume.Source.Type.DOCKER_VOLUME)
+ .setDockerVolume(Volume.Source.DockerVolume.newBuilder()
+ .setDriver(e.provider)
+ .setName(e.name)
+ .setDriverOptions(Parameters.newBuilder()
+ .addAllParameter(e.options.map(_.toProto()).asJava).build()
+ ).build()
+ ).build()
+ ).build()
+ }
volumeBuilder.build()
}.foreach(builder.addVolumes)
- builder.setType(ContainerInfo.Type.DOCKER)
- builder.setDocker(DockerInfo.newBuilder()
- .setImage(job.container.image)
- .setNetwork(DockerInfo.Network.valueOf(job.container.network.toString.toUpperCase))
- .setForcePullImage(job.container.forcePullImage)
- .addAllParameters(job.container.parameters.map(_.toProto).asJava)
- .build()).build
+
+ job.container.`type` match {
+ case ContainerType.DOCKER =>
+ builder.setType(ContainerInfo.Type.DOCKER)
+ builder.setDocker(DockerInfo.newBuilder()
+ .setImage(job.container.image)
+ .setNetwork(DockerInfo.Network.valueOf(job.container.network.toString.toUpperCase))
+ .setForcePullImage(job.container.forcePullImage)
+ .addAllParameters(job.container.parameters.map(_.toProto()).asJava)
+ .build())
+ case ContainerType.MESOS =>
+ builder.setType(ContainerInfo.Type.MESOS)
+ builder.setMesos(ContainerInfo.MesosInfo.newBuilder()
+ .setImage(Image.newBuilder()
+ // TODO add APPC image support
+ .setType(Image.Type.DOCKER)
+ .setDocker(Image.Docker.newBuilder()
+ .setName(job.container.image)
+ // TODO add setCredential
+ .build())
+ .setCached(!job.container.forcePullImage)
+ .build())
+ .build())
+ }
+ job.container.networkName.foreach {
+ n => builder.addNetworkInfos(NetworkInfo.newBuilder()
+ .setName(n).build()
+ )
+ }
+
+ job.container.networkInfos.foreach {
+ n => builder.addNetworkInfos(NetworkInfo.newBuilder()
+ .setName(n.name)
+ .setLabels(Labels.newBuilder()
+ .addAllLabels(n.labels.map(_.toProto()).asJava).build()
+ )
+ // TODO add protocol, portMappings, requires mesos >= 1.1.0
+ .build()
+ )
+ }
+
+ builder.build
}
private def appendExecutorData(taskInfo: TaskInfo.Builder, job: BaseJob, environment: Environment.Builder, uriProtos: Seq[CommandInfo.URI]) {
diff --git a/src/main/scala/org/apache/mesos/chronos/utils/JobDeserializer.scala b/src/main/scala/org/apache/mesos/chronos/utils/JobDeserializer.scala
index 979336693..77eab0b82 100644
--- a/src/main/scala/org/apache/mesos/chronos/utils/JobDeserializer.scala
+++ b/src/main/scala/org/apache/mesos/chronos/utils/JobDeserializer.scala
@@ -144,7 +144,7 @@ class JobDeserializer extends JsonDeserializer[BaseJob] {
}
}
- var environmentVariables = scala.collection.mutable.ListBuffer[EnvironmentVariable]()
+ val environmentVariables = scala.collection.mutable.ListBuffer[EnvironmentVariable]()
if (node.has("environmentVariables")) {
node.get("environmentVariables").elements().map {
case node: ObjectNode =>
@@ -160,8 +160,8 @@ class JobDeserializer extends JsonDeserializer[BaseJob] {
if (node.has("runAsUser") && node.get("runAsUser") != null) node.get("runAsUser").asText
else JobDeserializer.config.user()
- var container: DockerContainer = null
- if (node.has("container")) {
+ var container: Container = null
+ if (node.has("container") && node.get("container").has("image")) {
val containerNode = node.get("container")
val networkMode =
if (containerNode.has("network") && containerNode.get("network") != null)
@@ -179,7 +179,23 @@ class JobDeserializer extends JsonDeserializer[BaseJob] {
val mode =
if (node.has("mode")) Option(VolumeMode.withName(node.get("mode").asText.toUpperCase))
else None
- Volume(hostPath, node.get("containerPath").asText, mode)
+
+ val externalVolumeOptions = scala.collection.mutable.ListBuffer[Parameter]()
+ if(node.has("external") && node.get("external").has("options")) {
+ node.get("external").get("options").elements().map {
+ case node: ObjectNode =>
+ Parameter(node.get("key").asText(), node.get("value").asText)
+ }.foreach(externalVolumeOptions.add)
+ }
+ val external =
+ if (node.has("external")) Option(ExternalVolume(
+ node.get("external").get("name").asText,
+ node.get("external").get("provider").asText,
+ externalVolumeOptions
+ ))
+ else None
+
+ Volume(hostPath, node.get("containerPath").asText, mode, external)
}.foreach(volumes.add)
}
@@ -188,7 +204,51 @@ class JobDeserializer extends JsonDeserializer[BaseJob] {
Try(containerNode.get("forcePullImage").asText.toBoolean).getOrElse(false)
else false
- var parameters = scala.collection.mutable.ListBuffer[Parameter]()
+ val containerType =
+ if (containerNode.has("type") && containerNode.get("type") != null)
+ ContainerType.withName(containerNode.get("type").asText.toUpperCase)
+ else ContainerType.DOCKER
+
+ val networkName =
+ if (containerNode.has("networkName") && containerNode.get("networkName") != null)
+ Option(containerNode.get("networkName").asText)
+ else None
+
+ val networks = scala.collection.mutable.ListBuffer[Network]()
+ if (containerNode.has("networkInfos")) {
+ containerNode.get("networkInfos").elements().map {
+ case node: ObjectNode =>
+ val name = node.get("name").asText()
+ val protocol =
+ if (node.has("protocol") && node.get("protocol") != null)
+ Option(ProtocolType.withName(node.get("protocol").asText))
+ else None
+ val labels = scala.collection.mutable.ListBuffer[Label]()
+ if(node.has("labels")) {
+ node.get("labels").elements().map {
+ case node: ObjectNode =>
+ Label(node.get("key").asText(), node.get("value").asText)
+ }.foreach(labels.add)
+ }
+ val portMappings = scala.collection.mutable.ListBuffer[PortMapping]()
+ if(node.has("portMappings")) {
+ node.get("portMappings").elements().map {
+ case pm: ObjectNode =>
+ val hostPort = pm.get("hostPort").asInt()
+ val containerPort = pm.get("containerPort").asInt()
+ val protocol =
+ if(pm.has("protocol") && pm.get("protocol") != null)
+ Option(pm.get("protocol").asText())
+ else None
+ PortMapping(hostPort, containerPort, protocol)
+ }.foreach(portMappings.add)
+ }
+
+ Network(name, protocol, labels, portMappings)
+ }.foreach(networks.add)
+ }
+
+ val parameters = scala.collection.mutable.ListBuffer[Parameter]()
if (containerNode.has("parameters")) {
containerNode.get("parameters").elements().map {
case node: ObjectNode =>
@@ -196,7 +256,7 @@ class JobDeserializer extends JsonDeserializer[BaseJob] {
}.foreach(parameters.add)
}
- container = DockerContainer(containerNode.get("image").asText, volumes, parameters, networkMode, forcePullImage)
+ container = Container(containerNode.get("image").asText, containerType, volumes, parameters, networkMode, networkName, networks, forcePullImage)
}
val constraints = scala.collection.mutable.ListBuffer[Constraint]()
diff --git a/src/main/scala/org/apache/mesos/chronos/utils/JobSerializer.scala b/src/main/scala/org/apache/mesos/chronos/utils/JobSerializer.scala
index 4ef3e6147..2ee43025c 100644
--- a/src/main/scala/org/apache/mesos/chronos/utils/JobSerializer.scala
+++ b/src/main/scala/org/apache/mesos/chronos/utils/JobSerializer.scala
@@ -129,13 +129,56 @@ class JobSerializer extends JsonSerializer[BaseJob] {
if (baseJob.container != null) {
json.writeFieldName("container")
json.writeStartObject()
- // TODO: Handle more container types when added.
json.writeFieldName("type")
- json.writeString("docker")
+ json.writeString(baseJob.container.`type`.toString)
json.writeFieldName("image")
json.writeString(baseJob.container.image)
json.writeFieldName("network")
json.writeString(baseJob.container.network.toString)
+ baseJob.container.networkName.foreach {
+ networkName =>
+ json.writeFieldName("networkName")
+ json.writeString(networkName)
+ }
+ json.writeFieldName("networkInfos")
+ json.writeStartArray()
+ baseJob.container.networkInfos.foreach { n =>
+ json.writeStartObject()
+ json.writeFieldName("name")
+ json.writeString(n.name)
+ n.protocol.foreach { p =>
+ json.writeFieldName("protocol")
+ json.writeString(p.toString)
+ }
+ json.writeFieldName("labels")
+ json.writeStartArray()
+ n.labels.foreach { label =>
+ json.writeStartObject()
+ json.writeFieldName("key")
+ json.writeString(label.key)
+ json.writeFieldName("value")
+ json.writeString(label.value)
+ json.writeEndObject()
+ }
+ json.writeEndArray()
+ json.writeFieldName("portMappings")
+ json.writeStartArray()
+ n.portMappings.foreach{ p =>
+ json.writeStartObject()
+ json.writeFieldName("hostPort")
+ json.writeString(p.hostPort.toString)
+ json.writeFieldName("containerPort")
+ json.writeString(p.containerPort.toString)
+ p.protocol.foreach { protocol =>
+ json.writeFieldName("protocol")
+ json.writeString(protocol)
+ }
+ json.writeEndObject()
+ }
+ json.writeEndArray()
+ json.writeEndObject()
+ }
+ json.writeEndArray()
json.writeFieldName("volumes")
json.writeStartArray()
baseJob.container.volumes.foreach { v =>
@@ -150,6 +193,26 @@ class JobSerializer extends JsonSerializer[BaseJob] {
json.writeFieldName("mode")
json.writeString(mode.toString)
}
+ v.external.foreach { external =>
+ json.writeFieldName("external")
+ json.writeStartObject()
+ json.writeFieldName("name")
+ json.writeString(external.name)
+ json.writeFieldName("provider")
+ json.writeString(external.provider)
+ json.writeFieldName("options")
+ json.writeStartArray()
+ external.options.foreach { o =>
+ json.writeStartObject()
+ json.writeFieldName("key")
+ json.writeString(o.key)
+ json.writeFieldName("value")
+ json.writeString(o.value)
+ json.writeEndObject()
+ }
+ json.writeEndArray()
+ json.writeEndObject()
+ }
json.writeEndObject()
}
json.writeEndArray()
diff --git a/src/test/scala/org/apache/mesos/chronos/scheduler/api/SerDeTest.scala b/src/test/scala/org/apache/mesos/chronos/scheduler/api/SerDeTest.scala
index 5bdc54ccc..8426623fd 100644
--- a/src/test/scala/org/apache/mesos/chronos/scheduler/api/SerDeTest.scala
+++ b/src/test/scala/org/apache/mesos/chronos/scheduler/api/SerDeTest.scala
@@ -1,6 +1,7 @@
package org.apache.mesos.chronos.scheduler.api
import org.apache.mesos.chronos.scheduler.jobs.constraints.{EqualsConstraint, LikeConstraint, UnlikeConstraint}
+import org.apache.mesos.chronos.scheduler.jobs.{DependencyBasedJob, Container, EnvironmentVariable, ScheduleBasedJob, _}
import org.apache.mesos.chronos.utils.{JobDeserializer, JobSerializer}
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.module.SimpleModule
@@ -26,15 +27,20 @@ class SerDeTest extends SpecificationWithJUnit {
)
val volumes = Seq(
- Volume(Option("/host/dir"), "container/dir", Option(VolumeMode.RO)),
- Volume(None, "container/dir", None)
+ Volume(Option("/host/dir"), "container/dir", Option(VolumeMode.RO), None),
+ Volume(None, "container/dir", None, None)
+ )
+
+ val networks = Seq(
+ Network("testnet", Option(ProtocolType.IPv4), Seq(), Seq()),
+ Network("testnet2", Option(ProtocolType.IPv4), Seq(Label("testlabel", "testvalue")), Seq())
)
val forcePullImage = false
val parameters = scala.collection.mutable.ListBuffer[Parameter]()
- val container = DockerContainer("dockerImage", volumes, parameters, NetworkMode.BRIDGE, forcePullImage)
+ val container = Container("dockerImage", ContainerType.DOCKER, volumes, parameters, NetworkMode.BRIDGE, None, networks, forcePullImage)
val arguments = Seq(
"-testOne"
@@ -74,14 +80,19 @@ class SerDeTest extends SpecificationWithJUnit {
)
val volumes = Seq(
- Volume(Option("/host/dir"), "container/dir", Option(VolumeMode.RW)),
- Volume(None, "container/dir", None)
+ Volume(Option("/host/dir"), "container/dir", Option(VolumeMode.RW), None),
+ Volume(None, "container/dir", None, None)
+ )
+
+ val networks = Seq(
+ Network("testnet", Option(ProtocolType.IPv4), Seq(), Seq()),
+ Network("testnet2", Option(ProtocolType.IPv4), Seq(Label("testlabel", "testvalue")), Seq())
)
val forcePullImage = true
val parameters = scala.collection.mutable.ListBuffer[Parameter]()
- val container = DockerContainer("dockerImage", volumes, parameters, NetworkMode.HOST, forcePullImage)
+ val container = Container("dockerImage", ContainerType.DOCKER, volumes, parameters, NetworkMode.HOST, None, networks, forcePullImage)
val arguments = Seq(
"-testOne"
diff --git a/src/test/scala/org/apache/mesos/chronos/scheduler/mesos/MesosTaskBuilderSpec.scala b/src/test/scala/org/apache/mesos/chronos/scheduler/mesos/MesosTaskBuilderSpec.scala
index e4c949051..4b422416c 100644
--- a/src/test/scala/org/apache/mesos/chronos/scheduler/mesos/MesosTaskBuilderSpec.scala
+++ b/src/test/scala/org/apache/mesos/chronos/scheduler/mesos/MesosTaskBuilderSpec.scala
@@ -3,14 +3,11 @@ package org.apache.mesos.chronos.scheduler.mesos
import scala.collection.JavaConversions._
import org.apache.mesos.Protos._
import org.apache.mesos.chronos.scheduler.config.SchedulerConfiguration
-import org.apache.mesos.chronos.scheduler.jobs.Parameter
-import org.apache.mesos.chronos.scheduler.jobs.Volume
-import org.apache.mesos.chronos.scheduler.jobs._
-import org.apache.mesos.chronos.scheduler.jobs.constraints.{LikeConstraint, EqualsConstraint}
-import org.joda.time.Minutes
+import org.apache.mesos.chronos.scheduler.jobs.{Label, Parameter, Volume, _}
+import org.apache.mesos.chronos.scheduler.jobs.constraints.{EqualsConstraint, LikeConstraint}
import org.specs2.mock.Mockito
import org.specs2.mutable.SpecificationWithJUnit
-
+import org.joda.time.Minutes
class MesosTaskBuilderSpec extends SpecificationWithJUnit with Mockito {
@@ -27,13 +24,18 @@ class MesosTaskBuilderSpec extends SpecificationWithJUnit with Mockito {
val job = {
val volumes = Seq(
- Volume(Option("/host/dir"), "container/dir", Option(VolumeMode.RW)),
- Volume(None, "container/dir", None)
+ Volume(Option("/host/dir"), "container/dir", Option(VolumeMode.RW), None),
+ Volume(None, "container/dir", None, None)
+ )
+
+ val networks = Seq(
+ Network("testnet", None, Seq(), Seq()),
+ Network("testnet", None, Seq(Label("testlabel", "testvalue")), Seq())
)
- var parameters = scala.collection.mutable.ListBuffer[Parameter]()
+ val parameters = scala.collection.mutable.ListBuffer[Parameter]()
- val container = DockerContainer("dockerImage", volumes, parameters, NetworkMode.HOST, true)
+ val container = Container("dockerImage", ContainerType.DOCKER, volumes, parameters, NetworkMode.HOST, None, networks, forcePullImage = true)
val constraints = Seq(
EqualsConstraint("rack", "rack-1"),