diff --git a/docs/docs/api.md b/docs/docs/api.md index 37dbdae73..aa049a8c1 100644 --- a/docs/docs/api.md +++ b/docs/docs/api.md @@ -31,6 +31,13 @@ All examples in this section assume that you've found a running leader at `chron When you have multiple Chronos nodes running, only one of them will be elected as the leader. The leader is the only node that responds to API requests, but if you attempt to talk to a non-leader your request will automatically be redirected to a leader. +To get the current leader you can hit the following endpoint. + +* Endpoint: __/leader__ +* Method: __GET__ +* Example: `curl -L chronos-node:8080/leader` +* Response: A JSON dict containing a single `leader` key. + ## Listing Jobs * Endpoint: __/scheduler/jobs__ diff --git a/src/main/scala/org/apache/mesos/chronos/scheduler/api/ChronosRestModule.scala b/src/main/scala/org/apache/mesos/chronos/scheduler/api/ChronosRestModule.scala index 22bd749ac..6adbbdc00 100644 --- a/src/main/scala/org/apache/mesos/chronos/scheduler/api/ChronosRestModule.scala +++ b/src/main/scala/org/apache/mesos/chronos/scheduler/api/ChronosRestModule.scala @@ -52,6 +52,7 @@ class ChronosRestModule extends ServletModule { bind(classOf[MetricsServlet]).in(Scopes.SINGLETON) bind(classOf[LogConfigServlet]).in(Scopes.SINGLETON) bind(classOf[ConstraintViolationExceptionMapper]).in(Scopes.SINGLETON) + bind(classOf[LeaderResource]).in(Scopes.SINGLETON) serve(pingUrl).`with`(classOf[PingServlet]) serve(metricsUrl).`with`(classOf[MetricsServlet]) diff --git a/src/main/scala/org/apache/mesos/chronos/scheduler/api/LeaderRestModule.scala b/src/main/scala/org/apache/mesos/chronos/scheduler/api/LeaderRestModule.scala new file mode 100644 index 000000000..b0ce4ba01 --- /dev/null +++ b/src/main/scala/org/apache/mesos/chronos/scheduler/api/LeaderRestModule.scala @@ -0,0 +1,18 @@ +package org.apache.mesos.chronos.scheduler.api + +import org.apache.mesos.chronos.scheduler.jobs.JobScheduler +import javax.ws.rs.core.{MediaType, Response} +import javax.ws.rs.{GET, Path, Produces} +import com.google.inject.Inject + + +@Path(PathConstants.getLeaderPattern) +@Produces(Array(MediaType.APPLICATION_JSON)) +class LeaderResource @Inject()( + val jobScheduler: JobScheduler +) { + @GET + def getLeader(): Response = { + Response.ok(Map("leader" -> jobScheduler.getLeader)).build + } +} diff --git a/src/main/scala/org/apache/mesos/chronos/scheduler/api/PathConstants.scala b/src/main/scala/org/apache/mesos/chronos/scheduler/api/PathConstants.scala index 186307dea..c67aba0c6 100644 --- a/src/main/scala/org/apache/mesos/chronos/scheduler/api/PathConstants.scala +++ b/src/main/scala/org/apache/mesos/chronos/scheduler/api/PathConstants.scala @@ -20,6 +20,7 @@ object PathConstants { final val jobGraphDotPath = "dot" final val jobGraphCsvPath = "csv" final val killTaskPattern = "kill/{jobName}" + final val getLeaderPattern = "/leader" final val isMasterPath = "isMaster" final val taskBasePath = "/task"