feat(mgmt): add alias endpoint for health check

This allow use to reference `/status` in the API documentation without
manually editing the `swagger.json` file.
This commit is contained in:
Thales Macedo Garitezi 2022-10-25 16:16:20 -03:00
parent ed8286aff7
commit d0ca79fc9e
3 changed files with 115 additions and 5 deletions

View File

@ -0,0 +1,38 @@
emqx_mgmt_api_status {
get_status_api {
desc {
en: "Serves as a health check for the node. Returns a plain text response"
" describing the status of the node. This endpoint requires no"
" authentication.\n"
"\n"
"Returns status code 200 if the EMQX application is up and running, "
"503 otherwise."
"\n"
"The GET `/status` endpoint (without the `/api/...` prefix) is also an alias"
" to this endpoint and works in the same way."
zh: "作为节点的健康检查。 返回一个纯文本的响应,描述节点的状态。\n"
"\n"
"如果 EMQX 应用程序已经启动并运行,返回状态代码 200否则返回 503。\n"
"\n"
"GET `/status`端点(没有`/api/...`前缀)也是这个端点的一个别名,工作方式相同。"
}
}
get_status_response200 {
desc {
en: "Node emqx@127.0.0.1 is started\n"
"emqx is running"
zh: "Node emqx@127.0.0.1 is started\n"
"emqx is running"
}
}
get_status_response503 {
desc {
en: "Node emqx@127.0.0.1 is stopped\n"
"emqx is not_running"
zh: "Node emqx@127.0.0.1 is stopped\n"
"emqx is not_running"
}
}
}

View File

@ -15,11 +15,50 @@
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
-module(emqx_mgmt_api_status). -module(emqx_mgmt_api_status).
-behaviour(minirest_api).
-include_lib("hocon/include/hoconsc.hrl").
%% minirest API
-export([api_spec/0, paths/0, schema/1]).
-export([get_status/2]).
-export([ -export([
init/2, init/2,
path/0 path/0
]). ]).
-define(TAGS, [<<"Status">>]).
%%--------------------------------------------------------------------
%% minirest API and schema
%%--------------------------------------------------------------------
api_spec() ->
emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
paths() ->
["/status"].
schema("/status") ->
#{
'operationId' => get_status,
get => #{
description => ?DESC(get_status_api),
tags => ?TAGS,
security => [],
responses => #{
200 => ?DESC(get_status_response200),
503 => ?DESC(get_status_response503)
}
}
}.
%%--------------------------------------------------------------------
%% non-minirest (cowboy) API
%%--------------------------------------------------------------------
%% Note: Because swagger now requires an HTTP prefix (e.g. /api/v5), %% Note: Because swagger now requires an HTTP prefix (e.g. /api/v5),
%% but the `/status` does not require this fixed prefix. %% but the `/status` does not require this fixed prefix.
%% %%
@ -39,6 +78,9 @@ init(Req0, State) ->
%% API Handler funcs %% API Handler funcs
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
get_status(get, _Params) ->
running_status().
running_status() -> running_status() ->
case emqx_dashboard_listener:is_ready(timer:seconds(20)) of case emqx_dashboard_listener:is_ready(timer:seconds(20)) of
true -> true ->

View File

@ -19,6 +19,7 @@
-compile(nowarn_export_all). -compile(nowarn_export_all).
-include_lib("eunit/include/eunit.hrl"). -include_lib("eunit/include/eunit.hrl").
-include_lib("common_test/include/ct.hrl").
-define(HOST, "http://127.0.0.1:18083/"). -define(HOST, "http://127.0.0.1:18083/").
@ -27,7 +28,24 @@
%%--------------------------------------------------------------------------------------- %%---------------------------------------------------------------------------------------
all() -> all() ->
emqx_common_test_helpers:all(?MODULE). OtherTCs = emqx_common_test_helpers:all(?MODULE) -- get_status_tests(),
[
{group, api_status_endpoint},
{group, non_api_status_endpoint}
| OtherTCs
].
get_status_tests() ->
[
t_status_ok,
t_status_not_ok
].
groups() ->
[
{api_status_endpoint, [], get_status_tests()},
{non_api_status_endpoint, [], get_status_tests()}
].
init_per_suite(Config) -> init_per_suite(Config) ->
emqx_mgmt_api_test_util:init_suite(), emqx_mgmt_api_test_util:init_suite(),
@ -36,6 +54,16 @@ init_per_suite(Config) ->
end_per_suite(_) -> end_per_suite(_) ->
emqx_mgmt_api_test_util:end_suite(). emqx_mgmt_api_test_util:end_suite().
init_per_group(api_status_endpoint, Config) ->
[{get_status_path, ["api", "v5", "status"]} | Config];
init_per_group(non_api_status_endpoint, Config) ->
[{get_status_path, ["status"]} | Config];
init_per_group(_Group, Config) ->
Config.
end_per_group(_Group, _Config) ->
ok.
init_per_testcase(t_status_not_ok, Config) -> init_per_testcase(t_status_not_ok, Config) ->
ok = application:stop(emqx), ok = application:stop(emqx),
Config; Config;
@ -97,13 +125,14 @@ data_loop(Gun, Ref, Acc) ->
%% Test cases %% Test cases
%%--------------------------------------------------------------------------------------- %%---------------------------------------------------------------------------------------
t_status_ok(_Config) -> t_status_ok(Config) ->
Path = ?config(get_status_path, Config),
#{ #{
body := Resp, body := Resp,
status_code := StatusCode status_code := StatusCode
} = do_request(#{ } = do_request(#{
method => get, method => get,
path => ["status"], path => Path,
headers => [], headers => [],
body => no_body body => no_body
}), }),
@ -114,14 +143,15 @@ t_status_ok(_Config) ->
), ),
ok. ok.
t_status_not_ok(_Config) -> t_status_not_ok(Config) ->
Path = ?config(get_status_path, Config),
#{ #{
body := Resp, body := Resp,
headers := Headers, headers := Headers,
status_code := StatusCode status_code := StatusCode
} = do_request(#{ } = do_request(#{
method => get, method => get,
path => ["status"], path => Path,
headers => [], headers => [],
body => no_body body => no_body
}), }),