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)