You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by vi...@apache.org on 2014/06/11 01:33:51 UTC

[6/7] git commit: Added MockAuthorizer and more authorization tests.

Added MockAuthorizer and more authorization tests.

Review: https://reviews.apache.org/r/22190


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/c4084554
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/c4084554
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/c4084554

Branch: refs/heads/vinod/authorize_tasks
Commit: c4084554e8245397c168d44d0e54a1c2491ca3a8
Parents: a6c4ee7
Author: Vinod Kone <vi...@twitter.com>
Authored: Mon Jun 2 22:20:11 2014 -0700
Committer: Vinod Kone <vi...@twitter.com>
Committed: Tue Jun 10 16:33:36 2014 -0700

----------------------------------------------------------------------
 src/tests/cluster.hpp                    |  44 ++-
 src/tests/master_authorization_tests.cpp | 396 +++++++++++++++++++++++++-
 src/tests/mesos.cpp                      |  24 ++
 src/tests/mesos.hpp                      |  46 +++
 4 files changed, 502 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/c4084554/src/tests/cluster.hpp
----------------------------------------------------------------------
diff --git a/src/tests/cluster.hpp b/src/tests/cluster.hpp
index 449165c..1c96ee7 100644
--- a/src/tests/cluster.hpp
+++ b/src/tests/cluster.hpp
@@ -98,12 +98,25 @@ public:
     Try<process::PID<master::Master> > start(
         const master::Flags& flags = master::Flags());
 
+    // Start and manage a new master using the specified allocator
+    // process.
+    Try<process::PID<master::Master> > start(
+        master::allocator::AllocatorProcess* allocatorProcess,
+        const master::Flags& flags = master::Flags());
+
+    // Start and manage a new master using the specified authorizer.
+    Try<process::PID<master::Master> > start(
+        Authorizer* authorizer,
+        const master::Flags& flags = master::Flags());
+
     // Start and manage a new master using the specified flags.
-    // An allocator process may be specified in which case it will outlive
-    // the launched master.  If no allocator process is specified then
-    // the default allocator will be instantiated.
+    // An allocator process or authorizer may be specified in which
+    // case it will outlive the launched master. If either allocator
+    // process or authorizer is not specified then the default
+    // allocator or authorizer will be used.
     Try<process::PID<master::Master> > start(
         const Option<master::allocator::AllocatorProcess*>& allocatorProcess,
+        const Option<Authorizer*>& authorizer,
         const master::Flags& flags = master::Flags());
 
     // Stops and cleans up a master at the specified PID.
@@ -272,12 +285,29 @@ inline void Cluster::Masters::shutdown()
 inline Try<process::PID<master::Master> > Cluster::Masters::start(
     const master::Flags& flags)
 {
-  return start(None(), flags);
+  return start(None(), None(), flags);
+}
+
+
+inline Try<process::PID<master::Master> > Cluster::Masters::start(
+    master::allocator::AllocatorProcess* allocator,
+    const master::Flags& flags)
+{
+  return start(allocator, None(), flags);
+}
+
+
+inline Try<process::PID<master::Master> > Cluster::Masters::start(
+    Authorizer* authorizer,
+    const master::Flags& flags)
+{
+  return start(None(), authorizer, flags);
 }
 
 
 inline Try<process::PID<master::Master> > Cluster::Masters::start(
     const Option<master::allocator::AllocatorProcess*>& allocatorProcess,
+    const Option<Authorizer*>& authorizer,
     const master::Flags& flags)
 {
   // Disallow multiple masters when not using ZooKeeper.
@@ -354,7 +384,9 @@ inline Try<process::PID<master::Master> > Cluster::Masters::start(
     master.detector = new StandaloneMasterDetector();
   }
 
-  if (flags.acls.isSome()) {
+  if (authorizer.isSome()) {
+    CHECK_NOTNULL(authorizer.get());
+  } else if (flags.acls.isSome()) {
     Try<process::Owned<Authorizer> > authorizer_ =
       Authorizer::create(flags.acls.get());
     if (authorizer_.isError()) {
@@ -372,7 +404,7 @@ inline Try<process::PID<master::Master> > Cluster::Masters::start(
       &cluster->files,
       master.contender,
       master.detector,
-      master.authorizer,
+      authorizer.isSome() ? authorizer : master.authorizer,
       flags);
 
   if (url.isNone()) {

http://git-wip-us.apache.org/repos/asf/mesos/blob/c4084554/src/tests/master_authorization_tests.cpp
----------------------------------------------------------------------
diff --git a/src/tests/master_authorization_tests.cpp b/src/tests/master_authorization_tests.cpp
index 17debaf..3a28ca2 100644
--- a/src/tests/master_authorization_tests.cpp
+++ b/src/tests/master_authorization_tests.cpp
@@ -31,6 +31,7 @@
 #include <stout/gtest.hpp>
 #include <stout/try.hpp>
 
+#include "master/allocator.hpp"
 #include "master/master.hpp"
 
 #include "messages/messages.hpp"
@@ -45,16 +46,21 @@ using namespace mesos::internal::tests;
 
 using mesos::internal::master::Master;
 
+using mesos::internal::master::allocator::AllocatorProcess;
+
 using mesos::internal::slave::Slave;
 
 using process::Clock;
 using process::Future;
 using process::PID;
+using process::Promise;
 
 using std::vector;
 
 using testing::_;
+using testing::An;
 using testing::AtMost;
+using testing::DoAll;
 using testing::Return;
 
 
@@ -64,9 +70,8 @@ class MasterAuthorizationTest : public MesosTest {};
 // This test verifies that an authorized task launch is successful.
 TEST_F(MasterAuthorizationTest, AuthorizedTask)
 {
-  // Setup ACLs so that the framework can only launch tasks as "foo".
+  // Setup ACLs so that the framework can launch tasks as "foo".
   ACLs acls;
-  acls.set_permissive(false);
   mesos::ACL::RunTasks* acl = acls.add_run_tasks();
   acl->mutable_principals()->add_values(DEFAULT_FRAMEWORK_INFO.principal());
   acl->mutable_users()->add_values("foo");
@@ -207,3 +212,390 @@ TEST_F(MasterAuthorizationTest, UnauthorizedTask)
 
   Shutdown(); // Must shutdown before 'containerizer' gets deallocated.
 }
+
+
+// This test verifies that a 'killTask()' that comes before
+// '_launchTasks()' is called results in TASK_KILLED.
+TEST_F(MasterAuthorizationTest, KillTask)
+{
+  MockAuthorizer authorizer;
+  Try<PID<Master> > master = StartMaster(&authorizer);
+  ASSERT_SOME(master);
+
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  Try<PID<Slave> > slave = StartSlave(&exec);
+  ASSERT_SOME(slave);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .Times(1);
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  driver.start();
+
+  AWAIT_READY(offers);
+  EXPECT_NE(0u, offers.get().size());
+
+  TaskInfo task = createTask(offers.get()[0], "", DEFAULT_EXECUTOR_ID);
+  vector<TaskInfo> tasks;
+  tasks.push_back(task);
+
+  // Return a pending future from authorizer.
+  Future<Nothing> future;
+  Promise<bool> promise;
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+    .WillOnce(DoAll(FutureSatisfy(&future),
+                    Return(promise.future())));
+
+  driver.launchTasks(offers.get()[0].id(), tasks);
+
+  // Wait until authorization is in progress.
+  AWAIT_READY(future);
+
+  Future<TaskStatus> status;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&status));
+
+  // Now kill the task.
+  driver.killTask(task.task_id());
+
+  // Framework should get a TASK_KILLED right away.
+  AWAIT_READY(status);
+  EXPECT_EQ(TASK_KILLED, status.get().state());
+
+  Future<Nothing> resourcesUnused =
+    FUTURE_DISPATCH(_, &AllocatorProcess::resourcesUnused);
+
+  // Now complete authorization.
+  promise.set(true);
+
+  // No task launch should happen resulting in all resources being
+  // returned to the allocator.
+  AWAIT_READY(resourcesUnused);
+
+  driver.stop();
+  driver.join();
+
+  Shutdown(); // Must shutdown before 'containerizer' gets deallocated.
+}
+
+
+// This test verifies that a slave removal that comes before
+// '_launchTasks()' is called results in TASK_LOST.
+TEST_F(MasterAuthorizationTest, SlaveRemoved)
+{
+  MockAuthorizer authorizer;
+  Try<PID<Master> > master = StartMaster(&authorizer);
+  ASSERT_SOME(master);
+
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  Try<PID<Slave> > slave = StartSlave(&exec);
+  ASSERT_SOME(slave);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .Times(1);
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  driver.start();
+
+  AWAIT_READY(offers);
+  EXPECT_NE(0u, offers.get().size());
+
+  TaskInfo task = createTask(offers.get()[0], "", DEFAULT_EXECUTOR_ID);
+  vector<TaskInfo> tasks;
+  tasks.push_back(task);
+
+  // Return a pending future from authorizer.
+  Future<Nothing> future;
+  Promise<bool> promise;
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+    .WillOnce(DoAll(FutureSatisfy(&future),
+                    Return(promise.future())));
+
+  driver.launchTasks(offers.get()[0].id(), tasks);
+
+  // Wait until authorization is in progress.
+  AWAIT_READY(future);
+
+  Future<Nothing> slaveLost;
+  EXPECT_CALL(sched, slaveLost(&driver, _))
+    .WillOnce(FutureSatisfy(&slaveLost));
+
+  // Now stop the slave.
+  Stop(slave.get());
+
+  AWAIT_READY(slaveLost);
+
+  Future<TaskStatus> status;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&status));
+
+  Future<Nothing> resourcesRecovered =
+    FUTURE_DISPATCH(_, &AllocatorProcess::resourcesRecovered);
+
+  // Now complete authorization.
+  promise.set(true);
+
+  // Framework should get a TASK_LOST.
+  AWAIT_READY(status);
+  EXPECT_EQ(TASK_LOST, status.get().state());
+
+  // No task launch should happen resulting in all resources being
+  // returned to the allocator.
+  AWAIT_READY(resourcesRecovered);
+
+  driver.stop();
+  driver.join();
+
+  Shutdown(); // Must shutdown before 'containerizer' gets deallocated.
+}
+
+
+// This test verifies that a slave disconnection that comes before
+// '_launchTasks()' is called results in TASK_LOST.
+TEST_F(MasterAuthorizationTest, SlaveDisconnected)
+{
+  MockAuthorizer authorizer;
+  Try<PID<Master> > master = StartMaster(&authorizer);
+  ASSERT_SOME(master);
+
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  // Create a checkpointing slave so that a disconnected slave is not
+  // immediately removed.
+  slave::Flags flags = CreateSlaveFlags();
+  flags.checkpoint = true;
+  Try<PID<Slave> > slave = StartSlave(&exec, flags);
+  ASSERT_SOME(slave);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .Times(1);
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  driver.start();
+
+  AWAIT_READY(offers);
+  EXPECT_NE(0u, offers.get().size());
+
+  TaskInfo task = createTask(offers.get()[0], "", DEFAULT_EXECUTOR_ID);
+  vector<TaskInfo> tasks;
+  tasks.push_back(task);
+
+  // Return a pending future from authorizer.
+  Future<Nothing> future;
+  Promise<bool> promise;
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+    .WillOnce(DoAll(FutureSatisfy(&future),
+                    Return(promise.future())));
+
+  driver.launchTasks(offers.get()[0].id(), tasks);
+
+  // Wait until authorization is in progress.
+  AWAIT_READY(future);
+
+  EXPECT_CALL(sched, slaveLost(&driver, _))
+    .Times(AtMost(1));
+
+  Future<Nothing> slaveDisconnected =
+    FUTURE_DISPATCH(_, &AllocatorProcess::slaveDisconnected);
+
+  // Now stop the slave.
+  Stop(slave.get());
+
+  AWAIT_READY(slaveDisconnected);
+
+  Future<TaskStatus> status;
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .WillOnce(FutureArg<1>(&status));
+
+  Future<Nothing> resourcesRecovered =
+    FUTURE_DISPATCH(_, &AllocatorProcess::resourcesRecovered);
+
+  // Now complete authorization.
+  promise.set(true);
+
+  // Framework should get a TASK_LOST.
+  AWAIT_READY(status);
+  EXPECT_EQ(TASK_LOST, status.get().state());
+
+  // No task launch should happen resulting in all resources being
+  // returned to the allocator.
+  AWAIT_READY(resourcesRecovered);
+
+  driver.stop();
+  driver.join();
+
+  Shutdown(); // Must shutdown before 'containerizer' gets deallocated.
+}
+
+
+// This test verifies that a framework removal that comes before
+// '_launchTasks()' is called results in recovery of resources.
+TEST_F(MasterAuthorizationTest, FrameworkRemoved)
+{
+  MockAuthorizer authorizer;
+  Try<PID<Master> > master = StartMaster(&authorizer);
+  ASSERT_SOME(master);
+
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  Try<PID<Slave> > slave = StartSlave(&exec);
+  ASSERT_SOME(slave);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .Times(1);
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  driver.start();
+
+  AWAIT_READY(offers);
+  EXPECT_NE(0u, offers.get().size());
+
+  TaskInfo task = createTask(offers.get()[0], "", DEFAULT_EXECUTOR_ID);
+  vector<TaskInfo> tasks;
+  tasks.push_back(task);
+
+  // Return a pending future from authorizer.
+  Future<Nothing> future;
+  Promise<bool> promise;
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+    .WillOnce(DoAll(FutureSatisfy(&future),
+                    Return(promise.future())));
+
+  driver.launchTasks(offers.get()[0].id(), tasks);
+
+  // Wait until authorization is in progress.
+  AWAIT_READY(future);
+
+  Future<Nothing> frameworkRemoved =
+    FUTURE_DISPATCH(_, &AllocatorProcess::frameworkRemoved);
+
+  // Now stop the framework.
+  driver.stop();
+  driver.join();
+
+  AWAIT_READY(frameworkRemoved);
+
+  Future<Nothing> resourcesRecovered =
+    FUTURE_DISPATCH(_, &AllocatorProcess::resourcesRecovered);
+
+  // Now complete authorization.
+  promise.set(true);
+
+  // No task launch should happen resulting in all resources being
+  // returned to the allocator.
+  AWAIT_READY(resourcesRecovered);
+
+  Shutdown(); // Must shutdown before 'containerizer' gets deallocated.
+}
+
+
+// This test verifies that a reconciliation request that comes before
+// '_launchTasks()' is ignored.
+TEST_F(MasterAuthorizationTest, ReconcileTask)
+{
+  MockAuthorizer authorizer;
+  Try<PID<Master> > master = StartMaster(&authorizer);
+  ASSERT_SOME(master);
+
+  MockExecutor exec(DEFAULT_EXECUTOR_ID);
+
+  Try<PID<Slave> > slave = StartSlave(&exec);
+  ASSERT_SOME(slave);
+
+  MockScheduler sched;
+  MesosSchedulerDriver driver(
+      &sched, DEFAULT_FRAMEWORK_INFO, master.get(), DEFAULT_CREDENTIAL);
+
+  EXPECT_CALL(sched, registered(&driver, _, _))
+    .Times(1);
+
+  Future<vector<Offer> > offers;
+  EXPECT_CALL(sched, resourceOffers(&driver, _))
+    .WillOnce(FutureArg<1>(&offers))
+    .WillRepeatedly(Return()); // Ignore subsequent offers.
+
+  driver.start();
+
+  AWAIT_READY(offers);
+  EXPECT_NE(0u, offers.get().size());
+
+  TaskInfo task = createTask(offers.get()[0], "", DEFAULT_EXECUTOR_ID);
+  vector<TaskInfo> tasks;
+  tasks.push_back(task);
+
+  // Return a pending future from authorizer.
+  Future<Nothing> future;
+  Promise<bool> promise;
+  EXPECT_CALL(authorizer, authorize(An<const mesos::ACL::RunTasks&>()))
+    .WillOnce(DoAll(FutureSatisfy(&future),
+                    Return(promise.future())));
+
+  driver.launchTasks(offers.get()[0].id(), tasks);
+
+  // Wait until authorization is in progress.
+  AWAIT_READY(future);
+
+  // Scheduler shouldn't get an update from reconciliation.
+  EXPECT_CALL(sched, statusUpdate(&driver, _))
+    .Times(0);
+
+  Future<ReconcileTasksMessage> reconcileTasksMessage =
+    FUTURE_PROTOBUF(ReconcileTasksMessage(), _, _);
+
+  vector<TaskStatus> statuses;
+
+  TaskStatus status;
+  status.mutable_task_id()->CopyFrom(task.task_id());
+  status.mutable_slave_id()->CopyFrom(offers.get()[0].slave_id());
+  status.set_state(TASK_STAGING);
+
+  statuses.push_back(status);
+
+  driver.reconcileTasks(statuses);
+
+  AWAIT_READY(reconcileTasksMessage);
+
+  // Make sure the framework doesn't receive any update.
+  Clock::pause();
+  Clock::settle();
+
+  // Now stop the framework.
+  driver.stop();
+  driver.join();
+
+  Shutdown(); // Must shutdown before 'containerizer' gets deallocated.
+}

http://git-wip-us.apache.org/repos/asf/mesos/blob/c4084554/src/tests/mesos.cpp
----------------------------------------------------------------------
diff --git a/src/tests/mesos.cpp b/src/tests/mesos.cpp
index ea6a1c0..e6d807c 100644
--- a/src/tests/mesos.cpp
+++ b/src/tests/mesos.cpp
@@ -27,6 +27,8 @@
 #include <stout/stringify.hpp>
 #include <stout/uuid.hpp>
 
+#include "authorizer/authorizer.hpp"
+
 #ifdef __linux__
 #include "linux/cgroups.hpp"
 #endif
@@ -199,6 +201,28 @@ Try<process::PID<master::Master> > MesosTest::StartMaster(
 }
 
 
+Try<process::PID<master::Master> > MesosTest::StartMaster(
+    Authorizer* authorizer,
+    const Option<master::Flags>& flags,
+    bool wait)
+{
+  Future<Nothing> detected = FUTURE_DISPATCH(_, &master::Master::detected);
+
+  Try<process::PID<master::Master> > master = cluster.masters.start(
+      authorizer, flags.isNone() ? CreateMasterFlags() : flags.get());
+
+  // Wait until the leader is detected because otherwise this master
+  // may reject authentication requests because it doesn't know it's
+  // the leader yet [MESOS-881].
+  if (wait && master.isSome() && !detected.await(Seconds(10))) {
+    return Error("Failed to wait " + stringify(Seconds(10)) +
+                 " for master to detect the leader");
+  }
+
+  return master;
+}
+
+
 Try<process::PID<slave::Slave> > MesosTest::StartSlave(
     const Option<slave::Flags>& flags)
 {

http://git-wip-us.apache.org/repos/asf/mesos/blob/c4084554/src/tests/mesos.hpp
----------------------------------------------------------------------
diff --git a/src/tests/mesos.hpp b/src/tests/mesos.hpp
index 2e01e5e..0b9b2f9 100644
--- a/src/tests/mesos.hpp
+++ b/src/tests/mesos.hpp
@@ -41,6 +41,8 @@
 #include <stout/try.hpp>
 #include <stout/uuid.hpp>
 
+#include "authorizer/authorizer.hpp"
+
 #include "messages/messages.hpp" // For google::protobuf::Message.
 
 #include "master/allocator.hpp"
@@ -101,6 +103,14 @@ protected:
       const Option<master::Flags>& flags = None(),
       bool wait = true);
 
+  // Starts a master with the specified authorizer and flags.
+  // Waits for the master to detect a leader (could be itself) before
+  // returning if 'wait' is set to true.
+  virtual Try<process::PID<master::Master> > StartMaster(
+      Authorizer* authorizer,
+      const Option<master::Flags>& flags = None(),
+      bool wait = true);
+
   // Starts a slave with the specified flags.
   virtual Try<process::PID<slave::Slave> > StartSlave(
       const Option<slave::Flags>& flags = None());
@@ -469,6 +479,42 @@ public:
 };
 
 
+// Definition of a MockAuthozier that can be used in tests with gmock.
+class MockAuthorizer : public Authorizer
+{
+public:
+  MockAuthorizer()
+  {
+    using ::testing::An;
+    using ::testing::Return;
+
+    // NOTE: We use 'EXPECT_CALL' and 'WillRepeatedly' here instead of
+    // 'ON_CALL' and 'WillByDefault'. See 'TestContainerizer::SetUp()'
+    // for more details.
+    EXPECT_CALL(*this, authorize(An<const mesos::ACL::RunTasks&>()))
+      .WillRepeatedly(Return(true));
+
+    EXPECT_CALL(*this, authorize(An<const mesos::ACL::ReceiveOffers&>()))
+      .WillRepeatedly(Return(true));
+
+    EXPECT_CALL(*this, authorize(An<const mesos::ACL::HTTPGet&>()))
+      .WillRepeatedly(Return(true));
+
+    EXPECT_CALL(*this, authorize(An<const mesos::ACL::HTTPPut&>()))
+      .WillRepeatedly(Return(true));
+  }
+
+  MOCK_METHOD1(
+      authorize, process::Future<bool>(const ACL::RunTasks& request));
+  MOCK_METHOD1(
+      authorize, process::Future<bool>(const ACL::ReceiveOffers& request));
+  MOCK_METHOD1(
+      authorize, process::Future<bool>(const ACL::HTTPGet& request));
+  MOCK_METHOD1(
+      authorize, process::Future<bool>(const ACL::HTTPPut& request));
+};
+
+
 template <typename T = master::allocator::AllocatorProcess>
 class MockAllocatorProcess : public master::allocator::AllocatorProcess
 {