mirror of https://github.com/k3s-io/k3s
Split operations code and add comments
parent
9069696514
commit
fe7f611d88
|
@ -79,35 +79,32 @@ func New(storage map[string]RESTStorage, prefix string) *APIServer {
|
|||
mux: http.NewServeMux(),
|
||||
}
|
||||
|
||||
s.mux.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log/"))))
|
||||
// Primary API methods
|
||||
s.mux.HandleFunc(s.prefix+"/", s.handleREST)
|
||||
healthz.InstallHandler(s.mux)
|
||||
s.mux.HandleFunc(s.watchPrefix()+"/", s.handleWatch)
|
||||
|
||||
s.mux.HandleFunc("/version", s.handleVersionReq)
|
||||
// Support services for the apiserver
|
||||
s.mux.Handle("/logs/", http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log/"))))
|
||||
healthz.InstallHandler(s.mux)
|
||||
s.mux.HandleFunc("/version", handleVersion)
|
||||
s.mux.HandleFunc("/", handleIndex)
|
||||
|
||||
// Handle both operations and operations/* with the same handler
|
||||
s.mux.HandleFunc(s.operationPrefix(), s.handleOperationRequest)
|
||||
s.mux.HandleFunc(s.operationPrefix()+"/", s.handleOperationRequest)
|
||||
|
||||
s.mux.HandleFunc(s.watchPrefix()+"/", s.handleWatch)
|
||||
|
||||
// Proxy minion requests
|
||||
s.mux.HandleFunc("/proxy/minion/", s.handleProxyMinion)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// handleVersionReq writes the server's version information.
|
||||
func (s *APIServer) handleVersionReq(w http.ResponseWriter, req *http.Request) {
|
||||
writeRawJSON(http.StatusOK, version.Get(), w)
|
||||
}
|
||||
|
||||
// HTTP Handler interface
|
||||
// ServeHTTP implements the standard net/http interface.
|
||||
func (s *APIServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprint(w, "apiserver panic. Look in log for details.")
|
||||
fmt.Fprint(w, "apis panic. Look in log for details.")
|
||||
glog.Infof("APIServer panic'd on %v %v: %#v\n%s\n", req.Method, req.RequestURI, x, debug.Stack())
|
||||
}
|
||||
}()
|
||||
|
@ -145,33 +142,6 @@ func (s *APIServer) handleREST(w http.ResponseWriter, req *http.Request) {
|
|||
s.handleRESTStorage(requestParts, req, w, storage)
|
||||
}
|
||||
|
||||
// finishReq finishes up a request, waiting until the operation finishes or, after a timeout, creating an
|
||||
// Operation to receive the result and returning its ID down the writer.
|
||||
func (s *APIServer) finishReq(out <-chan interface{}, sync bool, timeout time.Duration, w http.ResponseWriter) {
|
||||
op := s.ops.NewOperation(out)
|
||||
if sync {
|
||||
op.WaitFor(timeout)
|
||||
}
|
||||
obj, complete := op.StatusOrResult()
|
||||
if complete {
|
||||
status := http.StatusOK
|
||||
switch stat := obj.(type) {
|
||||
case api.Status:
|
||||
httplog.LogOf(w).Addf("programmer error: use *api.Status as a result, not api.Status.")
|
||||
if stat.Code != 0 {
|
||||
status = stat.Code
|
||||
}
|
||||
case *api.Status:
|
||||
if stat.Code != 0 {
|
||||
status = stat.Code
|
||||
}
|
||||
}
|
||||
writeJSON(status, obj, w)
|
||||
} else {
|
||||
writeJSON(http.StatusAccepted, obj, w)
|
||||
}
|
||||
}
|
||||
|
||||
// handleRESTStorage is the main dispatcher for a storage object. It switches on the HTTP method, and then
|
||||
// on path length, according to the following table:
|
||||
// Method Path Action
|
||||
|
@ -217,6 +187,7 @@ func (s *APIServer) handleRESTStorage(parts []string, req *http.Request, w http.
|
|||
default:
|
||||
notFound(w, req)
|
||||
}
|
||||
|
||||
case "POST":
|
||||
if len(parts) != 1 {
|
||||
notFound(w, req)
|
||||
|
@ -245,7 +216,9 @@ func (s *APIServer) handleRESTStorage(parts []string, req *http.Request, w http.
|
|||
internalError(err, w)
|
||||
return
|
||||
}
|
||||
s.finishReq(out, sync, timeout, w)
|
||||
op := s.createOperation(out, sync, timeout)
|
||||
s.finishReq(op, w)
|
||||
|
||||
case "DELETE":
|
||||
if len(parts) != 2 {
|
||||
notFound(w, req)
|
||||
|
@ -260,7 +233,9 @@ func (s *APIServer) handleRESTStorage(parts []string, req *http.Request, w http.
|
|||
internalError(err, w)
|
||||
return
|
||||
}
|
||||
s.finishReq(out, sync, timeout, w)
|
||||
op := s.createOperation(out, sync, timeout)
|
||||
s.finishReq(op, w)
|
||||
|
||||
case "PUT":
|
||||
if len(parts) != 2 {
|
||||
notFound(w, req)
|
||||
|
@ -289,12 +264,51 @@ func (s *APIServer) handleRESTStorage(parts []string, req *http.Request, w http.
|
|||
internalError(err, w)
|
||||
return
|
||||
}
|
||||
s.finishReq(out, sync, timeout, w)
|
||||
op := s.createOperation(out, sync, timeout)
|
||||
s.finishReq(op, w)
|
||||
|
||||
default:
|
||||
notFound(w, req)
|
||||
}
|
||||
}
|
||||
|
||||
// handleVersionReq writes the server's version information.
|
||||
func handleVersion(w http.ResponseWriter, req *http.Request) {
|
||||
writeRawJSON(http.StatusOK, version.Get(), w)
|
||||
}
|
||||
|
||||
// createOperation creates an operation to process a channel response
|
||||
func (s *APIServer) createOperation(out <-chan interface{}, sync bool, timeout time.Duration) *Operation {
|
||||
op := s.ops.NewOperation(out)
|
||||
if sync {
|
||||
op.WaitFor(timeout)
|
||||
}
|
||||
return op
|
||||
}
|
||||
|
||||
// finishReq finishes up a request, waiting until the operation finishes or, after a timeout, creating an
|
||||
// Operation to receive the result and returning its ID down the writer.
|
||||
func (s *APIServer) finishReq(op *Operation, w http.ResponseWriter) {
|
||||
obj, complete := op.StatusOrResult()
|
||||
if complete {
|
||||
status := http.StatusOK
|
||||
switch stat := obj.(type) {
|
||||
case api.Status:
|
||||
httplog.LogOf(w).Addf("programmer error: use *api.Status as a result, not api.Status.")
|
||||
if stat.Code != 0 {
|
||||
status = stat.Code
|
||||
}
|
||||
case *api.Status:
|
||||
if stat.Code != 0 {
|
||||
status = stat.Code
|
||||
}
|
||||
}
|
||||
writeJSON(status, obj, w)
|
||||
} else {
|
||||
writeJSON(http.StatusAccepted, obj, w)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *APIServer) operationPrefix() string {
|
||||
return path.Join(s.prefix, "operations")
|
||||
}
|
||||
|
@ -340,6 +354,7 @@ func (s *APIServer) watchPrefix() string {
|
|||
return path.Join(s.prefix, "watch")
|
||||
}
|
||||
|
||||
// handleWatch processes a watch request
|
||||
func (s *APIServer) handleWatch(w http.ResponseWriter, req *http.Request) {
|
||||
prefix := s.watchPrefix()
|
||||
if !strings.HasPrefix(req.URL.Path, prefix) {
|
||||
|
@ -381,6 +396,7 @@ func (s *APIServer) handleWatch(w http.ResponseWriter, req *http.Request) {
|
|||
notFound(w, req)
|
||||
}
|
||||
|
||||
// writeJSON renders an object as JSON to the response
|
||||
func writeJSON(statusCode int, object interface{}, w http.ResponseWriter) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(statusCode)
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"net/http"
|
||||
)
|
||||
|
||||
// internalError renders a generic error to the response
|
||||
func internalError(err error, w http.ResponseWriter) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, "Internal Error: %#v", err)
|
||||
|
|
Loading…
Reference in New Issue