Merge pull request #11198 from savonarola/0705-fix-rebalance-swagger
fix(rebalance): fix rebalance swagger examples
This commit is contained in:
commit
a6019a2846
|
@ -899,15 +899,25 @@ typename_to_spec("json_binary()", _Mod) ->
|
||||||
typename_to_spec("port_number()", _Mod) ->
|
typename_to_spec("port_number()", _Mod) ->
|
||||||
range("1..65535");
|
range("1..65535");
|
||||||
typename_to_spec(Name, Mod) ->
|
typename_to_spec(Name, Mod) ->
|
||||||
Spec = range(Name),
|
try_convert_to_spec(Name, Mod, [
|
||||||
Spec1 = remote_module_type(Spec, Name, Mod),
|
fun try_remote_module_type/2,
|
||||||
Spec2 = typerefl_array(Spec1, Name, Mod),
|
fun try_typerefl_array/2,
|
||||||
Spec3 = integer(Spec2, Name),
|
fun try_range/2,
|
||||||
Spec3 =:= nomatch andalso
|
fun try_integer/2
|
||||||
throw({error, #{msg => <<"Unsupported Type">>, type => Name, module => Mod}}),
|
]).
|
||||||
Spec3.
|
|
||||||
|
|
||||||
range(Name) ->
|
range(Name) ->
|
||||||
|
#{} = try_range(Name, undefined).
|
||||||
|
|
||||||
|
try_convert_to_spec(Name, Mod, []) ->
|
||||||
|
throw({error, #{msg => <<"Unsupported Type">>, type => Name, module => Mod}});
|
||||||
|
try_convert_to_spec(Name, Mod, [Converter | Rest]) ->
|
||||||
|
case Converter(Name, Mod) of
|
||||||
|
nomatch -> try_convert_to_spec(Name, Mod, Rest);
|
||||||
|
Spec -> Spec
|
||||||
|
end.
|
||||||
|
|
||||||
|
try_range(Name, _Mod) ->
|
||||||
case string:split(Name, "..") of
|
case string:split(Name, "..") of
|
||||||
%% 1..10 1..inf -inf..10
|
%% 1..10 1..inf -inf..10
|
||||||
[MinStr, MaxStr] ->
|
[MinStr, MaxStr] ->
|
||||||
|
@ -919,39 +929,33 @@ range(Name) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% Module:Type
|
%% Module:Type
|
||||||
remote_module_type(nomatch, Name, Mod) ->
|
try_remote_module_type(Name, Mod) ->
|
||||||
case string:split(Name, ":") of
|
case string:split(Name, ":") of
|
||||||
[_Module, Type] -> typename_to_spec(Type, Mod);
|
[_Module, Type] -> typename_to_spec(Type, Mod);
|
||||||
_ -> nomatch
|
_ -> nomatch
|
||||||
end;
|
end.
|
||||||
remote_module_type(Spec, _Name, _Mod) ->
|
|
||||||
Spec.
|
|
||||||
|
|
||||||
%% [string()] or [integer()] or [xxx].
|
%% [string()] or [integer()] or [xxx] or [xxx,...]
|
||||||
typerefl_array(nomatch, Name, Mod) ->
|
try_typerefl_array(Name, Mod) ->
|
||||||
case string:trim(Name, leading, "[") of
|
case string:trim(Name, leading, "[") of
|
||||||
Name ->
|
Name ->
|
||||||
nomatch;
|
nomatch;
|
||||||
Name1 ->
|
Name1 ->
|
||||||
case string:trim(Name1, trailing, "]") of
|
case string:trim(Name1, trailing, ",.]") of
|
||||||
Name1 ->
|
Name1 ->
|
||||||
notmatch;
|
notmatch;
|
||||||
Name2 ->
|
Name2 ->
|
||||||
Schema = typename_to_spec(Name2, Mod),
|
Schema = typename_to_spec(Name2, Mod),
|
||||||
#{type => array, items => Schema}
|
#{type => array, items => Schema}
|
||||||
end
|
end
|
||||||
end;
|
end.
|
||||||
typerefl_array(Spec, _Name, _Mod) ->
|
|
||||||
Spec.
|
|
||||||
|
|
||||||
%% integer(1)
|
%% integer(1)
|
||||||
integer(nomatch, Name) ->
|
try_integer(Name, _Mod) ->
|
||||||
case string:to_integer(Name) of
|
case string:to_integer(Name) of
|
||||||
{Int, []} -> #{type => integer, enum => [Int], default => Int};
|
{Int, []} -> #{type => integer, enum => [Int], default => Int};
|
||||||
_ -> nomatch
|
_ -> nomatch
|
||||||
end;
|
end.
|
||||||
integer(Spec, _Name) ->
|
|
||||||
Spec.
|
|
||||||
|
|
||||||
add_integer_prop(Schema, Key, Value) ->
|
add_integer_prop(Schema, Key, Value) ->
|
||||||
case string:to_integer(Value) of
|
case string:to_integer(Value) of
|
||||||
|
|
|
@ -105,6 +105,20 @@ t_deprecated(_Config) ->
|
||||||
emqx_dashboard_swagger:components([{?MODULE, deprecated_ref}], #{})
|
emqx_dashboard_swagger:components([{?MODULE, deprecated_ref}], #{})
|
||||||
).
|
).
|
||||||
|
|
||||||
|
t_nonempty_list(_Config) ->
|
||||||
|
?assertMatch(
|
||||||
|
[
|
||||||
|
#{
|
||||||
|
<<"emqx_swagger_requestBody_SUITE.nonempty_list_ref">> :=
|
||||||
|
#{
|
||||||
|
<<"properties">> :=
|
||||||
|
[{<<"list">>, #{items := #{type := string}, type := array}}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
emqx_dashboard_swagger:components([{?MODULE, nonempty_list_ref}], #{})
|
||||||
|
).
|
||||||
|
|
||||||
t_nest_object(_Config) ->
|
t_nest_object(_Config) ->
|
||||||
GoodRef = <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>,
|
GoodRef = <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>,
|
||||||
Spec = #{
|
Spec = #{
|
||||||
|
@ -829,6 +843,10 @@ fields(deprecated_ref) ->
|
||||||
{tag1, mk(binary(), #{desc => <<"tag1">>, deprecated => {since, "4.3.0"}})},
|
{tag1, mk(binary(), #{desc => <<"tag1">>, deprecated => {since, "4.3.0"}})},
|
||||||
{tag2, mk(binary(), #{desc => <<"tag2">>, deprecated => true})},
|
{tag2, mk(binary(), #{desc => <<"tag2">>, deprecated => true})},
|
||||||
{tag3, mk(binary(), #{desc => <<"tag3">>, deprecated => false})}
|
{tag3, mk(binary(), #{desc => <<"tag3">>, deprecated => false})}
|
||||||
|
];
|
||||||
|
fields(nonempty_list_ref) ->
|
||||||
|
[
|
||||||
|
{list, mk(nonempty_list(binary()), #{})}
|
||||||
].
|
].
|
||||||
|
|
||||||
enable(type) -> boolean();
|
enable(type) -> boolean();
|
||||||
|
|
|
@ -709,25 +709,30 @@ fields(global_status) ->
|
||||||
|
|
||||||
rebalance_example() ->
|
rebalance_example() ->
|
||||||
#{
|
#{
|
||||||
wait_health_check => <<"10s">>,
|
rebalance =>
|
||||||
conn_evict_rate => 10,
|
#{
|
||||||
sess_evict_rate => 20,
|
wait_health_check => <<"10s">>,
|
||||||
abs_conn_threshold => 10,
|
conn_evict_rate => 10,
|
||||||
rel_conn_threshold => 1.5,
|
sess_evict_rate => 20,
|
||||||
abs_sess_threshold => 10,
|
abs_conn_threshold => 10,
|
||||||
rel_sess_threshold => 1.5,
|
rel_conn_threshold => 1.5,
|
||||||
wait_takeover => <<"10s">>,
|
abs_sess_threshold => 10,
|
||||||
nodes => [<<"othernode@127.0.0.1">>]
|
rel_sess_threshold => 1.5,
|
||||||
|
wait_takeover => <<"10s">>,
|
||||||
|
nodes => [<<"othernode@127.0.0.1">>]
|
||||||
|
}
|
||||||
}.
|
}.
|
||||||
|
|
||||||
rebalance_evacuation_example() ->
|
rebalance_evacuation_example() ->
|
||||||
#{
|
#{
|
||||||
wait_health_check => <<"10s">>,
|
evacuation => #{
|
||||||
conn_evict_rate => 100,
|
wait_health_check => <<"10s">>,
|
||||||
sess_evict_rate => 100,
|
conn_evict_rate => 100,
|
||||||
redirect_to => <<"othernode:1883">>,
|
sess_evict_rate => 100,
|
||||||
wait_takeover => <<"10s">>,
|
redirect_to => <<"othernode:1883">>,
|
||||||
migrate_to => [<<"othernode@127.0.0.1">>]
|
wait_takeover => <<"10s">>,
|
||||||
|
migrate_to => [<<"othernode@127.0.0.1">>]
|
||||||
|
}
|
||||||
}.
|
}.
|
||||||
|
|
||||||
local_status_response_schema() ->
|
local_status_response_schema() ->
|
||||||
|
|
|
@ -51,7 +51,7 @@ format_local_status(Status) ->
|
||||||
|
|
||||||
-spec global_status() -> #{rebalances := [{node(), map()}], evacuations := [{node(), map()}]}.
|
-spec global_status() -> #{rebalances := [{node(), map()}], evacuations := [{node(), map()}]}.
|
||||||
global_status() ->
|
global_status() ->
|
||||||
Nodes = mria_mnesia:running_nodes(),
|
Nodes = emqx:running_nodes(),
|
||||||
{RebalanceResults, _} = emqx_node_rebalance_status_proto_v1:rebalance_status(Nodes),
|
{RebalanceResults, _} = emqx_node_rebalance_status_proto_v1:rebalance_status(Nodes),
|
||||||
Rebalances = [
|
Rebalances = [
|
||||||
{Node, coordinator_rebalance(Status)}
|
{Node, coordinator_rebalance(Status)}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Copyright (c) 2020-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||||
|
%%
|
||||||
|
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
%% you may not use this file except in compliance with the License.
|
||||||
|
%% You may obtain a copy of the License at
|
||||||
|
%%
|
||||||
|
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
%%
|
||||||
|
%% Unless required by applicable law or agreed to in writing, software
|
||||||
|
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
%% See the License for the specific language governing permissions and
|
||||||
|
%% limitations under the License.
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
-module(emqx_node_rebalance_status_SUITE).
|
||||||
|
|
||||||
|
-compile(export_all).
|
||||||
|
-compile(nowarn_export_all).
|
||||||
|
|
||||||
|
-include_lib("common_test/include/ct.hrl").
|
||||||
|
-include_lib("stdlib/include/assert.hrl").
|
||||||
|
|
||||||
|
all() -> emqx_common_test_helpers:all(?MODULE).
|
||||||
|
|
||||||
|
suite() ->
|
||||||
|
[{timetrap, {seconds, 90}}].
|
||||||
|
|
||||||
|
init_per_suite(Config) ->
|
||||||
|
WorkDir = ?config(priv_dir, Config),
|
||||||
|
Apps = [
|
||||||
|
emqx_conf,
|
||||||
|
emqx,
|
||||||
|
emqx_node_rebalance
|
||||||
|
],
|
||||||
|
Cluster = [
|
||||||
|
{emqx_node_rebalance_status_SUITE1, #{
|
||||||
|
role => core,
|
||||||
|
apps => Apps
|
||||||
|
}},
|
||||||
|
{emqx_node_rebalance_status_SUITE2, #{
|
||||||
|
role => replicant,
|
||||||
|
apps => Apps
|
||||||
|
}}
|
||||||
|
],
|
||||||
|
Nodes = emqx_cth_cluster:start(Cluster, #{work_dir => WorkDir}),
|
||||||
|
[{cluster_nodes, Nodes} | Config].
|
||||||
|
|
||||||
|
end_per_suite(Config) ->
|
||||||
|
ok = emqx_cth_cluster:stop(?config(cluster_nodes, Config)),
|
||||||
|
ok.
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Tests
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
t_cluster_status(Config) ->
|
||||||
|
[CoreNode, ReplicantNode] = ?config(cluster_nodes, Config),
|
||||||
|
ok = emqx_node_rebalance_api_proto_v1:node_rebalance_evacuation_start(CoreNode, #{}),
|
||||||
|
|
||||||
|
?assertMatch(
|
||||||
|
#{evacuations := [_], rebalances := []},
|
||||||
|
rpc:call(ReplicantNode, emqx_node_rebalance_status, global_status, [])
|
||||||
|
).
|
Loading…
Reference in New Issue