feat(dashboard): support bind specific ip(port or ip:port).
This commit is contained in:
parent
0cde9e6ecf
commit
ec5d1b1463
|
@ -14,7 +14,7 @@ dashboard {
|
|||
protocol = http
|
||||
num_acceptors = 4
|
||||
max_connections = 512
|
||||
port = 18083
|
||||
bind = 18083
|
||||
backlog = 512
|
||||
send_timeout = 5s
|
||||
inet6 = false
|
||||
|
@ -23,7 +23,7 @@ dashboard {
|
|||
# ,
|
||||
# {
|
||||
# protocol = https
|
||||
# port = 18084
|
||||
# bind = "127.0.0.1:18084"
|
||||
# num_acceptors = 2
|
||||
# backlog = 512
|
||||
# send_timeout = 5s
|
||||
|
|
|
@ -61,15 +61,26 @@ start_listeners() ->
|
|||
dispatch => Dispatch,
|
||||
middlewares => [cowboy_router, ?EMQX_MIDDLE, cowboy_handler]
|
||||
},
|
||||
[begin
|
||||
Minirest = maps:put(protocol, Protocol, BaseMinirest),
|
||||
{ok, _} = minirest:start(Name, RanchOptions, Minirest),
|
||||
?ULOG("Start listener ~ts on ~p successfully.~n", [Name, Port])
|
||||
end || {Name, Protocol, Port, RanchOptions} <- listeners()].
|
||||
Res =
|
||||
lists:foldl(fun({Name, Protocol, Port, RanchOptions}, Acc) ->
|
||||
Minirest = BaseMinirest#{protocol => Protocol},
|
||||
case minirest:start(Name, RanchOptions, Minirest) of
|
||||
{ok, _} ->
|
||||
?ULOG("Start listener ~ts on ~p successfully.~n", [Name, Port]),
|
||||
Acc;
|
||||
{error, _Reason} ->
|
||||
%% Don't record the reason because minirest already does(too much logs noise).
|
||||
[Name | Acc]
|
||||
end
|
||||
end, [], listeners()),
|
||||
case Res of
|
||||
[] -> ok;
|
||||
_ -> {error, Res}
|
||||
end.
|
||||
|
||||
stop_listeners() ->
|
||||
[begin
|
||||
ok = minirest:stop(Name),
|
||||
_ = minirest:stop(Name),
|
||||
?ULOG("Stop listener ~ts on ~p successfully.~n", [Name, Port])
|
||||
end || {Name, _, Port, _} <- listeners()].
|
||||
|
||||
|
@ -85,12 +96,19 @@ apps() ->
|
|||
|
||||
listeners() ->
|
||||
[begin
|
||||
Protocol = maps:get(protocol, ListenerOptions, http),
|
||||
Port = maps:get(port, ListenerOptions, 18083),
|
||||
Name = listener_name(Protocol, Port),
|
||||
RanchOptions = ranch_opts(maps:without([protocol], ListenerOptions)),
|
||||
Protocol = maps:get(protocol, ListenerOption0, http),
|
||||
{ListenerOption, Port} = ip_port(ListenerOption0),
|
||||
Name = listener_name(Protocol, ListenerOption),
|
||||
RanchOptions = ranch_opts(maps:without([protocol], ListenerOption)),
|
||||
{Name, Protocol, Port, RanchOptions}
|
||||
end || ListenerOptions <- emqx_conf:get([dashboard, listeners], [])].
|
||||
end || ListenerOption0 <- emqx_conf:get([dashboard, listeners], [])].
|
||||
|
||||
ip_port(Opts) -> ip_port(maps:take(bind, Opts), Opts).
|
||||
|
||||
ip_port(error, Opts) -> {Opts#{port => 18083}, 18083};
|
||||
ip_port({Port, Opts}, _) when is_integer(Port) -> {Opts#{port => Port}, Port};
|
||||
ip_port({{IP, Port}, Opts}, _) -> {Opts#{port => Port, ip => IP}, Port}.
|
||||
|
||||
|
||||
ranch_opts(RanchOptions) ->
|
||||
Keys = [ {ack_timeout, handshake_timeout}
|
||||
|
@ -119,8 +137,16 @@ key_only(K , true , S) -> [K | S];
|
|||
key_only(_K, false, S) -> S;
|
||||
key_only(K , V , S) -> [{K, V} | S].
|
||||
|
||||
listener_name(Protocol, Port) ->
|
||||
Name = "dashboard:" ++ atom_to_list(Protocol) ++ ":" ++ integer_to_list(Port),
|
||||
listener_name(Protocol, #{port := Port, ip := IP}) ->
|
||||
Name = "dashboard:"
|
||||
++ atom_to_list(Protocol) ++ ":"
|
||||
++ inet:ntoa(IP) ++ ":"
|
||||
++ integer_to_list(Port),
|
||||
list_to_atom(Name);
|
||||
listener_name(Protocol, #{port := Port}) ->
|
||||
Name = "dashboard:"
|
||||
++ atom_to_list(Protocol) ++ ":"
|
||||
++ integer_to_list(Port),
|
||||
list_to_atom(Name).
|
||||
|
||||
authorize(Req) ->
|
||||
|
|
|
@ -27,10 +27,13 @@
|
|||
start(_StartType, _StartArgs) ->
|
||||
{ok, Sup} = emqx_dashboard_sup:start_link(),
|
||||
ok = mria_rlog:wait_for_shards([?DASHBOARD_SHARD], infinity),
|
||||
_ = emqx_dashboard:start_listeners(),
|
||||
emqx_dashboard_cli:load(),
|
||||
{ok, _Result} = emqx_dashboard_admin:add_default_user(),
|
||||
{ok, Sup}.
|
||||
case emqx_dashboard:start_listeners() of
|
||||
ok ->
|
||||
emqx_dashboard_cli:load(),
|
||||
{ok, _Result} = emqx_dashboard_admin:add_default_user(),
|
||||
{ok, Sup};
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
stop(_State) ->
|
||||
emqx_dashboard_cli:unload(),
|
||||
|
|
|
@ -25,8 +25,18 @@ namespace() -> <<"dashboard">>.
|
|||
roots() -> ["dashboard"].
|
||||
|
||||
fields("dashboard") ->
|
||||
[ {listeners, hoconsc:array(hoconsc:union([hoconsc:ref(?MODULE, "http"),
|
||||
hoconsc:ref(?MODULE, "https")]))}
|
||||
[ {listeners,
|
||||
sc(hoconsc:array(hoconsc:union([hoconsc:ref(?MODULE, "http"),
|
||||
hoconsc:ref(?MODULE, "https")])),
|
||||
#{ desc =>
|
||||
"""HTTP(s) listeners identified by their protocol type,
|
||||
is used to serve dashboard UI and restful HTTP API.<br>
|
||||
Listeners must have a unique combination of port number and IP address.<br>
|
||||
For example, an HTTP listener can listen on all configured IP addresses
|
||||
on a given port for a machine by specifying the IP address 0.0.0.0.<br>
|
||||
Alternatively, the HTTP listener can specify a unique IP address for each listener,
|
||||
but use the same port.
|
||||
""" })}
|
||||
, {default_username, fun default_username/1}
|
||||
, {default_password, fun default_password/1}
|
||||
, {sample_interval, sc(emqx_schema:duration_s(), #{default => "10s"})}
|
||||
|
@ -35,11 +45,23 @@ fields("dashboard") ->
|
|||
];
|
||||
|
||||
fields("http") ->
|
||||
[ {"protocol", hoconsc:enum([http, https])}
|
||||
, {"port", hoconsc:mk(integer(), #{default => 18083})}
|
||||
, {"num_acceptors", sc(integer(), #{default => 4})}
|
||||
[ {"protocol", sc(
|
||||
hoconsc:enum([http, https]),
|
||||
#{ desc => "HTTP/HTTPS protocol."
|
||||
, nullable => false
|
||||
, default => http})}
|
||||
, {"bind", fun bind/1}
|
||||
, {"num_acceptors", sc(
|
||||
integer(),
|
||||
#{ default => 4
|
||||
, desc => "Socket acceptor pool for TCP protocols."
|
||||
})}
|
||||
, {"max_connections", sc(integer(), #{default => 512})}
|
||||
, {"backlog", sc(integer(), #{default => 1024})}
|
||||
, {"backlog", sc(
|
||||
integer(),
|
||||
#{ default => 1024
|
||||
, desc => "Defines the maximum length that the queue of pending connections can grow to."
|
||||
})}
|
||||
, {"send_timeout", sc(emqx_schema:duration(), #{default => "5s"})}
|
||||
, {"inet6", sc(boolean(), #{default => false})}
|
||||
, {"ipv6_v6only", sc(boolean(), #{default => false})}
|
||||
|
@ -50,6 +72,12 @@ fields("https") ->
|
|||
proplists:delete("fail_if_no_peer_cert",
|
||||
emqx_schema:server_ssl_opts_schema(#{}, true)).
|
||||
|
||||
bind(type) -> hoconsc:union([non_neg_integer(), emqx_schema:ip_port()]);
|
||||
bind(default) -> 18083;
|
||||
bind(nullable) -> false;
|
||||
bind(desc) -> "Port without IP(18083) or port with specified IP(127.0.0.1:18083).";
|
||||
bind(_) -> undefined.
|
||||
|
||||
default_username(type) -> string();
|
||||
default_username(default) -> "admin";
|
||||
default_username(nullable) -> false;
|
||||
|
@ -67,6 +95,10 @@ default_password(_) -> undefined.
|
|||
cors(type) -> boolean();
|
||||
cors(default) -> false;
|
||||
cors(nullable) -> true;
|
||||
cors(desc) ->
|
||||
"""Support Cross-Origin Resource Sharing (CORS).
|
||||
Allows a server to indicate any origins (domain, scheme, or port) other than
|
||||
its own from which a browser should permit loading resources.""";
|
||||
cors(_) -> undefined.
|
||||
|
||||
sc(Type, Meta) -> hoconsc:mk(Type, Meta).
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
%% FIXME: tag this as v3.1.3
|
||||
{prometheus, {git, "https://github.com/emqx/prometheus.erl", {ref, "9994c76adca40d91a2545102230ccce2423fd8a7"}}},
|
||||
{hocon, {git, "https://github.com/emqx/hocon.git", {tag, "0.23.0"}}},
|
||||
{minirest, {git, "https://github.com/emqx/minirest", {tag, "1.2.10"}}}
|
||||
{minirest, {git, "https://github.com/emqx/minirest", {tag, "1.2.11"}}}
|
||||
]}.
|
||||
|
||||
{edoc_opts, [{preprocess, true}]}.
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
, {mria, {git, "https://github.com/emqx/mria", {tag, "0.1.5"}}}
|
||||
, {ekka, {git, "https://github.com/emqx/ekka", {tag, "0.11.3"}}}
|
||||
, {gen_rpc, {git, "https://github.com/emqx/gen_rpc", {tag, "2.8.0"}}}
|
||||
, {minirest, {git, "https://github.com/emqx/minirest", {tag, "1.2.10"}}}
|
||||
, {minirest, {git, "https://github.com/emqx/minirest", {tag, "1.2.11"}}}
|
||||
, {ecpool, {git, "https://github.com/emqx/ecpool", {tag, "0.5.2"}}}
|
||||
, {replayq, "0.3.3"}
|
||||
, {pbkdf2, {git, "https://github.com/emqx/erlang-pbkdf2.git", {tag, "2.0.4"}}}
|
||||
|
|
Loading…
Reference in New Issue