Merge pull request #7797 from zmstone/0427-5.0-dashboard-add-listener-enable-disable-config
feat(dashboard): add listener enable/disable config toggle
This commit is contained in:
commit
061d9198ce
|
@ -74,8 +74,8 @@ Note: `sample_interval` should be a divisor of 60."""
|
||||||
}
|
}
|
||||||
inet6 {
|
inet6 {
|
||||||
desc {
|
desc {
|
||||||
en: "Enable IPv6 support."
|
en: "Enable IPv6 support, default is false, which means IPv4 only."
|
||||||
zh: "启用IPv6"
|
zh: "启用IPv6, 如果机器不支持IPv6,请关闭此选项,否则会导致仪表盘无法使用。"
|
||||||
}
|
}
|
||||||
label {
|
label {
|
||||||
en: "IPv6"
|
en: "IPv6"
|
||||||
|
@ -85,7 +85,7 @@ Note: `sample_interval` should be a divisor of 60."""
|
||||||
ipv6_v6only {
|
ipv6_v6only {
|
||||||
desc {
|
desc {
|
||||||
en: "Disable IPv4-to-IPv6 mapping for the listener."
|
en: "Disable IPv4-to-IPv6 mapping for the listener."
|
||||||
zh: "禁用IPv4-to-IPv6映射"
|
zh: "当开启 inet6 功能的同时禁用 IPv4-to-IPv6 映射。该配置仅在 inet6 功能开启时有效。"
|
||||||
}
|
}
|
||||||
label {
|
label {
|
||||||
en: "IPv6 only"
|
en: "IPv6 only"
|
||||||
|
@ -132,6 +132,16 @@ Note: `sample_interval` should be a divisor of 60."""
|
||||||
zh: "HTTPS"
|
zh: "HTTPS"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
listener_enable {
|
||||||
|
desc {
|
||||||
|
en: "Ignore or enable this listener"
|
||||||
|
zh: "忽略或启用该监听器配置"
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
en: "Enable"
|
||||||
|
zh: "启用"
|
||||||
|
}
|
||||||
|
}
|
||||||
bind {
|
bind {
|
||||||
desc {
|
desc {
|
||||||
en: "Port without IP(18083) or port with specified IP(127.0.0.1:18083)."
|
en: "Port without IP(18083) or port with specified IP(127.0.0.1:18083)."
|
||||||
|
|
|
@ -153,10 +153,13 @@ apps() ->
|
||||||
].
|
].
|
||||||
|
|
||||||
listeners(Listeners) ->
|
listeners(Listeners) ->
|
||||||
lists:map(
|
lists:filtermap(
|
||||||
fun({Protocol, Conf}) ->
|
fun({Protocol, Conf}) ->
|
||||||
|
maps:get(enable, Conf) andalso
|
||||||
|
begin
|
||||||
{Conf1, Bind} = ip_port(Conf),
|
{Conf1, Bind} = ip_port(Conf),
|
||||||
{listener_name(Protocol, Conf1), Protocol, Bind, ranch_opts(Conf1)}
|
{true, {listener_name(Protocol, Conf1), Protocol, Bind, ranch_opts(Conf1)}}
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
maps:to_list(Listeners)
|
maps:to_list(Listeners)
|
||||||
).
|
).
|
||||||
|
@ -172,34 +175,34 @@ init_i18n() ->
|
||||||
Lang = emqx_conf:get([dashboard, i18n_lang], en),
|
Lang = emqx_conf:get([dashboard, i18n_lang], en),
|
||||||
init_i18n(File, Lang).
|
init_i18n(File, Lang).
|
||||||
|
|
||||||
ranch_opts(RanchOptions) ->
|
ranch_opts(Options) ->
|
||||||
Keys = [
|
Keys = [
|
||||||
{ack_timeout, handshake_timeout},
|
handshake_timeout,
|
||||||
connection_type,
|
connection_type,
|
||||||
max_connections,
|
max_connections,
|
||||||
num_acceptors,
|
num_acceptors,
|
||||||
shutdown,
|
shutdown,
|
||||||
socket
|
socket
|
||||||
],
|
],
|
||||||
{S, R} = lists:foldl(fun key_take/2, {RanchOptions, #{}}, Keys),
|
RanchOpts = maps:with(Keys, Options),
|
||||||
R#{socket_opts => maps:fold(fun key_only/3, [], S)}.
|
SocketOpts = maps:fold(
|
||||||
|
fun filter_false/3,
|
||||||
key_take(Key, {All, R}) ->
|
[],
|
||||||
{K, KX} =
|
maps:without([enable, inet6, ipv6_v6only | Keys], Options)
|
||||||
case Key of
|
),
|
||||||
{K1, K2} -> {K1, K2};
|
InetOpts =
|
||||||
_ -> {Key, Key}
|
case Options of
|
||||||
|
#{inet6 := true, ipv6_v6only := true} ->
|
||||||
|
[inet6, {ipv6_v6only, true}];
|
||||||
|
#{inet6 := true, ipv6_v6only := false} ->
|
||||||
|
[inet6];
|
||||||
|
_ ->
|
||||||
|
[inet]
|
||||||
end,
|
end,
|
||||||
case maps:get(K, All, undefined) of
|
RanchOpts#{socket_opts => InetOpts ++ SocketOpts}.
|
||||||
undefined ->
|
|
||||||
{All, R};
|
|
||||||
V ->
|
|
||||||
{maps:remove(K, All), R#{KX => V}}
|
|
||||||
end.
|
|
||||||
|
|
||||||
key_only(K, true, S) -> [K | S];
|
filter_false(_K, false, S) -> S;
|
||||||
key_only(_K, false, S) -> S;
|
filter_false(K, V, S) -> [{K, V} | S].
|
||||||
key_only(K, V, S) -> [{K, V} | S].
|
|
||||||
|
|
||||||
listener_name(Protocol, #{port := Port, ip := IP}) ->
|
listener_name(Protocol, #{port := Port, ip := IP}) ->
|
||||||
Name =
|
Name =
|
||||||
|
|
|
@ -63,22 +63,42 @@ remove_handler() ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
pre_config_update(_Path, UpdateConf0, RawConf) ->
|
pre_config_update(_Path, UpdateConf0, RawConf) ->
|
||||||
UpdateConf =
|
UpdateConf = remove_sensitive_data(UpdateConf0),
|
||||||
case UpdateConf0 of
|
|
||||||
#{<<"default_password">> := <<"******">>} ->
|
|
||||||
maps:remove(<<"default_password">>, UpdateConf0);
|
|
||||||
_ ->
|
|
||||||
UpdateConf0
|
|
||||||
end,
|
|
||||||
NewConf = emqx_map_lib:deep_merge(RawConf, UpdateConf),
|
NewConf = emqx_map_lib:deep_merge(RawConf, UpdateConf),
|
||||||
{ok, NewConf}.
|
{ok, NewConf}.
|
||||||
|
|
||||||
|
-define(SENSITIVE_PASSWORD, <<"******">>).
|
||||||
|
|
||||||
|
remove_sensitive_data(Conf0) ->
|
||||||
|
Conf1 =
|
||||||
|
case Conf0 of
|
||||||
|
#{<<"default_password">> := ?SENSITIVE_PASSWORD} ->
|
||||||
|
maps:remove(<<"default_password">>, Conf0);
|
||||||
|
_ ->
|
||||||
|
Conf0
|
||||||
|
end,
|
||||||
|
case Conf1 of
|
||||||
|
#{<<"listeners">> := #{<<"https">> := #{<<"password">> := ?SENSITIVE_PASSWORD}}} ->
|
||||||
|
emqx_map_lib:deep_remove([<<"listeners">>, <<"https">>, <<"password">>], Conf1);
|
||||||
|
_ ->
|
||||||
|
Conf1
|
||||||
|
end.
|
||||||
|
|
||||||
post_config_update(_, _Req, NewConf, OldConf, _AppEnvs) ->
|
post_config_update(_, _Req, NewConf, OldConf, _AppEnvs) ->
|
||||||
#{listeners := NewListeners} = NewConf,
|
#{listeners := #{http := NewHttp, https := NewHttps}} = NewConf,
|
||||||
#{listeners := OldListeners} = OldConf,
|
#{listeners := #{http := OldHttp, https := OldHttps}} = OldConf,
|
||||||
_ =
|
_ =
|
||||||
case NewListeners =:= OldListeners of
|
case diff_listeners(OldHttp, NewHttp, OldHttps, NewHttps) of
|
||||||
true -> ok;
|
identical -> ok;
|
||||||
false -> erlang:send_after(500, ?MODULE, {update_listeners, OldListeners, NewListeners})
|
{Stop, Start} -> erlang:send_after(500, ?MODULE, {update_listeners, Stop, Start})
|
||||||
end,
|
end,
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
diff_listeners(Http, Http, Https, Https) ->
|
||||||
|
identical;
|
||||||
|
diff_listeners(OldHttp, NewHttp, Https, Https) ->
|
||||||
|
{#{http => OldHttp}, #{http => NewHttp}};
|
||||||
|
diff_listeners(Http, Http, OldHttps, NewHttps) ->
|
||||||
|
{#{https => OldHttps}, #{https => NewHttps}};
|
||||||
|
diff_listeners(OldHttp, NewHttp, OldHttps, NewHttps) ->
|
||||||
|
{#{http => OldHttp, https => OldHttps}, #{http => NewHttp, https => NewHttps}}.
|
||||||
|
|
|
@ -77,7 +77,32 @@ fields("listeners") ->
|
||||||
];
|
];
|
||||||
fields("http") ->
|
fields("http") ->
|
||||||
[
|
[
|
||||||
{"bind", fun bind/1},
|
enable(true),
|
||||||
|
bind(18803)
|
||||||
|
| common_listener_fields()
|
||||||
|
];
|
||||||
|
fields("https") ->
|
||||||
|
[
|
||||||
|
enable(false),
|
||||||
|
bind(18804)
|
||||||
|
| common_listener_fields() ++
|
||||||
|
exclude_fields(
|
||||||
|
["enable", "fail_if_no_peer_cert"],
|
||||||
|
emqx_schema:server_ssl_opts_schema(#{}, true)
|
||||||
|
)
|
||||||
|
].
|
||||||
|
|
||||||
|
exclude_fields([], Fields) ->
|
||||||
|
Fields;
|
||||||
|
exclude_fields([FieldName | Rest], Fields) ->
|
||||||
|
%% assert field exists
|
||||||
|
case lists:keytake(FieldName, 1, Fields) of
|
||||||
|
{value, _, New} -> exclude_fields(Rest, New);
|
||||||
|
false -> error({FieldName, Fields})
|
||||||
|
end.
|
||||||
|
|
||||||
|
common_listener_fields() ->
|
||||||
|
[
|
||||||
{"num_acceptors",
|
{"num_acceptors",
|
||||||
sc(
|
sc(
|
||||||
integer(),
|
integer(),
|
||||||
|
@ -126,25 +151,40 @@ fields("http") ->
|
||||||
desc => ?DESC(ipv6_v6only)
|
desc => ?DESC(ipv6_v6only)
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
];
|
].
|
||||||
fields("https") ->
|
|
||||||
fields("http") ++
|
|
||||||
proplists:delete(
|
|
||||||
"fail_if_no_peer_cert",
|
|
||||||
emqx_schema:server_ssl_opts_schema(#{}, true)
|
|
||||||
).
|
|
||||||
|
|
||||||
desc("dashboard") -> ?DESC(desc_dashboard);
|
enable(Bool) ->
|
||||||
desc("listeners") -> ?DESC(desc_listeners);
|
{"enable",
|
||||||
desc("http") -> ?DESC(desc_http);
|
sc(
|
||||||
desc("https") -> ?DESC(desc_https);
|
boolean(),
|
||||||
desc(_) -> undefined.
|
#{
|
||||||
|
default => Bool,
|
||||||
|
required => true,
|
||||||
|
desc => ?DESC(listener_enable)
|
||||||
|
}
|
||||||
|
)}.
|
||||||
|
|
||||||
bind(type) -> hoconsc:union([non_neg_integer(), emqx_schema:ip_port()]);
|
bind(Port) ->
|
||||||
bind(default) -> 18083;
|
{"bind",
|
||||||
bind(required) -> true;
|
sc(
|
||||||
bind(desc) -> ?DESC(bind);
|
hoconsc:union([non_neg_integer(), emqx_schema:ip_port()]),
|
||||||
bind(_) -> undefined.
|
#{
|
||||||
|
default => Port,
|
||||||
|
required => true,
|
||||||
|
desc => ?DESC(bind)
|
||||||
|
}
|
||||||
|
)}.
|
||||||
|
|
||||||
|
desc("dashboard") ->
|
||||||
|
?DESC(desc_dashboard);
|
||||||
|
desc("listeners") ->
|
||||||
|
?DESC(desc_listeners);
|
||||||
|
desc("http") ->
|
||||||
|
?DESC(desc_http);
|
||||||
|
desc("https") ->
|
||||||
|
?DESC(desc_https);
|
||||||
|
desc(_) ->
|
||||||
|
undefined.
|
||||||
|
|
||||||
default_username(type) -> binary();
|
default_username(type) -> binary();
|
||||||
default_username(default) -> "admin";
|
default_username(default) -> "admin";
|
||||||
|
|
|
@ -37,6 +37,7 @@ set_default_config(DefaultUsername) ->
|
||||||
Config = #{
|
Config = #{
|
||||||
listeners => #{
|
listeners => #{
|
||||||
http => #{
|
http => #{
|
||||||
|
enable => true,
|
||||||
port => 18083
|
port => 18083
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
2
mix.exs
2
mix.exs
|
@ -48,7 +48,7 @@ defmodule EMQXUmbrella.MixProject do
|
||||||
[
|
[
|
||||||
{:lc, github: "emqx/lc", tag: "0.2.1"},
|
{:lc, github: "emqx/lc", tag: "0.2.1"},
|
||||||
{:redbug, "2.0.7"},
|
{:redbug, "2.0.7"},
|
||||||
{:typerefl, github: "ieQu1/typerefl", tag: "0.9.0", override: true},
|
{:typerefl, github: "ieQu1/typerefl", tag: "0.9.1", override: true},
|
||||||
{:ehttpc, github: "emqx/ehttpc", tag: "0.1.12"},
|
{:ehttpc, github: "emqx/ehttpc", tag: "0.1.12"},
|
||||||
{:gproc, github: "uwiger/gproc", tag: "0.8.0", override: true},
|
{:gproc, github: "uwiger/gproc", tag: "0.8.0", override: true},
|
||||||
{:jiffy, github: "emqx/jiffy", tag: "1.0.5", override: true},
|
{:jiffy, github: "emqx/jiffy", tag: "1.0.5", override: true},
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
[ {lc, {git, "https://github.com/emqx/lc.git", {tag, "0.2.1"}}}
|
[ {lc, {git, "https://github.com/emqx/lc.git", {tag, "0.2.1"}}}
|
||||||
, {redbug, "2.0.7"}
|
, {redbug, "2.0.7"}
|
||||||
, {gpb, "4.11.2"} %% gpb only used to build, but not for release, pin it here to avoid fetching a wrong version due to rebar plugins scattered in all the deps
|
, {gpb, "4.11.2"} %% gpb only used to build, but not for release, pin it here to avoid fetching a wrong version due to rebar plugins scattered in all the deps
|
||||||
, {typerefl, {git, "https://github.com/ieQu1/typerefl", {tag, "0.9.0"}}}
|
, {typerefl, {git, "https://github.com/ieQu1/typerefl", {tag, "0.9.1"}}}
|
||||||
, {ehttpc, {git, "https://github.com/emqx/ehttpc", {tag, "0.1.12"}}}
|
, {ehttpc, {git, "https://github.com/emqx/ehttpc", {tag, "0.1.12"}}}
|
||||||
, {gproc, {git, "https://github.com/uwiger/gproc", {tag, "0.8.0"}}}
|
, {gproc, {git, "https://github.com/uwiger/gproc", {tag, "0.8.0"}}}
|
||||||
, {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.5"}}}
|
, {jiffy, {git, "https://github.com/emqx/jiffy", {tag, "1.0.5"}}}
|
||||||
|
|
Loading…
Reference in New Issue