100 lines
2.5 KiB
Go
100 lines
2.5 KiB
Go
package apiserver
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/pprof"
|
|
"regexp"
|
|
"sync"
|
|
|
|
"encoding/json"
|
|
"github.com/Sirupsen/logrus"
|
|
)
|
|
|
|
type ClusterInformer interface {
|
|
Status() interface{}
|
|
ClusterStatus(team, cluster string) interface{}
|
|
}
|
|
|
|
type Server struct {
|
|
logger *logrus.Entry
|
|
http http.Server
|
|
controller ClusterInformer
|
|
}
|
|
|
|
var (
|
|
clusterStatusURL = regexp.MustCompile("^/clusters/(?P<team>[a-zA-Z][a-zA-Z0-9]*)/(?P<cluster>[a-zA-Z][a-zA-Z0-9]*)/?$")
|
|
teamURL = regexp.MustCompile("^/clusters/(?P<team>[a-zA-Z][a-zA-Z0-9]*)/?$")
|
|
)
|
|
|
|
func New(controller ClusterInformer, port int, logger *logrus.Logger) *Server {
|
|
s := &Server{
|
|
logger: logger.WithField("pkg", "apiserver"),
|
|
controller: controller,
|
|
}
|
|
mux := http.NewServeMux()
|
|
|
|
mux.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index))
|
|
mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline))
|
|
mux.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile))
|
|
mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol))
|
|
mux.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace))
|
|
mux.HandleFunc("/status", func(w http.ResponseWriter, req *http.Request) {
|
|
status := s.controller.Status()
|
|
|
|
b, err := json.Marshal(status)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
fmt.Fprintf(w, "Could not marshal controller status: %v", err)
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write(b)
|
|
})
|
|
mux.HandleFunc("/clusters/", func(w http.ResponseWriter, req *http.Request) {
|
|
var resp interface{}
|
|
if matches := clusterStatusURL.FindAllStringSubmatch(req.URL.Path, -1); matches != nil {
|
|
resp = s.controller.ClusterStatus(matches[0][1], matches[0][2])
|
|
} else if matches := teamURL.FindAllStringSubmatch(req.URL.Path, -1); matches != nil {
|
|
// TODO
|
|
} else {
|
|
http.NotFound(w, req)
|
|
return
|
|
}
|
|
|
|
b, err := json.Marshal(resp)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
fmt.Fprintf(w, "Could not marshal %T: %v", resp, err)
|
|
} else {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write(b)
|
|
}
|
|
})
|
|
|
|
s.http = http.Server{
|
|
Addr: fmt.Sprintf(":%d", port),
|
|
Handler: mux,
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
func (s *Server) Run(stopCh <-chan struct{}, wg *sync.WaitGroup) {
|
|
defer wg.Done()
|
|
|
|
go func() {
|
|
err := s.http.ListenAndServe()
|
|
if err != http.ErrServerClosed {
|
|
s.logger.Fatalf("could not start http server: %v", err)
|
|
}
|
|
}()
|
|
s.logger.Infof("listening on %s", s.http.Addr)
|
|
|
|
<-stopCh
|
|
|
|
ctx, _ := context.WithCancel(context.Background())
|
|
s.http.Shutdown(ctx)
|
|
}
|