fix(mgmt_api): Friendly HTTP Status Code for Listeners.
This commit is contained in:
parent
54b3dd8718
commit
e737f18548
|
@ -46,6 +46,7 @@
|
||||||
-export([post_config_update/4]).
|
-export([post_config_update/4]).
|
||||||
|
|
||||||
-define(CONF_KEY_PATH, [listeners]).
|
-define(CONF_KEY_PATH, [listeners]).
|
||||||
|
-define(TYPES_STRING, ["tcp","ssl","ws","wss","quic"]).
|
||||||
|
|
||||||
%% @doc List configured listeners.
|
%% @doc List configured listeners.
|
||||||
-spec(list() -> [{ListenerId :: atom(), ListenerConf :: map()}]).
|
-spec(list() -> [{ListenerId :: atom(), ListenerConf :: map()}]).
|
||||||
|
@ -349,11 +350,10 @@ listener_id(Type, ListenerName) ->
|
||||||
list_to_atom(lists:append([str(Type), ":", str(ListenerName)])).
|
list_to_atom(lists:append([str(Type), ":", str(ListenerName)])).
|
||||||
|
|
||||||
parse_listener_id(Id) ->
|
parse_listener_id(Id) ->
|
||||||
try
|
[Type, Name] = string:split(str(Id), ":", leading),
|
||||||
[Type, Name] = string:split(str(Id), ":", leading),
|
case lists:member(Type, ?TYPES_STRING) of
|
||||||
{list_to_existing_atom(Type), list_to_atom(Name)}
|
true -> {list_to_existing_atom(Type), list_to_atom(Name)};
|
||||||
catch
|
false -> {error, {invalid_listener_id, Id}}
|
||||||
_ : _ -> error({invalid_listener_id, Id})
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
zone(Opts) ->
|
zone(Opts) ->
|
||||||
|
|
|
@ -508,12 +508,16 @@ update_listener(Id, Config) ->
|
||||||
[update_listener(Node, Id, Config) || Node <- ekka_mnesia:running_nodes()].
|
[update_listener(Node, Id, Config) || Node <- ekka_mnesia:running_nodes()].
|
||||||
|
|
||||||
update_listener(Node, Id, Config) when Node =:= node() ->
|
update_listener(Node, Id, Config) when Node =:= node() ->
|
||||||
{Type, Name} = emqx_listeners:parse_listener_id(Id),
|
case emqx_listeners:parse_listener_id(Id) of
|
||||||
case emqx:update_config([listeners, Type, Name], Config, #{}) of
|
{error, {invalid_listener_id, Id}} ->
|
||||||
{ok, #{raw_config := RawConf}} ->
|
{error, {invalid_listener_id, Id}};
|
||||||
RawConf#{node => Node, id => Id, running => true};
|
{Type, Name} ->
|
||||||
{error, Reason} ->
|
case emqx:update_config([listeners, Type, Name], Config, #{}) of
|
||||||
error(Reason)
|
{ok, #{raw_config := RawConf}} ->
|
||||||
|
RawConf#{node => Node, id => Id, running => true};
|
||||||
|
{error, Reason} ->
|
||||||
|
{error, Reason}
|
||||||
|
end
|
||||||
end;
|
end;
|
||||||
update_listener(Node, Id, Config) ->
|
update_listener(Node, Id, Config) ->
|
||||||
rpc_call(Node, update_listener, [Node, Id, Config]).
|
rpc_call(Node, update_listener, [Node, Id, Config]).
|
||||||
|
|
|
@ -35,6 +35,11 @@
|
||||||
-define(NODE_LISTENER_NOT_FOUND, <<"Node name or listener id not found">>).
|
-define(NODE_LISTENER_NOT_FOUND, <<"Node name or listener id not found">>).
|
||||||
-define(NODE_NOT_FOUND_OR_DOWN, <<"Node not found or Down">>).
|
-define(NODE_NOT_FOUND_OR_DOWN, <<"Node not found or Down">>).
|
||||||
-define(LISTENER_NOT_FOUND, <<"Listener id not found">>).
|
-define(LISTENER_NOT_FOUND, <<"Listener id not found">>).
|
||||||
|
-define(ADDR_PORT_INUSE, <<"Addr port in use">>).
|
||||||
|
-define(CONFIG_SCHEMA_ERROR, <<"Config schema error">>).
|
||||||
|
-define(INVALID_LISTENER_PROTOCOL, <<"Invalid listener type">>).
|
||||||
|
-define(UPDATE_CONFIG_FAILED, <<"Update configuration failed">>).
|
||||||
|
-define(OPERATION_FAILED, <<"Operation failed">>).
|
||||||
|
|
||||||
api_spec() ->
|
api_spec() ->
|
||||||
{
|
{
|
||||||
|
@ -49,11 +54,11 @@ api_spec() ->
|
||||||
[]
|
[]
|
||||||
}.
|
}.
|
||||||
|
|
||||||
-define(TYPES, [tcp, ssl, ws, wss, quic]).
|
-define(TYPES_ATOM, [tcp, ssl, ws, wss, quic]).
|
||||||
req_schema() ->
|
req_schema() ->
|
||||||
Schema = [emqx_mgmt_api_configs:gen_schema(
|
Schema = [emqx_mgmt_api_configs:gen_schema(
|
||||||
emqx:get_raw_config([listeners, T, default], #{}))
|
emqx:get_raw_config([listeners, T, default], #{}))
|
||||||
|| T <- ?TYPES],
|
|| T <- ?TYPES_ATOM],
|
||||||
#{oneOf => Schema}.
|
#{oneOf => Schema}.
|
||||||
|
|
||||||
resp_schema() ->
|
resp_schema() ->
|
||||||
|
@ -91,8 +96,12 @@ api_list_update_listeners_by_id() ->
|
||||||
parameters => [param_path_id()],
|
parameters => [param_path_id()],
|
||||||
requestBody => emqx_mgmt_util:schema(req_schema(), <<"Listener Config">>),
|
requestBody => emqx_mgmt_util:schema(req_schema(), <<"Listener Config">>),
|
||||||
responses => #{
|
responses => #{
|
||||||
|
<<"400">> =>
|
||||||
|
emqx_mgmt_util:error_schema(?UPDATE_CONFIG_FAILED, ['BAD_LISTENER_ID', 'BAD_CONFIG_SCHEMA']),
|
||||||
<<"404">> =>
|
<<"404">> =>
|
||||||
emqx_mgmt_util:error_schema(?LISTENER_NOT_FOUND, ['BAD_LISTENER_ID']),
|
emqx_mgmt_util:error_schema(?LISTENER_NOT_FOUND, ['BAD_LISTENER_ID']),
|
||||||
|
<<"500">> =>
|
||||||
|
emqx_mgmt_util:error_schema(?OPERATION_FAILED, ['INTERNAL_ERROR']),
|
||||||
<<"200">> =>
|
<<"200">> =>
|
||||||
emqx_mgmt_util:array_schema(resp_schema(), <<"Create or update listener successfully">>)}},
|
emqx_mgmt_util:array_schema(resp_schema(), <<"Create or update listener successfully">>)}},
|
||||||
delete => #{
|
delete => #{
|
||||||
|
@ -115,7 +124,7 @@ api_list_listeners_on_node() ->
|
||||||
<<"404">> =>
|
<<"404">> =>
|
||||||
emqx_mgmt_util:error_schema(?NODE_NOT_FOUND_OR_DOWN, ['RESOURCE_NOT_FOUND']),
|
emqx_mgmt_util:error_schema(?NODE_NOT_FOUND_OR_DOWN, ['RESOURCE_NOT_FOUND']),
|
||||||
<<"500">> =>
|
<<"500">> =>
|
||||||
emqx_mgmt_util:error_schema(<<"Operation Failed">>, ['INTERNAL_ERROR']),
|
emqx_mgmt_util:error_schema(?OPERATION_FAILED, ['INTERNAL_ERROR']),
|
||||||
<<"200">> =>
|
<<"200">> =>
|
||||||
emqx_mgmt_util:schema(resp_schema(), <<"List listeners successfully">>)}}},
|
emqx_mgmt_util:schema(resp_schema(), <<"List listeners successfully">>)}}},
|
||||||
{"/nodes/:node/listeners", Metadata, list_listeners_on_node}.
|
{"/nodes/:node/listeners", Metadata, list_listeners_on_node}.
|
||||||
|
@ -136,9 +145,13 @@ api_get_update_listener_by_id_on_node() ->
|
||||||
parameters => [param_path_node(), param_path_id()],
|
parameters => [param_path_node(), param_path_id()],
|
||||||
requestBody => emqx_mgmt_util:schema(req_schema(), <<"Listener Config">>),
|
requestBody => emqx_mgmt_util:schema(req_schema(), <<"Listener Config">>),
|
||||||
responses => #{
|
responses => #{
|
||||||
|
<<"400">> =>
|
||||||
|
emqx_mgmt_util:error_schema(?UPDATE_CONFIG_FAILED, ['BAD_LISTENER_ID', 'BAD_CONFIG_SCHEMA']),
|
||||||
<<"404">> =>
|
<<"404">> =>
|
||||||
emqx_mgmt_util:error_schema(?NODE_LISTENER_NOT_FOUND,
|
emqx_mgmt_util:error_schema(?NODE_LISTENER_NOT_FOUND,
|
||||||
['BAD_NODE_NAME', 'BAD_LISTENER_ID']),
|
['BAD_NODE_NAME', 'BAD_LISTENER_ID']),
|
||||||
|
<<"500">> =>
|
||||||
|
emqx_mgmt_util:error_schema(?OPERATION_FAILED, ['INTERNAL_ERROR']),
|
||||||
<<"200">> =>
|
<<"200">> =>
|
||||||
emqx_mgmt_util:schema(resp_schema(), <<"Get listener successfully">>)}},
|
emqx_mgmt_util:schema(resp_schema(), <<"Get listener successfully">>)}},
|
||||||
delete => #{
|
delete => #{
|
||||||
|
@ -160,7 +173,7 @@ api_manage_listeners() ->
|
||||||
param_path_id(),
|
param_path_id(),
|
||||||
param_path_operation()],
|
param_path_operation()],
|
||||||
responses => #{
|
responses => #{
|
||||||
<<"500">> => emqx_mgmt_util:error_schema(<<"Operation Failed">>, ['INTERNAL_ERROR']),
|
<<"500">> => emqx_mgmt_util:error_schema(?OPERATION_FAILED, ['INTERNAL_ERROR']),
|
||||||
<<"200">> => emqx_mgmt_util:schema(<<"Operation success">>)}}},
|
<<"200">> => emqx_mgmt_util:schema(<<"Operation success">>)}}},
|
||||||
{"/listeners/:id/operation/:operation", Metadata, manage_listeners}.
|
{"/listeners/:id/operation/:operation", Metadata, manage_listeners}.
|
||||||
|
|
||||||
|
@ -173,7 +186,7 @@ api_manage_listeners_on_node() ->
|
||||||
param_path_id(),
|
param_path_id(),
|
||||||
param_path_operation()],
|
param_path_operation()],
|
||||||
responses => #{
|
responses => #{
|
||||||
<<"500">> => emqx_mgmt_util:error_schema(<<"Operation Failed">>, ['INTERNAL_ERROR']),
|
<<"500">> => emqx_mgmt_util:error_schema(?OPERATION_FAILED, ['INTERNAL_ERROR']),
|
||||||
<<"200">> => emqx_mgmt_util:schema(<<"Operation success">>)}}},
|
<<"200">> => emqx_mgmt_util:schema(<<"Operation success">>)}}},
|
||||||
{"/nodes/:node/listeners/:id/operation/:operation", Metadata, manage_listeners}.
|
{"/nodes/:node/listeners/:id/operation/:operation", Metadata, manage_listeners}.
|
||||||
|
|
||||||
|
@ -221,10 +234,23 @@ crud_listeners_by_id(get, #{bindings := #{id := Id}}) ->
|
||||||
{200, format(Listeners)}
|
{200, format(Listeners)}
|
||||||
end;
|
end;
|
||||||
crud_listeners_by_id(put, #{bindings := #{id := Id}, body := Conf}) ->
|
crud_listeners_by_id(put, #{bindings := #{id := Id}, body := Conf}) ->
|
||||||
return_listeners(emqx_mgmt:update_listener(Id, Conf));
|
Results = format(emqx_mgmt:update_listener(Id, Conf)),
|
||||||
|
case lists:filter(fun filter_errors/1, Results) of
|
||||||
|
[{error, {invalid_listener_id, Id}} | _] ->
|
||||||
|
{400, #{code => 'BAD_REQUEST', message => ?INVALID_LISTENER_PROTOCOL}};
|
||||||
|
[{error, {emqx_machine_schema, _}} | _] ->
|
||||||
|
{400, #{code => 'BAD_REQUEST', message => ?CONFIG_SCHEMA_ERROR}};
|
||||||
|
[{error, {eaddrinuse, _}} | _] ->
|
||||||
|
{400, #{code => 'BAD_REQUEST', message => ?ADDR_PORT_INUSE}};
|
||||||
|
[{error, Reason} | _] ->
|
||||||
|
{500, #{code => 'UNKNOWN_ERROR', message => err_msg(Reason)}};
|
||||||
|
[] ->
|
||||||
|
{200, Results}
|
||||||
|
end;
|
||||||
|
|
||||||
crud_listeners_by_id(delete, #{bindings := #{id := Id}}) ->
|
crud_listeners_by_id(delete, #{bindings := #{id := Id}}) ->
|
||||||
Results = emqx_mgmt:remove_listener(Id),
|
Results = emqx_mgmt:remove_listener(Id),
|
||||||
case lists:filter(fun({error, _}) -> true; (_) -> false end, Results) of
|
case lists:filter(fun filter_errors/1, Results) of
|
||||||
[] -> {200};
|
[] -> {200};
|
||||||
Errors -> {500, #{code => 'UNKNOW_ERROR', message => err_msg(Errors)}}
|
Errors -> {500, #{code => 'UNKNOW_ERROR', message => err_msg(Errors)}}
|
||||||
end.
|
end.
|
||||||
|
@ -250,6 +276,14 @@ crud_listener_by_id_on_node(get, #{bindings := #{id := Id, node := Node}}) ->
|
||||||
end;
|
end;
|
||||||
crud_listener_by_id_on_node(put, #{bindings := #{id := Id, node := Node}, body := Conf}) ->
|
crud_listener_by_id_on_node(put, #{bindings := #{id := Id, node := Node}, body := Conf}) ->
|
||||||
case emqx_mgmt:update_listener(atom(Node), Id, Conf) of
|
case emqx_mgmt:update_listener(atom(Node), Id, Conf) of
|
||||||
|
{error, nodedown} ->
|
||||||
|
{404, #{code => 'RESOURCE_NOT_FOUND', message => ?NODE_NOT_FOUND_OR_DOWN}};
|
||||||
|
{error, {invalid_listener_id, _}} ->
|
||||||
|
{400, #{code => 'BAD_REQUEST', message => ?INVALID_LISTENER_PROTOCOL}};
|
||||||
|
{error, {emqx_machine_schema, _}} ->
|
||||||
|
{400, #{code => 'BAD_REQUEST', message => ?CONFIG_SCHEMA_ERROR}};
|
||||||
|
{error, {eaddrinuse, _}} ->
|
||||||
|
{400, #{code => 'BAD_REQUEST', message => ?ADDR_PORT_INUSE}};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{500, #{code => 'UNKNOW_ERROR', message => err_msg(Reason)}};
|
{500, #{code => 'UNKNOW_ERROR', message => err_msg(Reason)}};
|
||||||
Listener ->
|
Listener ->
|
||||||
|
@ -301,13 +335,6 @@ do_manage_listeners2(<<"restart">>, Param) ->
|
||||||
{500, #{code => 'UNKNOW_ERROR', message => err_msg(Reason)}}
|
{500, #{code => 'UNKNOW_ERROR', message => err_msg(Reason)}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
return_listeners(Listeners) ->
|
|
||||||
Results = format(Listeners),
|
|
||||||
case lists:filter(fun({error, _}) -> true; (_) -> false end, Results) of
|
|
||||||
[] -> {200, Results};
|
|
||||||
Errors -> {500, #{code => 'UNKNOW_ERROR', message => manage_listeners_err(Errors)}}
|
|
||||||
end.
|
|
||||||
|
|
||||||
manage_listeners_err(Errors) ->
|
manage_listeners_err(Errors) ->
|
||||||
list_to_binary(lists:foldl(fun({Node, Err}, Str) ->
|
list_to_binary(lists:foldl(fun({Node, Err}, Str) ->
|
||||||
err_msg_str(#{node => Node, error => Err}) ++ "; " ++ Str
|
err_msg_str(#{node => Node, error => Err}) ++ "; " ++ Str
|
||||||
|
@ -332,6 +359,11 @@ trans_running(Conf) ->
|
||||||
Running
|
Running
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
filter_errors({error, _}) ->
|
||||||
|
true;
|
||||||
|
filter_errors(_) ->
|
||||||
|
false.
|
||||||
|
|
||||||
jsonable_resp(bind, Port) when is_integer(Port) ->
|
jsonable_resp(bind, Port) when is_integer(Port) ->
|
||||||
{bind, Port};
|
{bind, Port};
|
||||||
jsonable_resp(bind, {Addr, Port}) when is_tuple(Addr); is_integer(Port)->
|
jsonable_resp(bind, {Addr, Port}) when is_tuple(Addr); is_integer(Port)->
|
||||||
|
|
Loading…
Reference in New Issue