You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by an...@apache.org on 2016/07/07 18:19:57 UTC

[01/11] mesos git commit: Added `FilesError` class.

Repository: mesos
Updated Branches:
  refs/heads/master 6af407510 -> bad1cfa7e


Added `FilesError` class.

`FilesError` class represents the various errors that can be
returned by methods on the `Files` class via a `Try` that
has failed.

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


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

Branch: refs/heads/master
Commit: 73eeb1dffc18ab7fa768eeeba0a3d545503ae20a
Parents: 6af4075
Author: zhou xing <xi...@cn.ibm.com>
Authored: Thu Jul 7 10:52:00 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:01:35 2016 -0700

----------------------------------------------------------------------
 src/files/files.hpp | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/73eeb1df/src/files/files.hpp
----------------------------------------------------------------------
diff --git a/src/files/files.hpp b/src/files/files.hpp
index 06a91a5..790a849 100644
--- a/src/files/files.hpp
+++ b/src/files/files.hpp
@@ -52,6 +52,30 @@ namespace internal {
 class FilesProcess;
 
 
+// Represents the various errors that can be returned by methods on the `Files`
+// class via a `Try` that has failed.
+class FilesError : public Error
+{
+public:
+  enum Type
+  {
+    INVALID,        // Invalid argument.
+    NOT_FOUND,      // Not found.
+    UNAUTHORIZED,   // Not authorized to perform the operation.
+    UNKNOWN         // Internal error/all other errors.
+  };
+
+  FilesError(Type _type)
+    : Error(stringify(_type)), type(_type) {}
+
+  FilesError(Type _type, const std::string& _message)
+    : Error(stringify(_type)), type(_type), message(_message) {}
+
+  Type type;
+  std::string message;
+};
+
+
 // Provides an abstraction for browsing and reading files via HTTP
 // endpoints. A path (file or directory) may be "attached" to a name
 // (similar to "mounting" a device) for subsequent browsing and


[09/11] mesos git commit: Added `evolve()` overload for `FileInfo`.

Posted by an...@apache.org.
Added `evolve()` overload for `FileInfo`.

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


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

Branch: refs/heads/master
Commit: 94302631077bd8417b54d114d5c8d692c37ea8d0
Parents: 6600ebe
Author: Abhishek Dasgupta <a1...@linux.vnet.ibm.com>
Authored: Thu Jul 7 10:52:22 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:06:37 2016 -0700

----------------------------------------------------------------------
 src/internal/evolve.cpp | 6 ++++++
 src/internal/evolve.hpp | 1 +
 2 files changed, 7 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/94302631/src/internal/evolve.cpp
----------------------------------------------------------------------
diff --git a/src/internal/evolve.cpp b/src/internal/evolve.cpp
index bb99cb2..64818cc 100644
--- a/src/internal/evolve.cpp
+++ b/src/internal/evolve.cpp
@@ -162,6 +162,12 @@ v1::MasterInfo evolve(const MasterInfo& masterInfo)
 }
 
 
+v1::FileInfo evolve(const FileInfo& fileInfo)
+{
+  return evolve<v1::FileInfo>(fileInfo);
+}
+
+
 v1::Resource evolve(const Resource& resource)
 {
   return evolve<v1::Resource>(resource);

http://git-wip-us.apache.org/repos/asf/mesos/blob/94302631/src/internal/evolve.hpp
----------------------------------------------------------------------
diff --git a/src/internal/evolve.hpp b/src/internal/evolve.hpp
index 582f347..1e2d49b 100644
--- a/src/internal/evolve.hpp
+++ b/src/internal/evolve.hpp
@@ -69,6 +69,7 @@ v1::TaskInfo evolve(const TaskInfo& taskInfo);
 v1::TaskStatus evolve(const TaskStatus& status);
 v1::Task evolve(const Task& task);
 v1::MasterInfo evolve(const MasterInfo& masterInfo);
+v1::FileInfo evolve(const FileInfo& fileInfo);
 v1::Resource evolve(const Resource& resource);
 
 v1::agent::Response evolve(const mesos::agent::Response& response);


[08/11] mesos git commit: Implemented `LIST_FILES` call in v1 agent API.

Posted by an...@apache.org.
Implemented `LIST_FILES` call in v1 agent API.

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


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

Branch: refs/heads/master
Commit: 6600ebe5697240a2df9ed68d3e4456d2168e9150
Parents: 2238ccf
Author: Abhishek Dasgupta <a1...@linux.vnet.ibm.com>
Authored: Thu Jul 7 10:52:19 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:06:16 2016 -0700

----------------------------------------------------------------------
 include/mesos/agent/agent.proto    |  6 ++--
 include/mesos/v1/agent/agent.proto |  6 ++--
 src/slave/http.cpp                 | 51 ++++++++++++++++++++++++++++++++-
 src/slave/slave.hpp                |  5 ++++
 4 files changed, 63 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/6600ebe5/include/mesos/agent/agent.proto
----------------------------------------------------------------------
diff --git a/include/mesos/agent/agent.proto b/include/mesos/agent/agent.proto
index 538d12f..ef07b1f 100644
--- a/include/mesos/agent/agent.proto
+++ b/include/mesos/agent/agent.proto
@@ -72,6 +72,7 @@ message Call {
     required DurationInfo duration = 2;
   }
 
+  // Provides the file listing for a directory.
   message ListFiles {
     required string path = 1;
   }
@@ -140,8 +141,9 @@ message Response {
     required uint32 level = 1;
   }
 
+  // Contains the file listing(similar to `ls -l`) for a directory.
   message ListFiles {
-    repeated string files = 1;
+    repeated FileInfo file_infos = 1;
   }
 
   message GetFileContents {
@@ -179,4 +181,4 @@ message Response {
   optional GetFileContents get_file_contents = 8;
   optional GetState get_state = 9;
   optional GetContainers get_containers = 10;
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/mesos/blob/6600ebe5/include/mesos/v1/agent/agent.proto
----------------------------------------------------------------------
diff --git a/include/mesos/v1/agent/agent.proto b/include/mesos/v1/agent/agent.proto
index 48f1517..8f84508 100644
--- a/include/mesos/v1/agent/agent.proto
+++ b/include/mesos/v1/agent/agent.proto
@@ -72,6 +72,7 @@ message Call {
     required DurationInfo duration = 2;
   }
 
+  // Provides the file listing for a directory.
   message ListFiles {
     required string path = 1;
   }
@@ -140,8 +141,9 @@ message Response {
     required uint32 level = 1;
   }
 
+  // Contains the file listing(similar to `ls -l`) for a directory.
   message ListFiles {
-    repeated string files = 1;
+    repeated FileInfo file_infos = 1;
   }
 
   message GetFileContents {
@@ -179,4 +181,4 @@ message Response {
   optional GetFileContents get_file_contents = 8;
   optional GetState get_state = 9;
   optional GetContainers get_containers = 10;
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/mesos/blob/6600ebe5/src/slave/http.cpp
----------------------------------------------------------------------
diff --git a/src/slave/http.cpp b/src/slave/http.cpp
index ef2d510..86803fe 100644
--- a/src/slave/http.cpp
+++ b/src/slave/http.cpp
@@ -78,6 +78,7 @@ using process::TLDR;
 using process::http::Accepted;
 using process::http::BadRequest;
 using process::http::Forbidden;
+using process::http::NotFound;
 using process::http::InternalServerError;
 using process::http::MethodNotAllowed;
 using process::http::NotAcceptable;
@@ -378,7 +379,7 @@ Future<Response> Slave::Http::api(
       return setLoggingLevel(call, principal, acceptType);
 
     case agent::Call::LIST_FILES:
-      return NotImplemented();
+      return listFiles(call, principal, acceptType);
 
     case agent::Call::READ_FILE:
       return NotImplemented();
@@ -734,6 +735,54 @@ Future<Response> Slave::Http::setLoggingLevel(
 }
 
 
+Future<Response> Slave::Http::listFiles(
+    const mesos::agent::Call& call,
+    const Option<string>& principal,
+    ContentType contentType) const
+{
+  CHECK_EQ(mesos::agent::Call::LIST_FILES, call.type());
+
+  const string& path = call.list_files().path();
+
+  return slave->files->browse(path, principal)
+    .then([contentType](const Try<list<FileInfo>, FilesError>& result)
+      -> Future<Response> {
+      if (result.isError()) {
+        const FilesError& error = result.error();
+
+        switch (error.type) {
+          case FilesError::Type::INVALID:
+            return BadRequest(error.message);
+
+          case FilesError::Type::UNAUTHORIZED:
+            return Forbidden(error.message);
+
+          case FilesError::Type::NOT_FOUND:
+            return NotFound(error.message);
+
+          case FilesError::Type::UNKNOWN:
+            return InternalServerError(error.message);
+        }
+
+        UNREACHABLE();
+      }
+
+      mesos::agent::Response response;
+      response.set_type(mesos::agent::Response::LIST_FILES);
+
+      mesos::agent::Response::ListFiles* listFiles =
+        response.mutable_list_files();
+
+      foreach (const FileInfo& fileInfo, result.get()) {
+        listFiles->add_file_infos()->CopyFrom(fileInfo);
+      }
+
+      return OK(serialize(contentType, evolve(response)),
+                stringify(contentType));
+    });
+}
+
+
 string Slave::Http::STATE_HELP() {
   return HELP(
     TLDR(

http://git-wip-us.apache.org/repos/asf/mesos/blob/6600ebe5/src/slave/slave.hpp
----------------------------------------------------------------------
diff --git a/src/slave/slave.hpp b/src/slave/slave.hpp
index 6a82c36..a8952f0 100644
--- a/src/slave/slave.hpp
+++ b/src/slave/slave.hpp
@@ -534,6 +534,11 @@ private:
         const Option<std::string>& principal,
         ContentType contentType) const;
 
+    process::Future<process::http::Response> listFiles(
+        const mesos::agent::Call& call,
+        const Option<std::string>& principal,
+        ContentType contentType) const;
+
     process::Future<process::http::Response> getContainers(
         const mesos::agent::Call& call,
         const Option<std::string>& principal,


[10/11] mesos git commit: Added equality(==) operator overload for `FileInfo`.

Posted by an...@apache.org.
Added equality(==) operator overload for `FileInfo`.

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


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

Branch: refs/heads/master
Commit: d9739f1be0e25db281e77b275948136c767df1ea
Parents: 9430263
Author: Abhishek Dasgupta <a1...@linux.vnet.ibm.com>
Authored: Thu Jul 7 10:52:24 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:06:55 2016 -0700

----------------------------------------------------------------------
 include/mesos/v1/mesos.hpp |  1 +
 src/v1/mesos.cpp           | 12 ++++++++++++
 2 files changed, 13 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/d9739f1b/include/mesos/v1/mesos.hpp
----------------------------------------------------------------------
diff --git a/include/mesos/v1/mesos.hpp b/include/mesos/v1/mesos.hpp
index d220966..936af77 100644
--- a/include/mesos/v1/mesos.hpp
+++ b/include/mesos/v1/mesos.hpp
@@ -49,6 +49,7 @@ bool operator==(const Credential& left, const Credential& right);
 bool operator==(const DiscoveryInfo& left, const DiscoveryInfo& right);
 bool operator==(const Environment& left, const Environment& right);
 bool operator==(const ExecutorInfo& left, const ExecutorInfo& right);
+bool operator==(const FileInfo& left, const FileInfo& right);
 bool operator==(const Label& left, const Label& right);
 bool operator==(const Labels& left, const Labels& right);
 bool operator==(const MasterInfo& left, const MasterInfo& right);

http://git-wip-us.apache.org/repos/asf/mesos/blob/d9739f1b/src/v1/mesos.cpp
----------------------------------------------------------------------
diff --git a/src/v1/mesos.cpp b/src/v1/mesos.cpp
index 30788dc..c6a8799 100644
--- a/src/v1/mesos.cpp
+++ b/src/v1/mesos.cpp
@@ -318,6 +318,18 @@ bool operator==(const ExecutorInfo& left, const ExecutorInfo& right)
 }
 
 
+bool operator==(const FileInfo& left, const FileInfo& right)
+{
+  return left.path() == right.path() &&
+    left.nlink() == right.nlink() &&
+    left.size() == right.size() &&
+    left.mtime() == right.mtime() &&
+    left.mode() == right.mode() &&
+    left.uid() == right.uid() &&
+    left.gid() == right.gid();
+}
+
+
 bool operator==(const MasterInfo& left, const MasterInfo& right)
 {
   return left.id() == right.id() &&


[02/11] mesos git commit: Added a helper function to construct `FileInfo` protobuf message.

Posted by an...@apache.org.
Added a helper function to construct `FileInfo` protobuf message.

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


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

Branch: refs/heads/master
Commit: e36e71a9cec74698e4173bc308abc95e3427b01b
Parents: 73eeb1d
Author: Abhishek Dasgupta <a1...@linux.vnet.ibm.com>
Authored: Thu Jul 7 10:52:03 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:02:11 2016 -0700

----------------------------------------------------------------------
 src/common/protobuf_utils.cpp | 43 ++++++++++++++++++++++++++++++++++++++
 src/common/protobuf_utils.hpp |  6 ++++++
 2 files changed, 49 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/e36e71a9/src/common/protobuf_utils.cpp
----------------------------------------------------------------------
diff --git a/src/common/protobuf_utils.cpp b/src/common/protobuf_utils.cpp
index a2885d0..8c4a726 100644
--- a/src/common/protobuf_utils.cpp
+++ b/src/common/protobuf_utils.cpp
@@ -14,6 +14,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#ifdef __WINDOWS__
+#include <stout/internal/windows/grp.hpp>
+#include <stout/internal/windows/pwd.hpp>
+#else
+#include <grp.h>
+#include <pwd.h>
+#endif // __WINDOWS__
+
 #include <mesos/slave/isolator.hpp>
 
 #include <mesos/type_utils.hpp>
@@ -22,11 +30,18 @@
 #include <process/pid.hpp>
 
 #include <stout/adaptor.hpp>
+#include <stout/duration.hpp>
 #include <stout/foreach.hpp>
 #include <stout/net.hpp>
 #include <stout/stringify.hpp>
 #include <stout/uuid.hpp>
 
+#include <stout/os/permissions.hpp>
+
+#ifdef __WINDOWS__
+#include <stout/windows.hpp>
+#endif // __WINDOWS__
+
 #include "common/protobuf_utils.hpp"
 
 #include "messages/messages.hpp"
@@ -301,6 +316,34 @@ TimeInfo getCurrentTime()
   return timeInfo;
 }
 
+
+FileInfo createFileInfo(const string& path, const struct stat& s)
+{
+  FileInfo file;
+  file.set_path(path);
+  file.set_nlink(s.st_nlink);
+  file.set_size(s.st_size);
+  file.mutable_mtime()->set_nanoseconds(Seconds((s.st_mtime)).ns());
+  file.set_mode(s.st_mode);
+
+  // NOTE: `getpwuid` and `getgrgid` return `nullptr` on Windows.
+  passwd* p = getpwuid(s.st_uid);
+  if (p != nullptr) {
+    file.set_uid(p->pw_name);
+  } else {
+    file.set_uid(stringify(s.st_uid));
+  }
+
+  struct group* g = getgrgid(s.st_gid);
+  if (g != nullptr) {
+    file.set_gid(g->gr_name);
+  } else {
+    file.set_gid(stringify(s.st_gid));
+  }
+
+  return file;
+}
+
 namespace slave {
 
 ContainerLimitation createContainerLimitation(

http://git-wip-us.apache.org/repos/asf/mesos/blob/e36e71a9/src/common/protobuf_utils.hpp
----------------------------------------------------------------------
diff --git a/src/common/protobuf_utils.hpp b/src/common/protobuf_utils.hpp
index cb02022..3324838 100644
--- a/src/common/protobuf_utils.hpp
+++ b/src/common/protobuf_utils.hpp
@@ -20,6 +20,8 @@
 #include <initializer_list>
 #include <string>
 
+#include <sys/stat.h>
+
 #include <mesos/mesos.hpp>
 
 #include <mesos/maintenance/maintenance.hpp>
@@ -105,6 +107,10 @@ Label createLabel(
 // Helper function that fills in a TimeInfo from the current time.
 TimeInfo getCurrentTime();
 
+
+// Helper function that creates a `FileInfo` from data returned by `stat()`.
+FileInfo createFileInfo(const std::string& path, const struct stat& s);
+
 namespace slave {
 
 mesos::slave::ContainerLimitation createContainerLimitation(


[06/11] mesos git commit: Removed `jsonFileInfo()` implementation from files.hpp.

Posted by an...@apache.org.
Removed `jsonFileInfo()` implementation from files.hpp.

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


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

Branch: refs/heads/master
Commit: 74edde66a60e38b3d90fa11479be85ed3cb1b4ac
Parents: 7d00e1c
Author: Abhishek Dasgupta <a1...@linux.vnet.ibm.com>
Authored: Thu Jul 7 10:52:13 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:05:32 2016 -0700

----------------------------------------------------------------------
 src/files/files.hpp | 74 ------------------------------------------------
 1 file changed, 74 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/74edde66/src/files/files.hpp
----------------------------------------------------------------------
diff --git a/src/files/files.hpp b/src/files/files.hpp
index e28136a..c36ecfb 100644
--- a/src/files/files.hpp
+++ b/src/files/files.hpp
@@ -98,80 +98,6 @@ private:
   FilesProcess* process;
 };
 
-
-// Returns our JSON representation of a file or directory.
-// The JSON contains all of the information one would find in ls -l.
-// Example JSON:
-// {
-//   'path': '\/some\/file',
-//   'mode': '-rwxrwxrwx',
-//   'nlink': 5,
-//   'uid': 'bmahler',
-//   'gid': 'employee',
-//   'size': 4096,           // Bytes.
-//   'mtime': 1348258116,    // Unix timestamp.
-// }
-inline JSON::Object jsonFileInfo(const std::string& path,
-                                 const struct stat& s)
-{
-  JSON::Object file;
-  file.values["path"] = path;
-  file.values["nlink"] = s.st_nlink;
-  file.values["size"] = s.st_size;
-  file.values["mtime"] = s.st_mtime;
-
-  char filetype;
-  if (S_ISREG(s.st_mode)) {
-    filetype = '-';
-  } else if (S_ISDIR(s.st_mode)) {
-    filetype = 'd';
-  } else if (S_ISCHR(s.st_mode)) {
-    filetype = 'c';
-  } else if (S_ISBLK(s.st_mode)) {
-    filetype = 'b';
-  } else if (S_ISFIFO(s.st_mode)) {
-    filetype = 'p';
-  } else if (S_ISLNK(s.st_mode)) {
-    filetype = 'l';
-  } else if (S_ISSOCK(s.st_mode)) {
-    filetype = 's';
-  } else {
-    filetype = '-';
-  }
-
-  struct os::Permissions permissions(s.st_mode);
-
-  file.values["mode"] = strings::format(
-      "%c%c%c%c%c%c%c%c%c%c",
-      filetype,
-      permissions.owner.r ? 'r' : '-',
-      permissions.owner.w ? 'w' : '-',
-      permissions.owner.x ? 'x' : '-',
-      permissions.group.r ? 'r' : '-',
-      permissions.group.w ? 'w' : '-',
-      permissions.group.x ? 'x' : '-',
-      permissions.others.r ? 'r' : '-',
-      permissions.others.w ? 'w' : '-',
-      permissions.others.x ? 'x' : '-').get();
-
-  // NOTE: `getpwuid` and `getgrgid` return `nullptr` on Windows.
-  passwd* p = getpwuid(s.st_uid);
-  if (p != nullptr) {
-    file.values["uid"] = p->pw_name;
-  } else {
-    file.values["uid"] = stringify(s.st_uid);
-  }
-
-  struct group* g = getgrgid(s.st_gid);
-  if (g != nullptr) {
-    file.values["gid"] = g->gr_name;
-  } else {
-    file.values["gid"] = stringify(s.st_gid);
-  }
-
-  return file;
-}
-
 } // namespace internal {
 } // namespace mesos {
 


[04/11] mesos git commit: Updated `FilesProcess` to support `LIST_FILES` Call in Operator API v1.

Posted by an...@apache.org.
Updated `FilesProcess` to support `LIST_FILES` Call in Operator API v1.

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


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

Branch: refs/heads/master
Commit: 7d124a4a840c157394a53b36f5a560ef7f21e8f0
Parents: 4d26ead
Author: Abhishek Dasgupta <a1...@linux.vnet.ibm.com>
Authored: Thu Jul 7 10:52:08 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:03:31 2016 -0700

----------------------------------------------------------------------
 src/files/files.cpp       | 133 +++++++++++++++++++++++++++--------------
 src/files/files.hpp       |  21 +++----
 src/tests/files_tests.cpp |  11 ++--
 3 files changed, 101 insertions(+), 64 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/7d124a4a/src/files/files.cpp
----------------------------------------------------------------------
diff --git a/src/files/files.cpp b/src/files/files.cpp
index 0368f67..44fe1ac 100644
--- a/src/files/files.cpp
+++ b/src/files/files.cpp
@@ -102,6 +102,10 @@ public:
 
   void detach(const string& name);
 
+  Future<Try<list<FileInfo>, FilesError>> browse(
+    const string& path,
+    const Option<string>& principal);
+
 protected:
   virtual void initialize();
 
@@ -121,15 +125,11 @@ private:
   // Requests have the following parameters:
   //   path: The directory to browse. Required.
   // The response will contain a list of JSON files and directories contained
-  // in the path (see files::jsonFileInfo for the format).
-  Future<Response> browse(
+  // in the path (see `FileInfo` model override for the format).
+  Future<Response> _browse(
       const Request& request,
       const Option<string>& principal);
 
-  Future<Response> _browse(
-      const string& path,
-      const Option<string>& jsonp);
-
   // Reads data from a file at a given offset and for a given length.
   // See the jquery pailer for the expected behavior.
   Future<Response> read(
@@ -195,7 +195,7 @@ void FilesProcess::initialize()
     route("/browse.json",
           authenticationRealm.get(),
           FilesProcess::BROWSE_HELP,
-          &FilesProcess::browse);
+          &FilesProcess::_browse);
     route("/read.json",
           authenticationRealm.get(),
           FilesProcess::READ_HELP,
@@ -212,7 +212,7 @@ void FilesProcess::initialize()
     route("/browse",
           authenticationRealm.get(),
           FilesProcess::BROWSE_HELP,
-          &FilesProcess::browse);
+          &FilesProcess::_browse);
     route("/read",
           authenticationRealm.get(),
           FilesProcess::READ_HELP,
@@ -230,7 +230,7 @@ void FilesProcess::initialize()
     // deprecation cycle on 0.26.
     route("/browse.json",
           FilesProcess::BROWSE_HELP,
-          lambda::bind(&FilesProcess::browse, this, lambda::_1, None()));
+          lambda::bind(&FilesProcess::_browse, this, lambda::_1, None()));
     route("/read.json",
           FilesProcess::READ_HELP,
           lambda::bind(&FilesProcess::read, this, lambda::_1, None()));
@@ -243,7 +243,7 @@ void FilesProcess::initialize()
 
     route("/browse",
           FilesProcess::BROWSE_HELP,
-          lambda::bind(&FilesProcess::browse, this, lambda::_1, None()));
+          lambda::bind(&FilesProcess::_browse, this, lambda::_1, None()));
     route("/read",
           FilesProcess::READ_HELP,
           lambda::bind(&FilesProcess::read, this, lambda::_1, None()));
@@ -349,7 +349,8 @@ Future<bool> FilesProcess::authorize(
   return true;
 }
 
-Future<Response> FilesProcess::browse(
+
+Future<Response> FilesProcess::_browse(
     const Request& request,
     const Option<string>& principal)
 {
@@ -362,54 +363,86 @@ Future<Response> FilesProcess::browse(
   string requestedPath = path.get();
   Option<string> jsonp = request.url.query.get("jsonp");
 
-  return authorize(requestedPath, principal)
-    .then(defer(self(),
-        [this, path, jsonp](bool authorized) -> Future<Response> {
-      if (authorized) {
-        return _browse(path.get(), jsonp);
+  return browse(requestedPath, principal)
+  .then([jsonp](const Try<list<FileInfo>, FilesError>& result)
+    -> Future<http::Response> {
+    if (result.isError()) {
+      const FilesError& error = result.error();
+
+      switch (error.type) {
+        case FilesError::Type::INVALID:
+          return BadRequest(error.message);
+
+        case FilesError::Type::NOT_FOUND:
+          return NotFound(error.message);
+
+        case FilesError::Type::UNAUTHORIZED:
+          return Forbidden(error.message);
+
+        case FilesError::Type::UNKNOWN:
+          return InternalServerError(error.message);
       }
 
-      return Forbidden();
-    }));
+      UNREACHABLE();
+    }
+
+    JSON::Array listing;
+    foreach (const FileInfo& fileInfo, result.get()) {
+      listing.values.push_back(model(fileInfo));
+    }
+
+    return OK(listing, jsonp);
+  });
 }
 
 
-Future<Response> FilesProcess::_browse(
+Future<Try<list<FileInfo>, FilesError>> FilesProcess::browse(
     const string& path,
-    const Option<string>& jsonp)
+    const Option<string>& principal)
 {
-  Result<string> resolvedPath = resolve(path);
+  return authorize(path, principal)
+    .then(defer(self(),
+        [this, path](bool authorized)
+          -> Future<Try<list<FileInfo>, FilesError>> {
+      if (!authorized) {
+        return FilesError(FilesError::Type::UNAUTHORIZED);
+      }
 
-  if (resolvedPath.isError()) {
-    return InternalServerError(resolvedPath.error() + ".\n");
-  } else if (resolvedPath.isNone()) {
-    return NotFound();
-  }
+      Result<string> resolvedPath = resolve(path);
 
-  // The result will be a sorted (on path) array of files and dirs:
-  // [{"name": "README", "path": "dir/README" "dir":False, "size":42}, ...]
-  map<string, JSON::Object> files;
-  Try<list<string> > entries = os::ls(resolvedPath.get());
-  if (entries.isSome()) {
-    foreach (const string& entry, entries.get()) {
-      struct stat s;
-      string fullPath = path::join(resolvedPath.get(), entry);
-
-      if (stat(fullPath.c_str(), &s) < 0) {
-        PLOG(WARNING) << "Found " << fullPath << " in ls but stat failed";
-        continue;
+      if (resolvedPath.isError()) {
+        return FilesError(
+            FilesError::Type::INVALID,
+            resolvedPath.error() + ".\n");
+      } else if (resolvedPath.isNone()) {
+        return FilesError(FilesError::Type::NOT_FOUND);
       }
 
-      files[fullPath] = jsonFileInfo(path::join(path, entry), s);
-    }
-  }
+      // The result will be a sorted (on path) list of files and dirs.
+      map<string, FileInfo> files;
+      Try<list<string> > entries = os::ls(resolvedPath.get());
+      if (entries.isSome()) {
+        foreach (const string& entry, entries.get()) {
+          struct stat s;
+          string fullPath = path::join(resolvedPath.get(), entry);
+
+          if (stat(fullPath.c_str(), &s) < 0) {
+            PLOG(WARNING) << "Found " << fullPath << " in ls but stat failed";
+            continue;
+          }
 
-  JSON::Array listing;
-  foreachvalue (const JSON::Object& file, files) {
-    listing.values.push_back(file);
-  }
+          files[fullPath] =
+            protobuf::createFileInfo(path::join(path, entry), s);
+        }
+      }
+
+      list<FileInfo> listing;
+      foreachvalue (const FileInfo& fileInfo, files) {
+        listing.push_back(fileInfo);
+      }
 
-  return OK(listing, jsonp);
+      return listing;
+    }));
 }
 
 
@@ -835,5 +868,13 @@ void Files::detach(const string& name)
   dispatch(process, &FilesProcess::detach, name);
 }
 
+
+Future<Try<list<FileInfo>, FilesError>> Files::browse(
+    const string& path,
+    const Option<string>& principal)
+{
+  return dispatch(process, &FilesProcess::browse, path, principal);
+}
+
 } // namespace internal {
 } // namespace mesos {

http://git-wip-us.apache.org/repos/asf/mesos/blob/7d124a4a/src/files/files.hpp
----------------------------------------------------------------------
diff --git a/src/files/files.hpp b/src/files/files.hpp
index 790a849..e28136a 100644
--- a/src/files/files.hpp
+++ b/src/files/files.hpp
@@ -17,16 +17,6 @@
 #ifndef __FILES_HPP__
 #define __FILES_HPP__
 
-#ifdef __WINDOWS__
-#include <stout/internal/windows/grp.hpp>
-#include <stout/internal/windows/pwd.hpp>
-#else
-#include <grp.h>
-#include <pwd.h>
-#endif // __WINDOWS__
-
-#include <sys/stat.h>
-
 #include <string>
 
 #include <mesos/authorizer/authorizer.hpp>
@@ -39,11 +29,9 @@
 #include <stout/nothing.hpp>
 #include <stout/path.hpp>
 
-#include <stout/os/permissions.hpp>
+#include "common/protobuf_utils.hpp"
 
-#ifdef __WINDOWS__
-#include <stout/windows.hpp>
-#endif // __WINDOWS__
+#include "mesos/mesos.hpp"
 
 namespace mesos {
 namespace internal {
@@ -101,6 +89,11 @@ public:
   // Removes the specified name.
   void detach(const std::string& name);
 
+  // Returns a file listing for a directory similar to `ls -l`.
+  process::Future<Try<std::list<FileInfo>, FilesError>> browse(
+      const std::string& path,
+      const Option<std::string>& principal);
+
 private:
   FilesProcess* process;
 };

http://git-wip-us.apache.org/repos/asf/mesos/blob/7d124a4a/src/tests/files_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/files_tests.cpp b/src/tests/files_tests.cpp
index a30e452..78719da 100644
--- a/src/tests/files_tests.cpp
+++ b/src/tests/files_tests.cpp
@@ -33,6 +33,9 @@
 
 #include <stout/tests/utils.hpp>
 
+#include "common/http.hpp"
+#include "common/protobuf_utils.hpp"
+
 #include "files/files.hpp"
 
 #include "tests/mesos.hpp"
@@ -331,13 +334,13 @@ TEST_F(FilesTest, BrowseTest)
   struct stat s;
   JSON::Array expected;
   ASSERT_EQ(0, stat("1/2", &s));
-  expected.values.push_back(jsonFileInfo("one/2", s));
+  expected.values.push_back(model(protobuf::createFileInfo("one/2", s)));
   ASSERT_EQ(0, stat("1/3", &s));
-  expected.values.push_back(jsonFileInfo("one/3", s));
+  expected.values.push_back(model(protobuf::createFileInfo("one/3", s)));
   ASSERT_EQ(0, stat("1/three", &s));
-  expected.values.push_back(jsonFileInfo("one/three", s));
+  expected.values.push_back(model(protobuf::createFileInfo("one/three", s)));
   ASSERT_EQ(0, stat("1/two", &s));
-  expected.values.push_back(jsonFileInfo("one/two", s));
+  expected.values.push_back(model(protobuf::createFileInfo("one/two", s)));
 
   Future<Response> response =
       process::http::get(upid, "browse", "path=one/");


[05/11] mesos git commit: Used namespace alias for 'process::http'.

Posted by an...@apache.org.
Used namespace alias for 'process::http'.

This is needed since `mesos::Request` collides with the libprocess
`process::http::Request` class.

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


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

Branch: refs/heads/master
Commit: 7d00e1c1e3d18f30462733fbb0b7b6d9b97e34ba
Parents: 7d124a4
Author: Abhishek Dasgupta <a1...@linux.vnet.ibm.com>
Authored: Thu Jul 7 10:52:10 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:04:11 2016 -0700

----------------------------------------------------------------------
 src/files/files.cpp | 73 ++++++++++++++++++++++++++----------------------
 1 file changed, 39 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/7d00e1c1/src/files/files.cpp
----------------------------------------------------------------------
diff --git a/src/files/files.cpp b/src/files/files.cpp
index 44fe1ac..8b04ff2 100644
--- a/src/files/files.cpp
+++ b/src/files/files.cpp
@@ -59,23 +59,30 @@
 
 #include "logging/logging.hpp"
 
-using namespace process;
+namespace http = process::http;
+
+using http::BadRequest;
+using http::Forbidden;
+using http::InternalServerError;
+using http::NotFound;
+using http::OK;
+
+namespace io = process::io;
+namespace mime = process::mime;
 
 using mesos::Authorizer;
 
 using process::AUTHENTICATION;
 using process::AUTHORIZATION;
+using process::defer;
 using process::DESCRIPTION;
+using process::Failure;
+using process::Future;
 using process::HELP;
+using process::Process;
 using process::TLDR;
 using process::wait; // Necessary on some OS's to disambiguate.
 
-using process::http::BadRequest;
-using process::http::Forbidden;
-using process::http::InternalServerError;
-using process::http::NotFound;
-using process::http::OK;
-
 using std::list;
 using std::map;
 using std::string;
@@ -84,9 +91,6 @@ using std::vector;
 namespace mesos {
 namespace internal {
 
-using process::http::Response;
-using process::http::Request;
-
 class FilesProcess : public Process<FilesProcess>
 {
 public:
@@ -126,17 +130,17 @@ private:
   //   path: The directory to browse. Required.
   // The response will contain a list of JSON files and directories contained
   // in the path (see `FileInfo` model override for the format).
-  Future<Response> _browse(
-      const Request& request,
+  Future<http::Response> _browse(
+      const http::Request& request,
       const Option<string>& principal);
 
   // Reads data from a file at a given offset and for a given length.
   // See the jquery pailer for the expected behavior.
-  Future<Response> read(
-      const Request& request,
+  Future<http::Response> read(
+      const http::Request& request,
       const Option<string>& principal);
 
-  Future<Response> _read(
+  Future<http::Response> _read(
       off_t offset,
       Option<size_t> length,
       const string& path,
@@ -145,15 +149,15 @@ private:
   // Returns the raw file contents for a given path.
   // Requests have the following parameters:
   //   path: The directory to browse. Required.
-  Future<Response> download(
-      const Request& request,
+  Future<http::Response> download(
+      const http::Request& request,
       const Option<string>& principal);
 
-  Future<Response> _download(const string& path);
+  Future<http::Response> _download(const string& path);
 
   // Returns the internal virtual path mapping.
-  Future<Response> debug(
-      const Request& request,
+  Future<http::Response> debug(
+      const http::Request& request,
       const Option<string>& principal);
 
   const static string BROWSE_HELP;
@@ -350,8 +354,8 @@ Future<bool> FilesProcess::authorize(
 }
 
 
-Future<Response> FilesProcess::_browse(
-    const Request& request,
+Future<http::Response> FilesProcess::_browse(
+    const http::Request& request,
     const Option<string>& principal)
 {
   Option<string> path = request.url.query.get("path");
@@ -447,7 +451,7 @@ Future<Try<list<FileInfo>, FilesError>> FilesProcess::browse(
 
 
 // TODO(benh): Remove 'const &' from size after fixing libprocess.
-Future<Response> __read(int fd,
+Future<http::Response> __read(int fd,
                        const size_t& size,
                        off_t offset,
                        const boost::shared_array<char>& data,
@@ -486,8 +490,8 @@ const string FilesProcess::READ_HELP = HELP(
         "See authorization documentation for details."));
 
 
-Future<Response> FilesProcess::read(
-    const Request& request,
+Future<http::Response> FilesProcess::read(
+    const http::Request& request,
     const Option<string>& principal)
 {
   Option<string> path = request.url.query.get("path");
@@ -539,7 +543,7 @@ Future<Response> FilesProcess::read(
   return authorize(requestedPath, principal)
     .then(defer(self(),
         [this, offset, length, path, jsonp](bool authorized)
-          -> Future<Response> {
+          -> Future<http::Response> {
       if (authorized) {
         return _read(offset, length, path.get(), jsonp);
       }
@@ -549,7 +553,7 @@ Future<Response> FilesProcess::read(
 }
 
 
-Future<Response> FilesProcess::_read(
+Future<http::Response> FilesProcess::_read(
     off_t offset,
     Option<size_t> length,
     const string& path,
@@ -672,8 +676,8 @@ const string FilesProcess::DOWNLOAD_HELP = HELP(
         "See authorization documentation for details."));
 
 
-Future<Response> FilesProcess::download(
-    const Request& request,
+Future<http::Response> FilesProcess::download(
+    const http::Request& request,
     const Option<string>& principal)
 {
   Option<string> path = request.url.query.get("path");
@@ -686,7 +690,7 @@ Future<Response> FilesProcess::download(
 
   return authorize(requestedPath, principal)
     .then(defer(self(),
-        [this, path](bool authorized) -> Future<Response> {
+        [this, path](bool authorized) -> Future<http::Response> {
       if (authorized) {
         return _download(path.get());
       }
@@ -696,7 +700,7 @@ Future<Response> FilesProcess::download(
 }
 
 
-Future<Response> FilesProcess::_download(const string& path)
+Future<http::Response> FilesProcess::_download(const string& path)
 {
   Result<string> resolvedPath = resolve(path);
 
@@ -743,8 +747,8 @@ const string FilesProcess::DEBUG_HELP = HELP(
         "See the authorization documentation for details."));
 
 
-Future<Response> FilesProcess::debug(
-    const Request& request,
+Future<http::Response> FilesProcess::debug(
+    const http::Request& request,
     const Option<string>&  principal )
 {
   JSON::Object object;
@@ -759,7 +763,8 @@ Future<Response> FilesProcess::debug(
       request.method,
       authorizer,
       principal)
-    .then(defer([object, jsonp](bool authorized) -> Future<Response> {
+    .then(defer([object, jsonp](bool authorized)
+                  -> Future<http::Response> {
           if (!authorized) {
             return Forbidden();
           }


[11/11] mesos git commit: Added testcases for `LIST_FILES` call for v1 Operator API.

Posted by an...@apache.org.
Added testcases for `LIST_FILES` call for v1 Operator API.

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


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

Branch: refs/heads/master
Commit: bad1cfa7e0684e2be6542fdb7dd8d0b056554940
Parents: d9739f1
Author: Abhishek Dasgupta <a1...@linux.vnet.ibm.com>
Authored: Thu Jul 7 10:52:27 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:07:15 2016 -0700

----------------------------------------------------------------------
 src/tests/api_tests.cpp | 143 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 143 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/bad1cfa7/src/tests/api_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/api_tests.cpp b/src/tests/api_tests.cpp
index 7cf716d..4cb7072 100644
--- a/src/tests/api_tests.cpp
+++ b/src/tests/api_tests.cpp
@@ -69,6 +69,7 @@ using process::Future;
 using process::Owned;
 
 using process::http::Accepted;
+using process::http::NotFound;
 using process::http::OK;
 using process::http::Pipe;
 using process::http::Response;
@@ -779,6 +780,68 @@ TEST_P(MasterAPITest, SetLoggingLevel)
 }
 
 
+// This test verifies if we can retrieve the file listing for a directory
+// in the master.
+TEST_P(MasterAPITest, ListFiles)
+{
+  Files files;
+
+  ASSERT_SOME(os::mkdir("1/2"));
+  ASSERT_SOME(os::mkdir("1/3"));
+  ASSERT_SOME(os::write("1/two", "two"));
+
+  AWAIT_EXPECT_READY(files.attach("1", "one"));
+
+  // Get the `FileInfo` for "1/two" file.
+  struct stat s;
+  ASSERT_EQ(0, stat("1/two", &s));
+  FileInfo file = protobuf::createFileInfo("one/two", s);
+
+  Try<Owned<cluster::Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  v1::master::Call v1Call;
+  v1Call.set_type(v1::master::Call::LIST_FILES);
+  v1Call.mutable_list_files()->set_path("one/");
+
+  ContentType contentType = GetParam();
+
+  Future<v1::master::Response> v1Response =
+    post(master.get()->pid, v1Call, contentType);
+
+  AWAIT_READY(v1Response);
+  ASSERT_TRUE(v1Response.get().IsInitialized());
+  ASSERT_EQ(v1::master::Response::LIST_FILES, v1Response.get().type());
+  ASSERT_EQ(3, v1Response.get().list_files().file_infos().size());
+  ASSERT_EQ(internal::evolve(file),
+            v1Response.get().list_files().file_infos(2));
+}
+
+
+// This test verifies that the client will receive a `NotFound` response when it
+// tries to make a `LIST_FILES` call with an invalid path.
+TEST_P(MasterAPITest, ListFilesInvalidPath)
+{
+  Try<Owned<cluster::Master>> master = StartMaster();
+  ASSERT_SOME(master);
+
+  v1::master::Call v1Call;
+  v1Call.set_type(v1::master::Call::LIST_FILES);
+  v1Call.mutable_list_files()->set_path("five/");
+
+  ContentType contentType = GetParam();
+
+  Future<Response> response = process::http::post(
+    master.get()->pid,
+    "api/v1",
+    createBasicAuthHeaders(DEFAULT_CREDENTIAL),
+    serialize(contentType, v1Call),
+    stringify(contentType));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(NotFound().status, response);
+}
+
+
 TEST_P(MasterAPITest, GetRoles)
 {
   master::Flags masterFlags = CreateMasterFlags();
@@ -2154,6 +2217,86 @@ TEST_P(AgentAPITest, SetLoggingLevel)
 }
 
 
+// This test verifies if we can retrieve the file listing for a directory
+// in an agent.
+TEST_P(AgentAPITest, ListFiles)
+{
+  Files files;
+
+  ASSERT_SOME(os::mkdir("1/2"));
+  ASSERT_SOME(os::mkdir("1/3"));
+  ASSERT_SOME(os::write("1/two", "two"));
+
+  AWAIT_EXPECT_READY(files.attach("1", "one"));
+
+  // Get the `FileInfo` for "1/two" file.
+  struct stat s;
+  ASSERT_EQ(0, stat("1/two", &s));
+  FileInfo file = protobuf::createFileInfo("one/two", s);
+
+  Future<Nothing> __recover = FUTURE_DISPATCH(_, &Slave::__recover);
+
+  StandaloneMasterDetector detector;
+  Try<Owned<cluster::Slave>> slave = StartSlave(&detector);
+  ASSERT_SOME(slave);
+
+  AWAIT_READY(__recover);
+
+  // Wait until the agent has finished recovery.
+  Clock::pause();
+  Clock::settle();
+
+  v1::agent::Call v1Call;
+  v1Call.set_type(v1::agent::Call::LIST_FILES);
+  v1Call.mutable_list_files()->set_path("one/");
+
+  ContentType contentType = GetParam();
+
+  Future<v1::agent::Response> v1Response =
+    post(slave.get()->pid, v1Call, contentType);
+
+  AWAIT_READY(v1Response);
+  ASSERT_TRUE(v1Response.get().IsInitialized());
+  ASSERT_EQ(v1::agent::Response::LIST_FILES, v1Response.get().type());
+  ASSERT_EQ(3, v1Response.get().list_files().file_infos().size());
+  ASSERT_EQ(internal::evolve(file),
+            v1Response.get().list_files().file_infos(2));
+}
+
+
+// This test verifies that the client will receive a `NotFound` response when it
+// tries to make a `LIST_FILES` call with an invalid path.
+TEST_P(AgentAPITest, ListFilesInvalidPath)
+{
+  Future<Nothing> __recover = FUTURE_DISPATCH(_, &Slave::__recover);
+
+  StandaloneMasterDetector detector;
+  Try<Owned<cluster::Slave>> slave = StartSlave(&detector);
+  ASSERT_SOME(slave);
+
+  AWAIT_READY(__recover);
+
+  // Wait until the agent has finished recovery.
+  Clock::pause();
+  Clock::settle();
+
+  v1::agent::Call v1Call;
+  v1Call.set_type(v1::agent::Call::LIST_FILES);
+  v1Call.mutable_list_files()->set_path("five/");
+
+  ContentType contentType = GetParam();
+
+  Future<Response> response = process::http::post(
+    slave.get()->pid,
+    "api/v1",
+    createBasicAuthHeaders(DEFAULT_CREDENTIAL),
+    serialize(contentType, v1Call),
+    stringify(contentType));
+
+  AWAIT_EXPECT_RESPONSE_STATUS_EQ(NotFound().status, response);
+}
+
+
 TEST_P(AgentAPITest, GetContainers)
 {
   Try<Owned<cluster::Master>> master = StartMaster();


[07/11] mesos git commit: Implemented `LIST_FILES` call in v1 master API.

Posted by an...@apache.org.
Implemented `LIST_FILES` call in v1 master API.

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


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

Branch: refs/heads/master
Commit: 2238ccf50211bd4b9606979f9cce8560dace1bf3
Parents: 74edde6
Author: Abhishek Dasgupta <a1...@linux.vnet.ibm.com>
Authored: Thu Jul 7 10:52:15 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:05:43 2016 -0700

----------------------------------------------------------------------
 include/mesos/master/master.proto    |  4 ++-
 include/mesos/v1/master/master.proto |  4 ++-
 src/master/http.cpp                  | 52 +++++++++++++++++++++++++++++--
 src/master/master.hpp                |  5 +++
 4 files changed, 61 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/2238ccf5/include/mesos/master/master.proto
----------------------------------------------------------------------
diff --git a/include/mesos/master/master.proto b/include/mesos/master/master.proto
index 236a286..d82b245 100644
--- a/include/mesos/master/master.proto
+++ b/include/mesos/master/master.proto
@@ -108,6 +108,7 @@ message Call {
     required DurationInfo duration = 2;
   }
 
+  // Provides the file listing for a directory.
   message ListFiles {
     required string path = 1;
   }
@@ -261,8 +262,9 @@ message Response {
     required uint32 level = 1;
   }
 
+  // Contains the file listing(similar to `ls -l`) for a directory.
   message ListFiles {
-    repeated string files = 1;
+    repeated FileInfo file_infos = 1;
   }
 
   message GetFileContents {

http://git-wip-us.apache.org/repos/asf/mesos/blob/2238ccf5/include/mesos/v1/master/master.proto
----------------------------------------------------------------------
diff --git a/include/mesos/v1/master/master.proto b/include/mesos/v1/master/master.proto
index 55eb2d8..711a664 100644
--- a/include/mesos/v1/master/master.proto
+++ b/include/mesos/v1/master/master.proto
@@ -108,6 +108,7 @@ message Call {
     required DurationInfo duration = 2;
   }
 
+  // Provides the file listing for a directory.
   message ListFiles {
     required string path = 1;
   }
@@ -262,8 +263,9 @@ message Response {
     required uint32 level = 1;
   }
 
+  // Contains the file listing(similar to `ls -l`) for a directory.
   message ListFiles {
-    repeated string files = 1;
+    repeated FileInfo file_infos = 1;
   }
 
   message GetFileContents {

http://git-wip-us.apache.org/repos/asf/mesos/blob/2238ccf5/src/master/http.cpp
----------------------------------------------------------------------
diff --git a/src/master/http.cpp b/src/master/http.cpp
index bff1fd5..8b7e917 100644
--- a/src/master/http.cpp
+++ b/src/master/http.cpp
@@ -517,7 +517,7 @@ Future<Response> Master::Http::api(
       return setLoggingLevel(call, principal, acceptType);
 
     case mesos::master::Call::LIST_FILES:
-      return NotImplemented();
+      return listFiles(call, principal, acceptType);
 
     case mesos::master::Call::READ_FILE:
       return NotImplemented();
@@ -3237,6 +3237,54 @@ Future<Response> Master::Http::roles(
 }
 
 
+Future<Response> Master::Http::listFiles(
+    const mesos::master::Call& call,
+    const Option<string>& principal,
+    ContentType contentType) const
+{
+  CHECK_EQ(mesos::master::Call::LIST_FILES, call.type());
+
+  const string& path = call.list_files().path();
+
+  return master->files->browse(path, principal)
+    .then([contentType](const Try<list<FileInfo>, FilesError>& result)
+      -> Future<Response> {
+      if (result.isError()) {
+        const FilesError& error = result.error();
+
+        switch (error.type) {
+          case FilesError::Type::INVALID:
+            return BadRequest(error.message);
+
+          case FilesError::Type::UNAUTHORIZED:
+            return Forbidden(error.message);
+
+          case FilesError::Type::NOT_FOUND:
+            return NotFound(error.message);
+
+          case FilesError::Type::UNKNOWN:
+            return InternalServerError(error.message);
+        }
+
+        UNREACHABLE();
+      }
+
+      mesos::master::Response response;
+      response.set_type(mesos::master::Response::LIST_FILES);
+
+      mesos::master::Response::ListFiles* listFiles =
+        response.mutable_list_files();
+
+      foreach (const FileInfo& fileInfo, result.get()) {
+        listFiles->add_file_infos()->CopyFrom(fileInfo);
+      }
+
+      return OK(serialize(contentType, evolve(response)),
+                stringify(contentType));
+    });
+}
+
+
 // This duplicates the functionality offered by `roles()`. This was necessary
 // as the JSON object returned by `roles()` was not specified in a formal way
 // i.e. via a corresponding protobuf object and would have been very hard to
@@ -4229,7 +4277,7 @@ Future<Response> Master::Http::maintenanceStatus(
 
   return _getMaintenanceStatus()
     .then([request](const mesos::maintenance::ClusterStatus& status)
-            -> Response {
+      -> Response {
       return OK(JSON::protobuf(status), request.url.query.get("jsonp"));
     });
 }

http://git-wip-us.apache.org/repos/asf/mesos/blob/2238ccf5/src/master/master.hpp
----------------------------------------------------------------------
diff --git a/src/master/master.hpp b/src/master/master.hpp
index 60efd22..845f2f6 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -1425,6 +1425,11 @@ private:
         const Option<std::string>& principal,
         ContentType contentType) const;
 
+    process::Future<process::http::Response> listFiles(
+        const mesos::master::Call& call,
+        const Option<std::string>& principal,
+        ContentType contentType) const;
+
     process::Future<process::http::Response> getLeadingMaster(
         const mesos::master::Call& call,
         const Option<std::string>& principal,


[03/11] mesos git commit: Added a helper function for JSON:Object to FileInfo protobuf conversion.

Posted by an...@apache.org.
Added a helper function for JSON:Object to FileInfo protobuf conversion.

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


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

Branch: refs/heads/master
Commit: 4d26eaddab60d883ff8fc7de040dd2b8eaf87ab2
Parents: e36e71a
Author: Abhishek Dasgupta <a1...@linux.vnet.ibm.com>
Authored: Thu Jul 7 10:52:05 2016 -0700
Committer: Anand Mazumdar <an...@apache.org>
Committed: Thu Jul 7 11:02:36 2016 -0700

----------------------------------------------------------------------
 src/common/http.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/common/http.hpp |  1 +
 2 files changed, 63 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/4d26eadd/src/common/http.cpp
----------------------------------------------------------------------
diff --git a/src/common/http.cpp b/src/common/http.cpp
index dfe44da..d73170d 100644
--- a/src/common/http.cpp
+++ b/src/common/http.cpp
@@ -32,11 +32,14 @@
 #include <process/http.hpp>
 #include <process/pid.hpp>
 
+#include <stout/duration.hpp>
 #include <stout/foreach.hpp>
 #include <stout/protobuf.hpp>
 #include <stout/stringify.hpp>
 #include <stout/unreachable.hpp>
 
+#include <stout/os/permissions.hpp>
+
 #include "common/http.hpp"
 
 #include "messages/messages.hpp"
@@ -387,6 +390,65 @@ JSON::Object model(const ExecutorInfo& executorInfo)
 }
 
 
+// Returns JSON representation of a FileInfo protobuf message.
+// Example JSON:
+// {
+//   'path': '\/some\/file',
+//   'mode': '-rwxrwxrwx',
+//   'nlink': 5,
+//   'uid': 'bmahler',
+//   'gid': 'employee',
+//   'size': 4096,           // Bytes.
+//   'mtime': 1348258116,    // Unix timestamp.
+// }
+JSON::Object model(const FileInfo& fileInfo)
+{
+  JSON::Object file;
+  file.values["path"] = fileInfo.path();
+  file.values["nlink"] = fileInfo.nlink();
+  file.values["size"] = fileInfo.size();
+  file.values["mtime"] = Nanoseconds(fileInfo.mtime().nanoseconds()).secs();
+
+  char filetype;
+  if (S_ISREG(fileInfo.mode())) {
+    filetype = '-';
+  } else if (S_ISDIR(fileInfo.mode())) {
+    filetype = 'd';
+  } else if (S_ISCHR(fileInfo.mode())) {
+    filetype = 'c';
+  } else if (S_ISBLK(fileInfo.mode())) {
+    filetype = 'b';
+  } else if (S_ISFIFO(fileInfo.mode())) {
+    filetype = 'p';
+  } else if (S_ISLNK(fileInfo.mode())) {
+    filetype = 'l';
+  } else if (S_ISSOCK(fileInfo.mode())) {
+    filetype = 's';
+  } else {
+    filetype = '-';
+  }
+
+  struct os::Permissions permissions(fileInfo.mode());
+
+  file.values["mode"] = strings::format(
+      "%c%c%c%c%c%c%c%c%c%c",
+      filetype,
+      permissions.owner.r ? 'r' : '-',
+      permissions.owner.w ? 'w' : '-',
+      permissions.owner.x ? 'x' : '-',
+      permissions.group.r ? 'r' : '-',
+      permissions.group.w ? 'w' : '-',
+      permissions.group.x ? 'x' : '-',
+      permissions.others.r ? 'r' : '-',
+      permissions.others.w ? 'w' : '-',
+      permissions.others.x ? 'x' : '-').get();
+
+  file.values["uid"] = fileInfo.uid();
+  file.values["gid"] = fileInfo.gid();
+
+  return file;
+}
+
 }  // namespace internal {
 
 void json(JSON::ObjectWriter* writer, const Attributes& attributes)

http://git-wip-us.apache.org/repos/asf/mesos/blob/4d26eadd/src/common/http.hpp
----------------------------------------------------------------------
diff --git a/src/common/http.hpp b/src/common/http.hpp
index ca44b11..2dfa789 100644
--- a/src/common/http.hpp
+++ b/src/common/http.hpp
@@ -87,6 +87,7 @@ JSON::Object model(const CommandInfo& command);
 JSON::Object model(const ExecutorInfo& executorInfo);
 JSON::Array model(const Labels& labels);
 JSON::Object model(const Task& task);
+JSON::Object model(const FileInfo& fileInfo);
 
 void json(JSON::ObjectWriter* writer, const Task& task);