|
|
@@ -16,7 +16,13 @@
|
|
|
|
|
|
-module (emqttd_cli_config).
|
|
|
|
|
|
--export ([register_config_cli/0, register_config/0, run/1]).
|
|
|
+-export ([register_config_cli/0,
|
|
|
+ register_config/0,
|
|
|
+ run/1,
|
|
|
+ set_usage/0,
|
|
|
+ all_cfgs/0,
|
|
|
+ get_cfg/2,
|
|
|
+ get_cfg/3]).
|
|
|
|
|
|
-define(APP, emqttd).
|
|
|
|
|
|
@@ -46,6 +52,54 @@ register_config_cli() ->
|
|
|
register_broker_config(),
|
|
|
register_lager_config().
|
|
|
|
|
|
+set_usage() ->
|
|
|
+ io:format("~-40s# ~-20s# ~-20s ~p~n", ["key", "value", "datatype", "app"]),
|
|
|
+ io:format("------------------------------------------------------------------------------------------------~n"),
|
|
|
+ lists:foreach(fun({Key, Val, Datatype, App}) ->
|
|
|
+ io:format("~-40s# ~-20s# ~-20s ~p~n", [Key, Val, Datatype, App])
|
|
|
+ end, all_cfgs()),
|
|
|
+ io:format("------------------------------------------------------------------------------------------------~n"),
|
|
|
+ io:format("Usage: set key=value --app=appname~n").
|
|
|
+
|
|
|
+all_cfgs() ->
|
|
|
+ {Mappings, Mappings1} = lists:foldl(
|
|
|
+ fun({Key, {_, Map, _}}, {Acc, Acc1}) ->
|
|
|
+ Map1 = lists:map(fun(M) -> {cuttlefish_mapping:variable(M), Key} end, Map),
|
|
|
+ {Acc ++ Map, Acc1 ++ Map1}
|
|
|
+ end, {[], []}, ets:tab2list(clique_schema)),
|
|
|
+ lists:foldl(fun({Key, _}, Acc) ->
|
|
|
+ case lists:keyfind(cuttlefish_variable:tokenize(Key), 2, Mappings) of
|
|
|
+ false -> Acc;
|
|
|
+ Map ->
|
|
|
+ Datatype = format_datatype(cuttlefish_mapping:datatype(Map)),
|
|
|
+ App = proplists:get_value(cuttlefish_variable:tokenize(Key), Mappings1),
|
|
|
+ [{_, [Val0]}] = clique_config:show([Key], [{app, App}]),
|
|
|
+ Val = any_to_string(proplists:get_value(Key, Val0)),
|
|
|
+ [{Key, Val, Datatype, App} | Acc]
|
|
|
+ end
|
|
|
+ end, [],lists:sort(ets:tab2list(clique_config))).
|
|
|
+
|
|
|
+get_cfg(App, Key) ->
|
|
|
+ get_cfg(App, Key, undefined).
|
|
|
+
|
|
|
+get_cfg(App, Key, Def) ->
|
|
|
+ [{_, [Val0]}] = clique_config:show([Key], [{app, App}]),
|
|
|
+ proplists:get_value(Key, Val0, Def).
|
|
|
+
|
|
|
+format_datatype(Value) ->
|
|
|
+ format_datatype(Value, "").
|
|
|
+
|
|
|
+format_datatype([Head], Acc) when is_tuple(Head) ->
|
|
|
+ [Head1 | _] = erlang:tuple_to_list(Head),
|
|
|
+ lists:concat([Acc, Head1]);
|
|
|
+format_datatype([Head], Acc) ->
|
|
|
+ lists:concat([Acc, Head]);
|
|
|
+format_datatype([Head | Tail], Acc) when is_tuple(Head)->
|
|
|
+ [Head1 | _] = erlang:tuple_to_list(Head),
|
|
|
+ format_datatype(Tail, Acc ++ lists:concat([Head1, ", "]));
|
|
|
+format_datatype([Head | Tail], Acc) ->
|
|
|
+ format_datatype(Tail, Acc ++ lists:concat([Head, ", "])).
|
|
|
+
|
|
|
%%--------------------------------------------------------------------
|
|
|
%% Auth/Acl
|
|
|
%%--------------------------------------------------------------------
|
|
|
@@ -72,6 +126,8 @@ register_protocol_formatter() ->
|
|
|
"keepalive_backoff"],
|
|
|
[clique:register_formatter(["mqtt", Key], fun protocol_formatter_callback/2) || Key <- ConfigKeys].
|
|
|
|
|
|
+protocol_formatter_callback([_, "websocket_protocol_header"], Params) ->
|
|
|
+ Params;
|
|
|
protocol_formatter_callback([_, Key], Params) ->
|
|
|
proplists:get_value(l2a(Key), Params).
|
|
|
|
|
|
@@ -85,6 +141,9 @@ register_protocol_config() ->
|
|
|
|
|
|
protocol_config_callback([_AppStr, KeyStr], Value) ->
|
|
|
protocol_config_callback(protocol, l2a(KeyStr), Value).
|
|
|
+protocol_config_callback(_App, websocket_protocol_header, Value) ->
|
|
|
+ application:set_env(?APP, websocket_protocol_header, Value),
|
|
|
+ " successfully\n";
|
|
|
protocol_config_callback(App, Key, Value) ->
|
|
|
{ok, Env} = emqttd:env(App),
|
|
|
application:set_env(?APP, App, lists:keyreplace(Key, 1, Env, {Key, Value})),
|
|
|
@@ -126,6 +185,15 @@ register_client_config() ->
|
|
|
|
|
|
client_config_callback([_, AppStr, KeyStr], Value) ->
|
|
|
client_config_callback(l2a(AppStr), l2a(KeyStr), Value).
|
|
|
+
|
|
|
+client_config_callback(App, idle_timeout, Value) ->
|
|
|
+ {ok, Env} = emqttd:env(App),
|
|
|
+ application:set_env(?APP, App, lists:keyreplace(client_idle_timeout, 1, Env, {client_idle_timeout, Value})),
|
|
|
+ " successfully\n";
|
|
|
+client_config_callback(App, enable_stats, Value) ->
|
|
|
+ {ok, Env} = emqttd:env(App),
|
|
|
+ application:set_env(?APP, App, lists:keyreplace(client_enable_stats, 1, Env, {client_enable_stats, Value})),
|
|
|
+ " successfully\n";
|
|
|
client_config_callback(App, Key, Value) ->
|
|
|
{ok, Env} = emqttd:env(App),
|
|
|
application:set_env(?APP, App, lists:keyreplace(Key, 1, Env, {Key, Value})),
|
|
|
@@ -200,6 +268,23 @@ register_queue_config() ->
|
|
|
|
|
|
queue_config_callback([_, AppStr, KeyStr], Value) ->
|
|
|
queue_config_callback(l2a(AppStr), l2a(KeyStr), Value).
|
|
|
+
|
|
|
+queue_config_callback(App, low_watermark, Value) ->
|
|
|
+ {ok, Env} = emqttd:env(App),
|
|
|
+ Parse = fun(S) ->
|
|
|
+ {match, [N]} = re:run(S, "^([0-9]+)%$", [{capture, all_but_first, list}]),
|
|
|
+ list_to_integer(N) / 100
|
|
|
+ end,
|
|
|
+ application:set_env(?APP, App, lists:keyreplace(low_watermark, 1, Env, {low_watermark, Parse(Value)})),
|
|
|
+ " successfully\n";
|
|
|
+queue_config_callback(App, high_watermark, Value) ->
|
|
|
+ {ok, Env} = emqttd:env(App),
|
|
|
+ Parse = fun(S) ->
|
|
|
+ {match, [N]} = re:run(S, "^([0-9]+)%$", [{capture, all_but_first, list}]),
|
|
|
+ list_to_integer(N) / 100
|
|
|
+ end,
|
|
|
+ application:set_env(?APP, App, lists:keyreplace(high_watermark, 1, Env, {high_watermark, Parse(Value)})),
|
|
|
+ " successfully\n";
|
|
|
queue_config_callback(App, Key, Value) ->
|
|
|
{ok, Env} = emqttd:env(App),
|
|
|
application:set_env(?APP, App, lists:keyreplace(Key, 1, Env, {Key, Value})),
|
|
|
@@ -242,3 +327,16 @@ lager_config_callback(_, Value) ->
|
|
|
register_config_whitelist(ConfigKeys) ->
|
|
|
clique:register_config_whitelist(ConfigKeys, ?APP).
|
|
|
|
|
|
+%%--------------------------------------------------------------------
|
|
|
+%% Inner Function
|
|
|
+%%--------------------------------------------------------------------
|
|
|
+any_to_string(I) when is_integer(I) ->
|
|
|
+ integer_to_list(I);
|
|
|
+any_to_string(F) when is_float(F)->
|
|
|
+ float_to_list(F,[{decimals, 4}]);
|
|
|
+any_to_string(A) when is_atom(A) ->
|
|
|
+ atom_to_list(A);
|
|
|
+any_to_string(B) when is_binary(B) ->
|
|
|
+ binary_to_list(B);
|
|
|
+any_to_string(L) when is_list(L) ->
|
|
|
+ L.
|