You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by gr...@apache.org on 2018/10/29 18:17:11 UTC

[mesos] branch master updated: Added task health check definitions to master API responses.

This is an automated email from the ASF dual-hosted git repository.

grag pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git


The following commit(s) were added to refs/heads/master by this push:
     new d8466a8  Added task health check definitions to master API responses.
d8466a8 is described below

commit d8466a8a0a7d84d997f4c20b5631fadee7110b94
Author: Greg Mann <gr...@mesosphere.io>
AuthorDate: Mon Oct 29 10:59:25 2018 -0700

    Added task health check definitions to master API responses.
    
    The `Task` protobuf message is updated to include the health check
    definition of a task when it is specified. Associated helpers are
    also updated along with tests which verify that this field is
    reflected in master API responses.
    
    Review: https://reviews.apache.org/r/69110/
---
 include/mesos/mesos.proto        |  8 +++--
 include/mesos/v1/mesos.proto     |  8 +++--
 src/common/http.cpp              |  4 +++
 src/common/protobuf_utils.cpp    |  4 +++
 src/tests/api_tests.cpp          | 64 ++++++++++++++++++++++++++++++++++++++++
 src/tests/health_check_tests.cpp | 58 +++++++++++++++++++++++++++++++++---
 6 files changed, 138 insertions(+), 8 deletions(-)

diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index 72966da..f6989cd 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -2165,8 +2165,8 @@ message TaskGroupInfo {
  *   1) we need additional IDs, such as a specific
  *      framework, executor, or agent; or
  *   2) we do not need the additional data, such as the command run by the
- *      task or the health checks.  These additional fields may be large and
- *      unnecessary for some Mesos messages.
+ *      task. These additional fields may be large and unnecessary for some
+ *      Mesos messages.
  *
  * `Task` is generally constructed from a `TaskInfo`.  See protobuf::createTask.
  */
@@ -2197,6 +2197,10 @@ message Task {
   // Container information for the task.
   optional ContainerInfo container = 13;
 
+  optional HealthCheck health_check = 15;
+
+  // TODO(greggomann): Add the task's `CheckInfo`. See MESOS-8780.
+
   // Specific user under which task is running.
   optional string user = 14;
 }
diff --git a/include/mesos/v1/mesos.proto b/include/mesos/v1/mesos.proto
index c6c1dae..edad35a 100644
--- a/include/mesos/v1/mesos.proto
+++ b/include/mesos/v1/mesos.proto
@@ -2158,8 +2158,8 @@ message TaskGroupInfo {
  *   1) we need additional IDs, such as a specific
  *      framework, executor, or agent; or
  *   2) we do not need the additional data, such as the command run by the
- *      task or the health checks.  These additional fields may be large and
- *      unnecessary for some Mesos messages.
+ *      task. These additional fields may be large and unnecessary for some
+ *      Mesos messages.
  *
  * `Task` is generally constructed from a `TaskInfo`.  See protobuf::createTask.
  */
@@ -2190,6 +2190,10 @@ message Task {
   // Container information for the task.
   optional ContainerInfo container = 13;
 
+  optional HealthCheck health_check = 15;
+
+  // TODO(greggomann): Add the task's `CheckInfo`. See MESOS-8780.
+
   // Specific user under which task is running.
   optional string user = 14;
 }
diff --git a/src/common/http.cpp b/src/common/http.cpp
index 80848aa..eeeed97 100644
--- a/src/common/http.cpp
+++ b/src/common/http.cpp
@@ -827,6 +827,10 @@ void json(JSON::ObjectWriter* writer, const Task& task)
   if (task.has_container()) {
     writer->field("container", JSON::Protobuf(task.container()));
   }
+
+  if (task.has_health_check()) {
+    writer->field("health_check", JSON::Protobuf(task.health_check()));
+  }
 }
 
 
diff --git a/src/common/protobuf_utils.cpp b/src/common/protobuf_utils.cpp
index 77139d8..2ae37ac 100644
--- a/src/common/protobuf_utils.cpp
+++ b/src/common/protobuf_utils.cpp
@@ -341,6 +341,10 @@ Task createTask(
     t.mutable_container()->CopyFrom(task.container());
   }
 
+  if (task.has_health_check()) {
+    t.mutable_health_check()->CopyFrom(task.health_check());
+  }
+
   // Copy `user` if set.
   if (task.has_command() && task.command().has_user()) {
     t.set_user(task.command().user());
diff --git a/src/tests/api_tests.cpp b/src/tests/api_tests.cpp
index 97fd0bb..fdd9f87 100644
--- a/src/tests/api_tests.cpp
+++ b/src/tests/api_tests.cpp
@@ -551,6 +551,26 @@ TEST_P(MasterAPITest, GetState)
 
   TaskInfo task = createTask(offers.get()[0], "", DEFAULT_EXECUTOR_ID);
 
+  const string checkCommandValue = "exit 0";
+
+  // Add a health check to the task.
+  {
+    CommandInfo healthCommand;
+    healthCommand.set_value(checkCommandValue);
+
+    HealthCheck healthCheck;
+
+    healthCheck.set_type(HealthCheck::COMMAND);
+    healthCheck.mutable_command()->CopyFrom(healthCommand);
+    healthCheck.set_delay_seconds(1);
+    healthCheck.set_interval_seconds(1);
+    healthCheck.set_timeout_seconds(1);
+    healthCheck.set_consecutive_failures(1);
+    healthCheck.set_grace_period_seconds(1);
+
+    task.mutable_health_check()->CopyFrom(healthCheck);
+  }
+
   Future<ExecutorDriver*> execDriver;
   EXPECT_CALL(exec, registered(_, _, _, _))
     .WillOnce(FutureArg<0>(&execDriver));
@@ -589,6 +609,28 @@ TEST_P(MasterAPITest, GetState)
     const v1::master::Response::GetState& getState = v1Response->get_state();
     ASSERT_EQ(1, getState.get_tasks().tasks_size());
     ASSERT_TRUE(getState.get_tasks().completed_tasks().empty());
+
+    // Confirm that the health check definition is included.
+    ASSERT_TRUE(getState.get_tasks().tasks(0).has_health_check());
+    ASSERT_EQ(
+        v1::HealthCheck::COMMAND,
+        getState.get_tasks().tasks(0).health_check().type());
+    ASSERT_EQ(
+        checkCommandValue,
+        getState.get_tasks().tasks(0).health_check().command().value());
+    ASSERT_EQ(1, getState.get_tasks().tasks(0).health_check().delay_seconds());
+    ASSERT_EQ(
+        1,
+        getState.get_tasks().tasks(0).health_check().interval_seconds());
+    ASSERT_EQ(
+        1,
+        getState.get_tasks().tasks(0).health_check().timeout_seconds());
+    ASSERT_EQ(
+        1u,
+        getState.get_tasks().tasks(0).health_check().consecutive_failures());
+    ASSERT_EQ(
+        1,
+        getState.get_tasks().tasks(0).health_check().grace_period_seconds());
   }
 
   acknowledgement = FUTURE_PROTOBUF(
@@ -2316,6 +2358,21 @@ TEST_P(MasterAPITest, Subscribe)
 
   TaskInfo task = createTask(devolve(offer), "", executorId);
 
+  const string checkCommandValue = "exit 0";
+
+  // Add a health check to the task.
+  {
+    CommandInfo healthCommand;
+    healthCommand.set_value(checkCommandValue);
+
+    HealthCheck healthCheck;
+
+    healthCheck.set_type(HealthCheck::COMMAND);
+    healthCheck.mutable_command()->CopyFrom(healthCommand);
+
+    task.mutable_health_check()->CopyFrom(healthCheck);
+  }
+
   Future<Nothing> update;
   EXPECT_CALL(*scheduler, update(_, _))
     .WillOnce(FutureSatisfy(&update));
@@ -2354,6 +2411,13 @@ TEST_P(MasterAPITest, Subscribe)
   ASSERT_EQ(v1::master::Event::TASK_ADDED, event->get().type());
   ASSERT_EQ(evolve(task.task_id()),
             event->get().task_added().task().task_id());
+  ASSERT_TRUE(event->get().task_added().task().has_health_check());
+  ASSERT_EQ(
+      v1::HealthCheck::COMMAND,
+      event->get().task_added().task().health_check().type());
+  ASSERT_EQ(
+      checkCommandValue,
+      event->get().task_added().task().health_check().command().value());
 
   event = decoder.read();
 
diff --git a/src/tests/health_check_tests.cpp b/src/tests/health_check_tests.cpp
index c972b90..da64dc2 100644
--- a/src/tests/health_check_tests.cpp
+++ b/src/tests/health_check_tests.cpp
@@ -15,10 +15,14 @@
 // limitations under the License.
 
 #include <mesos/executor.hpp>
+#include <mesos/http.hpp>
 #include <mesos/scheduler.hpp>
 
+#include <mesos/v1/master/master.hpp>
+
 #include <process/collect.hpp>
 #include <process/future.hpp>
+#include <process/http.hpp>
 #include <process/owned.hpp>
 #include <process/pid.hpp>
 
@@ -65,6 +69,7 @@ using mesos::master::detector::MasterDetector;
 using mesos::slave::ContainerLogger;
 using mesos::slave::ContainerTermination;
 
+using process::Failure;
 using process::Future;
 using process::Owned;
 using process::PID;
@@ -334,8 +339,15 @@ TEST_F(HealthCheckTest, HealthyTask)
   AWAIT_READY(offers);
   ASSERT_FALSE(offers->empty());
 
-  vector<TaskInfo> tasks =
-    populateTasks(SLEEP_COMMAND(120), "exit 0", offers.get()[0]);
+  vector<TaskInfo> tasks = populateTasks(
+      SLEEP_COMMAND(120),
+      "exit 0",
+      offers.get()[0],
+      1,
+      1,
+      None(),
+      None(),
+      1);
 
   Future<TaskStatus> statusStarting;
   Future<TaskStatus> statusRunning;
@@ -398,7 +410,8 @@ TEST_F(HealthCheckTest, HealthyTask)
   EXPECT_TRUE(implicitReconciliation->has_healthy());
   EXPECT_TRUE(implicitReconciliation->healthy());
 
-  // Verify that task health is exposed in the master's state endpoint.
+  // Verify that task's health check definition and current health status
+  // are exposed in the master's state endpoint.
   {
     Future<http::Response> response = http::get(
         master.get()->pid,
@@ -414,9 +427,38 @@ TEST_F(HealthCheckTest, HealthyTask)
     Result<JSON::Value> find = parse->find<JSON::Value>(
         "frameworks[0].tasks[0].statuses[1].healthy");
     EXPECT_SOME_TRUE(find);
+
+    find = parse->find<JSON::Value>(
+        "frameworks[0].tasks[0].health_check.type");
+    EXPECT_SOME_EQ("COMMAND", find);
+
+    find = parse->find<JSON::Value>(
+        "frameworks[0].tasks[0].health_check.command.value");
+    EXPECT_SOME_EQ("exit 0", find);
+
+    find = parse->find<JSON::Value>(
+        "frameworks[0].tasks[0].health_check.delay_seconds");
+    EXPECT_SOME_EQ(0, find);
+
+    find = parse->find<JSON::Value>(
+        "frameworks[0].tasks[0].health_check.interval_seconds");
+    EXPECT_SOME_EQ(0, find);
+
+    find = parse->find<JSON::Value>(
+        "frameworks[0].tasks[0].health_check.timeout_seconds");
+    EXPECT_SOME_EQ(1, find);
+
+    find = parse->find<JSON::Value>(
+        "frameworks[0].tasks[0].health_check.consecutive_failures");
+    EXPECT_SOME_EQ(1u, find);
+
+    find = parse->find<JSON::Value>(
+        "frameworks[0].tasks[0].health_check.grace_period_seconds");
+    EXPECT_SOME_EQ(1, find);
   }
 
-  // Verify that task health is exposed in the agent's state endpoint.
+  // Verify that the task's health definition and current health status
+  // are exposed in the agent's state endpoint.
   {
     Future<http::Response> response = http::get(
         agent.get()->pid,
@@ -432,6 +474,14 @@ TEST_F(HealthCheckTest, HealthyTask)
     Result<JSON::Value> find = parse->find<JSON::Value>(
         "frameworks[0].executors[0].tasks[0].statuses[1].healthy");
     EXPECT_SOME_TRUE(find);
+
+    find = parse->find<JSON::Value>(
+        "frameworks[0].executors[0].tasks[0].health_check.type");
+    EXPECT_SOME_EQ("COMMAND", find);
+
+    find = parse->find<JSON::Value>(
+        "frameworks[0].executors[0].tasks[0].health_check.command.value");
+    EXPECT_SOME_EQ("exit 0", find);
   }
 
   driver.stop();