You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by al...@apache.org on 2017/04/24 10:14:47 UTC

[1/7] mesos git commit: Added TCP checks in Mesos API.

Repository: mesos
Updated Branches:
  refs/heads/master 02d8426a3 -> 12a01d925


Added TCP checks in Mesos API.

>From now on executors may implement TCP checks for tasks.

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


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

Branch: refs/heads/master
Commit: bbed0e87f6661ada310a6822b5171f32aea1f3d9
Parents: ace9432
Author: Alexander Rukletsov <al...@apache.org>
Authored: Tue Apr 4 12:29:03 2017 +0200
Committer: Alexander Rukletsov <al...@apache.org>
Committed: Mon Apr 24 12:04:51 2017 +0200

----------------------------------------------------------------------
 include/mesos/mesos.proto         | 25 ++++++++++++++++++++++---
 include/mesos/v1/mesos.proto      | 25 ++++++++++++++++++++++---
 src/checks/checker.cpp            | 26 +++++++++++++++++++-------
 src/common/type_utils.cpp         |  9 +++++++++
 src/launcher/default_executor.cpp |  6 ++++--
 src/launcher/executor.cpp         |  6 ++++--
 src/tests/check_tests.cpp         | 14 ++++++++++++++
 src/v1/mesos.cpp                  |  9 +++++++++
 8 files changed, 103 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/bbed0e87/include/mesos/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/mesos.proto b/include/mesos/mesos.proto
index eaa2d2a..fbb491c 100644
--- a/include/mesos/mesos.proto
+++ b/include/mesos/mesos.proto
@@ -381,10 +381,11 @@ message CheckInfo {
     UNKNOWN = 0;
     COMMAND = 1;
     HTTP = 2;
+    TCP = 3;
 
-    // TODO(alexr): Consider supporting TCP checks and custom user checks.
-    // The latter should probably be paired with a `data` field and
-    // complemented by a `data` response in `CheckStatusInfo`.
+    // TODO(alexr): Consider supporting custom user checks. They should
+    // probably be paired with a `data` field and complemented by a
+    // `data` response in `CheckStatusInfo`.
   }
 
   // Describes a command check. If applicable, enters mount and/or network
@@ -413,6 +414,13 @@ message CheckInfo {
     // validation, TLS version.
   }
 
+  // Describes a TCP check, i.e. based on establishing a TCP connection to
+  // the specified port. Note that <host> is not configurable and is resolved
+  // automatically to 127.0.0.1.
+  message Tcp {
+    required uint32 port = 1;
+  }
+
   // The type of the check.
   optional Type type = 1;
 
@@ -422,6 +430,9 @@ message CheckInfo {
   // HTTP check.
   optional Http http = 3;
 
+  // TCP check.
+  optional Tcp tcp = 7;
+
   // Amount of time to wait to start checking the task after it
   // transitions to `TASK_RUNNING` or `TASK_STARTING` if the latter
   // is used by the executor.
@@ -1759,6 +1770,11 @@ message CheckStatusInfo {
     optional uint32 status_code = 1;
   }
 
+  message Tcp {
+    // Whether a TCP connection succeeded.
+    optional bool succeeded = 1;
+  }
+
   // TODO(alexr): Consider adding a `data` field, which can contain, e.g.,
   // truncated stdout/stderr output for command checks or HTTP response body
   // for HTTP checks. Alternatively, it can be an even shorter `message` field
@@ -1774,6 +1790,9 @@ message CheckStatusInfo {
   // Status of an HTTP check.
   optional Http http = 3;
 
+  // Status of a TCP check.
+  optional Tcp tcp = 4;
+
   // TODO(alexr): Consider introducing a "last changed at" timestamp, since
   // task status update's timestamp may not correspond to the last check's
   // state, e.g., for reconciliation.

http://git-wip-us.apache.org/repos/asf/mesos/blob/bbed0e87/include/mesos/v1/mesos.proto
----------------------------------------------------------------------
diff --git a/include/mesos/v1/mesos.proto b/include/mesos/v1/mesos.proto
index 1a32a7b..54a9efc 100644
--- a/include/mesos/v1/mesos.proto
+++ b/include/mesos/v1/mesos.proto
@@ -381,10 +381,11 @@ message CheckInfo {
     UNKNOWN = 0;
     COMMAND = 1;
     HTTP = 2;
+    TCP = 3;
 
-    // TODO(alexr): Consider supporting TCP checks and custom user checks.
-    // The latter should probably be paired with a `data` field and
-    // complemented by a `data` response in `CheckStatusInfo`.
+    // TODO(alexr): Consider supporting custom user checks. They should
+    // probably be paired with a `data` field and complemented by a
+    // `data` response in `CheckStatusInfo`.
   }
 
   // Describes a command check. If applicable, enters mount and/or network
@@ -413,6 +414,13 @@ message CheckInfo {
     // validation, TLS version.
   }
 
+  // Describes a TCP check, i.e. based on establishing a TCP connection to
+  // the specified port. Note that <host> is not configurable and is resolved
+  // automatically to 127.0.0.1.
+  message Tcp {
+    required uint32 port = 1;
+  }
+
   // The type of the check.
   optional Type type = 1;
 
@@ -422,6 +430,9 @@ message CheckInfo {
   // HTTP check.
   optional Http http = 3;
 
+  // TCP check.
+  optional Tcp tcp = 7;
+
   // Amount of time to wait to start checking the task after it
   // transitions to `TASK_RUNNING` or `TASK_STARTING` if the latter
   // is used by the executor.
@@ -1753,6 +1764,11 @@ message CheckStatusInfo {
     optional uint32 status_code = 1;
   }
 
+  message Tcp {
+    // Whether a TCP connection succeeded.
+    optional bool succeeded = 1;
+  }
+
   // TODO(alexr): Consider adding a `data` field, which can contain, e.g.,
   // truncated stdout/stderr output for command checks or HTTP response body
   // for HTTP checks. Alternatively, it can be an even shorter `message` field
@@ -1768,6 +1784,9 @@ message CheckStatusInfo {
   // Status of an HTTP check.
   optional Http http = 3;
 
+  // Status of a TCP check.
+  optional Tcp tcp = 4;
+
   // TODO(alexr): Consider introducing a "last changed at" timestamp, since
   // task status update's timestamp may not correspond to the last check's
   // state, e.g., for reconciliation.

http://git-wip-us.apache.org/repos/asf/mesos/blob/bbed0e87/src/checks/checker.cpp
----------------------------------------------------------------------
diff --git a/src/checks/checker.cpp b/src/checks/checker.cpp
index a883656..2fcf527 100644
--- a/src/checks/checker.cpp
+++ b/src/checks/checker.cpp
@@ -345,12 +345,14 @@ CheckerProcess::CheckerProcess(
       previousCheckStatus.mutable_command();
       break;
     }
-
     case CheckInfo::HTTP: {
       previousCheckStatus.mutable_http();
       break;
     }
-
+    case CheckInfo::TCP: {
+      previousCheckStatus.mutable_tcp();
+      break;
+    }
     case CheckInfo::UNKNOWN: {
       LOG(FATAL) << "Received UNKNOWN check type";
       break;
@@ -398,14 +400,15 @@ void CheckerProcess::performCheck()
           &Self::processCommandCheckResult, stopwatch, lambda::_1));
       break;
     }
-
     case CheckInfo::HTTP: {
       httpCheck().onAny(defer(
           self(),
           &Self::processHttpCheckResult, stopwatch, lambda::_1));
       break;
     }
-
+    case CheckInfo::TCP: {
+      break;
+    }
     case CheckInfo::UNKNOWN: {
       LOG(FATAL) << "Received UNKNOWN check type";
       break;
@@ -1099,7 +1102,6 @@ Option<Error> checkInfo(const CheckInfo& checkInfo)
 
       break;
     }
-
     case CheckInfo::HTTP: {
       if (!checkInfo.has_http()) {
         return Error("Expecting 'http' to be set for HTTP check");
@@ -1114,7 +1116,13 @@ Option<Error> checkInfo(const CheckInfo& checkInfo)
 
       break;
     }
+    case CheckInfo::TCP: {
+      if (!checkInfo.has_tcp()) {
+        return Error("Expecting 'tcp' to be set for TCP check");
+      }
 
+      break;
+    }
     case CheckInfo::UNKNOWN: {
       return Error(
           "'" + CheckInfo::Type_Name(checkInfo.type()) + "'"
@@ -1152,14 +1160,18 @@ Option<Error> checkStatusInfo(const CheckStatusInfo& checkStatusInfo)
       }
       break;
     }
-
     case CheckInfo::HTTP: {
       if (!checkStatusInfo.has_http()) {
         return Error("Expecting 'http' to be set for HTTP check's status");
       }
       break;
     }
-
+    case CheckInfo::TCP: {
+      if (!checkStatusInfo.has_tcp()) {
+        return Error("Expecting 'tcp' to be set for TCP check's status");
+      }
+      break;
+    }
     case CheckInfo::UNKNOWN: {
       return Error(
           "'" + CheckInfo::Type_Name(checkStatusInfo.type()) + "'"

http://git-wip-us.apache.org/repos/asf/mesos/blob/bbed0e87/src/common/type_utils.cpp
----------------------------------------------------------------------
diff --git a/src/common/type_utils.cpp b/src/common/type_utils.cpp
index dc0dd71..9bc32af 100644
--- a/src/common/type_utils.cpp
+++ b/src/common/type_utils.cpp
@@ -487,6 +487,15 @@ ostream& operator<<(ostream& stream, const CheckStatusInfo& checkStatusInfo)
         }
       }
       break;
+    case CheckInfo::TCP:
+      if (checkStatusInfo.has_tcp()) {
+        stream << "TCP";
+        if (checkStatusInfo.tcp().has_succeeded()) {
+          stream << (checkStatusInfo.tcp().succeeded() ? " connection success"
+                                                       : " connection failure");
+        }
+      }
+      break;
     case CheckInfo::UNKNOWN:
       stream << "UNKNOWN";
       break;

http://git-wip-us.apache.org/repos/asf/mesos/blob/bbed0e87/src/launcher/default_executor.cpp
----------------------------------------------------------------------
diff --git a/src/launcher/default_executor.cpp b/src/launcher/default_executor.cpp
index ef60f5b..95505fc 100644
--- a/src/launcher/default_executor.cpp
+++ b/src/launcher/default_executor.cpp
@@ -1147,12 +1147,14 @@ private:
           checkStatusInfo.mutable_command();
           break;
         }
-
         case CheckInfo::HTTP: {
           checkStatusInfo.mutable_http();
           break;
         }
-
+        case CheckInfo::TCP: {
+          checkStatusInfo.mutable_tcp();
+          break;
+        }
         case CheckInfo::UNKNOWN: {
           LOG(FATAL) << "UNKNOWN check type is invalid";
           break;

http://git-wip-us.apache.org/repos/asf/mesos/blob/bbed0e87/src/launcher/executor.cpp
----------------------------------------------------------------------
diff --git a/src/launcher/executor.cpp b/src/launcher/executor.cpp
index d14fbfb..c9cecb5 100644
--- a/src/launcher/executor.cpp
+++ b/src/launcher/executor.cpp
@@ -1004,12 +1004,14 @@ private:
           checkStatusInfo.mutable_command();
           break;
         }
-
         case CheckInfo::HTTP: {
           checkStatusInfo.mutable_http();
           break;
         }
-
+        case CheckInfo::TCP: {
+          checkStatusInfo.mutable_tcp();
+          break;
+        }
         case CheckInfo::UNKNOWN: {
           LOG(FATAL) << "UNKNOWN check type is invalid";
           break;

http://git-wip-us.apache.org/repos/asf/mesos/blob/bbed0e87/src/tests/check_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/check_tests.cpp b/src/tests/check_tests.cpp
index 2d1a122..67124c9 100644
--- a/src/tests/check_tests.cpp
+++ b/src/tests/check_tests.cpp
@@ -1761,6 +1761,13 @@ TEST_F(CheckTest, CheckInfoValidation)
     EXPECT_EQ(
         "Expecting 'http' to be set for HTTP check",
         validate->message);
+
+    checkInfo.set_type(CheckInfo::TCP);
+    validate = validation::checkInfo(checkInfo);
+    EXPECT_SOME(validate);
+    EXPECT_EQ(
+        "Expecting 'tcp' to be set for TCP check",
+        validate->message);
   }
 
   // Command check must specify an actual command in `command.command.value`.
@@ -1893,6 +1900,13 @@ TEST_F(CheckTest, CheckStatusInfoValidation)
     EXPECT_EQ(
         "Expecting 'http' to be set for HTTP check's status",
         validate->message);
+
+    checkStatusInfo.set_type(CheckInfo::TCP);
+    validate = validation::checkStatusInfo(checkStatusInfo);
+    EXPECT_SOME(validate);
+    EXPECT_EQ(
+        "Expecting 'tcp' to be set for TCP check's status",
+        validate->message);
   }
 }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/bbed0e87/src/v1/mesos.cpp
----------------------------------------------------------------------
diff --git a/src/v1/mesos.cpp b/src/v1/mesos.cpp
index 9c7d641..babe39e 100644
--- a/src/v1/mesos.cpp
+++ b/src/v1/mesos.cpp
@@ -409,6 +409,15 @@ ostream& operator<<(ostream& stream, const CheckStatusInfo& checkStatusInfo)
         }
       }
       break;
+    case CheckInfo::TCP:
+      if (checkStatusInfo.has_tcp()) {
+        stream << "TCP";
+        if (checkStatusInfo.tcp().has_succeeded()) {
+          stream << (checkStatusInfo.tcp().succeeded() ? " connection success"
+                                                       : " connection failure");
+        }
+      }
+      break;
     case CheckInfo::UNKNOWN:
       stream << "UNKNOWN";
       break;


[3/7] mesos git commit: Improved termination logging in default executor.

Posted by al...@apache.org.
Improved termination logging in default executor.

WSTRINGIFY already includes a preamble in addition to exit status,
no need to repeat it.

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


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

Branch: refs/heads/master
Commit: 674a619052acd5069426f371d8961abbad487648
Parents: 02d8426
Author: Alexander Rukletsov <al...@apache.org>
Authored: Mon Apr 3 14:41:12 2017 +0200
Committer: Alexander Rukletsov <al...@apache.org>
Committed: Mon Apr 24 12:04:51 2017 +0200

----------------------------------------------------------------------
 src/launcher/default_executor.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/674a6190/src/launcher/default_executor.cpp
----------------------------------------------------------------------
diff --git a/src/launcher/default_executor.cpp b/src/launcher/default_executor.cpp
index d003c1b..ef60f5b 100644
--- a/src/launcher/default_executor.cpp
+++ b/src/launcher/default_executor.cpp
@@ -802,8 +802,9 @@ protected:
 
     LOG(INFO)
       << "Child container " << container->containerId << " of task '" << taskId
-      << "' in state " << stringify(taskState) << " terminated with status "
-      << (status.isSome() ? WSTRINGIFY(status.get()) : "unknown");
+      << "' in state " << stringify(taskState) << " "
+      << (status.isSome() ? WSTRINGIFY(status.get())
+                          : "terminated with unknown status");
 
     // Shutdown the executor if all the active child containers have terminated.
     if (containers.empty()) {


[7/7] mesos git commit: Hardened HTTP check tests.

Posted by al...@apache.org.
Hardened HTTP check tests.

Introduce 1s delay to ensure the task (HTTP server) has enough time
to start and start serving request.

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


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

Branch: refs/heads/master
Commit: 12a01d925b6c605d5a55f09634f7bced4beae0c9
Parents: 26e135d
Author: Alexander Rukletsov <al...@apache.org>
Authored: Wed Apr 5 00:04:27 2017 +0200
Committer: Alexander Rukletsov <al...@apache.org>
Committed: Mon Apr 24 12:06:24 2017 +0200

----------------------------------------------------------------------
 src/tests/check_tests.cpp | 58 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 55 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/12a01d92/src/tests/check_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/check_tests.cpp b/src/tests/check_tests.cpp
index 67ca6fb..ec0d5ee 100644
--- a/src/tests/check_tests.cpp
+++ b/src/tests/check_tests.cpp
@@ -113,7 +113,7 @@ namespace tests {
 #endif // !__WINDOWS__
 
 
-// Tests for checks support in built in executors. Logically the tests
+// Tests for checks support in built-in executors. Logically the tests
 // are elements of the cartesian product `executor-type` x `check-type`
 // and are split into groups by `executor-type`:
 //   * command executor tests,
@@ -860,7 +860,33 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(CommandExecutorCheckTest, HTTPCheckDelivered)
   EXPECT_EQ(taskInfo.task_id(), checkResult.task_id());
   EXPECT_TRUE(checkResult.has_check_status());
   EXPECT_TRUE(checkResult.check_status().http().has_status_code());
-  EXPECT_EQ(200, checkResult.check_status().http().status_code());
+
+  // Since it takes some time for the HTTP server to start serving requests,
+  // the first several HTTP checks may not return 200. However we still expect
+  // a successful HTTP check and hence an extra status update.
+  if (checkResult.check_status().http().status_code() != 200)
+  {
+    // Inject an expectation for the extra status update we expect.
+    Future<v1::scheduler::Event::Update> updateCheckResult2;
+    EXPECT_CALL(*scheduler, update(_, _))
+      .WillOnce(FutureArg<1>(&updateCheckResult2))
+      .RetiresOnSaturation();
+
+    // Acknowledge (to be able to get the next update).
+    acknowledge(&mesos, frameworkId, checkResult);
+
+    AWAIT_READY(updateCheckResult2);
+    const v1::TaskStatus& checkResult2 = updateCheckResult2->status();
+
+    ASSERT_EQ(TASK_RUNNING, checkResult2.state());
+    ASSERT_EQ(
+        v1::TaskStatus::REASON_TASK_CHECK_STATUS_UPDATED,
+        checkResult2.reason());
+    EXPECT_EQ(taskInfo.task_id(), checkResult2.task_id());
+    EXPECT_TRUE(checkResult2.has_check_status());
+    EXPECT_TRUE(checkResult2.check_status().http().has_status_code());
+    EXPECT_EQ(200, checkResult2.check_status().http().status_code());
+  }
 }
 
 
@@ -1849,7 +1875,33 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(DefaultExecutorCheckTest, HTTPCheckDelivered)
   EXPECT_EQ(taskInfo.task_id(), checkResult.task_id());
   EXPECT_TRUE(checkResult.has_check_status());
   EXPECT_TRUE(checkResult.check_status().http().has_status_code());
-  EXPECT_EQ(200, checkResult.check_status().http().status_code());
+
+  // Since it takes some time for the HTTP server to start serving requests,
+  // the first several HTTP checks may not return 200. However we still expect
+  // a successful HTTP check and hence an extra status update.
+  if (checkResult.check_status().http().status_code() != 200)
+  {
+    // Inject an expectation for the extra status update we expect.
+    Future<v1::scheduler::Event::Update> updateCheckResult2;
+    EXPECT_CALL(*scheduler, update(_, _))
+      .WillOnce(FutureArg<1>(&updateCheckResult2))
+      .RetiresOnSaturation();
+
+    // Acknowledge (to be able to get the next update).
+    acknowledge(&mesos, frameworkId, checkResult);
+
+    AWAIT_READY(updateCheckResult2);
+    const v1::TaskStatus& checkResult2 = updateCheckResult2->status();
+
+    ASSERT_EQ(TASK_RUNNING, checkResult2.state());
+    ASSERT_EQ(
+        v1::TaskStatus::REASON_TASK_CHECK_STATUS_UPDATED,
+        checkResult2.reason());
+    EXPECT_EQ(taskInfo.task_id(), checkResult2.task_id());
+    EXPECT_TRUE(checkResult2.has_check_status());
+    EXPECT_TRUE(checkResult2.check_status().http().has_status_code());
+    EXPECT_EQ(200, checkResult2.check_status().http().status_code());
+  }
 }
 
 


[5/7] mesos git commit: Used constexpr char instead of static const string for consistency.

Posted by al...@apache.org.
Used constexpr char instead of static const string for consistency.

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


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

Branch: refs/heads/master
Commit: 4b22e0d50a44d2971cdca1337089e2f33d9712f2
Parents: 69fd4af
Author: Alexander Rukletsov <al...@apache.org>
Authored: Tue Apr 4 13:42:23 2017 +0200
Committer: Alexander Rukletsov <al...@apache.org>
Committed: Mon Apr 24 12:04:51 2017 +0200

----------------------------------------------------------------------
 src/checks/checker.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/4b22e0d5/src/checks/checker.cpp
----------------------------------------------------------------------
diff --git a/src/checks/checker.cpp b/src/checks/checker.cpp
index cf7a086..2a7d511 100644
--- a/src/checks/checker.cpp
+++ b/src/checks/checker.cpp
@@ -92,11 +92,11 @@ constexpr char HTTP_CHECK_COMMAND[] = "curl";
 constexpr char HTTP_CHECK_COMMAND[] = "curl.exe";
 #endif // __WINDOWS__
 
-static const string DEFAULT_HTTP_SCHEME = "http";
+constexpr char DEFAULT_HTTP_SCHEME[] = "http";
 
 // Use '127.0.0.1' instead of 'localhost', because the host
 // file in some container images may not contain 'localhost'.
-static const string DEFAULT_DOMAIN = "127.0.0.1";
+constexpr char DEFAULT_DOMAIN[] = "127.0.0.1";
 
 
 #ifdef __linux__


[6/7] mesos git commit: Implemented TCP check support in command and default executors.

Posted by al...@apache.org.
Implemented TCP check support in command and default executors.

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


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

Branch: refs/heads/master
Commit: 26e135d7abe457a858deb9762ee5ff735f6048cc
Parents: bbed0e8
Author: Alexander Rukletsov <al...@apache.org>
Authored: Wed Apr 5 00:09:01 2017 +0200
Committer: Alexander Rukletsov <al...@apache.org>
Committed: Mon Apr 24 12:06:22 2017 +0200

----------------------------------------------------------------------
 src/checks/checker.cpp            | 155 ++++++++++++++++++
 src/checks/checker.hpp            |   6 +
 src/launcher/default_executor.cpp |   1 +
 src/launcher/executor.cpp         |   1 +
 src/tests/check_tests.cpp         | 281 +++++++++++++++++++++++++++++++++
 5 files changed, 444 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/26e135d7/src/checks/checker.cpp
----------------------------------------------------------------------
diff --git a/src/checks/checker.cpp b/src/checks/checker.cpp
index 2fcf527..dcc3164 100644
--- a/src/checks/checker.cpp
+++ b/src/checks/checker.cpp
@@ -88,8 +88,10 @@ namespace checks {
 
 #ifndef __WINDOWS__
 constexpr char HTTP_CHECK_COMMAND[] = "curl";
+constexpr char TCP_CHECK_COMMAND[] = "mesos-tcp-connect";
 #else
 constexpr char HTTP_CHECK_COMMAND[] = "curl.exe";
+constexpr char TCP_CHECK_COMMAND[] = "mesos-tcp-connect.exe";
 #endif // __WINDOWS__
 
 constexpr char DEFAULT_HTTP_SCHEME[] = "http";
@@ -133,6 +135,7 @@ class CheckerProcess : public ProtobufProcess<CheckerProcess>
 public:
   CheckerProcess(
       const CheckInfo& _check,
+      const string& _launcherDir,
       const lambda::function<void(const CheckStatusInfo&)>& _callback,
       const TaskID& _taskId,
       const Option<pid_t>& _taskPid,
@@ -193,11 +196,21 @@ private:
       const Stopwatch& stopwatch,
       const Future<int>& future);
 
+  Future<bool> tcpCheck();
+  Future<bool> _tcpCheck(
+      const tuple<Future<Option<int>>, Future<string>, Future<string>>& t);
+  void processTcpCheckResult(
+      const Stopwatch& stopwatch,
+      const Future<bool>& future);
+
   const CheckInfo check;
   Duration checkDelay;
   Duration checkInterval;
   Duration checkTimeout;
 
+  // Contains the binary for TCP checks.
+  const string launcherDir;
+
   const lambda::function<void(const CheckStatusInfo&)> updateCallback;
   const TaskID taskId;
   const Option<pid_t> taskPid;
@@ -220,6 +233,7 @@ private:
 
 Try<Owned<Checker>> Checker::create(
     const CheckInfo& check,
+    const string& launcherDir,
     const lambda::function<void(const CheckStatusInfo&)>& callback,
     const TaskID& taskId,
     const Option<pid_t>& taskPid,
@@ -233,6 +247,7 @@ Try<Owned<Checker>> Checker::create(
 
   Owned<CheckerProcess> process(new CheckerProcess(
       check,
+      launcherDir,
       callback,
       taskId,
       taskPid,
@@ -248,6 +263,7 @@ Try<Owned<Checker>> Checker::create(
 
 Try<Owned<Checker>> Checker::create(
     const CheckInfo& check,
+    const string& launcherDir,
     const lambda::function<void(const CheckStatusInfo&)>& callback,
     const TaskID& taskId,
     const ContainerID& taskContainerId,
@@ -262,6 +278,7 @@ Try<Owned<Checker>> Checker::create(
 
   Owned<CheckerProcess> process(new CheckerProcess(
       check,
+      launcherDir,
       callback,
       taskId,
       None(),
@@ -303,6 +320,7 @@ void Checker::resume()
 
 CheckerProcess::CheckerProcess(
     const CheckInfo& _check,
+    const string& _launcherDir,
     const lambda::function<void(const CheckStatusInfo&)>& _callback,
     const TaskID& _taskId,
     const Option<pid_t>& _taskPid,
@@ -313,6 +331,7 @@ CheckerProcess::CheckerProcess(
     bool _commandCheckViaAgent)
   : ProcessBase(process::ID::generate("checker")),
     check(_check),
+    launcherDir(_launcherDir),
     updateCallback(_callback),
     taskId(_taskId),
     taskPid(_taskPid),
@@ -407,6 +426,9 @@ void CheckerProcess::performCheck()
       break;
     }
     case CheckInfo::TCP: {
+      tcpCheck().onAny(defer(
+          self(),
+          &Self::processTcpCheckResult, stopwatch, lambda::_1));
       break;
     }
     case CheckInfo::UNKNOWN: {
@@ -1068,6 +1090,139 @@ void CheckerProcess::processHttpCheckResult(
   processCheckResult(stopwatch, result);
 }
 
+
+Future<bool> CheckerProcess::tcpCheck()
+{
+  CHECK_EQ(CheckInfo::TCP, check.type());
+  CHECK(check.has_tcp());
+
+  // TCP_CHECK_COMMAND should be reachable.
+  CHECK(os::exists(launcherDir));
+
+  const CheckInfo::Tcp& tcp = check.tcp();
+
+  VLOG(1) << "Launching TCP check for task '" << taskId << "' at port "
+          << tcp.port();
+
+  const string command = path::join(launcherDir, TCP_CHECK_COMMAND);
+
+  const vector<string> argv = {
+    command,
+    "--ip=" + stringify(DEFAULT_DOMAIN),
+    "--port=" + stringify(tcp.port())
+  };
+
+  // TODO(alexr): Consider launching the helper binary once per task lifetime,
+  // see MESOS-6766.
+  Try<Subprocess> s = subprocess(
+      command,
+      argv,
+      Subprocess::PATH(os::DEV_NULL),
+      Subprocess::PIPE(),
+      Subprocess::PIPE(),
+      nullptr,
+      None(),
+      clone);
+
+  if (s.isError()) {
+    return Failure(
+        "Failed to create the " + command + " subprocess: " + s.error());
+  }
+
+  // TODO(alexr): Use lambda named captures for
+  // these cached values once they are available.
+  pid_t commandPid = s->pid();
+  const Duration timeout = checkTimeout;
+  const TaskID _taskId = taskId;
+
+  return await(
+      s->status(),
+      process::io::read(s->out().get()),
+      process::io::read(s->err().get()))
+    .after(
+        timeout,
+        [timeout, commandPid, _taskId](Future<tuple<Future<Option<int>>,
+                                                    Future<string>,
+                                                    Future<string>>> future)
+    {
+      future.discard();
+
+      if (commandPid != -1) {
+        // Cleanup the TCP_CHECK_COMMAND process.
+        VLOG(1) << "Killing the TCP check process " << commandPid
+                << " for task '" << _taskId << "'";
+
+        os::killtree(commandPid, SIGKILL);
+      }
+
+      return Failure(
+          string(TCP_CHECK_COMMAND) + " timed out after " + stringify(timeout));
+    })
+    .then(defer(self(), &Self::_tcpCheck, lambda::_1));
+}
+
+
+Future<bool> CheckerProcess::_tcpCheck(
+    const tuple<Future<Option<int>>, Future<string>, Future<string>>& t)
+{
+  const Future<Option<int>>& status = std::get<0>(t);
+  if (!status.isReady()) {
+    return Failure(
+        "Failed to get the exit status of the " + string(TCP_CHECK_COMMAND) +
+        " process: " + (status.isFailed() ? status.failure() : "discarded"));
+  }
+
+  if (status->isNone()) {
+    return Failure(
+        "Failed to reap the " + string(TCP_CHECK_COMMAND) + " process");
+  }
+
+  int exitCode = status->get();
+
+  const Future<string>& commandOutput = std::get<1>(t);
+  if (commandOutput.isReady()) {
+    VLOG(1) << string(TCP_CHECK_COMMAND) << ": " << commandOutput.get();
+  }
+
+  if (exitCode != 0) {
+    const Future<string>& commandError = std::get<2>(t);
+    if (commandError.isReady()) {
+      VLOG(1) << string(TCP_CHECK_COMMAND) << ": " << commandError.get();
+    }
+  }
+
+  // Non-zero exit code of TCP_CHECK_COMMAND can mean configuration problem
+  // (e.g., bad command flag), system error (e.g., a socket cannot be
+  // created), or actually a failed connection. We cannot distinguish between
+  // these cases, hence treat all of them as connection failure.
+  return (exitCode == 0 ? true : false);
+}
+
+
+void CheckerProcess::processTcpCheckResult(
+    const Stopwatch& stopwatch,
+    const Future<bool>& future)
+{
+  CheckStatusInfo result;
+  result.set_type(check.type());
+
+  if (future.isReady()) {
+    VLOG(1) << check.type() << " check for task '"
+            << taskId << "' returned: " << stringify(future.get());
+
+    result.mutable_tcp()->set_succeeded(future.get());
+  } else {
+    // Check's status is currently not available, which may indicate a change
+    // that should be reported as an empty `CheckStatusInfo.Tcp` message.
+    LOG(WARNING) << check.type() << " check for task '" << taskId << "' failed:"
+                 << " " << (future.isFailed() ? future.failure() : "discarded");
+
+    result.mutable_tcp();
+  }
+
+  processCheckResult(stopwatch, result);
+}
+
 namespace validation {
 
 Option<Error> checkInfo(const CheckInfo& checkInfo)

http://git-wip-us.apache.org/repos/asf/mesos/blob/26e135d7/src/checks/checker.hpp
----------------------------------------------------------------------
diff --git a/src/checks/checker.hpp b/src/checks/checker.hpp
index fec30a2..bbe147f 100644
--- a/src/checks/checker.hpp
+++ b/src/checks/checker.hpp
@@ -48,6 +48,8 @@ public:
    * the task's namespaces, and execute the commmand.
    *
    * @param check The protobuf message definition of a check.
+   * @param launcherDir A directory where Mesos helper binaries are located.
+   *     Executor must have access to this directory for TCP checks.
    * @param callback A callback `Checker` uses to send check status updates
    *     to its owner (usually an executor).
    * @param taskId The TaskID of the target task.
@@ -61,6 +63,7 @@ public:
    */
   static Try<process::Owned<Checker>> create(
       const CheckInfo& check,
+      const std::string& launcherDir,
       const lambda::function<void(const CheckStatusInfo&)>& callback,
       const TaskID& taskId,
       const Option<pid_t>& taskPid,
@@ -75,6 +78,8 @@ public:
    * API call.
    *
    * @param check The protobuf message definition of a check.
+   * @param launcherDir A directory where Mesos helper binaries are located.
+   *     Executor must have access to this directory for TCP checks.
    * @param callback A callback `Checker` uses to send check status updates
    *     to its owner (usually an executor).
    * @param taskId The TaskID of the target task.
@@ -89,6 +94,7 @@ public:
    */
   static Try<process::Owned<Checker>> create(
       const CheckInfo& check,
+      const std::string& launcherDir,
       const lambda::function<void(const CheckStatusInfo&)>& callback,
       const TaskID& taskId,
       const ContainerID& taskContainerId,

http://git-wip-us.apache.org/repos/asf/mesos/blob/26e135d7/src/launcher/default_executor.cpp
----------------------------------------------------------------------
diff --git a/src/launcher/default_executor.cpp b/src/launcher/default_executor.cpp
index 95505fc..5c31f94 100644
--- a/src/launcher/default_executor.cpp
+++ b/src/launcher/default_executor.cpp
@@ -506,6 +506,7 @@ protected:
         Try<Owned<checks::Checker>> checker =
           checks::Checker::create(
               task.check(),
+              launcherDirectory,
               defer(self(), &Self::taskCheckUpdated, taskId, lambda::_1),
               taskId,
               containerId,

http://git-wip-us.apache.org/repos/asf/mesos/blob/26e135d7/src/launcher/executor.cpp
----------------------------------------------------------------------
diff --git a/src/launcher/executor.cpp b/src/launcher/executor.cpp
index c9cecb5..b05f73e 100644
--- a/src/launcher/executor.cpp
+++ b/src/launcher/executor.cpp
@@ -643,6 +643,7 @@ protected:
       Try<Owned<checks::Checker>> _checker =
         checks::Checker::create(
             task.check(),
+            launcherDir,
             defer(self(), &Self::taskCheckUpdated, taskId.get(), lambda::_1),
             taskId.get(),
             pid,

http://git-wip-us.apache.org/repos/asf/mesos/blob/26e135d7/src/tests/check_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/check_tests.cpp b/src/tests/check_tests.cpp
index 67124c9..67ca6fb 100644
--- a/src/tests/check_tests.cpp
+++ b/src/tests/check_tests.cpp
@@ -864,6 +864,138 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(CommandExecutorCheckTest, HTTPCheckDelivered)
 }
 
 
+// Verifies that a TCP check is supported by the command executor and
+// its status is delivered in a task status update.
+//
+// TODO(alexr): Check if this test works on Windows.
+TEST_F_TEMP_DISABLED_ON_WINDOWS(CommandExecutorCheckTest, TCPCheckDelivered)
+{
+  Try<Owned<cluster::Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  Owned<MasterDetector> detector = master.get()->createDetector();
+  Try<Owned<cluster::Slave>> agent = StartSlave(detector.get());
+  ASSERT_SOME(agent);
+
+  v1::FrameworkInfo frameworkInfo = v1::DEFAULT_FRAMEWORK_INFO;
+
+  auto scheduler = std::make_shared<v1::MockHTTPScheduler>();
+
+  Future<Nothing> connected;
+  EXPECT_CALL(*scheduler, connected(_))
+    .WillOnce(FutureSatisfy(&connected));
+
+  v1::scheduler::TestMesos mesos(
+      master.get()->pid,
+      ContentType::PROTOBUF,
+      scheduler);
+
+  AWAIT_READY(connected);
+
+  Future<v1::scheduler::Event::Subscribed> subscribed;
+  EXPECT_CALL(*scheduler, subscribed(_, _))
+    .WillOnce(FutureArg<1>(&subscribed));
+
+  Future<v1::scheduler::Event::Offers> offers;
+  EXPECT_CALL(*scheduler, offers(_, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  EXPECT_CALL(*scheduler, heartbeat(_))
+    .WillRepeatedly(Return()); // Ignore heartbeats.
+
+  subscribe(&mesos, frameworkInfo);
+
+  AWAIT_READY(subscribed);
+
+  v1::FrameworkID frameworkId(subscribed->framework_id());
+
+  AWAIT_READY(offers);
+  EXPECT_NE(0, offers->offers().size());
+  const v1::Offer& offer = offers->offers(0);
+  const v1::AgentID agentId = offer.agent_id();
+
+  Future<v1::scheduler::Event::Update> updateTaskRunning;
+  Future<v1::scheduler::Event::Update> updateCheckResult;
+  EXPECT_CALL(*scheduler, update(_, _))
+    .WillOnce(FutureArg<1>(&updateTaskRunning))
+    .WillOnce(FutureArg<1>(&updateCheckResult))
+    .WillRepeatedly(Return()); // Ignore subsequent updates.
+
+  const uint16_t testPort = getFreePort().get();
+
+  // Use `test-helper` to launch a simple HTTP
+  // server to respond to TCP checks.
+  const string command = strings::format(
+      "%s %s --ip=127.0.0.1 --port=%u",
+      getTestHelperPath("test-helper"),
+      HttpServerTestHelper::NAME,
+      testPort).get();
+
+  v1::Resources resources =
+      v1::Resources::parse("cpus:0.1;mem:32;disk:32").get();
+
+  v1::TaskInfo taskInfo = v1::createTask(agentId, resources, command);
+
+  v1::CheckInfo* checkInfo = taskInfo.mutable_check();
+  checkInfo->set_type(v1::CheckInfo::TCP);
+  checkInfo->mutable_tcp()->set_port(testPort);
+  checkInfo->set_delay_seconds(0);
+  checkInfo->set_interval_seconds(0);
+
+  launchTask(&mesos, offer, taskInfo);
+
+  AWAIT_READY(updateTaskRunning);
+  const v1::TaskStatus& taskRunning = updateTaskRunning->status();
+
+  ASSERT_EQ(TASK_RUNNING, taskRunning.state());
+  EXPECT_EQ(taskInfo.task_id(), taskRunning.task_id());
+  EXPECT_TRUE(taskRunning.has_check_status());
+  EXPECT_TRUE(taskRunning.check_status().has_tcp());
+  EXPECT_FALSE(taskRunning.check_status().tcp().has_succeeded());
+
+  acknowledge(&mesos, frameworkId, taskRunning);
+
+  AWAIT_READY(updateCheckResult);
+  const v1::TaskStatus& checkResult = updateCheckResult->status();
+
+  ASSERT_EQ(TASK_RUNNING, checkResult.state());
+  ASSERT_EQ(
+      v1::TaskStatus::REASON_TASK_CHECK_STATUS_UPDATED,
+      checkResult.reason());
+  EXPECT_EQ(taskInfo.task_id(), checkResult.task_id());
+  EXPECT_TRUE(checkResult.has_check_status());
+  EXPECT_TRUE(checkResult.check_status().tcp().has_succeeded());
+
+  // Since it takes some time for the HTTP server to start serving requests,
+  // the first several TCP checks may fail. However we still expect a
+  // successful TCP check and hence an extra status update.
+  if (checkResult.check_status().tcp().succeeded() == false)
+  {
+    // Inject an expectation for the extra status update we expect.
+    Future<v1::scheduler::Event::Update> updateCheckResult2;
+    EXPECT_CALL(*scheduler, update(_, _))
+      .WillOnce(FutureArg<1>(&updateCheckResult2))
+      .RetiresOnSaturation();
+
+    // Acknowledge (to be able to get the next update).
+    acknowledge(&mesos, frameworkId, checkResult);
+
+    AWAIT_READY(updateCheckResult2);
+    const v1::TaskStatus& checkResult2 = updateCheckResult2->status();
+
+    ASSERT_EQ(TASK_RUNNING, checkResult2.state());
+    ASSERT_EQ(
+        v1::TaskStatus::REASON_TASK_CHECK_STATUS_UPDATED,
+        checkResult2.reason());
+    EXPECT_EQ(taskInfo.task_id(), checkResult2.task_id());
+    EXPECT_TRUE(checkResult2.has_check_status());
+    EXPECT_TRUE(checkResult2.check_status().tcp().has_succeeded());
+    EXPECT_EQ(true, checkResult2.check_status().tcp().succeeded());
+  }
+}
+
+
 // TODO(alexr): Implement following tests for the docker executor once
 // the docker executor supports checks.
 //
@@ -875,6 +1007,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(CommandExecutorCheckTest, HTTPCheckDelivered)
 // 4. COMMAND check and health check do not shadow each other; upon
 //    reconciliation both statuses are available.
 // 5. HTTP check works and is delivered.
+// 6. TCP check works and is delivered.
 
 
 // These are check tests with the default executor.
@@ -1720,6 +1853,154 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(DefaultExecutorCheckTest, HTTPCheckDelivered)
 }
 
 
+// Verifies that a TCP check is supported by the default executor and
+// its status is delivered in a task status update.
+//
+// TODO(alexr): Check if this test works on Windows.
+TEST_F_TEMP_DISABLED_ON_WINDOWS(DefaultExecutorCheckTest, TCPCheckDelivered)
+{
+  Try<Owned<cluster::Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  // Disable AuthN on the agent.
+  slave::Flags flags = CreateSlaveFlags();
+  flags.authenticate_http_readwrite = false;
+
+  Owned<MasterDetector> detector = master.get()->createDetector();
+  Try<Owned<cluster::Slave>> agent = StartSlave(detector.get(), flags);
+  ASSERT_SOME(agent);
+
+  v1::FrameworkInfo frameworkInfo = v1::DEFAULT_FRAMEWORK_INFO;
+
+  const v1::Resources resources =
+    v1::Resources::parse("cpus:0.1;mem:32;disk:32").get();
+
+  v1::ExecutorInfo executorInfo;
+  executorInfo.set_type(v1::ExecutorInfo::DEFAULT);
+  executorInfo.mutable_executor_id()->CopyFrom(v1::DEFAULT_EXECUTOR_ID);
+  executorInfo.mutable_resources()->CopyFrom(resources);
+
+  auto scheduler = std::make_shared<v1::MockHTTPScheduler>();
+
+  Future<Nothing> connected;
+  EXPECT_CALL(*scheduler, connected(_))
+    .WillOnce(FutureSatisfy(&connected));
+
+  v1::scheduler::TestMesos mesos(
+      master.get()->pid,
+      ContentType::PROTOBUF,
+      scheduler);
+
+  AWAIT_READY(connected);
+
+  Future<v1::scheduler::Event::Subscribed> subscribed;
+  EXPECT_CALL(*scheduler, subscribed(_, _))
+    .WillOnce(FutureArg<1>(&subscribed));
+
+  Future<v1::scheduler::Event::Offers> offers;
+  EXPECT_CALL(*scheduler, offers(_, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  EXPECT_CALL(*scheduler, heartbeat(_))
+    .WillRepeatedly(Return()); // Ignore heartbeats.
+
+  subscribe(&mesos, frameworkInfo);
+
+  AWAIT_READY(subscribed);
+
+  v1::FrameworkID frameworkId(subscribed->framework_id());
+
+  // Update `executorInfo` with the subscribed `frameworkId`.
+  executorInfo.mutable_framework_id()->CopyFrom(frameworkId);
+
+  AWAIT_READY(offers);
+  EXPECT_NE(0, offers->offers().size());
+  const v1::Offer& offer = offers->offers(0);
+  const v1::AgentID agentId = offer.agent_id();
+
+  Future<v1::scheduler::Event::Update> updateTaskRunning;
+  Future<v1::scheduler::Event::Update> updateCheckResult;
+  EXPECT_CALL(*scheduler, update(_, _))
+    .WillOnce(FutureArg<1>(&updateTaskRunning))
+    .WillOnce(FutureArg<1>(&updateCheckResult))
+    .WillRepeatedly(Return()); // Ignore subsequent updates.
+
+  const uint16_t testPort = getFreePort().get();
+
+  // Use `test-helper` to launch a simple HTTP
+  // server to respond to TCP checks.
+  const string command = strings::format(
+      "%s %s --ip=127.0.0.1 --port=%u",
+      getTestHelperPath("test-helper"),
+      HttpServerTestHelper::NAME,
+      testPort).get();
+
+  v1::TaskInfo taskInfo = v1::createTask(agentId, resources, command);
+
+  v1::CheckInfo* checkInfo = taskInfo.mutable_check();
+  checkInfo->set_type(v1::CheckInfo::TCP);
+  checkInfo->mutable_tcp()->set_port(testPort);
+  checkInfo->set_delay_seconds(0);
+  checkInfo->set_interval_seconds(0);
+
+  v1::TaskGroupInfo taskGroup;
+  taskGroup.add_tasks()->CopyFrom(taskInfo);
+
+  launchTaskGroup(&mesos, offer, executorInfo, taskGroup);
+
+  AWAIT_READY(updateTaskRunning);
+  const v1::TaskStatus& taskRunning = updateTaskRunning->status();
+
+  ASSERT_EQ(TASK_RUNNING, taskRunning.state());
+  EXPECT_EQ(taskInfo.task_id(), taskRunning.task_id());
+  EXPECT_TRUE(taskRunning.has_check_status());
+  EXPECT_TRUE(taskRunning.check_status().has_tcp());
+  EXPECT_FALSE(taskRunning.check_status().tcp().has_succeeded());
+
+  // Acknowledge (to be able to get the next update).
+  acknowledge(&mesos, frameworkId, taskRunning);
+
+  AWAIT_READY(updateCheckResult);
+  const v1::TaskStatus& checkResult = updateCheckResult->status();
+
+  ASSERT_EQ(TASK_RUNNING, checkResult.state());
+  ASSERT_EQ(
+      v1::TaskStatus::REASON_TASK_CHECK_STATUS_UPDATED,
+      checkResult.reason());
+  EXPECT_EQ(taskInfo.task_id(), checkResult.task_id());
+  EXPECT_TRUE(checkResult.has_check_status());
+  EXPECT_TRUE(checkResult.check_status().tcp().has_succeeded());
+
+  // Since it takes some time for the HTTP server to start serving requests,
+  // the first several TCP checks may fail. However we still expect a
+  // successful TCP check and hence an extra status update.
+  if (checkResult.check_status().tcp().succeeded() == false)
+  {
+    // Inject an expectation for the extra status update we expect.
+    Future<v1::scheduler::Event::Update> updateCheckResult2;
+    EXPECT_CALL(*scheduler, update(_, _))
+      .WillOnce(FutureArg<1>(&updateCheckResult2))
+      .RetiresOnSaturation();
+
+    // Acknowledge (to be able to get the next update).
+    acknowledge(&mesos, frameworkId, checkResult);
+
+    AWAIT_READY(updateCheckResult2);
+    const v1::TaskStatus& checkResult2 = updateCheckResult2->status();
+
+    ASSERT_EQ(TASK_RUNNING, checkResult2.state());
+    ASSERT_EQ(
+        v1::TaskStatus::REASON_TASK_CHECK_STATUS_UPDATED,
+        checkResult2.reason());
+    EXPECT_EQ(taskInfo.task_id(), checkResult2.task_id());
+    EXPECT_TRUE(checkResult2.has_check_status());
+    EXPECT_TRUE(checkResult2.check_status().tcp().has_succeeded());
+    EXPECT_EQ(true, checkResult2.check_status().tcp().succeeded());
+  }
+}
+
+
 // These are protobuf validation tests.
 //
 // TODO(alexr): Move these tests once validation code is moved closer to


[4/7] mesos git commit: Renamed variables in checker library for clarity.

Posted by al...@apache.org.
Renamed variables in checker library for clarity.

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


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

Branch: refs/heads/master
Commit: ace943235b5f2b309b6d18e480192fb512ab89c6
Parents: 4b22e0d
Author: Alexander Rukletsov <al...@apache.org>
Authored: Tue Apr 4 13:47:25 2017 +0200
Committer: Alexander Rukletsov <al...@apache.org>
Committed: Mon Apr 24 12:04:51 2017 +0200

----------------------------------------------------------------------
 src/checks/checker.cpp | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/ace94323/src/checks/checker.cpp
----------------------------------------------------------------------
diff --git a/src/checks/checker.cpp b/src/checks/checker.cpp
index 2a7d511..a883656 100644
--- a/src/checks/checker.cpp
+++ b/src/checks/checker.cpp
@@ -184,14 +184,14 @@ private:
 
   void processCommandCheckResult(
       const Stopwatch& stopwatch,
-      const Future<int>& result);
+      const Future<int>& future);
 
   Future<int> httpCheck();
   Future<int> _httpCheck(
       const tuple<Future<Option<int>>, Future<string>, Future<string>>& t);
   void processHttpCheckResult(
       const Stopwatch& stopwatch,
-      const Future<int>& result);
+      const Future<int>& future);
 
   const CheckInfo check;
   Duration checkDelay;
@@ -937,7 +937,7 @@ Future<int> CheckerProcess::httpCheck()
     "-L",                 // Follows HTTP 3xx redirects.
     "-k",                 // Ignores SSL validation when scheme is https.
     "-w", "%{http_code}", // Displays HTTP response code on stdout.
-    "-o", os::DEV_NULL,    // Ignores output.
+    "-o", os::DEV_NULL,   // Ignores output.
     url
   };
 
@@ -1043,27 +1043,26 @@ Future<int> CheckerProcess::_httpCheck(
 
 void CheckerProcess::processHttpCheckResult(
     const Stopwatch& stopwatch,
-    const Future<int>& result)
+    const Future<int>& future)
 {
-  CheckStatusInfo checkStatusInfo;
-  checkStatusInfo.set_type(check.type());
+  CheckStatusInfo result;
+  result.set_type(check.type());
 
-  if (result.isReady()) {
+  if (future.isReady()) {
     VLOG(1) << check.type() << " check for task '"
-            << taskId << "' returned: " << result.get();
+            << taskId << "' returned: " << future.get();
 
-    checkStatusInfo.mutable_http()->set_status_code(
-        static_cast<uint32_t>(result.get()));
+    result.mutable_http()->set_status_code(static_cast<uint32_t>(future.get()));
   } else {
     // Check's status is currently not available, which may indicate a change
     // that should be reported as an empty `CheckStatusInfo.Http` message.
-    LOG(WARNING) << "Check for task '" << taskId << "' failed: "
-                 << (result.isFailed() ? result.failure() : "discarded");
+    LOG(WARNING) << check.type() << " check for task '" << taskId << "' failed:"
+                 << " " << (future.isFailed() ? future.failure() : "discarded");
 
-    checkStatusInfo.mutable_http();
+    result.mutable_http();
   }
 
-  processCheckResult(stopwatch, checkStatusInfo);
+  processCheckResult(stopwatch, result);
 }
 
 namespace validation {


[2/7] mesos git commit: Renamed a test helper for clarity.

Posted by al...@apache.org.
Renamed a test helper for clarity.

`HealthCheckTestHelper` is actually a simple libprocess-based HTTP
server. To make it clear and enable it usage in non health check
related tests, rename it to `HttpServerTestHelper`.

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


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

Branch: refs/heads/master
Commit: 69fd4af6ebfba3a6261a927ae1bec0f4a5d22af8
Parents: 674a619
Author: Alexander Rukletsov <al...@apache.org>
Authored: Mon Apr 3 19:20:07 2017 +0200
Committer: Alexander Rukletsov <al...@apache.org>
Committed: Mon Apr 24 12:04:51 2017 +0200

----------------------------------------------------------------------
 src/Makefile.am                        |  6 +--
 src/tests/CMakeLists.txt               |  4 +-
 src/tests/check_tests.cpp              |  6 +--
 src/tests/health_check_test_helper.cpp | 76 -----------------------------
 src/tests/health_check_test_helper.hpp | 56 ---------------------
 src/tests/health_check_tests.cpp       |  8 +--
 src/tests/http_server_test_helper.cpp  | 76 +++++++++++++++++++++++++++++
 src/tests/http_server_test_helper.hpp  | 56 +++++++++++++++++++++
 src/tests/test_helper_main.cpp         |  6 +--
 9 files changed, 147 insertions(+), 147 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/69fd4af6/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 1fc453c..29da17b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1120,7 +1120,7 @@ libmesos_no_3rdparty_la_SOURCES +=					\
   tests/containerizer.hpp						\
   tests/environment.hpp							\
   tests/flags.hpp							\
-  tests/health_check_test_helper.hpp					\
+  tests/http_server_test_helper.hpp					\
   tests/kill_policy_test_helper.hpp					\
   tests/limiter.hpp							\
   tests/mesos.hpp							\
@@ -2091,7 +2091,7 @@ check_PROGRAMS += test-helper
 test_helper_SOURCES =						\
   tests/active_user_test_helper.cpp				\
   tests/flags.cpp						\
-  tests/health_check_test_helper.cpp				\
+  tests/http_server_test_helper.cpp				\
   tests/kill_policy_test_helper.cpp				\
   tests/resources_utils.cpp					\
   tests/test_helper_main.cpp					\
@@ -2264,11 +2264,11 @@ mesos_tests_SOURCES =						\
   tests/gc_tests.cpp						\
   tests/hdfs_tests.cpp						\
   tests/health_check_tests.cpp					\
-  tests/health_check_test_helper.cpp				\
   tests/hierarchical_allocator_tests.cpp			\
   tests/hook_tests.cpp						\
   tests/http_authentication_tests.cpp				\
   tests/http_fault_tolerance_tests.cpp				\
+  tests/http_server_test_helper.cpp				\
   tests/kill_policy_test_helper.cpp				\
   tests/log_tests.cpp						\
   tests/logging_tests.cpp					\

http://git-wip-us.apache.org/repos/asf/mesos/blob/69fd4af6/src/tests/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 8e368a8..9f2af9c 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -23,7 +23,7 @@ set(TEST_HELPER_SRC
   ${TEST_HELPER_SRC}
   active_user_test_helper.cpp
   flags.cpp
-  health_check_test_helper.cpp
+  http_server_test_helper.cpp
   resources_utils.cpp
   test_helper_main.cpp
   utils.cpp
@@ -54,7 +54,7 @@ set(MESOS_TESTS_UTILS_SRC
   containerizer.cpp
   environment.cpp
   flags.cpp
-  health_check_test_helper.cpp
+  http_server_test_helper.cpp
   main.cpp
   mesos.cpp
   mock_docker.cpp

http://git-wip-us.apache.org/repos/asf/mesos/blob/69fd4af6/src/tests/check_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/check_tests.cpp b/src/tests/check_tests.cpp
index 72fa64c..2d1a122 100644
--- a/src/tests/check_tests.cpp
+++ b/src/tests/check_tests.cpp
@@ -36,7 +36,7 @@
 #include "slave/containerizer/fetcher.hpp"
 
 #include "tests/flags.hpp"
-#include "tests/health_check_test_helper.hpp"
+#include "tests/http_server_test_helper.hpp"
 #include "tests/mesos.hpp"
 #include "tests/utils.hpp"
 
@@ -822,7 +822,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(CommandExecutorCheckTest, HTTPCheckDelivered)
   const string command = strings::format(
       "%s %s --ip=127.0.0.1 --port=%u",
       getTestHelperPath("test-helper"),
-      HealthCheckTestHelper::NAME,
+      HttpServerTestHelper::NAME,
       testPort).get();
 
   v1::Resources resources =
@@ -1677,7 +1677,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(DefaultExecutorCheckTest, HTTPCheckDelivered)
   const string command = strings::format(
       "%s %s --ip=127.0.0.1 --port=%u",
       getTestHelperPath("test-helper"),
-      HealthCheckTestHelper::NAME,
+      HttpServerTestHelper::NAME,
       testPort).get();
 
   v1::TaskInfo taskInfo = v1::createTask(agentId, resources, command);

http://git-wip-us.apache.org/repos/asf/mesos/blob/69fd4af6/src/tests/health_check_test_helper.cpp
----------------------------------------------------------------------
diff --git a/src/tests/health_check_test_helper.cpp b/src/tests/health_check_test_helper.cpp
deleted file mode 100644
index 88352c1..0000000
--- a/src/tests/health_check_test_helper.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "tests/health_check_test_helper.hpp"
-
-#include <cstdlib>
-
-#include <process/id.hpp>
-#include <process/process.hpp>
-
-#include <stout/os.hpp>
-#include <stout/stringify.hpp>
-
-using process::Process;
-
-using std::cerr;
-using std::endl;
-
-namespace mesos {
-namespace internal {
-namespace tests {
-
-const char HealthCheckTestHelper::NAME[] = "HealthCheck";
-
-
-class HttpServer : public Process<HttpServer>
-{
-public:
-  HttpServer()
-    : ProcessBase(process::ID::generate("http-server")) {}
-};
-
-
-HealthCheckTestHelper::Flags::Flags()
-{
-  add(&Flags::ip,
-      "ip",
-      "IP address to listen on.");
-
-  add(&Flags::port,
-      "port",
-      "Port to listen on.");
-}
-
-
-int HealthCheckTestHelper::execute()
-{
-  os::setenv("LIBPROCESS_IP", flags.ip);
-  os::setenv("LIBPROCESS_PORT", stringify(flags.port));
-
-  HttpServer* server = new HttpServer();
-
-  process::spawn(server);
-  process::wait(server->self());
-
-  delete server;
-
-  return EXIT_SUCCESS;
-}
-
-} // namespace tests {
-} // namespace internal {
-} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/69fd4af6/src/tests/health_check_test_helper.hpp
----------------------------------------------------------------------
diff --git a/src/tests/health_check_test_helper.hpp b/src/tests/health_check_test_helper.hpp
deleted file mode 100644
index cdedf09..0000000
--- a/src/tests/health_check_test_helper.hpp
+++ /dev/null
@@ -1,56 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements.  See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership.  The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License.  You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef __HEALTH_CHECK_TEST_HELPER_HPP__
-#define __HEALTH_CHECK_TEST_HELPER_HPP__
-
-#include <cstdint>
-#include <string>
-
-#include <stout/flags.hpp>
-#include <stout/subcommand.hpp>
-
-namespace mesos {
-namespace internal {
-namespace tests {
-
-class HealthCheckTestHelper : public Subcommand
-{
-public:
-  static const char NAME[];
-
-  struct Flags : public virtual flags::FlagsBase
-  {
-    Flags();
-
-    std::string ip;
-    uint16_t port;
-  };
-
-  HealthCheckTestHelper() : Subcommand(NAME) {}
-
-  Flags flags;
-
-protected:
-  virtual int execute();
-  virtual flags::FlagsBase* getFlags() { return &flags; }
-};
-
-} // namespace tests {
-} // namespace internal {
-} // namespace mesos {
-
-#endif // __HEALTH_CHECK_TEST_HELPER_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/69fd4af6/src/tests/health_check_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/health_check_tests.cpp b/src/tests/health_check_tests.cpp
index f5375ac..6c1b9a0 100644
--- a/src/tests/health_check_tests.cpp
+++ b/src/tests/health_check_tests.cpp
@@ -32,7 +32,7 @@
 
 #include "tests/containerizer.hpp"
 #include "tests/flags.hpp"
-#include "tests/health_check_test_helper.hpp"
+#include "tests/http_server_test_helper.hpp"
 #include "tests/mesos.hpp"
 #include "tests/mock_docker.hpp"
 #include "tests/resources_utils.hpp"
@@ -1291,7 +1291,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(HealthCheckTest, HealthyTaskViaHTTP)
   const string command = strings::format(
       "%s %s --ip=127.0.0.1 --port=%u",
       getTestHelperPath("test-helper"),
-      HealthCheckTestHelper::NAME,
+      HttpServerTestHelper::NAME,
       testPort).get();
 
   TaskInfo task = createTask(offers.get()[0], command);
@@ -1377,7 +1377,7 @@ TEST_F_TEMP_DISABLED_ON_WINDOWS(HealthCheckTest, HealthyTaskViaHTTPWithoutType)
   const string command = strings::format(
       "%s %s --ip=127.0.0.1 --port=%u",
       getTestHelperPath("test-helper"),
-      HealthCheckTestHelper::NAME,
+      HttpServerTestHelper::NAME,
       testPort).get();
 
   TaskInfo task = createTask(offers.get()[0], command);
@@ -1454,7 +1454,7 @@ TEST_F(HealthCheckTest, HealthyTaskViaTCP)
   const string command = strings::format(
       "%s %s --ip=127.0.0.1 --port=%u",
       getTestHelperPath("test-helper"),
-      HealthCheckTestHelper::NAME,
+      HttpServerTestHelper::NAME,
       testPort).get();
 
   TaskInfo task = createTask(offers.get()[0], command);

http://git-wip-us.apache.org/repos/asf/mesos/blob/69fd4af6/src/tests/http_server_test_helper.cpp
----------------------------------------------------------------------
diff --git a/src/tests/http_server_test_helper.cpp b/src/tests/http_server_test_helper.cpp
new file mode 100644
index 0000000..14a9e0f
--- /dev/null
+++ b/src/tests/http_server_test_helper.cpp
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "tests/http_server_test_helper.hpp"
+
+#include <cstdlib>
+
+#include <process/id.hpp>
+#include <process/process.hpp>
+
+#include <stout/os.hpp>
+#include <stout/stringify.hpp>
+
+using process::Process;
+
+using std::cerr;
+using std::endl;
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+const char HttpServerTestHelper::NAME[] = "HttpServer";
+
+
+class HttpServer : public Process<HttpServer>
+{
+public:
+  HttpServer()
+    : ProcessBase(process::ID::generate("http-server")) {}
+};
+
+
+HttpServerTestHelper::Flags::Flags()
+{
+  add(&Flags::ip,
+      "ip",
+      "IP address to listen on.");
+
+  add(&Flags::port,
+      "port",
+      "Port to listen on.");
+}
+
+
+int HttpServerTestHelper::execute()
+{
+  os::setenv("LIBPROCESS_IP", flags.ip);
+  os::setenv("LIBPROCESS_PORT", stringify(flags.port));
+
+  HttpServer* server = new HttpServer();
+
+  process::spawn(server);
+  process::wait(server->self());
+
+  delete server;
+
+  return EXIT_SUCCESS;
+}
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/69fd4af6/src/tests/http_server_test_helper.hpp
----------------------------------------------------------------------
diff --git a/src/tests/http_server_test_helper.hpp b/src/tests/http_server_test_helper.hpp
new file mode 100644
index 0000000..d034ef5
--- /dev/null
+++ b/src/tests/http_server_test_helper.hpp
@@ -0,0 +1,56 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __HTTP_SERVER_TEST_HELPER_HPP__
+#define __HTTP_SERVER_TEST_HELPER_HPP__
+
+#include <cstdint>
+#include <string>
+
+#include <stout/flags.hpp>
+#include <stout/subcommand.hpp>
+
+namespace mesos {
+namespace internal {
+namespace tests {
+
+class HttpServerTestHelper : public Subcommand
+{
+public:
+  static const char NAME[];
+
+  struct Flags : public virtual flags::FlagsBase
+  {
+    Flags();
+
+    std::string ip;
+    uint16_t port;
+  };
+
+  HttpServerTestHelper() : Subcommand(NAME) {}
+
+  Flags flags;
+
+protected:
+  virtual int execute();
+  virtual flags::FlagsBase* getFlags() { return &flags; }
+};
+
+} // namespace tests {
+} // namespace internal {
+} // namespace mesos {
+
+#endif // __HTTP_SERVER_TEST_HELPER_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/69fd4af6/src/tests/test_helper_main.cpp
----------------------------------------------------------------------
diff --git a/src/tests/test_helper_main.cpp b/src/tests/test_helper_main.cpp
index 5d99ede..845e7d4 100644
--- a/src/tests/test_helper_main.cpp
+++ b/src/tests/test_helper_main.cpp
@@ -18,7 +18,7 @@
 #include <stout/subcommand.hpp>
 
 #include "tests/active_user_test_helper.hpp"
-#include "tests/health_check_test_helper.hpp"
+#include "tests/http_server_test_helper.hpp"
 #include "tests/kill_policy_test_helper.hpp"
 
 #ifndef __WINDOWS__
@@ -30,7 +30,7 @@
 #endif
 
 using mesos::internal::tests::ActiveUserTestHelper;
-using mesos::internal::tests::HealthCheckTestHelper;
+using mesos::internal::tests::HttpServerTestHelper;
 #ifndef __WINDOWS__
 using mesos::internal::tests::KillPolicyTestHelper;
 using mesos::internal::tests::MemoryTestHelper;
@@ -51,7 +51,7 @@ int main(int argc, char** argv)
       new CapabilitiesTestHelper(),
       new SetnsTestHelper(),
 #endif
-      new HealthCheckTestHelper(),
+      new HttpServerTestHelper(),
 #ifndef __WINDOWS__
       new KillPolicyTestHelper(),
       new MemoryTestHelper(),