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
import (
"fmt"
"net/http"
"github.com/k3s-io/k3s/pkg/util"
)
// 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.
func (c *Cluster) router() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
if c.config.Runtime.Handler == nil {
http.Error(rw, "starting", http.StatusServiceUnavailable)
return
if c.config.Runtime.Handler != nil {
c.config.Runtime.Handler.ServeHTTP(rw, req)
} 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) {
logrus.Debugf("Tunnel server error: %d %v", code, err)
rw.WriteHeader(code)
rw.Write([]byte(err.Error()))
util.SendError(err, rw, req, code)
}
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.
func toTLSConfig(runtime *config.ControlRuntime) (*tls.Config, error) {
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)
@ -1177,7 +1177,7 @@ func (e *ETCD) manageLearners(ctx context.Context) {
func (e *ETCD) getETCDNodes() ([]*v1.Node, error) {
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()

View File

@ -30,8 +30,8 @@ import (
func caCertReplaceHandler(server *config.Control) http.HandlerFunc {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil || req.Method != http.MethodPut {
resp.WriteHeader(http.StatusNotFound)
if req.Method != http.MethodPut {
util.SendError(fmt.Errorf("method not allowed"), resp, req, http.StatusMethodNotAllowed)
return
}
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 {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil {
resp.WriteHeader(http.StatusNotFound)
return
}
nodeName, errCode, err := auth(req)
if err != nil {
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 {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil {
resp.WriteHeader(http.StatusNotFound)
return
}
nodeName, errCode, err := auth(req)
if err != nil {
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 {
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")
if len(fileName) == 1 {
@ -310,8 +296,7 @@ func fileHandler(fileName ...string) http.Handler {
for _, f := range fileName {
bytes, err := os.ReadFile(f)
if err != nil {
logrus.Errorf("Failed to read %s: %v", f, err)
resp.WriteHeader(http.StatusInternalServerError)
util.SendError(errors.Wrapf(err, "failed to read %s", f), resp, req, http.StatusInternalServerError)
return
}
resp.Write(bytes)
@ -336,18 +321,13 @@ func apiserversHandler(server *config.Control) http.Handler {
resp.Header().Set("content-type", "application/json")
if err := json.NewEncoder(resp).Encode(endpoints); err != nil {
logrus.Errorf("Failed to encode apiserver endpoints: %v", err)
resp.WriteHeader(http.StatusInternalServerError)
util.SendError(errors.Wrap(err, "failed to encode apiserver endpoints"), resp, req, http.StatusInternalServerError)
}
})
}
func configHandler(server *config.Control, cfg *cmds.Server) http.Handler {
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
// 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.
@ -355,23 +335,21 @@ func configHandler(server *config.Control, cfg *cmds.Server) http.Handler {
server.DisableKubeProxy = cfg.DisableKubeProxy
resp.Header().Set("content-type", "application/json")
if err := json.NewEncoder(resp).Encode(server); err != nil {
logrus.Errorf("Failed to encode agent config: %v", err)
resp.WriteHeader(http.StatusInternalServerError)
util.SendError(errors.Wrap(err, "failed to encode agent config"), resp, req, http.StatusInternalServerError)
}
})
}
func readyzHandler(server *config.Control) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
code := http.StatusOK
data := []byte("ok")
if server.Runtime.Core == nil {
code = http.StatusInternalServerError
data = []byte("runtime core not ready")
util.SendError(util.ErrCoreNotReady, resp, req, http.StatusServiceUnavailable)
return
}
resp.WriteHeader(code)
data := []byte("ok")
resp.WriteHeader(http.StatusOK)
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)
})
}
@ -379,6 +357,7 @@ func readyzHandler(server *config.Control) http.Handler {
func ping() http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
data := []byte("pong")
resp.WriteHeader(http.StatusOK)
resp.Header().Set("Content-Type", "text/plain")
resp.Header().Set("Content-Length", strconv.Itoa(len(data)))
resp.Write(data)
@ -432,7 +411,7 @@ func passwordBootstrap(ctx context.Context, config *Config) nodePassBootstrapper
return verifyRemotePassword(ctx, config, &mu, deferredNodes, node)
} else {
// 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 {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil {
resp.WriteHeader(http.StatusNotFound)
return
}
status, err := encryptionStatus(server)
if err != nil {
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 {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil {
resp.WriteHeader(http.StatusNotFound)
return
}
if req.Method != http.MethodPut {
resp.WriteHeader(http.StatusBadRequest)
util.SendError(fmt.Errorf("method not allowed"), resp, req, http.StatusMethodNotAllowed)
return
}
encryptReq, err := getEncryptionRequest(req)
if err != nil {
resp.WriteHeader(http.StatusBadRequest)
resp.Write([]byte(err.Error()))
util.SendError(err, resp, req, http.StatusBadRequest)
return
}
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 {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if req.TLS == nil || req.Method != http.MethodPut {
resp.WriteHeader(http.StatusBadRequest)
if req.Method != http.MethodPut {
util.SendError(fmt.Errorf("method not allowed"), resp, req, http.StatusMethodNotAllowed)
return
}
var err error
sTokenReq, err := getServerTokenRequest(req)
logrus.Debug("Received token request")
if err != nil {
resp.WriteHeader(http.StatusBadRequest)
resp.Write([]byte(err.Error()))
util.SendError(err, resp, req, http.StatusBadRequest)
return
}
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/daemons/config"
"github.com/k3s-io/k3s/pkg/util"
"github.com/k3s-io/k3s/pkg/version"
"github.com/libp2p/go-libp2p/core/peer"
"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) {
if s.controlConfig.Runtime.Core == nil {
return nil, errors.New("runtime core not ready")
return nil, util.ErrCoreNotReady
}
nodeName := os.Getenv("NODE_NAME")
if nodeName == "" {

View File

@ -17,6 +17,7 @@ import (
var ErrAPINotReady = errors.New("apiserver not ready")
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
// between the REST API (which does not provide any detailed error output, to avoid