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 2018/09/06 14:34:31 UTC
[mesos] 02/02: Added '/roles' to the set of batched master
endpoints.
This is an automated email from the ASF dual-hosted git repository.
alexr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git
commit 0c5f300aa9cbe6043498d586c1150ba7483b08f1
Author: Benno Evers <be...@mesosphere.com>
AuthorDate: Thu Sep 6 14:08:29 2018 +0200
Added '/roles' to the set of batched master endpoints.
For improved consistency, the '/roles' endpoint on the
master is now marked as read-only and uses the batching
mechanism shared by the other read-only endpoints.
Review: https://reviews.apache.org/r/68568/
---
src/master/http.cpp | 126 +++-------------------------------------
src/master/master.cpp | 43 ++++++++++++++
src/master/master.hpp | 13 ++++-
src/master/readonly_handler.cpp | 85 +++++++++++++++++++++++++++
4 files changed, 145 insertions(+), 122 deletions(-)
diff --git a/src/master/http.cpp b/src/master/http.cpp
index 8a37349..deb65af 100644
--- a/src/master/http.cpp
+++ b/src/master/http.cpp
@@ -2565,49 +2565,6 @@ Future<Response> Master::Http::stateSummary(
}
-// Returns a JSON object modeled after a role.
-JSON::Object model(
- const string& name,
- Option<double> weight,
- Option<Quota> quota,
- Option<Role*> _role)
-{
- JSON::Object object;
- object.values["name"] = name;
-
- if (weight.isSome()) {
- object.values["weight"] = weight.get();
- } else {
- object.values["weight"] = 1.0; // Default weight.
- }
-
- if (quota.isSome()) {
- object.values["quota"] = model(quota->info);
- }
-
- if (_role.isNone()) {
- object.values["resources"] = model(Resources());
- object.values["frameworks"] = JSON::Array();
- } else {
- Role* role = _role.get();
-
- object.values["resources"] = model(role->allocatedResources());
-
- {
- JSON::Array array;
-
- foreachkey (const FrameworkID& frameworkId, role->frameworks) {
- array.values.push_back(frameworkId.value());
- }
-
- object.values["frameworks"] = std::move(array);
- }
- }
-
- return object;
-}
-
-
string Master::Http::ROLES_HELP()
{
return HELP(
@@ -2631,49 +2588,6 @@ string Master::Http::ROLES_HELP()
}
-vector<string> Master::Http::_filterRoles(
- const Owned<ObjectApprovers>& approvers) const
-{
- JSON::Object object;
-
- // Compute the role names to return results for. When an explicit
- // role whitelist has been configured, we use that list of names.
- // When using implicit roles, the right behavior is a bit more
- // subtle. There are no constraints on possible role names, so we
- // instead list all the "interesting" roles: all roles with one or
- // more registered frameworks, and all roles with a non-default
- // weight or quota.
- //
- // NOTE: we use a `std::set` to store the role names to ensure a
- // deterministic output order.
- set<string> roleList;
- if (master->roleWhitelist.isSome()) {
- const hashset<string>& whitelist = master->roleWhitelist.get();
- roleList.insert(whitelist.begin(), whitelist.end());
- } else {
- hashset<string> roles = master->roles.keys();
- roleList.insert(roles.begin(), roles.end());
-
- hashset<string> weights = master->weights.keys();
- roleList.insert(weights.begin(), weights.end());
-
- hashset<string> quotas = master->quotas.keys();
- roleList.insert(quotas.begin(), quotas.end());
- }
-
- vector<string> filteredRoleList;
- filteredRoleList.reserve(roleList.size());
-
- foreach (const string& role, roleList) {
- if (approvers->approved<VIEW_ROLE>(role)) {
- filteredRoleList.push_back(role);
- }
- }
-
- return filteredRoleList;
-}
-
-
Future<Response> Master::Http::roles(
const Request& request,
const Option<Principal>& principal) const
@@ -2694,38 +2608,12 @@ Future<Response> Master::Http::roles(
return ObjectApprovers::create(master->authorizer, principal, {VIEW_ROLE})
.then(defer(master->self(),
- [this, request](const Owned<ObjectApprovers>& approvers)
- -> Response {
- JSON::Object object;
- const vector<string> filteredRoles = _filterRoles(approvers);
-
- {
- JSON::Array array;
-
- foreach (const string& name, filteredRoles) {
- Option<double> weight = None();
- if (master->weights.contains(name)) {
- weight = master->weights[name];
- }
-
- Option<Quota> quota = None();
- if (master->quotas.contains(name)) {
- quota = master->quotas.at(name);
- }
-
- Option<Role*> role = None();
- if (master->roles.contains(name)) {
- role = master->roles.at(name);
- }
-
- array.values.push_back(model(name, weight, quota, role));
- }
-
- object.values["roles"] = std::move(array);
- }
-
- return OK(object, request.url.query.get("jsonp"));
- }));
+ [this, request](const Owned<ObjectApprovers>& approvers) {
+ return deferBatchedRequest(
+ &Master::ReadOnlyHandler::roles,
+ request,
+ approvers);
+ }));
}
@@ -2791,7 +2679,7 @@ Future<Response> Master::Http::getRoles(
.then(defer(master->self(),
[this, contentType](const Owned<ObjectApprovers>& approvers)
-> Response {
- const vector<string> filteredRoles = _filterRoles(approvers);
+ const vector<string> filteredRoles = master->filterRoles(approvers);
mesos::master::Response response;
response.set_type(mesos::master::Response::GET_ROLES);
diff --git a/src/master/master.cpp b/src/master/master.cpp
index 3277b57..982bfcc 100644
--- a/src/master/master.cpp
+++ b/src/master/master.cpp
@@ -3403,6 +3403,49 @@ void Master::suppress(
}
+vector<string> Master::filterRoles(
+ const Owned<ObjectApprovers>& approvers) const
+{
+ JSON::Object object;
+
+ // Compute the role names to return results for. When an explicit
+ // role whitelist has been configured, we use that list of names.
+ // When using implicit roles, the right behavior is a bit more
+ // subtle. There are no constraints on possible role names, so we
+ // instead list all the "interesting" roles: all roles with one or
+ // more registered frameworks, and all roles with a non-default
+ // weight or quota.
+ //
+ // NOTE: we use a `std::set` to store the role names to ensure a
+ // deterministic output order.
+ set<string> roleList;
+ if (roleWhitelist.isSome()) {
+ const hashset<string>& whitelist = roleWhitelist.get();
+ roleList.insert(whitelist.begin(), whitelist.end());
+ } else {
+ hashset<string> roles = this->roles.keys();
+ roleList.insert(roles.begin(), roles.end());
+
+ hashset<string> weights = this->weights.keys();
+ roleList.insert(weights.begin(), weights.end());
+
+ hashset<string> quotas = this->quotas.keys();
+ roleList.insert(quotas.begin(), quotas.end());
+ }
+
+ vector<string> filteredRoleList;
+ filteredRoleList.reserve(roleList.size());
+
+ foreach (const string& role, roleList) {
+ if (approvers->approved<VIEW_ROLE>(role)) {
+ filteredRoleList.push_back(role);
+ }
+ }
+
+ return filteredRoleList;
+}
+
+
bool Master::isWhitelistedRole(const string& name) const
{
if (roleWhitelist.isNone()) {
diff --git a/src/master/master.hpp b/src/master/master.hpp
index 5d01de4..ec2ae01 100644
--- a/src/master/master.hpp
+++ b/src/master/master.hpp
@@ -1181,6 +1181,9 @@ private:
process::Future<bool> authorizeLogAccess(
const Option<process::http::authentication::Principal>& principal);
+ std::vector<std::string> filterRoles(
+ const process::Owned<ObjectApprovers>& approvers) const;
+
/**
* Returns whether the given role is on the whitelist.
*
@@ -1401,6 +1404,11 @@ private:
const process::http::Request& request,
const process::Owned<ObjectApprovers>& approvers) const;
+ // /roles
+ process::http::Response roles(
+ const process::http::Request& request,
+ const process::Owned<ObjectApprovers>& approvers) const;
+
// /slaves
process::http::Response slaves(
const process::http::Request& request,
@@ -1488,6 +1496,8 @@ private:
principal) const;
// /master/roles
+ //
+ // NOTE: Requests to this endpoint are batched.
process::Future<process::http::Response> roles(
const process::http::Request& request,
const Option<process::http::authentication::Principal>&
@@ -1695,9 +1705,6 @@ private:
Resources required,
const Offer::Operation& operation) const;
- std::vector<std::string> _filterRoles(
- const process::Owned<ObjectApprovers>& approvers) const;
-
// Master API handlers.
process::Future<process::http::Response> getAgents(
diff --git a/src/master/readonly_handler.cpp b/src/master/readonly_handler.cpp
index 47d7de5..8895374 100644
--- a/src/master/readonly_handler.cpp
+++ b/src/master/readonly_handler.cpp
@@ -53,6 +53,9 @@ namespace mesos {
namespace internal {
namespace master {
+// Pull in model overrides from common.
+using mesos::internal::model;
+
// The summary representation of `T` to support the `/state-summary` endpoint.
// e.g., `Summary<Slave>`.
template <typename T>
@@ -74,6 +77,9 @@ struct Full : Representation<T>
// Filtered representation of Full<Framework>.
// Executors and Tasks are filtered based on whether the
// user is authorized to view them.
+//
+// TODO(bevers): Consider moving writers and other json-related
+// code into a separate file.
struct FullFrameworkWriter {
FullFrameworkWriter(
const process::Owned<ObjectApprovers>& approvers,
@@ -688,6 +694,85 @@ process::http::Response Master::ReadOnlyHandler::frameworks(
}
+// Returns a JSON object modeled after a role.
+JSON::Object model(
+ const string& name,
+ Option<double> weight,
+ Option<Quota> quota,
+ Option<Role*> _role)
+{
+ JSON::Object object;
+ object.values["name"] = name;
+
+ if (weight.isSome()) {
+ object.values["weight"] = weight.get();
+ } else {
+ object.values["weight"] = 1.0; // Default weight.
+ }
+
+ if (quota.isSome()) {
+ object.values["quota"] = model(quota->info);
+ }
+
+ if (_role.isNone()) {
+ object.values["resources"] = model(Resources());
+ object.values["frameworks"] = JSON::Array();
+ } else {
+ Role* role = _role.get();
+
+ object.values["resources"] = model(role->allocatedResources());
+
+ {
+ JSON::Array array;
+
+ foreachkey (const FrameworkID& frameworkId, role->frameworks) {
+ array.values.push_back(frameworkId.value());
+ }
+
+ object.values["frameworks"] = std::move(array);
+ }
+ }
+
+ return object;
+}
+
+
+process::http::Response Master::ReadOnlyHandler::roles(
+ const process::http::Request& request,
+ const process::Owned<ObjectApprovers>& approvers) const
+{
+ JSON::Object object;
+ const vector<string> filteredRoles = master->filterRoles(approvers);
+
+ {
+ JSON::Array array;
+
+ foreach (const string& name, filteredRoles) {
+ Option<double> weight = None();
+ if (master->weights.contains(name)) {
+ weight = master->weights.at(name);
+ }
+
+ Option<Quota> quota = None();
+ if (master->quotas.contains(name)) {
+ quota = master->quotas.at(name);
+ }
+
+ Option<Role*> role = None();
+ if (master->roles.contains(name)) {
+ role = master->roles.at(name);
+ }
+
+ array.values.push_back(model(name, weight, quota, role));
+ }
+
+ object.values["roles"] = std::move(array);
+ }
+
+ return OK(object, request.url.query.get("jsonp"));
+}
+
+
process::http::Response Master::ReadOnlyHandler::slaves(
const process::http::Request& request,
const process::Owned<ObjectApprovers>& approvers) const