refactor(listener): GET /listeners API returns full config of listeners
This commit is contained in:
parent
c0eaa30064
commit
ca327b7c55
|
@ -24,13 +24,16 @@
|
|||
, safe_atom_key_map/1
|
||||
, unsafe_atom_key_map/1
|
||||
, jsonable_map/1
|
||||
, jsonable_value/1
|
||||
, deep_convert/2
|
||||
, jsonable_map/2
|
||||
, binary_string/1
|
||||
, deep_convert/3
|
||||
]).
|
||||
|
||||
-export_type([config_key/0, config_key_path/0]).
|
||||
-type config_key() :: atom() | binary().
|
||||
-type config_key_path() :: [config_key()].
|
||||
-type convert_fun() :: fun((K::any(), V::any(), Args::list()) ->
|
||||
{K1::any(), V1::any()} | drop).
|
||||
|
||||
%%-----------------------------------------------------------------
|
||||
-spec deep_get(config_key_path(), map()) -> term().
|
||||
|
@ -100,15 +103,17 @@ deep_merge(BaseMap, NewMap) ->
|
|||
end, #{}, BaseMap),
|
||||
maps:merge(MergedBase, maps:with(NewKeys, NewMap)).
|
||||
|
||||
-spec deep_convert(map(), fun((K::any(), V::any()) -> {K1::any(), V1::any()})) -> map().
|
||||
deep_convert(Map, ConvFun) when is_map(Map) ->
|
||||
-spec deep_convert(map(), convert_fun(), Args::list()) -> map().
|
||||
deep_convert(Map, ConvFun, Args) when is_map(Map) ->
|
||||
maps:fold(fun(K, V, Acc) ->
|
||||
{K1, V1} = ConvFun(K, deep_convert(V, ConvFun)),
|
||||
Acc#{K1 => V1}
|
||||
case apply(ConvFun, [K, deep_convert(V, ConvFun, Args) | Args]) of
|
||||
drop -> Acc;
|
||||
{K1, V1} -> Acc#{K1 => V1}
|
||||
end
|
||||
end, #{}, Map);
|
||||
deep_convert(ListV, ConvFun) when is_list(ListV) ->
|
||||
[deep_convert(V, ConvFun) || V <- ListV];
|
||||
deep_convert(Val, _) -> Val.
|
||||
deep_convert(ListV, ConvFun, Args) when is_list(ListV) ->
|
||||
[deep_convert(V, ConvFun, Args) || V <- ListV];
|
||||
deep_convert(Val, _, _Args) -> Val.
|
||||
|
||||
-spec unsafe_atom_key_map(#{binary() | atom() => any()}) -> #{atom() => any()}.
|
||||
unsafe_atom_key_map(Map) ->
|
||||
|
@ -120,17 +125,24 @@ safe_atom_key_map(Map) ->
|
|||
|
||||
-spec jsonable_map(map() | list()) -> map() | list().
|
||||
jsonable_map(Map) ->
|
||||
deep_convert(Map, fun(K, V) ->
|
||||
{jsonable_value(K), jsonable_value(V)}
|
||||
end).
|
||||
jsonable_map(Map, fun(K, V) -> {K, V} end).
|
||||
|
||||
jsonable_value([]) -> [];
|
||||
jsonable_value(Val) when is_list(Val) ->
|
||||
jsonable_map(Map, JsonableFun) ->
|
||||
deep_convert(Map, fun binary_string_kv/3, [JsonableFun]).
|
||||
|
||||
binary_string_kv(K, V, JsonableFun) ->
|
||||
case JsonableFun(K, V) of
|
||||
drop -> drop;
|
||||
{K1, V1} -> {binary_string(K1), binary_string(V1)}
|
||||
end.
|
||||
|
||||
binary_string([]) -> [];
|
||||
binary_string(Val) when is_list(Val) ->
|
||||
case io_lib:printable_unicode_list(Val) of
|
||||
true -> unicode:characters_to_binary(Val);
|
||||
false -> Val
|
||||
false -> [binary_string(V) || V <- Val]
|
||||
end;
|
||||
jsonable_value(Val) ->
|
||||
binary_string(Val) ->
|
||||
Val.
|
||||
|
||||
%%---------------------------------------------------------------------------
|
||||
|
@ -138,4 +150,4 @@ covert_keys_to_atom(BinKeyMap, Conv) ->
|
|||
deep_convert(BinKeyMap, fun
|
||||
(K, V) when is_atom(K) -> {K, V};
|
||||
(K, V) when is_binary(K) -> {Conv(K), V}
|
||||
end).
|
||||
end, []).
|
||||
|
|
|
@ -188,7 +188,7 @@ gen_schema(_Conf) ->
|
|||
#{type => string}.
|
||||
|
||||
with_default_value(Type, Value) ->
|
||||
Type#{example => emqx_map_lib:jsonable_value(Value)}.
|
||||
Type#{example => emqx_map_lib:binary_string(Value)}.
|
||||
|
||||
path_join(Path) ->
|
||||
path_join(Path, "/").
|
||||
|
|
|
@ -24,13 +24,8 @@
|
|||
, list_listeners_by_id/2
|
||||
, list_listeners_on_node/2
|
||||
, get_listener_by_id_on_node/2
|
||||
, manage_listeners/2]).
|
||||
|
||||
-import(emqx_mgmt_util, [ schema/1
|
||||
, object_schema/2
|
||||
, object_array_schema/2
|
||||
, error_schema/2
|
||||
, properties/1
|
||||
, manage_listeners/2
|
||||
, jsonable_resp/2
|
||||
]).
|
||||
|
||||
-export([format/1]).
|
||||
|
@ -53,17 +48,23 @@ api_spec() ->
|
|||
[]
|
||||
}.
|
||||
|
||||
properties() ->
|
||||
properties([
|
||||
{node, string, <<"Node">>},
|
||||
{id, string, <<"Identifier">>},
|
||||
{acceptors, integer, <<"Number of Acceptor process">>},
|
||||
{max_conn, integer, <<"Maximum number of allowed connection">>},
|
||||
{type, string, <<"Listener type">>},
|
||||
{listen_on, string, <<"Listener port">>},
|
||||
{running, boolean, <<"Open or close">>},
|
||||
{auth, boolean, <<"Has auth">>}
|
||||
]).
|
||||
-define(TYPES, [tcp, ssl, ws, wss, quic]).
|
||||
req_schema() ->
|
||||
Schema = [emqx_mgmt_api_configs:gen_schema(
|
||||
emqx:get_raw_config([listeners, T, default], #{}))
|
||||
|| T <- ?TYPES],
|
||||
#{oneOf => Schema}.
|
||||
|
||||
resp_schema() ->
|
||||
#{oneOf := Schema} = req_schema(),
|
||||
AddMetadata = fun(Prop) ->
|
||||
Prop#{running => #{type => boolean},
|
||||
id => #{type => string},
|
||||
node => #{type => string}}
|
||||
end,
|
||||
Schema1 = [S#{properties => AddMetadata(Prop)}
|
||||
|| S = #{properties := Prop} <- Schema],
|
||||
#{oneOf => Schema1}.
|
||||
|
||||
api_list_listeners() ->
|
||||
Metadata = #{
|
||||
|
@ -71,7 +72,7 @@ api_list_listeners() ->
|
|||
description => <<"List listeners from all nodes in the cluster">>,
|
||||
responses => #{
|
||||
<<"200">> =>
|
||||
object_array_schema(properties(), <<"List listeners successfully">>)}}},
|
||||
emqx_mgmt_util:array_schema(resp_schema(), <<"List listeners successfully">>)}}},
|
||||
{"/listeners", Metadata, list_listeners}.
|
||||
|
||||
api_list_listeners_by_id() ->
|
||||
|
@ -81,9 +82,9 @@ api_list_listeners_by_id() ->
|
|||
parameters => [param_path_id()],
|
||||
responses => #{
|
||||
<<"404">> =>
|
||||
error_schema(?LISTENER_NOT_FOUND, ['BAD_LISTENER_ID']),
|
||||
emqx_mgmt_util:error_schema(?LISTENER_NOT_FOUND, ['BAD_LISTENER_ID']),
|
||||
<<"200">> =>
|
||||
object_array_schema(properties(), <<"List listeners successfully">>)}}},
|
||||
emqx_mgmt_util:array_schema(resp_schema(), <<"List listeners successfully">>)}}},
|
||||
{"/listeners/:id", Metadata, list_listeners_by_id}.
|
||||
|
||||
api_list_listeners_on_node() ->
|
||||
|
@ -92,7 +93,7 @@ api_list_listeners_on_node() ->
|
|||
description => <<"List listeners in one node">>,
|
||||
parameters => [param_path_node()],
|
||||
responses => #{
|
||||
<<"200">> => object_schema(properties(), <<"List listeners successfully">>)}}},
|
||||
<<"200">> => emqx_mgmt_util:object_schema(resp_schema(), <<"List listeners successfully">>)}}},
|
||||
{"/nodes/:node/listeners", Metadata, list_listeners_on_node}.
|
||||
|
||||
api_get_listener_by_id_on_node() ->
|
||||
|
@ -102,10 +103,10 @@ api_get_listener_by_id_on_node() ->
|
|||
parameters => [param_path_node(), param_path_id()],
|
||||
responses => #{
|
||||
<<"404">> =>
|
||||
error_schema(?NODE_LISTENER_NOT_FOUND,
|
||||
emqx_mgmt_util:error_schema(?NODE_LISTENER_NOT_FOUND,
|
||||
['BAD_NODE_NAME', 'BAD_LISTENER_ID']),
|
||||
<<"200">> =>
|
||||
object_schema(properties(), <<"Get listener successfully">>)}}},
|
||||
emqx_mgmt_util:object_schema(resp_schema(), <<"Get listener successfully">>)}}},
|
||||
{"/nodes/:node/listeners/:id", Metadata, get_listener_by_id_on_node}.
|
||||
|
||||
api_manage_listeners() ->
|
||||
|
@ -116,9 +117,9 @@ api_manage_listeners() ->
|
|||
param_path_id(),
|
||||
param_path_operation()],
|
||||
responses => #{
|
||||
<<"500">> => error_schema(<<"Operation Failed">>, ['INTERNAL_ERROR']),
|
||||
<<"200">> => schema(<<"Operation success">>)}}},
|
||||
{"/listeners/:id/:operation", Metadata, manage_listeners}.
|
||||
<<"500">> => emqx_mgmt_util:error_schema(<<"Operation Failed">>, ['INTERNAL_ERROR']),
|
||||
<<"200">> => emqx_mgmt_util:schema(<<"Operation success">>)}}},
|
||||
{"/listeners/:id/operation/:operation", Metadata, manage_listeners}.
|
||||
|
||||
api_manage_listeners_on_node() ->
|
||||
Metadata = #{
|
||||
|
@ -129,9 +130,9 @@ api_manage_listeners_on_node() ->
|
|||
param_path_id(),
|
||||
param_path_operation()],
|
||||
responses => #{
|
||||
<<"500">> => error_schema(<<"Operation Failed">>, ['INTERNAL_ERROR']),
|
||||
<<"200">> => schema(<<"Operation success">>)}}},
|
||||
{"/nodes/:node/listeners/:id/:operation", Metadata, manage_listeners}.
|
||||
<<"500">> => emqx_mgmt_util:error_schema(<<"Operation Failed">>, ['INTERNAL_ERROR']),
|
||||
<<"200">> => emqx_mgmt_util:schema(<<"Operation success">>)}}},
|
||||
{"/nodes/:node/listeners/:id/operation/:operation", Metadata, manage_listeners}.
|
||||
|
||||
%%%==============================================================================================
|
||||
%% parameters
|
||||
|
@ -247,16 +248,12 @@ format({error, Reason}) ->
|
|||
{error, Reason};
|
||||
|
||||
format({ID, Conf}) ->
|
||||
{Type, _Name} = emqx_listeners:parse_listener_id(ID),
|
||||
#{
|
||||
emqx_map_lib:jsonable_map(Conf#{
|
||||
id => ID,
|
||||
node => maps:get(node, Conf),
|
||||
acceptors => maps:get(acceptors, Conf),
|
||||
max_conn => maps:get(max_connections, Conf),
|
||||
type => Type,
|
||||
listen_on => list_to_binary(esockd:to_string(maps:get(bind, Conf))),
|
||||
running => trans_running(Conf)
|
||||
}.
|
||||
}, fun ?MODULE:jsonable_resp/2).
|
||||
|
||||
trans_running(Conf) ->
|
||||
case maps:get(running, Conf) of
|
||||
{error, _} ->
|
||||
|
@ -265,6 +262,15 @@ trans_running(Conf) ->
|
|||
Running
|
||||
end.
|
||||
|
||||
jsonable_resp(bind, Port) when is_integer(Port) ->
|
||||
{bind, Port};
|
||||
jsonable_resp(bind, {Addr, Port}) when is_tuple(Addr); is_integer(Port)->
|
||||
{bind, inet:ntoa(Addr) ++ ":" ++ integer_to_list(Port)};
|
||||
jsonable_resp(user_lookup_fun, _) ->
|
||||
drop;
|
||||
jsonable_resp(K, V) ->
|
||||
{K, V}.
|
||||
|
||||
atom(B) when is_binary(B) -> binary_to_atom(B, utf8);
|
||||
atom(S) when is_list(S) -> list_to_atom(S);
|
||||
atom(A) when is_atom(A) -> A.
|
||||
|
|
Loading…
Reference in New Issue