diff --git a/Documentation/upgrades/upgrade_3_3.md b/Documentation/upgrades/upgrade_3_3.md index 17e97fe8e69..b7a21896946 100644 --- a/Documentation/upgrades/upgrade_3_3.md +++ b/Documentation/upgrades/upgrade_3_3.md @@ -74,23 +74,23 @@ Set `embed.Config.Debug` field to `true` to enable gRPC server logs. #### Change in `/health` endpoint response value -Previously, `[endpoint]:[client-port]/health` returned manually marshaled JSON value. 3.3 instead defines [`etcdhttp.Health`](https://godoc.org/github.com/coreos/etcd/etcdserver/api/etcdhttp#Health) struct and returns properly encoded JSON value with errors, if any. +Previously, `[endpoint]:[client-port]/health` returned manually marshaled JSON value. 3.3 now defines [`etcdhttp.Health`](https://godoc.org/github.com/coreos/etcd/etcdserver/api/etcdhttp#Health) struct and includes errors, if any. Before ```bash $ curl http://localhost:2379/health -{"health": "true"} +{"health":"true"} ``` After ```bash $ curl http://localhost:2379/health -{"health":true} +{"health":"true"} # Or -{"health":false,"errors":["NOSPACE"]} +{"health":"false","errors":["NOSPACE"]} ``` #### Change in gRPC gateway HTTP endpoints (replaced `/v3alpha` with `/v3beta`) diff --git a/Documentation/v2/admin_guide.md b/Documentation/v2/admin_guide.md index 66bec34a186..b09a2ffba18 100644 --- a/Documentation/v2/admin_guide.md +++ b/Documentation/v2/admin_guide.md @@ -45,12 +45,12 @@ It is important to monitor your production etcd cluster for healthy information #### Health Monitoring -At lowest level, etcd exposes health information via HTTP at `/health` in JSON format. If it returns `{"health":true}`, then the cluster is healthy. +At lowest level, etcd exposes health information via HTTP at `/health` in JSON format. If it returns `{"health":"true"}`, then the cluster is healthy. ``` $ curl -L http://127.0.0.1:2379/health -{"health":true} +{"health":"true"} ``` You can also use etcdctl to check the cluster-wide health information. It will contact all the members of the cluster and collect the health information for you. diff --git a/Documentation/v2/other_apis.md b/Documentation/v2/other_apis.md index dfea231c2ff..ec21a886cbd 100644 --- a/Documentation/v2/other_apis.md +++ b/Documentation/v2/other_apis.md @@ -29,5 +29,5 @@ curl http://10.0.0.10:2379/health ``` ```json -{"health":true} +{"health":"true"} ``` diff --git a/e2e/ctl_v3_alarm_test.go b/e2e/ctl_v3_alarm_test.go index 395ac297a23..effdebd1b68 100644 --- a/e2e/ctl_v3_alarm_test.go +++ b/e2e/ctl_v3_alarm_test.go @@ -53,7 +53,7 @@ func alarmTest(cx ctlCtx) { } // '/health' handler should return 'false' - if err := cURLGet(cx.epc, cURLReq{endpoint: "/health", expected: `{"health":false,"errors":["NOSPACE"]}`}); err != nil { + if err := cURLGet(cx.epc, cURLReq{endpoint: "/health", expected: `{"health":"false","errors":["NOSPACE"]}`}); err != nil { cx.t.Fatalf("failed get with curl (%v)", err) } diff --git a/e2e/metrics_test.go b/e2e/metrics_test.go index 2ca7b483af7..8c548c92077 100644 --- a/e2e/metrics_test.go +++ b/e2e/metrics_test.go @@ -45,7 +45,7 @@ func metricsTest(cx ctlCtx) { if err := cURLGet(cx.epc, cURLReq{endpoint: "/metrics", expected: fmt.Sprintf(`etcd_server_version{server_version="%s"} 1`, version.Version), metricsURLScheme: cx.cfg.metricsURLScheme}); err != nil { cx.t.Fatalf("failed get with curl (%v)", err) } - if err := cURLGet(cx.epc, cURLReq{endpoint: "/health", expected: `{"health":true}`, metricsURLScheme: cx.cfg.metricsURLScheme}); err != nil { + if err := cURLGet(cx.epc, cURLReq{endpoint: "/health", expected: `{"health":"true"}`, metricsURLScheme: cx.cfg.metricsURLScheme}); err != nil { cx.t.Fatalf("failed get with curl (%v)", err) } } diff --git a/etcdserver/api/etcdhttp/metrics.go b/etcdserver/api/etcdhttp/metrics.go index 02eea64c223..a68d9cefd8a 100644 --- a/etcdserver/api/etcdhttp/metrics.go +++ b/etcdserver/api/etcdhttp/metrics.go @@ -58,7 +58,7 @@ func NewHealthHandler(hfunc func() Health) http.HandlerFunc { } h := hfunc() d, _ := json.Marshal(h) - if !h.Health { + if h.Health != "true" { http.Error(w, string(d), http.StatusServiceUnavailable) return } @@ -70,12 +70,12 @@ func NewHealthHandler(hfunc func() Health) http.HandlerFunc { // Health defines etcd server health status. // TODO: remove manual parsing in etcdctl cluster-health type Health struct { - Health bool `json:"health"` + Health string `json:"health"` Errors []string `json:"errors,omitempty"` } func checkHealth(srv etcdserver.ServerV2) Health { - h := Health{Health: false} + h := Health{Health: "false"} as := srv.Alarms() if len(as) > 0 { @@ -96,7 +96,8 @@ func checkHealth(srv etcdserver.ServerV2) Health { if err != nil { h.Errors = append(h.Errors, err.Error()) } - - h.Health = err == nil + if err == nil { + h.Health = "true" + } return h } diff --git a/proxy/grpcproxy/health.go b/proxy/grpcproxy/health.go index 9e2c93ca8a9..1a6d0cf670f 100644 --- a/proxy/grpcproxy/health.go +++ b/proxy/grpcproxy/health.go @@ -30,12 +30,14 @@ func HandleHealth(mux *http.ServeMux, c *clientv3.Client) { } func checkHealth(c *clientv3.Client) etcdhttp.Health { - h := etcdhttp.Health{Health: false} + h := etcdhttp.Health{Health: "false"} ctx, cancel := context.WithTimeout(c.Ctx(), time.Second) _, err := c.Get(ctx, "a") cancel() - h.Health = err == nil || err == rpctypes.ErrPermissionDenied - if !h.Health { + if err == nil || err == rpctypes.ErrPermissionDenied { + h.Health = "true" + } + if h.Health != "true" { h.Errors = append(h.Errors, err.Error()) } return h