mirror of https://github.com/waku-org/nwaku.git
feat: Rest endoint /health for rln (#2011)
* Rest endoint /health added * Remove dev-debug echo * Changed not ready message * Update waku/node/rest/health/handlers.nim Co-authored-by: Ivan Folgueira Bande <128452529+Ivansete-status@users.noreply.github.com> * Various fixes on PR foundings, added comments --------- Co-authored-by: Ivan Folgueira Bande <128452529+Ivansete-status@users.noreply.github.com>
This commit is contained in:
parent
a8095d871e
commit
fc6194bb6b
|
@ -47,6 +47,7 @@ import
|
||||||
../../waku/node/rest/relay/topic_cache,
|
../../waku/node/rest/relay/topic_cache,
|
||||||
../../waku/node/rest/filter/handlers as rest_filter_api,
|
../../waku/node/rest/filter/handlers as rest_filter_api,
|
||||||
../../waku/node/rest/store/handlers as rest_store_api,
|
../../waku/node/rest/store/handlers as rest_store_api,
|
||||||
|
../../waku/node/rest/health/handlers as rest_health_api,
|
||||||
../../waku/node/jsonrpc/admin/handlers as rpc_admin_api,
|
../../waku/node/jsonrpc/admin/handlers as rpc_admin_api,
|
||||||
../../waku/node/jsonrpc/debug/handlers as rpc_debug_api,
|
../../waku/node/jsonrpc/debug/handlers as rpc_debug_api,
|
||||||
../../waku/node/jsonrpc/filter/handlers as rpc_filter_api,
|
../../waku/node/jsonrpc/filter/handlers as rpc_filter_api,
|
||||||
|
@ -569,6 +570,9 @@ proc startRestServer(app: App, address: ValidIpAddress, port: Port, conf: WakuNo
|
||||||
## Debug REST API
|
## Debug REST API
|
||||||
installDebugApiHandlers(server.router, app.node)
|
installDebugApiHandlers(server.router, app.node)
|
||||||
|
|
||||||
|
## Health REST API
|
||||||
|
installHealthApiHandler(server.router, app.node)
|
||||||
|
|
||||||
## Relay REST API
|
## Relay REST API
|
||||||
if conf.relay:
|
if conf.relay:
|
||||||
let relayCache = TopicCache.init(capacity=conf.restRelayCacheCapacity)
|
let relayCache = TopicCache.init(capacity=conf.restRelayCacheCapacity)
|
||||||
|
|
|
@ -102,4 +102,5 @@ when defined(rln):
|
||||||
./waku_rln_relay/test_waku_rln_relay,
|
./waku_rln_relay/test_waku_rln_relay,
|
||||||
./waku_rln_relay/test_wakunode_rln_relay,
|
./waku_rln_relay/test_wakunode_rln_relay,
|
||||||
./waku_rln_relay/test_rln_group_manager_onchain,
|
./waku_rln_relay/test_rln_group_manager_onchain,
|
||||||
./waku_rln_relay/test_rln_group_manager_static
|
./waku_rln_relay/test_rln_group_manager_static,
|
||||||
|
./wakunode_rest/test_rest_health
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
{.used.}
|
||||||
|
|
||||||
|
import
|
||||||
|
std/tempfiles,
|
||||||
|
stew/shims/net,
|
||||||
|
testutils/unittests,
|
||||||
|
presto,
|
||||||
|
presto/client as presto_client,
|
||||||
|
libp2p/peerinfo,
|
||||||
|
libp2p/multiaddress,
|
||||||
|
libp2p/crypto/crypto
|
||||||
|
import
|
||||||
|
../../waku/waku_node,
|
||||||
|
../../waku/node/waku_node as waku_node2, # TODO: Remove after moving `git_version` to the app code.
|
||||||
|
../../waku/node/rest/server,
|
||||||
|
../../waku/node/rest/client,
|
||||||
|
../../waku/node/rest/responses,
|
||||||
|
../../waku/node/rest/health/handlers as health_api,
|
||||||
|
../../waku/node/rest/health/client as health_api_client,
|
||||||
|
../../waku/waku_rln_relay,
|
||||||
|
../testlib/common,
|
||||||
|
../testlib/wakucore,
|
||||||
|
../testlib/wakunode
|
||||||
|
|
||||||
|
|
||||||
|
proc testWakuNode(): WakuNode =
|
||||||
|
let
|
||||||
|
privkey = crypto.PrivateKey.random(Secp256k1, rng[]).tryGet()
|
||||||
|
bindIp = ValidIpAddress.init("0.0.0.0")
|
||||||
|
extIp = ValidIpAddress.init("127.0.0.1")
|
||||||
|
port = Port(0)
|
||||||
|
|
||||||
|
newTestWakuNode(privkey, bindIp, port, some(extIp), some(port))
|
||||||
|
|
||||||
|
|
||||||
|
suite "Waku v2 REST API - health":
|
||||||
|
asyncTest "Get node health info - GET /health":
|
||||||
|
# Given
|
||||||
|
let node = testWakuNode()
|
||||||
|
await node.start()
|
||||||
|
await node.mountRelay()
|
||||||
|
|
||||||
|
let restPort = Port(58001)
|
||||||
|
let restAddress = ValidIpAddress.init("0.0.0.0")
|
||||||
|
let restServer = RestServerRef.init(restAddress, restPort).tryGet()
|
||||||
|
|
||||||
|
installHealthApiHandler(restServer.router, node)
|
||||||
|
restServer.start()
|
||||||
|
let client = newRestHttpClient(initTAddress(restAddress, restPort))
|
||||||
|
|
||||||
|
# When
|
||||||
|
var response = await client.healthCheck()
|
||||||
|
|
||||||
|
# Then
|
||||||
|
check:
|
||||||
|
response.status == 503
|
||||||
|
$response.contentType == $MIMETYPE_TEXT
|
||||||
|
response.data == "Node is not ready"
|
||||||
|
|
||||||
|
# now kick in rln (currently the only check for health)
|
||||||
|
await node.mountRlnRelay(WakuRlnConfig(rlnRelayDynamic: false,
|
||||||
|
rlnRelayCredIndex: some(1.uint),
|
||||||
|
rlnRelayTreePath: genTempPath("rln_tree", "wakunode"),
|
||||||
|
))
|
||||||
|
|
||||||
|
# When
|
||||||
|
response = await client.healthCheck()
|
||||||
|
|
||||||
|
# Then
|
||||||
|
check:
|
||||||
|
response.status == 200
|
||||||
|
$response.contentType == $MIMETYPE_TEXT
|
||||||
|
response.data == "Node is healthy"
|
||||||
|
|
||||||
|
await restServer.stop()
|
||||||
|
await restServer.closeWait()
|
||||||
|
await node.stop()
|
|
@ -0,0 +1,30 @@
|
||||||
|
when (NimMajor, NimMinor) < (1, 4):
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
else:
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import
|
||||||
|
chronicles,
|
||||||
|
json_serialization,
|
||||||
|
json_serialization/std/options,
|
||||||
|
presto/[route, client]
|
||||||
|
import
|
||||||
|
../serdes,
|
||||||
|
../responses
|
||||||
|
|
||||||
|
logScope:
|
||||||
|
topics = "waku node rest health_api"
|
||||||
|
|
||||||
|
proc decodeBytes*(t: typedesc[string], value: openArray[byte],
|
||||||
|
contentType: Opt[ContentTypeData]): RestResult[string] =
|
||||||
|
if MediaType.init($contentType) != MIMETYPE_TEXT:
|
||||||
|
error "Unsupported contentType value", contentType = contentType
|
||||||
|
return err("Unsupported contentType")
|
||||||
|
|
||||||
|
var res: string
|
||||||
|
if len(value) > 0:
|
||||||
|
res = newString(len(value))
|
||||||
|
copyMem(addr res[0], unsafeAddr value[0], len(value))
|
||||||
|
return ok(res)
|
||||||
|
|
||||||
|
proc healthCheck*(): RestResponse[string] {.rest, endpoint: "/health", meth: HttpMethod.MethodGet.}
|
|
@ -0,0 +1,42 @@
|
||||||
|
when (NimMajor, NimMinor) < (1, 4):
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
else:
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import
|
||||||
|
chronicles,
|
||||||
|
json_serialization,
|
||||||
|
presto/route
|
||||||
|
import
|
||||||
|
../../waku_node,
|
||||||
|
../responses,
|
||||||
|
../serdes
|
||||||
|
|
||||||
|
logScope:
|
||||||
|
topics = "waku node rest health_api"
|
||||||
|
|
||||||
|
const ROUTE_HEALTH* = "/health"
|
||||||
|
|
||||||
|
const FutIsReadyTimout = 5.seconds
|
||||||
|
|
||||||
|
proc installHealthApiHandler*(router: var RestRouter, node: WakuNode) =
|
||||||
|
## /health endpoint provides information about node readiness to caller.
|
||||||
|
## Currently it is restricted to checking RLN (if mounted) proper setup
|
||||||
|
## TODO: Leter to extend it to a broader information about each subsystem state
|
||||||
|
## report. Rest response to change to JSON structure that can hold exact detailed
|
||||||
|
## information.
|
||||||
|
|
||||||
|
router.api(MethodGet, ROUTE_HEALTH) do () -> RestApiResponse:
|
||||||
|
|
||||||
|
let isReadyStateFut = node.isReady()
|
||||||
|
if not await isReadyStateFut.withTimeout(FutIsReadyTimout):
|
||||||
|
return RestApiResponse.internalServerError("Health check timed out")
|
||||||
|
|
||||||
|
var msg = "Node is healthy"
|
||||||
|
var status = Http200
|
||||||
|
|
||||||
|
if not isReadyStateFut.read():
|
||||||
|
msg = "Node is not ready"
|
||||||
|
status = Http503
|
||||||
|
|
||||||
|
return RestApiResponse.textResponse(msg, status)
|
|
@ -0,0 +1,41 @@
|
||||||
|
openapi: 3.0.3
|
||||||
|
info:
|
||||||
|
title: Waku V2 node REST API
|
||||||
|
version: 1.0.0
|
||||||
|
contact:
|
||||||
|
name: VAC Team
|
||||||
|
url: https://forum.vac.dev/
|
||||||
|
|
||||||
|
tags:
|
||||||
|
- name: health
|
||||||
|
description: Healt check REST API for WakuV2 node
|
||||||
|
|
||||||
|
paths:
|
||||||
|
/health:
|
||||||
|
get:
|
||||||
|
summary: Get node health status
|
||||||
|
description: Retrieve readiness of a Waku v2 node.
|
||||||
|
operationId: healthcheck
|
||||||
|
tags:
|
||||||
|
- health
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Waku v2 node is up and running.
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: Node is healty
|
||||||
|
'500':
|
||||||
|
description: Internal server error
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
'503':
|
||||||
|
description: Node not initialized or having issues
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: Node is not initialized
|
Loading…
Reference in New Issue