From fb361e43f069dc3fc33cc348414f059c8b0b2989 Mon Sep 17 00:00:00 2001 From: Marek Siarkowicz Date: Wed, 2 Feb 2022 13:31:51 +0100 Subject: [PATCH] server: Split code for debug and version endpoints --- .../api/etcdhttp/{base.go => basic.go} | 72 ++----------------- server/etcdserver/api/etcdhttp/debug.go | 47 ++++++++++++ server/etcdserver/api/etcdhttp/peer.go | 2 +- server/etcdserver/api/etcdhttp/version.go | 61 ++++++++++++++++ 4 files changed, 116 insertions(+), 66 deletions(-) rename server/etcdserver/api/etcdhttp/{base.go => basic.go} (57%) create mode 100644 server/etcdserver/api/etcdhttp/debug.go create mode 100644 server/etcdserver/api/etcdhttp/version.go diff --git a/server/etcdserver/api/etcdhttp/base.go b/server/etcdserver/api/etcdhttp/basic.go similarity index 57% rename from server/etcdserver/api/etcdhttp/base.go rename to server/etcdserver/api/etcdhttp/basic.go index 9dc313fc1..3c2e38a3b 100644 --- a/server/etcdserver/api/etcdhttp/base.go +++ b/server/etcdserver/api/etcdhttp/basic.go @@ -1,4 +1,4 @@ -// Copyright 2015 The etcd Authors +// Copyright 2022 The etcd Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,75 +15,17 @@ package etcdhttp import ( - "encoding/json" - "expvar" - "fmt" "net/http" - "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/types" + httptypes "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/types" "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" "go.uber.org/zap" ) -const ( - varsPath = "/debug/vars" - versionPath = "/version" -) - -// HandleBasic adds handlers to a mux for serving JSON etcd client requests -// that do not access the v2 store. -func HandleBasic(lg *zap.Logger, mux *http.ServeMux, server etcdserver.ServerPeer) { - mux.HandleFunc(varsPath, serveVars) - mux.HandleFunc(versionPath, versionHandler(server.Cluster(), serveVersion)) -} - -func versionHandler(c api.Cluster, fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - v := c.Version() - if v != nil { - fn(w, r, v.String()) - } else { - fn(w, r, "not_decided") - } - } -} - -func serveVersion(w http.ResponseWriter, r *http.Request, clusterV string) { - if !allowMethod(w, r, "GET") { - return - } - vs := version.Versions{ - Server: version.Version, - Cluster: clusterV, - } - - w.Header().Set("Content-Type", "application/json") - b, err := json.Marshal(&vs) - if err != nil { - panic(fmt.Sprintf("cannot marshal versions to json (%v)", err)) - } - w.Write(b) -} - -func serveVars(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r, "GET") { - return - } - - w.Header().Set("Content-Type", "application/json; charset=utf-8") - fmt.Fprintf(w, "{\n") - first := true - expvar.Do(func(kv expvar.KeyValue) { - if !first { - fmt.Fprintf(w, ",\n") - } - first = false - fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value) - }) - fmt.Fprintf(w, "\n}\n") +func HandleBasic(lg *zap.Logger, mux *http.ServeMux, peer etcdserver.ServerPeer) { + HandleDebug(mux) + HandleVersion(mux, peer) } func allowMethod(w http.ResponseWriter, r *http.Request, m string) bool { @@ -95,10 +37,10 @@ func allowMethod(w http.ResponseWriter, r *http.Request, m string) bool { return false } -// WriteError logs and writes the given Error to the ResponseWriter +// writeError logs and writes the given Error to the ResponseWriter // If Error is an etcdErr, it is rendered to the ResponseWriter // Otherwise, it is assumed to be a StatusInternalServerError -func WriteError(lg *zap.Logger, w http.ResponseWriter, r *http.Request, err error) { +func writeError(lg *zap.Logger, w http.ResponseWriter, r *http.Request, err error) { if err == nil { return } diff --git a/server/etcdserver/api/etcdhttp/debug.go b/server/etcdserver/api/etcdhttp/debug.go new file mode 100644 index 000000000..502079e2a --- /dev/null +++ b/server/etcdserver/api/etcdhttp/debug.go @@ -0,0 +1,47 @@ +// Copyright 2015 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package etcdhttp + +import ( + "expvar" + "fmt" + "net/http" +) + +const ( + varsPath = "/debug/vars" +) + +func HandleDebug(mux *http.ServeMux) { + mux.HandleFunc(varsPath, serveVars) +} + +func serveVars(w http.ResponseWriter, r *http.Request) { + if !allowMethod(w, r, "GET") { + return + } + + w.Header().Set("Content-Type", "application/json; charset=utf-8") + fmt.Fprintf(w, "{\n") + first := true + expvar.Do(func(kv expvar.KeyValue) { + if !first { + fmt.Fprintf(w, ",\n") + } + first = false + fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value) + }) + fmt.Fprintf(w, "\n}\n") +} diff --git a/server/etcdserver/api/etcdhttp/peer.go b/server/etcdserver/api/etcdhttp/peer.go index badc98634..4470bf9e6 100644 --- a/server/etcdserver/api/etcdhttp/peer.go +++ b/server/etcdserver/api/etcdhttp/peer.go @@ -145,7 +145,7 @@ func (h *peerMemberPromoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ case etcdserver.ErrLearnerNotReady: http.Error(w, err.Error(), http.StatusPreconditionFailed) default: - WriteError(h.lg, w, r, err) + writeError(h.lg, w, r, err) } h.lg.Warn( "failed to promote a member", diff --git a/server/etcdserver/api/etcdhttp/version.go b/server/etcdserver/api/etcdhttp/version.go new file mode 100644 index 000000000..296861175 --- /dev/null +++ b/server/etcdserver/api/etcdhttp/version.go @@ -0,0 +1,61 @@ +// Copyright 2015 The etcd Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package etcdhttp + +import ( + "encoding/json" + "fmt" + "net/http" + + "go.etcd.io/etcd/api/v3/version" + "go.etcd.io/etcd/server/v3/etcdserver" + "go.etcd.io/etcd/server/v3/etcdserver/api" +) + +const ( + versionPath = "/version" +) + +func HandleVersion(mux *http.ServeMux, server etcdserver.ServerPeer) { + mux.HandleFunc(versionPath, versionHandler(server.Cluster(), serveVersion)) +} + +func versionHandler(c api.Cluster, fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + v := c.Version() + if v != nil { + fn(w, r, v.String()) + } else { + fn(w, r, "not_decided") + } + } +} + +func serveVersion(w http.ResponseWriter, r *http.Request, clusterV string) { + if !allowMethod(w, r, "GET") { + return + } + vs := version.Versions{ + Server: version.Version, + Cluster: clusterV, + } + + w.Header().Set("Content-Type", "application/json") + b, err := json.Marshal(&vs) + if err != nil { + panic(fmt.Sprintf("cannot marshal versions to json (%v)", err)) + } + w.Write(b) +}