@@ -193,7 +193,9 @@ class UpdateFrameworkTest : public MesosTest {};
193
193
static Future<APIResult> callUpdateFramework (
194
194
Mesos* mesos,
195
195
const FrameworkInfo& info,
196
- const vector<string>& suppressedRoles = {})
196
+ const vector<string>& suppressedRoles = {},
197
+ const Option<::mesos::v1::scheduler::OfferConstraints>& offerConstraints =
198
+ None ())
197
199
{
198
200
CHECK (info.has_id ());
199
201
@@ -203,6 +205,12 @@ static Future<APIResult> callUpdateFramework(
203
205
*call.mutable_update_framework ()->mutable_framework_info () = info;
204
206
*call.mutable_update_framework ()->mutable_suppressed_roles () =
205
207
RepeatedPtrField<string>(suppressedRoles.begin (), suppressedRoles.end ());
208
+
209
+ if (offerConstraints.isSome ()) {
210
+ *call.mutable_update_framework ()->mutable_offer_constraints () =
211
+ *offerConstraints;
212
+ }
213
+
206
214
return mesos->call (call);
207
215
}
208
216
@@ -725,6 +733,103 @@ TEST_F(UpdateFrameworkTest, RemoveAndUnsuppress)
725
733
}
726
734
727
735
736
+ // This test ensures that it is possible to modify offer constraints
737
+ // via the UpdateFramework call.
738
+ TEST_F (UpdateFrameworkTest, OfferConstraints)
739
+ {
740
+ using ::mesos::v1::scheduler::AttributeConstraint;
741
+ using ::mesos::v1::scheduler::OfferConstraints;
742
+
743
+ mesos::internal::master::Flags masterFlags = CreateMasterFlags ();
744
+ Try<Owned<cluster::Master>> master = StartMaster (masterFlags);
745
+ ASSERT_SOME (master);
746
+
747
+ Owned<MasterDetector> detector = master->get ()->createDetector ();
748
+
749
+ mesos::internal::slave::Flags slaveFlags = CreateSlaveFlags ();
750
+ Try<Owned<cluster::Slave>> slave = StartSlave (detector.get (), slaveFlags);
751
+ ASSERT_SOME (slave);
752
+
753
+ auto scheduler = std::make_shared<MockHTTPScheduler>();
754
+
755
+ EXPECT_CALL (*scheduler, connected (_))
756
+ .WillOnce (Invoke ([](Mesos* mesos) {
757
+ Call call;
758
+ call.set_type (Call::SUBSCRIBE);
759
+ *call.mutable_subscribe ()->mutable_framework_info () =
760
+ DEFAULT_FRAMEWORK_INFO;
761
+
762
+ AttributeConstraint* constraint =
763
+ (*call.mutable_subscribe ()
764
+ ->mutable_offer_constraints ()
765
+ ->mutable_role_constraints ())[DEFAULT_FRAMEWORK_INFO.roles (0 )]
766
+ .add_groups ()
767
+ ->add_attribute_constraints ();
768
+
769
+ *constraint->mutable_selector ()->mutable_attribute_name () = " foo" ;
770
+ *constraint->mutable_predicate ()->mutable_exists () =
771
+ AttributeConstraint::Predicate::Exists ();
772
+
773
+ mesos->send (call);
774
+ }));
775
+
776
+ EXPECT_CALL (*scheduler, heartbeat (_))
777
+ .WillRepeatedly (Return ()); // Ignore heartbeats.
778
+
779
+ Future<Event::Subscribed> subscribed;
780
+
781
+ EXPECT_CALL (*scheduler, subscribed (_, _)).WillOnce (FutureArg<1 >(&subscribed));
782
+
783
+ // Expect that the framework gets no offers.
784
+ EXPECT_CALL (*scheduler, offers (_, _)).Times (AtMost (0 ));
785
+
786
+ TestMesos mesos (master->get ()->pid , ContentType::PROTOBUF, scheduler);
787
+
788
+ AWAIT_READY (subscribed);
789
+
790
+ // Trigger allocation to ensure that the agent is not offered before changing
791
+ // offer constraints.
792
+ Clock::pause ();
793
+ Clock::settle ();
794
+ Clock::advance (masterFlags.allocation_interval );
795
+ Clock::settle ();
796
+
797
+ // Expect an offer after constraints change.
798
+ Future<Event::Offers> offers;
799
+ EXPECT_CALL (*scheduler, offers (_, _)).WillOnce (FutureArg<1 >(&offers));
800
+
801
+ // Change constraint to `NotExists` so that the agent will now be offered to
802
+ // the framework.
803
+ {
804
+ FrameworkInfo framework = DEFAULT_FRAMEWORK_INFO;
805
+ *framework.mutable_id () = subscribed->framework_id ();
806
+
807
+ OfferConstraints constraints;
808
+ AttributeConstraint* constraint =
809
+ (*constraints.mutable_role_constraints ())[framework.roles (0 )]
810
+ .add_groups ()
811
+ ->add_attribute_constraints ();
812
+
813
+ *constraint->mutable_selector ()->mutable_attribute_name () = " foo" ;
814
+ *constraint->mutable_predicate ()->mutable_not_exists () =
815
+ AttributeConstraint::Predicate::NotExists ();
816
+
817
+ AWAIT_READY (callUpdateFramework (&mesos, framework, {}, constraints));
818
+ }
819
+
820
+ Clock::pause ();
821
+ Clock::settle ();
822
+ Clock::advance (masterFlags.allocation_interval );
823
+ Clock::settle ();
824
+
825
+ AWAIT_READY (offers);
826
+ EXPECT_EQ (offers->offers ().size (), 1 );
827
+
828
+ // TODO(asekretenko): After master starts exposing offer constraints via
829
+ // its endpoints (MESOS-10179), check the constraints in the endpoints.
830
+ }
831
+
832
+
728
833
} // namespace scheduler {
729
834
} // namespace v1 {
730
835
0 commit comments