This is an automated email from the ASF dual-hosted git repository. bmahler pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mesos.git
The following commit(s) were added to refs/heads/master by this push: new a4ce050f3 [agent] Add test for framework_id and executor_id support in /containers. a4ce050f3 is described below commit a4ce050f3bc791844db48f8282f88992bc4744f1 Author: None <None> AuthorDate: Thu May 23 19:11:08 2024 -0400 [agent] Add test for framework_id and executor_id support in /containers. Review: https://reviews.apache.org/r/75010/ --- src/tests/slave_tests.cpp | 172 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 170 insertions(+), 2 deletions(-) diff --git a/src/tests/slave_tests.cpp b/src/tests/slave_tests.cpp index a5e01ef42..89afbb8dc 100644 --- a/src/tests/slave_tests.cpp +++ b/src/tests/slave_tests.cpp @@ -134,6 +134,7 @@ using process::UPID; using process::filter; +using process::http::BadRequest; using process::http::InternalServerError; using process::http::OK; using process::http::Response; @@ -2512,7 +2513,8 @@ TEST_F(SlaveTest, ContainersEndpointNoExecutor) // This is an end-to-end test that verifies that the slave returns the // correct container status and resource statistics based on the currently // running executors, and ensures that '/containers' endpoint returns the -// correct container when it is provided a container ID query parameter. +// correct container when it is provided a container ID, framework ID, or +// executor ID query parameters. TEST_F(SlaveTest, ContainersEndpoint) { Try<Owned<cluster::Master>> master = StartMaster(); @@ -2540,7 +2542,9 @@ TEST_F(SlaveTest, ContainersEndpoint) MesosSchedulerDriver driver( &sched, DEFAULT_FRAMEWORK_INFO, master.get()->pid, DEFAULT_CREDENTIAL); - EXPECT_CALL(sched, registered(&driver, _, _)); + Future<FrameworkID> frameworkId; + EXPECT_CALL(sched, registered(&driver, _, _)) + .WillOnce(FutureArg<1>(&frameworkId)); Future<vector<Offer>> offers; EXPECT_CALL(sched, resourceOffers(&driver, _)) @@ -2549,6 +2553,7 @@ TEST_F(SlaveTest, ContainersEndpoint) driver.start(); + AWAIT_READY(frameworkId); AWAIT_READY(offers); ASSERT_FALSE(offers->empty()); @@ -2786,6 +2791,169 @@ TEST_F(SlaveTest, ContainersEndpoint) EXPECT_TRUE(value->contains(expected.get())); } + // Will be called once during the third request. + EXPECT_CALL(containerizer, usage(_)) + .WillOnce(Return(statistics2)); + + // Will be called once during the third request and might be called if + // the `TASK_FAILED` update reaches the agent before the test finishes. + EXPECT_CALL(containerizer, status(_)) + .WillOnce(Return(containerStatus2)) + .WillRepeatedly(Return(containerStatus2)); + + { + Future<Response> response = process::http::get( + slave.get()->pid, + "containers?executor_id=" + executor2.executor_id().value() + + "&framework_id=" + frameworkId->value(), + None(), + createBasicAuthHeaders(DEFAULT_CREDENTIAL)); + + Try<JSON::Value> value = JSON::parse<JSON::Value>(response->body); + ASSERT_SOME(value); + + JSON::Array array = value->as<JSON::Array>(); + EXPECT_TRUE(array.values.size() == 1); + + Try<JSON::Value> expected = JSON::parse( + "[{" + "\"executor_id\":\"" + executor2.executor_id().value() + "\"," + "\"framework_id\":\"" + frameworkId->value() + "\"," + "\"statistics\":{" + "}," + "\"status\":{" + "\"container_id\":{" + "\"parent\":{\"value\":\"parent\"}," + "\"value\":\"child2\"" + "}," + "\"cgroup_info\":{\"net_cls\":{\"classid\":42}}," + "\"network_infos\":[{" + "\"ip_addresses\":[{\"ip_address\":\"192.168.1.21\"}]" + "}]" + "}" + "}]"); + + ASSERT_SOME(expected); + + EXPECT_TRUE(value->contains(expected.get())); + } + + EXPECT_CALL(containerizer, usage(_)) + .WillOnce(DoAll(FutureArg<0>(&containerId1), Return(statistics1))) + .WillOnce(DoAll(FutureArg<0>(&containerId2), Return(statistics2))); + + EXPECT_CALL(containerizer, status(_)) + .WillOnce(Return(containerStatus1)) + .WillOnce(Return(containerStatus2)); + + { + Future<Response> response = process::http::get( + slave.get()->pid, + "containers?framework_id=" + frameworkId->value(), + None(), + createBasicAuthHeaders(DEFAULT_CREDENTIAL)); + + Try<JSON::Value> value = JSON::parse<JSON::Value>(response->body); + ASSERT_SOME(value); + + JSON::Array array = value->as<JSON::Array>(); + + EXPECT_TRUE(array.values.size() == 2); + + Try<JSON::Value> containerJson1 = JSON::parse( + "{" + "\"framework_id\":\"" + frameworkId->value() + "\"," + "\"executor_name\":\"\"," + "\"source\":\"\"," + "\"statistics\":{" + "\"mem_limit_bytes\":2048" + "}," + "\"status\":{" + "\"container_id\":{" + "\"parent\":{\"value\":\"parent\"}," + "\"value\":\"child1\"" + "}," + "\"cgroup_info\":{\"net_cls\":{\"classid\":42}}," + "\"network_infos\":[{" + "\"ip_addresses\":[{\"ip_address\":\"192.168.1.20\"}]" + "}]" + "}" + "}"); + + Try<JSON::Value> containerJson2 = JSON::parse( + "{" + "\"framework_id\":\"" + frameworkId->value() + "\"," + "\"executor_name\":\"\"," + "\"source\":\"\"," + "\"statistics\":{" + "\"mem_limit_bytes\":2048" + "}," + "\"status\":{" + "\"container_id\":{" + "\"parent\":{\"value\":\"parent\"}," + "\"value\":\"child2\"" + "}," + "\"cgroup_info\":{\"net_cls\":{\"classid\":42}}," + "\"network_infos\":[{" + "\"ip_addresses\":[{\"ip_address\":\"192.168.1.21\"}]" + "}]" + "}" + "}"); + + // Since containers are stored in a hashmap, there is no strict guarantee of + // their ordering when listed. For this reason, we test both possibilities. + if (array.values[0].contains(containerJson1.get())) { + ASSERT_TRUE(array.values[1].contains(containerJson2.get())); + } else { + ASSERT_TRUE(array.values[0].contains(containerJson2.get())); + ASSERT_TRUE(array.values[1].contains(containerJson1.get())); + } + } + + { + Future<Response> response = process::http::get( + slave.get()->pid, + "containers?executor_id=" + executor2.executor_id().value() + + "&container_id=" + containerId1->value(), + None(), + createBasicAuthHeaders(DEFAULT_CREDENTIAL)); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); + } + + { + Future<Response> response = process::http::get( + slave.get()->pid, + "containers?framework_id=" + frameworkId->value() + + "&container_id=" + containerId1->value(), + None(), + createBasicAuthHeaders(DEFAULT_CREDENTIAL)); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); + } + + { + Future<Response> response = process::http::get( + slave.get()->pid, + "containers?executor_id=" + executor2.executor_id().value(), + None(), + createBasicAuthHeaders(DEFAULT_CREDENTIAL)); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); + } + + { + Future<Response> response = process::http::get( + slave.get()->pid, + "containers?executor_id=" + executor2.executor_id().value() + + "&container_id=" + containerId1->value() + + "&framework_id=" + frameworkId->value(), + None(), + createBasicAuthHeaders(DEFAULT_CREDENTIAL)); + + AWAIT_EXPECT_RESPONSE_STATUS_EQ(BadRequest().status, response); + } + EXPECT_CALL(exec1, shutdown(_)) .Times(AtMost(1)); EXPECT_CALL(exec2, shutdown(_))