mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 10:12:35 +00:00
Add query parameters to /sys/health to specify return codes.
Fixes #1199
This commit is contained in:
@@ -3,6 +3,7 @@ package http
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/vault"
|
||||
@@ -20,9 +21,56 @@ func handleSysHealth(core *vault.Core) http.Handler {
|
||||
}
|
||||
|
||||
func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Check if being a standby is allowed for the purpose of a 200 OK
|
||||
_, standbyOK := r.URL.Query()["standbyok"]
|
||||
|
||||
// FIXME: Change the sealed code to http.StatusServiceUnavailable at some
|
||||
// point
|
||||
sealedCode := http.StatusInternalServerError
|
||||
standbyCode := http.StatusTooManyRequests // Consul warning code
|
||||
activeCode := http.StatusOK
|
||||
|
||||
var err error
|
||||
sealedCodeStr, sealedCodeOk := r.URL.Query()["sealedcode"]
|
||||
if sealedCodeOk {
|
||||
if len(sealedCodeStr) < 1 {
|
||||
respondError(w, http.StatusBadRequest, nil)
|
||||
return
|
||||
}
|
||||
sealedCode, err = strconv.Atoi(sealedCodeStr[0])
|
||||
if err != nil {
|
||||
respondError(w, http.StatusBadRequest, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
standbyCodeStr, standbyCodeOk := r.URL.Query()["standbycode"]
|
||||
if standbyCodeOk {
|
||||
if len(standbyCodeStr) < 1 {
|
||||
respondError(w, http.StatusBadRequest, nil)
|
||||
return
|
||||
}
|
||||
standbyCode, err = strconv.Atoi(standbyCodeStr[0])
|
||||
if err != nil {
|
||||
respondError(w, http.StatusBadRequest, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
activeCodeStr, activeCodeOk := r.URL.Query()["activecode"]
|
||||
if activeCodeOk {
|
||||
if len(activeCodeStr) < 1 {
|
||||
respondError(w, http.StatusBadRequest, nil)
|
||||
return
|
||||
}
|
||||
|
||||
activeCode, err = strconv.Atoi(activeCodeStr[0])
|
||||
if err != nil {
|
||||
respondError(w, http.StatusBadRequest, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Check system status
|
||||
sealed, _ := core.Sealed()
|
||||
standby, _ := core.Standby()
|
||||
@@ -33,14 +81,14 @@ func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
|
||||
// Determine the status code
|
||||
code := http.StatusOK
|
||||
code := activeCode
|
||||
switch {
|
||||
case !init:
|
||||
code = http.StatusInternalServerError
|
||||
case sealed:
|
||||
code = http.StatusInternalServerError
|
||||
code = sealedCode
|
||||
case !standbyOK && standby:
|
||||
code = 429 // Consul warning code
|
||||
code = standbyCode
|
||||
}
|
||||
|
||||
// Format the body
|
||||
|
||||
@@ -2,6 +2,7 @@ package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@@ -9,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func TestSysHealth_get(t *testing.T) {
|
||||
core, _, _ := vault.TestCoreUnsealed(t)
|
||||
core, _, root := vault.TestCoreUnsealed(t)
|
||||
ln, addr := TestServer(t, core)
|
||||
defer ln.Close()
|
||||
|
||||
@@ -30,4 +31,77 @@ func TestSysHealth_get(t *testing.T) {
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
|
||||
core.Seal(root)
|
||||
|
||||
resp, err = http.Get(addr + "/v1/sys/health")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual = map[string]interface{}{}
|
||||
expected = map[string]interface{}{
|
||||
"initialized": true,
|
||||
"sealed": true,
|
||||
"standby": false,
|
||||
}
|
||||
testResponseStatus(t, resp, 500)
|
||||
testResponseBody(t, resp, &actual)
|
||||
expected["server_time_utc"] = actual["server_time_utc"]
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSysHealth_customcodes(t *testing.T) {
|
||||
core, _, root := vault.TestCoreUnsealed(t)
|
||||
ln, addr := TestServer(t, core)
|
||||
defer ln.Close()
|
||||
|
||||
queryurl, err := url.Parse(addr + "/v1/sys/health?sealedcode=503&activecode=202")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
resp, err := http.Get(queryurl.String())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
var actual map[string]interface{}
|
||||
expected := map[string]interface{}{
|
||||
"initialized": true,
|
||||
"sealed": false,
|
||||
"standby": false,
|
||||
}
|
||||
testResponseStatus(t, resp, 202)
|
||||
testResponseBody(t, resp, &actual)
|
||||
|
||||
expected["server_time_utc"] = actual["server_time_utc"]
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
|
||||
core.Seal(root)
|
||||
|
||||
queryurl, err = url.Parse(addr + "/v1/sys/health?sealedcode=503&activecode=202")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
resp, err = http.Get(queryurl.String())
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
actual = map[string]interface{}{}
|
||||
expected = map[string]interface{}{
|
||||
"initialized": true,
|
||||
"sealed": true,
|
||||
"standby": false,
|
||||
}
|
||||
testResponseStatus(t, resp, 503)
|
||||
testResponseBody(t, resp, &actual)
|
||||
expected["server_time_utc"] = actual["server_time_utc"]
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@ description: |-
|
||||
<dl>
|
||||
<dt>Description</dt>
|
||||
<dd>
|
||||
Returns the health status of Vault. This matches the semantics of a Consul HTTP health
|
||||
check and provides a simple way to monitor the health of a Vault instance.
|
||||
Returns the health status of Vault. This matches the semantics of a
|
||||
Consul HTTP health check and provides a simple way to monitor the
|
||||
health of a Vault instance.
|
||||
</dd>
|
||||
|
||||
<dt>Method</dt>
|
||||
@@ -25,7 +26,25 @@ description: |-
|
||||
<span class="param">standbyok</span>
|
||||
<span class="param-flags">optional</span>
|
||||
A query parameter provided to indicate that being a standby should
|
||||
still return a 200 status code instead of the standard 429 status code.
|
||||
still return the active status code instead of the standby code
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">activecode</span>
|
||||
<span class="param-flags">optional</span>
|
||||
A query parameter provided to indicate the status code that should
|
||||
be returned for an active node instead of the default of `200`
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">standbycode</span>
|
||||
<span class="param-flags">optional</span>
|
||||
A query parameter provided to indicate the status code that should
|
||||
be returned for a standby node instead of the default of `429`
|
||||
</li>
|
||||
<li>
|
||||
<span class="param">sealedcode</span>
|
||||
<span class="param-flags">optional</span>
|
||||
A query parameter provided to indicate the status code that should
|
||||
be returned for a sealed node instead of the default of `500`
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
@@ -41,10 +60,10 @@ description: |-
|
||||
}
|
||||
```
|
||||
|
||||
Status Codes:
|
||||
Default Status Codes:
|
||||
|
||||
* `200` if initialized, unsealed and active.
|
||||
* `200` if initialized, unsealed, and active.
|
||||
* `429` if unsealed and standby.
|
||||
* `500` if not initialized or sealed.
|
||||
* `500` if sealed, or if not initialized.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
Reference in New Issue
Block a user