Convert remaining http handlers over to use util.SendError

Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
(cherry picked from commit f8e0648304)
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
pull/10288/head
Brad Davidson 2024-04-25 23:49:47 +00:00 committed by Brad Davidson
parent 7ef30a2c60
commit 0a728b8ff9
9 changed files with 30 additions and 58 deletions

View File

@ -1,7 +1,10 @@
package cluster package cluster
import ( import (
"fmt"
"net/http" "net/http"
"github.com/k3s-io/k3s/pkg/util"
) )
// getHandler returns a basic request handler that processes requests through // getHandler returns a basic request handler that processes requests through
@ -19,11 +22,10 @@ func (c *Cluster) getHandler(handler http.Handler) (http.Handler, error) {
// if no additional handlers are available. // if no additional handlers are available.
func (c *Cluster) router() http.Handler { func (c *Cluster) router() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if c.config.Runtime.Handler == nil { if c.config.Runtime.Handler != nil {
http.Error(rw, "starting", http.StatusServiceUnavailable) c.config.Runtime.Handler.ServeHTTP(rw, req)
return } else {
util.SendError(fmt.Errorf("starting"), rw, req, http.StatusServiceUnavailable)
} }
c.config.Runtime.Handler.ServeHTTP(rw, req)
}) })
} }

View File

@ -29,8 +29,7 @@ var defaultDialer = net.Dialer{}
func loggingErrorWriter(rw http.ResponseWriter, req *http.Request, code int, err error) { func loggingErrorWriter(rw http.ResponseWriter, req *http.Request, code int, err error) {
logrus.Debugf("Tunnel server error: %d %v", code, err) logrus.Debugf("Tunnel server error: %d %v", code, err)
rw.WriteHeader(code) util.SendError(err, rw, req, code)
rw.Write([]byte(err.Error()))
} }
func setupTunnel(ctx context.Context, cfg *config.Control) (http.Handler, error) { func setupTunnel(ctx context.Context, cfg *config.Control) (http.Handler, error) {

View File

@ -761,7 +761,7 @@ func getEndpoints(control *config.Control) []string {
// for use by etcd. // for use by etcd.
func toTLSConfig(runtime *config.ControlRuntime) (*tls.Config, error) { func toTLSConfig(runtime *config.ControlRuntime) (*tls.Config, error) {
if runtime.ClientETCDCert == "" || runtime.ClientETCDKey == "" || runtime.ETCDServerCA == "" { if runtime.ClientETCDCert == "" || runtime.ClientETCDKey == "" || runtime.ETCDServerCA == "" {
return nil, errors.New("runtime is not ready yet") return nil, util.ErrCoreNotReady
} }
clientCert, err := tls.LoadX509KeyPair(runtime.ClientETCDCert, runtime.ClientETCDKey) clientCert, err := tls.LoadX509KeyPair(runtime.ClientETCDCert, runtime.ClientETCDKey)
@ -1177,7 +1177,7 @@ func (e *ETCD) manageLearners(ctx context.Context) {
func (e *ETCD) getETCDNodes() ([]*v1.Node, error) { func (e *ETCD) getETCDNodes() ([]*v1.Node, error) {
if e.config.Runtime.Core == nil { if e.config.Runtime.Core == nil {
return nil, errors.New("runtime core not ready") return nil, util.ErrCoreNotReady
} }
nodes := e.config.Runtime.Core.Core().V1().Node() nodes := e.config.Runtime.Core.Core().V1().Node()

View File

@ -30,8 +30,8 @@ import (
func caCertReplaceHandler(server *config.Control) http.HandlerFunc { func caCertReplaceHandler(server *config.Control) http.HandlerFunc {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil || req.Method != http.MethodPut { if req.Method != http.MethodPut {
resp.WriteHeader(http.StatusNotFound) util.SendError(fmt.Errorf("method not allowed"), resp, req, http.StatusMethodNotAllowed)
return return
} }
force, _ := strconv.ParseBool(req.FormValue("force")) force, _ := strconv.ParseBool(req.FormValue("force"))

View File

@ -200,11 +200,6 @@ func getCACertAndKeys(caCertFile, caKeyFile, signingKeyFile string) ([]*x509.Cer
func servingKubeletCert(server *config.Control, keyFile string, auth nodePassBootstrapper) http.Handler { func servingKubeletCert(server *config.Control, keyFile string, auth nodePassBootstrapper) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil {
resp.WriteHeader(http.StatusNotFound)
return
}
nodeName, errCode, err := auth(req) nodeName, errCode, err := auth(req)
if err != nil { if err != nil {
util.SendError(err, resp, req, errCode) util.SendError(err, resp, req, errCode)
@ -256,11 +251,6 @@ func servingKubeletCert(server *config.Control, keyFile string, auth nodePassBoo
func clientKubeletCert(server *config.Control, keyFile string, auth nodePassBootstrapper) http.Handler { func clientKubeletCert(server *config.Control, keyFile string, auth nodePassBootstrapper) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil {
resp.WriteHeader(http.StatusNotFound)
return
}
nodeName, errCode, err := auth(req) nodeName, errCode, err := auth(req)
if err != nil { if err != nil {
util.SendError(err, resp, req, errCode) util.SendError(err, resp, req, errCode)
@ -296,10 +286,6 @@ func clientKubeletCert(server *config.Control, keyFile string, auth nodePassBoot
func fileHandler(fileName ...string) http.Handler { func fileHandler(fileName ...string) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil {
resp.WriteHeader(http.StatusNotFound)
return
}
resp.Header().Set("Content-Type", "text/plain") resp.Header().Set("Content-Type", "text/plain")
if len(fileName) == 1 { if len(fileName) == 1 {
@ -310,8 +296,7 @@ func fileHandler(fileName ...string) http.Handler {
for _, f := range fileName { for _, f := range fileName {
bytes, err := os.ReadFile(f) bytes, err := os.ReadFile(f)
if err != nil { if err != nil {
logrus.Errorf("Failed to read %s: %v", f, err) util.SendError(errors.Wrapf(err, "failed to read %s", f), resp, req, http.StatusInternalServerError)
resp.WriteHeader(http.StatusInternalServerError)
return return
} }
resp.Write(bytes) resp.Write(bytes)
@ -336,18 +321,13 @@ func apiserversHandler(server *config.Control) http.Handler {
resp.Header().Set("content-type", "application/json") resp.Header().Set("content-type", "application/json")
if err := json.NewEncoder(resp).Encode(endpoints); err != nil { if err := json.NewEncoder(resp).Encode(endpoints); err != nil {
logrus.Errorf("Failed to encode apiserver endpoints: %v", err) util.SendError(errors.Wrap(err, "failed to encode apiserver endpoints"), resp, req, http.StatusInternalServerError)
resp.WriteHeader(http.StatusInternalServerError)
} }
}) })
} }
func configHandler(server *config.Control, cfg *cmds.Server) http.Handler { func configHandler(server *config.Control, cfg *cmds.Server) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil {
resp.WriteHeader(http.StatusNotFound)
return
}
// Startup hooks may read and modify cmds.Server in a goroutine, but as these are copied into // Startup hooks may read and modify cmds.Server in a goroutine, but as these are copied into
// config.Control before the startup hooks are called, any modifications need to be sync'd back // config.Control before the startup hooks are called, any modifications need to be sync'd back
// into the struct before it is sent to agents. // into the struct before it is sent to agents.
@ -355,23 +335,21 @@ func configHandler(server *config.Control, cfg *cmds.Server) http.Handler {
server.DisableKubeProxy = cfg.DisableKubeProxy server.DisableKubeProxy = cfg.DisableKubeProxy
resp.Header().Set("content-type", "application/json") resp.Header().Set("content-type", "application/json")
if err := json.NewEncoder(resp).Encode(server); err != nil { if err := json.NewEncoder(resp).Encode(server); err != nil {
logrus.Errorf("Failed to encode agent config: %v", err) util.SendError(errors.Wrap(err, "failed to encode agent config"), resp, req, http.StatusInternalServerError)
resp.WriteHeader(http.StatusInternalServerError)
} }
}) })
} }
func readyzHandler(server *config.Control) http.Handler { func readyzHandler(server *config.Control) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
code := http.StatusOK
data := []byte("ok")
if server.Runtime.Core == nil { if server.Runtime.Core == nil {
code = http.StatusInternalServerError util.SendError(util.ErrCoreNotReady, resp, req, http.StatusServiceUnavailable)
data = []byte("runtime core not ready") return
} }
resp.WriteHeader(code) data := []byte("ok")
resp.WriteHeader(http.StatusOK)
resp.Header().Set("Content-Type", "text/plain") resp.Header().Set("Content-Type", "text/plain")
resp.Header().Set("Content-length", strconv.Itoa(len(data))) resp.Header().Set("Content-Length", strconv.Itoa(len(data)))
resp.Write(data) resp.Write(data)
}) })
} }
@ -379,6 +357,7 @@ func readyzHandler(server *config.Control) http.Handler {
func ping() http.Handler { func ping() http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
data := []byte("pong") data := []byte("pong")
resp.WriteHeader(http.StatusOK)
resp.Header().Set("Content-Type", "text/plain") resp.Header().Set("Content-Type", "text/plain")
resp.Header().Set("Content-Length", strconv.Itoa(len(data))) resp.Header().Set("Content-Length", strconv.Itoa(len(data)))
resp.Write(data) resp.Write(data)
@ -432,7 +411,7 @@ func passwordBootstrap(ctx context.Context, config *Config) nodePassBootstrapper
return verifyRemotePassword(ctx, config, &mu, deferredNodes, node) return verifyRemotePassword(ctx, config, &mu, deferredNodes, node)
} else { } else {
// Otherwise, reject the request until the core is ready. // Otherwise, reject the request until the core is ready.
return "", http.StatusServiceUnavailable, errors.New("runtime core not ready") return "", http.StatusServiceUnavailable, util.ErrCoreNotReady
} }
} }

View File

@ -56,10 +56,6 @@ func getEncryptionRequest(req *http.Request) (*EncryptionRequest, error) {
func encryptionStatusHandler(server *config.Control) http.Handler { func encryptionStatusHandler(server *config.Control) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil {
resp.WriteHeader(http.StatusNotFound)
return
}
status, err := encryptionStatus(server) status, err := encryptionStatus(server)
if err != nil { if err != nil {
util.SendErrorWithID(err, "secret-encrypt", resp, req, http.StatusInternalServerError) util.SendErrorWithID(err, "secret-encrypt", resp, req, http.StatusInternalServerError)
@ -160,18 +156,13 @@ func encryptionEnable(ctx context.Context, server *config.Control, enable bool)
func encryptionConfigHandler(ctx context.Context, server *config.Control) http.Handler { func encryptionConfigHandler(ctx context.Context, server *config.Control) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil {
resp.WriteHeader(http.StatusNotFound)
return
}
if req.Method != http.MethodPut { if req.Method != http.MethodPut {
resp.WriteHeader(http.StatusBadRequest) util.SendError(fmt.Errorf("method not allowed"), resp, req, http.StatusMethodNotAllowed)
return return
} }
encryptReq, err := getEncryptionRequest(req) encryptReq, err := getEncryptionRequest(req)
if err != nil { if err != nil {
resp.WriteHeader(http.StatusBadRequest) util.SendError(err, resp, req, http.StatusBadRequest)
resp.Write([]byte(err.Error()))
return return
} }
if encryptReq.Stage != nil { if encryptReq.Stage != nil {

View File

@ -32,16 +32,15 @@ func getServerTokenRequest(req *http.Request) (TokenRotateRequest, error) {
func tokenRequestHandler(ctx context.Context, server *config.Control) http.Handler { func tokenRequestHandler(ctx context.Context, server *config.Control) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil || req.Method != http.MethodPut { if req.Method != http.MethodPut {
resp.WriteHeader(http.StatusBadRequest) util.SendError(fmt.Errorf("method not allowed"), resp, req, http.StatusMethodNotAllowed)
return return
} }
var err error var err error
sTokenReq, err := getServerTokenRequest(req) sTokenReq, err := getServerTokenRequest(req)
logrus.Debug("Received token request") logrus.Debug("Received token request")
if err != nil { if err != nil {
resp.WriteHeader(http.StatusBadRequest) util.SendError(err, resp, req, http.StatusBadRequest)
resp.Write([]byte(err.Error()))
return return
} }
if err = tokenRotate(ctx, server, *sTokenReq.NewToken); err != nil { if err = tokenRotate(ctx, server, *sTokenReq.NewToken); err != nil {

View File

@ -10,6 +10,7 @@ import (
"github.com/k3s-io/k3s/pkg/clientaccess" "github.com/k3s-io/k3s/pkg/clientaccess"
"github.com/k3s-io/k3s/pkg/daemons/config" "github.com/k3s-io/k3s/pkg/daemons/config"
"github.com/k3s-io/k3s/pkg/util"
"github.com/k3s-io/k3s/pkg/version" "github.com/k3s-io/k3s/pkg/version"
"github.com/libp2p/go-libp2p/core/peer" "github.com/libp2p/go-libp2p/core/peer"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -133,7 +134,7 @@ func (s *serverBootstrapper) Run(_ context.Context, id string) error {
func (s *serverBootstrapper) Get() (addrInfo *peer.AddrInfo, err error) { func (s *serverBootstrapper) Get() (addrInfo *peer.AddrInfo, err error) {
if s.controlConfig.Runtime.Core == nil { if s.controlConfig.Runtime.Core == nil {
return nil, errors.New("runtime core not ready") return nil, util.ErrCoreNotReady
} }
nodeName := os.Getenv("NODE_NAME") nodeName := os.Getenv("NODE_NAME")
if nodeName == "" { if nodeName == "" {

View File

@ -17,6 +17,7 @@ import (
var ErrAPINotReady = errors.New("apiserver not ready") var ErrAPINotReady = errors.New("apiserver not ready")
var ErrAPIDisabled = errors.New("apiserver disabled") var ErrAPIDisabled = errors.New("apiserver disabled")
var ErrCoreNotReady = errors.New("runtime core not ready")
// SendErrorWithID sends and logs a random error ID so that logs can be correlated // SendErrorWithID sends and logs a random error ID so that logs can be correlated
// between the REST API (which does not provide any detailed error output, to avoid // between the REST API (which does not provide any detailed error output, to avoid