This is an automated email from the ASF dual-hosted git repository.

asekretenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git

commit f284314ba053ad4efaf964ec8fb0426f3784a1b5
Author: Andrei Sekretenko <[email protected]>
AuthorDate: Mon Aug 3 17:16:11 2020 +0200

    Added a scheduler API test for a valid offer constraints update.
    
    Review: https://reviews.apache.org/r/72744
---
 src/tests/master/update_framework_tests.cpp | 107 +++++++++++++++++++++++++++-
 1 file changed, 106 insertions(+), 1 deletion(-)

diff --git a/src/tests/master/update_framework_tests.cpp 
b/src/tests/master/update_framework_tests.cpp
index 514647d..6346a4e 100644
--- a/src/tests/master/update_framework_tests.cpp
+++ b/src/tests/master/update_framework_tests.cpp
@@ -193,7 +193,9 @@ class UpdateFrameworkTest : public MesosTest {};
 static Future<APIResult> callUpdateFramework(
     Mesos* mesos,
     const FrameworkInfo& info,
-    const vector<string>& suppressedRoles = {})
+    const vector<string>& suppressedRoles = {},
+    const Option<::mesos::v1::scheduler::OfferConstraints>& offerConstraints =
+      None())
 {
   CHECK(info.has_id());
 
@@ -203,6 +205,12 @@ static Future<APIResult> callUpdateFramework(
   *call.mutable_update_framework()->mutable_framework_info() = info;
   *call.mutable_update_framework()->mutable_suppressed_roles() =
     RepeatedPtrField<string>(suppressedRoles.begin(), suppressedRoles.end());
+
+  if (offerConstraints.isSome()) {
+    *call.mutable_update_framework()->mutable_offer_constraints() =
+      *offerConstraints;
+  }
+
   return mesos->call(call);
 }
 
@@ -725,6 +733,103 @@ TEST_F(UpdateFrameworkTest, RemoveAndUnsuppress)
 }
 
 
+// This test ensures that it is possible to modify offer constraints
+// via the UpdateFramework call.
+TEST_F(UpdateFrameworkTest, OfferConstraints)
+{
+  using ::mesos::v1::scheduler::AttributeConstraint;
+  using ::mesos::v1::scheduler::OfferConstraints;
+
+  mesos::internal::master::Flags masterFlags = CreateMasterFlags();
+  Try<Owned<cluster::Master>> master = StartMaster(masterFlags);
+  ASSERT_SOME(master);
+
+  Owned<MasterDetector> detector = master->get()->createDetector();
+
+  mesos::internal::slave::Flags slaveFlags = CreateSlaveFlags();
+  Try<Owned<cluster::Slave>> slave = StartSlave(detector.get(), slaveFlags);
+  ASSERT_SOME(slave);
+
+  auto scheduler = std::make_shared<MockHTTPScheduler>();
+
+  EXPECT_CALL(*scheduler, connected(_))
+    .WillOnce(Invoke([](Mesos* mesos) {
+      Call call;
+      call.set_type(Call::SUBSCRIBE);
+      *call.mutable_subscribe()->mutable_framework_info() =
+        DEFAULT_FRAMEWORK_INFO;
+
+      AttributeConstraint* constraint =
+        (*call.mutable_subscribe()
+            ->mutable_offer_constraints()
+            ->mutable_role_constraints())[DEFAULT_FRAMEWORK_INFO.roles(0)]
+          .add_groups()
+          ->add_attribute_constraints();
+
+      *constraint->mutable_selector()->mutable_attribute_name() = "foo";
+      *constraint->mutable_predicate()->mutable_exists() =
+        AttributeConstraint::Predicate::Exists();
+
+      mesos->send(call);
+    }));
+
+  EXPECT_CALL(*scheduler, heartbeat(_))
+    .WillRepeatedly(Return()); // Ignore heartbeats.
+
+  Future<Event::Subscribed> subscribed;
+
+  EXPECT_CALL(*scheduler, subscribed(_, 
_)).WillOnce(FutureArg<1>(&subscribed));
+
+  // Expect that the framework gets no offers.
+  EXPECT_CALL(*scheduler, offers(_, _)).Times(AtMost(0));
+
+  TestMesos mesos(master->get()->pid, ContentType::PROTOBUF, scheduler);
+
+  AWAIT_READY(subscribed);
+
+  // Trigger allocation to ensure that the agent is not offered before changing
+  // offer constraints.
+  Clock::pause();
+  Clock::settle();
+  Clock::advance(masterFlags.allocation_interval);
+  Clock::settle();
+
+  // Expect an offer after constraints change.
+  Future<Event::Offers> offers;
+  EXPECT_CALL(*scheduler, offers(_, _)).WillOnce(FutureArg<1>(&offers));
+
+  // Change constraint to `NotExists` so that the agent will now be offered to
+  // the framework.
+  {
+    FrameworkInfo framework = DEFAULT_FRAMEWORK_INFO;
+    *framework.mutable_id() = subscribed->framework_id();
+
+    OfferConstraints constraints;
+    AttributeConstraint* constraint =
+      (*constraints.mutable_role_constraints())[framework.roles(0)]
+        .add_groups()
+        ->add_attribute_constraints();
+
+    *constraint->mutable_selector()->mutable_attribute_name() = "foo";
+    *constraint->mutable_predicate()->mutable_not_exists() =
+      AttributeConstraint::Predicate::NotExists();
+
+    AWAIT_READY(callUpdateFramework(&mesos, framework, {}, constraints));
+  }
+
+  Clock::pause();
+  Clock::settle();
+  Clock::advance(masterFlags.allocation_interval);
+  Clock::settle();
+
+  AWAIT_READY(offers);
+  EXPECT_EQ(offers->offers().size(), 1);
+
+  // TODO(asekretenko): After master starts exposing offer constraints via
+  // its endpoints (MESOS-10179), check the constraints in the endpoints.
+}
+
+
 } // namespace scheduler {
 } // namespace v1 {
 

Reply via email to