server: Split code for debug and version endpoints

This commit is contained in:
Marek Siarkowicz 2022-02-02 13:31:51 +01:00
parent 722ec487df
commit fb361e43f0
4 changed files with 116 additions and 66 deletions

View File

@ -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
}

View File

@ -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")
}

View File

@ -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",

View File

@ -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)
}