This repository has been archived by the owner on Nov 18, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Joshua Deare
committed
Sep 20, 2016
1 parent
426748f
commit 982a5a2
Showing
11 changed files
with
283 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package api | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/compose/governor/fsm" | ||
"github.com/compose/governor/ha" | ||
"github.com/compose/governor/service" | ||
"github.com/gorilla/mux" | ||
"github.com/pkg/errors" | ||
"net/http" | ||
) | ||
|
||
func Router(singleFSM fsm.SingleLeaderFSM, singleHA *ha.SingleLeaderHA, singleService service.SingleLeaderService) (*mux.Router, error) { | ||
r := mux.NewRouter() | ||
if err := registerFSMRouter(singleFSM, singleService, r.PathPrefix("/fsm").Subrouter()); err != nil { | ||
return nil, errors.Wrap(err, "Error registering FSM subrouter for API") | ||
} | ||
if err := registerServiceRouter(singleService, r.PathPrefix("/service").Subrouter()); err != nil { | ||
return nil, errors.Wrap(err, "Error registering Service subrouter for API") | ||
} | ||
if err := registerHARouter(singleHA, r.PathPrefix("/ha").Subrouter()); err != nil { | ||
return nil, errors.Wrap(err, "Error registering HA subrouter for API") | ||
} | ||
return r, nil | ||
} | ||
|
||
type apiSuccessResponse struct { | ||
Data interface{} `json:"data,omitempty"` | ||
} | ||
type apiErrorResponse struct { | ||
Errors []error `json:"errors"` | ||
} | ||
|
||
func sendResponse(code int, jsonData interface{}, errorMsgs []error, w http.ResponseWriter) error { | ||
var resp interface{} | ||
if len(errorMsgs) > 0 { | ||
resp = apiErrorResponse{Errors: errorMsgs} | ||
} else if jsonData != nil { | ||
resp = apiSuccessResponse{Data: jsonData} | ||
} else { | ||
return errors.New("Must supply either errorsMsgs or jsonDATA to response") | ||
} | ||
|
||
w.Header().Set("Content-Type", "application/json") | ||
w.WriteHeader(code) | ||
|
||
if resp == nil { | ||
return nil | ||
} | ||
|
||
if err := json.NewEncoder(w).Encode(resp); err != nil { | ||
return errors.Wrap(err, "Error encoding JSON into response body") | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package api | ||
|
||
import ( | ||
log "github.com/Sirupsen/logrus" | ||
"github.com/compose/governor/fsm" | ||
"github.com/compose/governor/service" | ||
"github.com/gorilla/mux" | ||
"github.com/pkg/errors" | ||
"net/http" | ||
) | ||
|
||
// TODO: Add long listener for updates | ||
func registerFSMRouter(singleFSM fsm.SingleLeaderFSM, singleService service.SingleLeaderService, r *mux.Router) error { | ||
r.HandleFunc("/id", singleFSMIDHandler(singleFSM)).Methods("GET") | ||
r.HandleFunc("/leader", singleFSMLeaderHandler(singleFSM, singleService)).Methods("GET") | ||
r.HandleFunc("/member/{id}", singleFSMMemberHandler(singleFSM, singleService)).Methods("GET") | ||
r.HandleFunc("/members", singleFSMMembersHandler(singleFSM, singleService)).Methods("GET") | ||
return nil | ||
} | ||
|
||
func singleFSMIDHandler(singleFSM fsm.SingleLeaderFSM) http.HandlerFunc { | ||
type idAPIResp struct { | ||
ID uint64 `json:"id"` | ||
} | ||
return func(w http.ResponseWriter, req *http.Request) { | ||
id := singleFSM.UniqueID() | ||
if err := sendResponse(200, idAPIResp{ID: id}, []error{}, w); err != nil { | ||
log.Error("Error sending response for ID request") | ||
} | ||
} | ||
} | ||
|
||
func singleFSMLeaderHandler(singleFSM fsm.SingleLeaderFSM, singleService service.SingleLeaderService) http.HandlerFunc { | ||
type leaderAPIResp struct { | ||
Leader fsm.Leader `json:"leader"` | ||
Exists bool `json:"exists"` | ||
} | ||
return func(w http.ResponseWriter, req *http.Request) { | ||
leaderData, exists, err := singleFSM.Leader() | ||
if err != nil { | ||
if err := sendResponse(500, nil, []error{err}, w); err != nil { | ||
log.Error("Error sending error response") | ||
} | ||
} | ||
leader, err := singleService.FSMLeaderFromBytes(leaderData) | ||
if err != nil { | ||
if err := sendResponse(500, nil, []error{err}, w); err != nil { | ||
log.Error("Error sending error response") | ||
} | ||
} | ||
if err := sendResponse(200, leaderAPIResp{Leader: leader, Exists: exists}, []error{}, w); err != nil { | ||
log.Error("Error sending leader response") | ||
|
||
} | ||
} | ||
} | ||
|
||
func singleFSMMemberHandler(singleFSM fsm.SingleLeaderFSM, singleService service.SingleLeaderService) http.HandlerFunc { | ||
type memberAPIResp struct { | ||
Member fsm.Member `json:"member"` | ||
Exists bool `json:"exists"` | ||
} | ||
return func(w http.ResponseWriter, req *http.Request) { | ||
vars := mux.Vars(req) | ||
id, ok := vars["id"] | ||
if !ok { | ||
if err := sendResponse(400, nil, []error{errors.New("ID Not provided in request for member")}, w); err != nil { | ||
log.Error("Error sending error response") | ||
} | ||
} | ||
|
||
memberData, exists, err := singleFSM.Member(id) | ||
if err != nil { | ||
if err := sendResponse(500, nil, []error{err}, w); err != nil { | ||
log.Error("Error sending error response") | ||
} | ||
} | ||
member, err := singleService.FSMMemberFromBytes(memberData) | ||
if err != nil { | ||
if err := sendResponse(500, nil, []error{err}, w); err != nil { | ||
log.Error("Error sending error response") | ||
} | ||
} | ||
if err := sendResponse(200, memberAPIResp{Member: member, Exists: exists}, []error{}, w); err != nil { | ||
log.Error("Error sending leader response") | ||
|
||
} | ||
} | ||
} | ||
|
||
func singleFSMMembersHandler(singleFSM fsm.SingleLeaderFSM, singleService service.SingleLeaderService) http.HandlerFunc { | ||
type membersAPIResp struct { | ||
Members []fsm.Member `json:"members"` | ||
} | ||
return func(w http.ResponseWriter, req *http.Request) { | ||
membersData, err := singleFSM.Members() | ||
members := []fsm.Member{} | ||
for _, memberData := range membersData { | ||
member, err := singleService.FSMMemberFromBytes(memberData) | ||
if err != nil { | ||
if err := sendResponse(500, nil, []error{err}, w); err != nil { | ||
log.Error("Error sending error response") | ||
} | ||
} | ||
members = append(members, member) | ||
} | ||
if err != nil { | ||
if err := sendResponse(500, nil, []error{err}, w); err != nil { | ||
log.Error("Error sending error response") | ||
} | ||
} | ||
if err := sendResponse(200, membersAPIResp{Members: members}, []error{}, w); err != nil { | ||
log.Error("Error sending leader response") | ||
|
||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package api | ||
|
||
import ( | ||
log "github.com/Sirupsen/logrus" | ||
"github.com/compose/governor/ha" | ||
"github.com/gorilla/mux" | ||
"net/http" | ||
) | ||
|
||
func registerHARouter(singleHA *ha.SingleLeaderHA, r *mux.Router) error { | ||
r.HandleFunc("/is_leader", singleHAIsLeaderHandler(singleHA)).Methods("GET") | ||
return nil | ||
} | ||
|
||
func singleHAIsLeaderHandler(singleHA *ha.SingleLeaderHA) http.HandlerFunc { | ||
type isLeaderAPIResp struct { | ||
IsLeader bool `json:"is_leader"` | ||
} | ||
return func(w http.ResponseWriter, req *http.Request) { | ||
isLeader, err := singleHA.IsLeader() | ||
if err != nil { | ||
sendResponse(500, nil, []error{err}, w) | ||
} | ||
if err := sendResponse(200, isLeaderAPIResp{IsLeader: isLeader}, []error{}, w); err != nil { | ||
log.Error("Error sending response for request") | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package api | ||
|
||
import ( | ||
log "github.com/Sirupsen/logrus" | ||
"github.com/compose/governor/service" | ||
"github.com/gorilla/mux" | ||
"net/http" | ||
) | ||
|
||
func registerServiceRouter(singleService service.SingleLeaderService, r *mux.Router) error { | ||
r.HandleFunc("/running_as_leader", singleServiceRunningAsLeaderHandler(singleService)).Methods("GET") | ||
r.HandleFunc("/is_running", singleServiceIsRunningHandler(singleService)).Methods("GET") | ||
r.HandleFunc("/is_healthy", singleServiceIsHealthyHandler(singleService)).Methods("GET") | ||
return nil | ||
} | ||
|
||
func singleServiceRunningAsLeaderHandler(singleService service.SingleLeaderService) http.HandlerFunc { | ||
type isLeaderAPIResp struct { | ||
RunningAsLeader bool `json:"running_as_leader"` | ||
} | ||
return func(w http.ResponseWriter, req *http.Request) { | ||
runningAsLeader := singleService.RunningAsLeader() | ||
if err := sendResponse(200, isLeaderAPIResp{RunningAsLeader: runningAsLeader}, []error{}, w); err != nil { | ||
log.Error("Error sending response for ID request") | ||
} | ||
} | ||
} | ||
|
||
func singleServiceIsRunningHandler(singleService service.SingleLeaderService) http.HandlerFunc { | ||
type isRunningAPIResp struct { | ||
IsRunning bool `json:"is_running"` | ||
} | ||
return func(w http.ResponseWriter, req *http.Request) { | ||
running := singleService.IsRunning() | ||
if err := sendResponse(200, isRunningAPIResp{IsRunning: running}, []error{}, w); err != nil { | ||
log.Error("Error sending response for ID request") | ||
} | ||
} | ||
} | ||
|
||
func singleServiceIsHealthyHandler(singleService service.SingleLeaderService) http.HandlerFunc { | ||
type isHealthyAPIResp struct { | ||
IsHealthy bool `json:"is_healthy"` | ||
} | ||
return func(w http.ResponseWriter, req *http.Request) { | ||
healthy := singleService.IsHealthy() | ||
if err := sendResponse(200, isHealthyAPIResp{IsHealthy: healthy}, []error{}, w); err != nil { | ||
log.Error("Error sending response for ID request") | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters