Added cluster/leader endpoint
This commit is contained in:
parent
0fa0c2256a
commit
9699dc2a85
3 changed files with 55 additions and 0 deletions
|
@ -2,15 +2,22 @@ package cluster
|
|||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/cenk/backoff"
|
||||
"github.com/containous/mux"
|
||||
"github.com/containous/traefik/log"
|
||||
"github.com/containous/traefik/safe"
|
||||
"github.com/containous/traefik/types"
|
||||
"github.com/docker/leadership"
|
||||
"github.com/unrolled/render"
|
||||
)
|
||||
|
||||
var templatesRenderer = render.New(render.Options{
|
||||
Directory: "nowhere",
|
||||
})
|
||||
|
||||
// Leadership allows leadership election using a KV store
|
||||
type Leadership struct {
|
||||
*safe.Pool
|
||||
|
@ -98,7 +105,32 @@ func (l *Leadership) onElection(elected bool) {
|
|||
}
|
||||
}
|
||||
|
||||
type leaderResponse struct {
|
||||
Leader bool `json:"leader"`
|
||||
}
|
||||
|
||||
func (l *Leadership) getLeaderHandler(response http.ResponseWriter, request *http.Request) {
|
||||
leader := &leaderResponse{Leader: l.IsLeader()}
|
||||
|
||||
status := http.StatusOK
|
||||
if !leader.Leader {
|
||||
// Set status to be `429`, as this will typically cause load balancers to stop sending requests to the instance without removing them from rotation.
|
||||
status = http.StatusTooManyRequests
|
||||
}
|
||||
|
||||
err := templatesRenderer.JSON(response, status, leader)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// IsLeader returns true if current node is leader
|
||||
func (l *Leadership) IsLeader() bool {
|
||||
return l.leader.Get().(bool)
|
||||
}
|
||||
|
||||
// AddRoutes add dashboard routes on a router
|
||||
func (l *Leadership) AddRoutes(router *mux.Router) {
|
||||
// Expose cluster leader
|
||||
router.Methods(http.MethodGet).Path("/api/cluster/leader").HandlerFunc(l.getLeaderHandler)
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ For more customization, see [entry points](/configuration/entrypoints/) document
|
|||
| Path | Method | Description |
|
||||
|-----------------------------------------------------------------|------------------|-------------------------------------------|
|
||||
| `/` | `GET` | Provides a simple HTML frontend of Træfik |
|
||||
| `/cluster/leader` | `GET` | JSON leader true/false response |
|
||||
| `/health` | `GET` | JSON health metrics |
|
||||
| `/api` | `GET` | Configuration for all providers |
|
||||
| `/api/providers` | `GET` | Providers |
|
||||
|
@ -222,6 +223,25 @@ curl -s "http://localhost:8080/api" | jq .
|
|||
}
|
||||
```
|
||||
|
||||
### Cluster Leadership
|
||||
|
||||
```shell
|
||||
curl -s "http://localhost:8080/cluster/leader" | jq .
|
||||
```
|
||||
```shell
|
||||
< HTTP/1.1 200 OK
|
||||
< Content-Type: application/json; charset=UTF-8
|
||||
< Date: xxx
|
||||
< Content-Length: 15
|
||||
```
|
||||
If the given node is not a cluster leader, an HTTP status of `429-Too-Many-Requests` will be returned.
|
||||
```json
|
||||
{
|
||||
// current leadership status of the queried node
|
||||
"leader": true
|
||||
}
|
||||
```
|
||||
|
||||
### Health
|
||||
|
||||
```shell
|
||||
|
|
|
@ -739,6 +739,9 @@ func (s *Server) addInternalRoutes(entryPointName string, router *mux.Router) {
|
|||
|
||||
if s.globalConfiguration.API != nil && s.globalConfiguration.API.EntryPoint == entryPointName {
|
||||
s.globalConfiguration.API.AddRoutes(router)
|
||||
if s.leadership != nil {
|
||||
s.leadership.AddRoutes(router)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue