Repository: mesos
Updated Branches:
  refs/heads/master aeaec8940 -> 9f73082aa


Updated master validation for DOCKER ContainerInfo in TaskGroup.

DOCKER as ContainerInfo Type for both task group executor as well as
taskgroup task is currently not supported. Only MESOS as
ContainerInfo Type is supported. This patch is to validate that
TaskGroup executor and tasks do not use DOCKER ContainerInfo.

Review: https://reviews.apache.org/r/51771/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/9f73082a
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/9f73082a
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/9f73082a

Branch: refs/heads/master
Commit: 9f73082aac613f7430b0d713a672bcae90198c47
Parents: aeaec89
Author: Abhishek Dasgupta <a10gu...@linux.vnet.ibm.com>
Authored: Tue Sep 13 17:00:37 2016 -0700
Committer: Vinod Kone <vinodk...@gmail.com>
Committed: Tue Sep 13 17:00:37 2016 -0700

----------------------------------------------------------------------
 src/master/validation.cpp             |  15 ++-
 src/tests/master_validation_tests.cpp | 183 +++++++++++++++++++++++++++++
 2 files changed, 196 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/9f73082a/src/master/validation.cpp
----------------------------------------------------------------------
diff --git a/src/master/validation.cpp b/src/master/validation.cpp
index 137b9f9..aa743d7 100644
--- a/src/master/validation.cpp
+++ b/src/master/validation.cpp
@@ -1011,8 +1011,14 @@ Option<Error> validateTask(
     return Error("'TaskInfo.executor' must not be set");
   }
 
-  if (task.has_container() && task.container().network_infos().size() > 0) {
-    return Error("NetworkInfos must not be set on the task");
+  if (task.has_container()) {
+    if (task.container().network_infos().size() > 0) {
+      return Error("NetworkInfos must not be set on the task");
+    }
+
+    if (task.container().type() == ContainerInfo::DOCKER) {
+      return Error("Docker ContainerInfo is not supported on the task");
+    }
   }
 
   return None();
@@ -1072,6 +1078,11 @@ Option<Error> validateExecutor(
     return Error("Unknown executor type");
   }
 
+  if (executor.has_container() &&
+      executor.container().type() == ContainerInfo::DOCKER) {
+    return Error("Docker ContainerInfo is not supported on the executor");
+  }
+
   const Resources& executorResources = executor.resources();
 
   // Validate minimal cpus and memory resources of executor.

http://git-wip-us.apache.org/repos/asf/mesos/blob/9f73082a/src/tests/master_validation_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_validation_tests.cpp 
b/src/tests/master_validation_tests.cpp
index 3a5cfa2..16c5773 100644
--- a/src/tests/master_validation_tests.cpp
+++ b/src/tests/master_validation_tests.cpp
@@ -1719,6 +1719,98 @@ TEST_F(TaskGroupValidationTest, 
TaskGroupAndExecutorUsesRevocableResources)
 }
 
 
+// Verifies that an executor with `ContainerInfo` set as DOCKER
+// is rejected during `TaskGroupInfo` validation.
+TEST_F(TaskGroupValidationTest, ExecutorUsesDockerContainerInfo)
+{
+  Try<Owned<cluster::Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  Owned<MasterDetector> detector = master.get()->createDetector();
+  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get());
+  ASSERT_SOME(slave);
+
+  FrameworkInfo frameworkInfo = DEFAULT_FRAMEWORK_INFO;
+  frameworkInfo.mutable_id()->set_value("Test_Framework");
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, frameworkInfo, master.get()->pid, DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .Times(1);
+
+  Future<vector<Offer>> offers;
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  driver.start();
+
+  AWAIT_READY(offers);
+  EXPECT_NE(0u, offers->size());
+
+  Offer offer = offers.get()[0];
+
+  // Create an invalid executor with `ContainerInfo` set as DOCKER.
+  ExecutorInfo executor;
+  executor.set_type(ExecutorInfo::DEFAULT);
+  executor.mutable_executor_id()->set_value("E");
+  executor.mutable_framework_id()->CopyFrom(frameworkInfo.id());
+  executor.mutable_container()->set_type(ContainerInfo::DOCKER);
+
+  TaskInfo task1;
+  task1.set_name("1");
+  task1.mutable_task_id()->set_value("1");
+  task1.mutable_slave_id()->MergeFrom(offer.slave_id());
+  task1.mutable_resources()->MergeFrom(offer.resources());
+
+  TaskInfo task2;
+  task2.set_name("2");
+  task2.mutable_task_id()->set_value("2");
+  task2.mutable_slave_id()->MergeFrom(offer.slave_id());
+  task2.mutable_resources()->MergeFrom(offer.resources());
+
+  TaskGroupInfo taskGroup;
+  taskGroup.add_tasks()->CopyFrom(task1);
+  taskGroup.add_tasks()->CopyFrom(task2);
+
+  Future<TaskStatus> task1Status;
+  Future<TaskStatus> task2Status;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&task1Status))
+    .WillOnce(FutureArg<1>(&task2Status));
+
+  Offer::Operation operation;
+  operation.set_type(Offer::Operation::LAUNCH_GROUP);
+
+  Offer::Operation::LaunchGroup* launchGroup =
+    operation.mutable_launch_group();
+
+  launchGroup->mutable_executor()->CopyFrom(executor);
+  launchGroup->mutable_task_group()->CopyFrom(taskGroup);
+
+  driver.acceptOffers({offer.id()}, {operation});
+
+  AWAIT_READY(task1Status);
+  EXPECT_EQ(TASK_ERROR, task1Status->state());
+  EXPECT_EQ(TaskStatus::REASON_TASK_GROUP_INVALID, task1Status->reason());
+  EXPECT_EQ(
+      "Docker ContainerInfo is not supported on the executor",
+      task1Status->message());
+
+  AWAIT_READY(task2Status);
+  EXPECT_EQ(TASK_ERROR, task2Status->state());
+  EXPECT_EQ(TaskStatus::REASON_TASK_GROUP_INVALID, task2Status->reason());
+  EXPECT_EQ(
+      "Docker ContainerInfo is not supported on the executor",
+      task2Status->message());
+
+  driver.stop();
+  driver.join();
+}
+
+
 // Ensures that an executor without a framework id is
 // rejected during `TaskGroupInfo` validation.
 TEST_F(TaskGroupValidationTest, ExecutorWithoutFrameworkId)
@@ -1797,6 +1889,97 @@ TEST_F(TaskGroupValidationTest, 
ExecutorWithoutFrameworkId)
   driver.join();
 }
 
+
+// Verifies that a task in a task group that has `ContainerInfo`
+// set as DOCKER is rejected during `TaskGroupInfo` validation.
+TEST_F(TaskGroupValidationTest, TaskUsesDockerContainerInfo)
+{
+  Try<Owned<cluster::Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  Owned<MasterDetector> detector = master.get()->createDetector();
+  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get());
+  ASSERT_SOME(slave);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get()->pid, DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .Times(1);
+
+  Future<vector<Offer>> offers;
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  driver.start();
+
+  AWAIT_READY(offers);
+  EXPECT_NE(0u, offers->size());
+
+  Offer offer = offers.get()[0];
+
+  Resources resources = Resources::parse("cpus:1;mem:512;disk:32").get();
+
+  ExecutorInfo executor(DEFAULT_EXECUTOR_INFO);
+  executor.set_type(ExecutorInfo::CUSTOM);
+  executor.mutable_resources()->CopyFrom(resources);
+
+  // Create an invalid task that has `ContainerInfo` set as DOCKER.
+  TaskInfo task1;
+  task1.set_name("1");
+  task1.mutable_task_id()->set_value("1");
+  task1.mutable_slave_id()->MergeFrom(offer.slave_id());
+  task1.mutable_resources()->MergeFrom(resources);
+  task1.mutable_container()->set_type(ContainerInfo::DOCKER);
+
+  // Create a valid task.
+  TaskInfo task2;
+  task2.set_name("2");
+  task2.mutable_task_id()->set_value("2");
+  task2.mutable_slave_id()->MergeFrom(offer.slave_id());
+  task2.mutable_resources()->MergeFrom(resources);
+
+  TaskGroupInfo taskGroup;
+  taskGroup.add_tasks()->CopyFrom(task1);
+  taskGroup.add_tasks()->CopyFrom(task2);
+
+  Future<TaskStatus> task1Status;
+  Future<TaskStatus> task2Status;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&task1Status))
+    .WillOnce(FutureArg<1>(&task2Status));
+
+  Offer::Operation operation;
+  operation.set_type(Offer::Operation::LAUNCH_GROUP);
+
+  Offer::Operation::LaunchGroup* launchGroup =
+    operation.mutable_launch_group();
+
+  launchGroup->mutable_executor()->CopyFrom(executor);
+  launchGroup->mutable_task_group()->CopyFrom(taskGroup);
+
+  driver.acceptOffers({offer.id()}, {operation});
+
+  AWAIT_READY(task1Status);
+  EXPECT_EQ(task1.task_id(), task1Status->task_id());
+  EXPECT_EQ(TASK_ERROR, task1Status->state());
+  EXPECT_EQ(TaskStatus::REASON_TASK_GROUP_INVALID, task1Status->reason());
+  EXPECT_EQ(
+      "Task '1' is invalid: Docker ContainerInfo is not supported on the task",
+      task1Status->message());
+
+  AWAIT_READY(task2Status);
+  EXPECT_EQ(task2.task_id(), task2Status->task_id());
+  EXPECT_EQ(TASK_ERROR, task2Status->state());
+  EXPECT_EQ(TaskStatus::REASON_TASK_GROUP_INVALID, task2Status->reason());
+
+  driver.stop();
+  driver.join();
+}
+
+
 // Ensures that a task in a task group that has `NetworkInfo`
 // set is rejected during `TaskGroupInfo` validation.
 TEST_F(TaskGroupValidationTest, TaskUsesNetworkInfo)

Reply via email to