You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by mz...@apache.org on 2019/07/23 22:04:47 UTC
[mesos] 06/06: Added a test to ensure `UPDATE_QUOTA` is applied
all-or-nothing.
This is an automated email from the ASF dual-hosted git repository.
mzhu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git
commit 7aa2a96fea8a44f673a95b425bae71c946c09f2c
Author: Meng Zhu <mz...@mesosphere.io>
AuthorDate: Thu Jul 18 11:32:49 2019 -0700
Added a test to ensure `UPDATE_QUOTA` is applied all-or-nothing.
Review: https://reviews.apache.org/r/71119
---
src/tests/master_quota_tests.cpp | 138 +++++++++++++++++++++++++++++++++++++++
1 file changed, 138 insertions(+)
diff --git a/src/tests/master_quota_tests.cpp b/src/tests/master_quota_tests.cpp
index c0775f4..7745fb0 100644
--- a/src/tests/master_quota_tests.cpp
+++ b/src/tests/master_quota_tests.cpp
@@ -126,6 +126,20 @@ static string createUpdateQuotaRequestBody(
}
+static string createUpdateQuotaRequestBody(
+ const vector<QuotaConfig>& configs, bool force = false)
+{
+ mesos::master::Call call;
+ call.set_type(mesos::master::Call::UPDATE_QUOTA);
+ call.mutable_update_quota()->set_force(force);
+ foreach (const QuotaConfig& config, configs) {
+ *call.mutable_update_quota()->mutable_quota_configs()->Add() = config;
+ }
+
+ return stringify(JSON::protobuf(call));
+}
+
+
// Quota tests that are allocator-agnostic (i.e. we expect every
// allocator to implement basic quota guarantees) are in this
// file. All tests are split into logical groups:
@@ -264,6 +278,130 @@ TEST_F(MasterQuotaTest, UpdateQuota)
}
+// This ensures that `UPDATE_QUOTA` call with multiple quota configs are
+// updated all-or-nothing.
+TEST_F(MasterQuotaTest, UpdateQuotaMultipleRoles)
+{
+ MockAuthorizer authorizer;
+ Try<Owned<cluster::Master>> master = StartMaster(&authorizer);
+ ASSERT_SOME(master);
+
+ process::http::Headers headers = createBasicAuthHeaders(DEFAULT_CREDENTIAL);
+ headers["Content-Type"] = "application/json";
+
+ // Use force flag so that we can update quota with no agents.
+ string request = createUpdateQuotaRequestBody(
+ {
+ createQuotaConfig(ROLE1, "cpus:1;mem:1024", "cpus:2;mem:2048"),
+ createQuotaConfig(ROLE2, "cpus:1;mem:1024", "cpus:2;mem:2048"),
+ },
+ true);
+
+ EXPECT_CALL(authorizer, authorized(_))
+ // Particially deny the 1st `UPDATE_QUOTA` request.
+ .WillOnce(Return(true))
+ .WillOnce(Return(false))
+ // Approve all subsequent actions.
+ .WillRepeatedly(Return(true));
+
+ {
+ Future<Response> response =
+ process::http::post(master.get()->pid, "/api/v1", headers, request);
+
+ AWAIT_EXPECT_RESPONSE_STATUS_EQ(Forbidden().status, response);
+
+ response = process::http::get(
+ master.get()->pid,
+ "roles",
+ None(),
+ createBasicAuthHeaders(DEFAULT_CREDENTIAL));
+
+ AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+ Try<JSON::Value> parse = JSON::parse(response->body);
+ ASSERT_SOME(parse);
+
+ // Quota configs are applied a all-or-nothing.
+ Try<JSON::Value> expected = JSON::parse(
+ "{"
+ " \"roles\": []"
+ "}");
+
+ ASSERT_SOME(expected);
+ EXPECT_EQ(*expected, *parse) << "expected " << stringify(*expected)
+ << " vs actual " << stringify(*parse);
+ }
+
+ {
+ Future<Response> response =
+ process::http::post(master.get()->pid, "/api/v1", headers, request);
+
+ AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+ response = process::http::get(
+ master.get()->pid,
+ "roles",
+ None(),
+ createBasicAuthHeaders(DEFAULT_CREDENTIAL));
+
+ AWAIT_EXPECT_RESPONSE_STATUS_EQ(OK().status, response);
+
+ Try<JSON::Object> parse = JSON::parse<JSON::Object>(response->body);
+ ASSERT_SOME(parse);
+
+ Result<JSON::Array> roles = parse->find<JSON::Array>("roles");
+ ASSERT_SOME(roles);
+ EXPECT_EQ(2u, roles->values.size());
+
+ JSON::Value role1 = roles->values[0].as<JSON::Value>();
+ JSON::Value role2 = roles->values[1].as<JSON::Value>();
+
+ Try<JSON::Value> expected1 = JSON::parse(
+ "{"
+ " \"quota\": {"
+ " \"consumed\": {},"
+ " \"limit\": {"
+ " \"cpus\": 2.0,"
+ " \"mem\": 2048.0"
+ " },"
+ " \"guarantee\": {"
+ " \"cpus\": 1.0,"
+ " \"mem\": 1024.0"
+ " },"
+ " \"role\": \"role1\""
+ " }"
+ "}");
+
+ Try<JSON::Value> expected2 = JSON::parse(
+ "{"
+ " \"quota\": {"
+ " \"consumed\": {},"
+ " \"limit\": {"
+ " \"cpus\": 2.0,"
+ " \"mem\": 2048.0"
+ " },"
+ " \"guarantee\": {"
+ " \"cpus\": 1.0,"
+ " \"mem\": 1024.0"
+ " },"
+ " \"role\": \"role2\""
+ " }"
+ "}");
+
+ ASSERT_SOME(expected1);
+ ASSERT_SOME(expected2);
+
+
+ EXPECT_TRUE(role1.contains(*expected1))
+ << "expected " << stringify(*expected1) << " vs actual "
+ << stringify(role1);
+ EXPECT_TRUE(role2.contains(*expected2))
+ << "expected " << stringify(*expected2) << " vs actual "
+ << stringify(role2);
+ }
+}
+
+
// These are request validation tests. They verify JSON is well-formed,
// convertible to corresponding protobufs, all necessary fields are present,
// while irrelevant fields are not present.