refactor(gw): more readable CLI print
This commit is contained in:
parent
d8f49f8a5f
commit
79a653e2b4
|
@ -22,6 +22,7 @@
|
|||
%% @doc The Gateway defination
|
||||
-type gateway() ::
|
||||
#{ name := gateway_name()
|
||||
%% Description
|
||||
, descr => binary() | undefined
|
||||
%% Appears only in getting gateway info
|
||||
, status => stopped | running | unloaded
|
||||
|
|
|
@ -53,23 +53,16 @@ is_cmd(Fun) ->
|
|||
|
||||
gateway(["list"]) ->
|
||||
lists:foreach(
|
||||
fun (#{name := Name, status := unloaded}) ->
|
||||
print("Gateway(name=~ts, status=unloaded)\n", [Name]);
|
||||
(#{name := Name, status := stopped, stopped_at := StoppedAt}) ->
|
||||
print("Gateway(name=~ts, status=stopped, stopped_at=~ts)\n",
|
||||
[Name, StoppedAt]);
|
||||
(#{name := Name, status := running, current_connections := ConnCnt,
|
||||
started_at := StartedAt}) ->
|
||||
print("Gateway(name=~ts, status=running, clients=~w, started_at=~ts)\n",
|
||||
[Name, ConnCnt, StartedAt])
|
||||
fun (GwSummary) ->
|
||||
print(format_gw_summary(GwSummary))
|
||||
end, emqx_gateway_http:gateways(all));
|
||||
|
||||
gateway(["lookup", Name]) ->
|
||||
case emqx_gateway:lookup(atom(Name)) of
|
||||
undefined ->
|
||||
print("undefined\n");
|
||||
Info ->
|
||||
print("~p\n", [Info])
|
||||
Gateway ->
|
||||
print(format_gateway(Gateway))
|
||||
end;
|
||||
|
||||
gateway(["load", Name, Conf]) ->
|
||||
|
@ -80,7 +73,7 @@ gateway(["load", Name, Conf]) ->
|
|||
{ok, _} ->
|
||||
print("ok\n");
|
||||
{error, Reason} ->
|
||||
print("Error: ~p\n", [Reason])
|
||||
print("Error: ~ts\n", [format_error(Reason)])
|
||||
end;
|
||||
|
||||
gateway(["unload", Name]) ->
|
||||
|
@ -88,7 +81,7 @@ gateway(["unload", Name]) ->
|
|||
ok ->
|
||||
print("ok\n");
|
||||
{error, Reason} ->
|
||||
print("Error: ~p\n", [Reason])
|
||||
print("Error: ~ts\n", [format_error(Reason)])
|
||||
end;
|
||||
|
||||
gateway(["stop", Name]) ->
|
||||
|
@ -99,7 +92,7 @@ gateway(["stop", Name]) ->
|
|||
{ok, _} ->
|
||||
print("ok\n");
|
||||
{error, Reason} ->
|
||||
print("Error: ~p\n", [Reason])
|
||||
print("Error: ~ts\n", [format_error(Reason)])
|
||||
end;
|
||||
|
||||
gateway(["start", Name]) ->
|
||||
|
@ -110,23 +103,24 @@ gateway(["start", Name]) ->
|
|||
{ok, _} ->
|
||||
print("ok\n");
|
||||
{error, Reason} ->
|
||||
print("Error: ~p\n", [Reason])
|
||||
print("Error: ~ts\n", [format_error(Reason)])
|
||||
end;
|
||||
|
||||
gateway(_) ->
|
||||
emqx_ctl:usage([ {"gateway list",
|
||||
"List all gateway"}
|
||||
, {"gateway lookup <Name>",
|
||||
"Lookup a gateway detailed informations"}
|
||||
, {"gateway load <Name> <JsonConf>",
|
||||
"Load a gateway with config"}
|
||||
, {"gateway unload <Name>",
|
||||
"Unload the gateway"}
|
||||
, {"gateway stop <Name>",
|
||||
"Stop the gateway"}
|
||||
, {"gateway start <Name>",
|
||||
"Start the gateway"}
|
||||
]).
|
||||
emqx_ctl:usage(
|
||||
[ {"gateway list",
|
||||
"List all gateway"}
|
||||
, {"gateway lookup <Name>",
|
||||
"Lookup a gateway detailed informations"}
|
||||
, {"gateway load <Name> <JsonConf>",
|
||||
"Load a gateway with config"}
|
||||
, {"gateway unload <Name>",
|
||||
"Unload the gateway"}
|
||||
, {"gateway stop <Name>",
|
||||
"Stop the gateway"}
|
||||
, {"gateway start <Name>",
|
||||
"Start the gateway"}
|
||||
]).
|
||||
|
||||
'gateway-registry'(["list"]) ->
|
||||
lists:foreach(
|
||||
|
@ -255,3 +249,50 @@ format(peername, {IPAddr, Port}) ->
|
|||
|
||||
format(_, Val) ->
|
||||
Val.
|
||||
|
||||
format_gw_summary(#{name := Name, status := unloaded}) ->
|
||||
io_lib:format("Gateway(name=~ts, status=unloaded)\n", [Name]);
|
||||
|
||||
format_gw_summary(#{name := Name, status := stopped,
|
||||
stopped_at := StoppedAt}) ->
|
||||
io_lib:format("Gateway(name=~ts, status=stopped, stopped_at=~ts)\n",
|
||||
[Name, StoppedAt]);
|
||||
format_gw_summary(#{name := Name, status := running,
|
||||
current_connections := ConnCnt,
|
||||
started_at := StartedAt}) ->
|
||||
io_lib:format("Gateway(name=~ts, status=running, clients=~w, "
|
||||
"started_at=~ts)\n", [Name, ConnCnt, StartedAt]).
|
||||
|
||||
format_gateway(#{name := Name,
|
||||
status := unloaded}) ->
|
||||
io_lib:format(
|
||||
"name: ~ts\n"
|
||||
"status: unloaded\n", [Name]);
|
||||
|
||||
format_gateway(Gw =
|
||||
#{name := Name,
|
||||
status := Status,
|
||||
created_at := CreatedAt,
|
||||
config := Config
|
||||
}) ->
|
||||
{StopOrStart, Timestamp} =
|
||||
case Status of
|
||||
stopped -> {stopped_at, maps:get(stopped_at, Gw)};
|
||||
running -> {started_at, maps:get(started_at, Gw)}
|
||||
end,
|
||||
io_lib:format(
|
||||
"name: ~ts\n"
|
||||
"status: ~ts\n"
|
||||
"created_at: ~ts\n"
|
||||
"~ts: ~ts\n"
|
||||
"config: ~p\n",
|
||||
[Name, Status,
|
||||
emqx_gateway_utils:unix_ts_to_rfc3339(CreatedAt),
|
||||
StopOrStart, emqx_gateway_utils:unix_ts_to_rfc3339(Timestamp),
|
||||
Config]).
|
||||
|
||||
format_error(Reason) ->
|
||||
case emqx_gateway_http:reason2msg(Reason) of
|
||||
error -> io_lib:format("~p", [Reason]);
|
||||
Msg -> Msg
|
||||
end.
|
||||
|
|
|
@ -93,6 +93,7 @@ load_gateway(GwName, Conf) ->
|
|||
%% @doc convert listener array to map
|
||||
unconvert_listeners(Ls) when is_list(Ls) ->
|
||||
lists:foldl(fun(Lis, Acc) ->
|
||||
%% FIXME: params apperence guard?
|
||||
{[Type, Name], Lis1} = maps_key_take([<<"type">>, <<"name">>], Lis),
|
||||
NLis1 = maps:without([<<"id">>], Lis1),
|
||||
emqx_map_lib:deep_merge(Acc, #{Type => #{Name => NLis1}})
|
||||
|
|
|
@ -62,12 +62,15 @@
|
|||
, with_listener_authn/3
|
||||
, checks/2
|
||||
, reason2resp/1
|
||||
, reason2msg/1
|
||||
]).
|
||||
|
||||
-type gateway_summary() ::
|
||||
#{ name := binary()
|
||||
, status := running | stopped | unloaded
|
||||
, created_at => binary()
|
||||
, started_at => binary()
|
||||
, stopped_at => binary()
|
||||
, max_connections => integer()
|
||||
, current_connections => integer()
|
||||
, listeners => []
|
||||
|
@ -317,57 +320,13 @@ with_channel(GwName, ClientId, Fun) ->
|
|||
%%--------------------------------------------------------------------
|
||||
|
||||
-spec reason2resp({atom(), map()} | any()) -> binary() | any().
|
||||
reason2resp({badconf, #{key := Key, value := Value, reason := Reason}}) ->
|
||||
fmt400err("Bad config value '~s' for '~s', reason: ~s",
|
||||
[Value, Key, Reason]);
|
||||
reason2resp({badres, #{resource := gateway,
|
||||
gateway := GwName,
|
||||
reason := not_found}}) ->
|
||||
fmt400err("The ~s gateway is unloaded", [GwName]);
|
||||
|
||||
reason2resp({badres, #{resource := gateway,
|
||||
gateway := GwName,
|
||||
reason := already_exist}}) ->
|
||||
fmt400err("The ~s gateway has loaded", [GwName]);
|
||||
|
||||
reason2resp({badres, #{resource := listener,
|
||||
listener := {GwName, LType, LName},
|
||||
reason := not_found}}) ->
|
||||
fmt400err("Listener ~s not found",
|
||||
[listener_id(GwName, LType, LName)]);
|
||||
|
||||
reason2resp({badres, #{resource := listener,
|
||||
listener := {GwName, LType, LName},
|
||||
reason := already_exist}}) ->
|
||||
fmt400err("The listener ~s of ~s already exist",
|
||||
[listener_id(GwName, LType, LName), GwName]);
|
||||
|
||||
reason2resp({badres, #{resource := authn,
|
||||
gateway := GwName,
|
||||
reason := not_found}}) ->
|
||||
fmt400err("The authentication not found on ~s", [GwName]);
|
||||
|
||||
reason2resp({badres, #{resource := authn,
|
||||
gateway := GwName,
|
||||
reason := already_exist}}) ->
|
||||
fmt400err("The authentication already exist on ~s", [GwName]);
|
||||
|
||||
reason2resp({badres, #{resource := listener_authn,
|
||||
listener := {GwName, LType, LName},
|
||||
reason := not_found}}) ->
|
||||
fmt400err("The authentication not found on ~s",
|
||||
[listener_id(GwName, LType, LName)]);
|
||||
|
||||
reason2resp({badres, #{resource := listener_authn,
|
||||
listener := {GwName, LType, LName},
|
||||
reason := already_exist}}) ->
|
||||
fmt400err("The authentication already exist on ~s",
|
||||
[listener_id(GwName, LType, LName)]);
|
||||
|
||||
reason2resp(R) -> return_http_error(500, R).
|
||||
|
||||
fmt400err(Fmt, Args) ->
|
||||
return_http_error(400, io_lib:format(Fmt, Args)).
|
||||
reason2resp(R) ->
|
||||
case reason2msg(R) of
|
||||
error ->
|
||||
return_http_error(500, R);
|
||||
Msg ->
|
||||
return_http_error(400, Msg)
|
||||
end.
|
||||
|
||||
-spec return_http_error(integer(), any()) -> {integer(), binary()}.
|
||||
return_http_error(Code, Msg) ->
|
||||
|
@ -377,6 +336,56 @@ return_http_error(Code, Msg) ->
|
|||
})
|
||||
}.
|
||||
|
||||
-spec reason2msg({atom(), map()} | any()) -> error | io_lib:chars().
|
||||
reason2msg({badconf, #{key := Key, value := Value, reason := Reason}}) ->
|
||||
io_lib:format("Bad config value '~s' for '~s', reason: ~s",
|
||||
[Value, Key, Reason]);
|
||||
reason2msg({badres, #{resource := gateway,
|
||||
gateway := GwName,
|
||||
reason := not_found}}) ->
|
||||
io_lib:format("The ~s gateway is unloaded", [GwName]);
|
||||
|
||||
reason2msg({badres, #{resource := gateway,
|
||||
gateway := GwName,
|
||||
reason := already_exist}}) ->
|
||||
io_lib:format("The ~s gateway already loaded", [GwName]);
|
||||
|
||||
reason2msg({badres, #{resource := listener,
|
||||
listener := {GwName, LType, LName},
|
||||
reason := not_found}}) ->
|
||||
io_lib:format("Listener ~s not found",
|
||||
[listener_id(GwName, LType, LName)]);
|
||||
|
||||
reason2msg({badres, #{resource := listener,
|
||||
listener := {GwName, LType, LName},
|
||||
reason := already_exist}}) ->
|
||||
io_lib:format("The listener ~s of ~s already exist",
|
||||
[listener_id(GwName, LType, LName), GwName]);
|
||||
|
||||
reason2msg({badres, #{resource := authn,
|
||||
gateway := GwName,
|
||||
reason := not_found}}) ->
|
||||
io_lib:format("The authentication not found on ~s", [GwName]);
|
||||
|
||||
reason2msg({badres, #{resource := authn,
|
||||
gateway := GwName,
|
||||
reason := already_exist}}) ->
|
||||
io_lib:format("The authentication already exist on ~s", [GwName]);
|
||||
|
||||
reason2msg({badres, #{resource := listener_authn,
|
||||
listener := {GwName, LType, LName},
|
||||
reason := not_found}}) ->
|
||||
io_lib:format("The authentication not found on ~s",
|
||||
[listener_id(GwName, LType, LName)]);
|
||||
|
||||
reason2msg({badres, #{resource := listener_authn,
|
||||
listener := {GwName, LType, LName},
|
||||
reason := already_exist}}) ->
|
||||
io_lib:format("The authentication already exist on ~s",
|
||||
[listener_id(GwName, LType, LName)]);
|
||||
reason2msg(_) ->
|
||||
error.
|
||||
|
||||
codestr(400) -> 'BAD_REQUEST';
|
||||
codestr(401) -> 'NOT_SUPPORTED_NOW';
|
||||
codestr(404) -> 'RESOURCE_NOT_FOUND';
|
||||
|
|
|
@ -29,6 +29,23 @@
|
|||
gateway {}
|
||||
">>).
|
||||
|
||||
%% The config with json format for mqtt-sn gateway
|
||||
-define(CONF_MQTTSN, "
|
||||
{\"idle_timeout\": \"30s\",
|
||||
\"enable_stats\": true,
|
||||
\"mountpoint\": \"mqttsn/\",
|
||||
\"gateway_id\": 1,
|
||||
\"broadcast\": true,
|
||||
\"enable_qos3\": true,
|
||||
\"predefined\": [{\"id\": 1001, \"topic\": \"pred/a\"}],
|
||||
\"listeners\":
|
||||
[{\"type\": \"udp\",
|
||||
\"name\": \"ct\",
|
||||
\"bind\": \"2885\"
|
||||
}]
|
||||
}
|
||||
").
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Setup
|
||||
%%--------------------------------------------------------------------
|
||||
|
@ -109,16 +126,61 @@ t_gateway_list(_) ->
|
|||
"Gateway(name=stomp, status=unloaded)\n"
|
||||
, acc_print()).
|
||||
|
||||
t_gateway_load(_) ->
|
||||
t_gateway_load_unload_lookup(_) ->
|
||||
emqx_gateway_cli:gateway(["lookup", "mqttsn"]),
|
||||
?assertEqual("undefined\n", acc_print()),
|
||||
|
||||
emqx_gateway_cli:gateway(["load", "mqttsn", ?CONF_MQTTSN]),
|
||||
?assertEqual("ok\n", acc_print()),
|
||||
|
||||
%% TODO: bad config name, format???
|
||||
|
||||
emqx_gateway_cli:gateway(["lookup", "mqttsn"]),
|
||||
%% TODO: assert it. for example:
|
||||
%% name: mqttsn
|
||||
%% status: running
|
||||
%% created_at: 2022-01-05T14:40:20.039+08:00
|
||||
%% started_at: 2022-01-05T14:42:37.894+08:00
|
||||
%% config: #{broadcast => false,enable => true,enable_qos3 => true,
|
||||
%% enable_stats => true,gateway_id => 1,idle_timeout => 30000,
|
||||
%% mountpoint => <<>>,predefined => []}
|
||||
_ = acc_print(),
|
||||
|
||||
emqx_gateway_cli:gateway(["load", "mqttsn", "{}"]),
|
||||
?assertEqual(
|
||||
"Error: The mqttsn gateway already loaded\n"
|
||||
, acc_print()),
|
||||
|
||||
emqx_gateway_cli:gateway(["load", "bad-gw-name", "{}"]),
|
||||
%% TODO: assert it. for example:
|
||||
%% Error: Illegal gateway name
|
||||
_ = acc_print(),
|
||||
|
||||
emqx_gateway_cli:gateway(["unload", "mqttsn"]),
|
||||
?assertEqual("ok\n", acc_print()),
|
||||
%% Always return ok, even the gateway has unloaded
|
||||
emqx_gateway_cli:gateway(["unload", "mqttsn"]),
|
||||
?assertEqual("ok\n", acc_print()),
|
||||
|
||||
emqx_gateway_cli:gateway(["lookup", "mqttsn"]),
|
||||
?assertEqual("undefined\n", acc_print()),
|
||||
ok.
|
||||
|
||||
t_gateway_unload(_) ->
|
||||
ok.
|
||||
t_gateway_start_stop(_) ->
|
||||
emqx_gateway_cli:gateway(["load", "mqttsn", ?CONF_MQTTSN]),
|
||||
?assertEqual("ok\n", acc_print()),
|
||||
|
||||
t_gateway_start(_) ->
|
||||
ok.
|
||||
emqx_gateway_cli:gateway(["stop", "mqttsn"]),
|
||||
?assertEqual("ok\n", acc_print()),
|
||||
%% dupliacted stop gateway, return ok
|
||||
emqx_gateway_cli:gateway(["stop", "mqttsn"]),
|
||||
?assertEqual("ok\n", acc_print()),
|
||||
|
||||
t_gateway_stop(_) ->
|
||||
emqx_gateway_cli:gateway(["start", "mqttsn"]),
|
||||
?assertEqual("ok\n", acc_print()),
|
||||
%% dupliacted start gateway, return ok
|
||||
emqx_gateway_cli:gateway(["start", "mqttsn"]),
|
||||
?assertEqual("ok\n", acc_print()),
|
||||
ok.
|
||||
|
||||
t_gateway_clients_usage(_) ->
|
||||
|
|
Loading…
Reference in New Issue