From dca6fe62006ee7ad01ecddbb0c3f7e8ac02a4e68 Mon Sep 17 00:00:00 2001 From: Ilya Averyanov Date: Wed, 5 Jul 2023 12:48:09 +0300 Subject: [PATCH 1/2] fix(rebalance): fix global status evaluation on replicant nodes --- .../src/emqx_node_rebalance_status.erl | 2 +- .../test/emqx_node_rebalance_status_SUITE.erl | 65 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 apps/emqx_node_rebalance/test/emqx_node_rebalance_status_SUITE.erl diff --git a/apps/emqx_node_rebalance/src/emqx_node_rebalance_status.erl b/apps/emqx_node_rebalance/src/emqx_node_rebalance_status.erl index 1d45d64e8..a0102c4f4 100644 --- a/apps/emqx_node_rebalance/src/emqx_node_rebalance_status.erl +++ b/apps/emqx_node_rebalance/src/emqx_node_rebalance_status.erl @@ -51,7 +51,7 @@ format_local_status(Status) -> -spec global_status() -> #{rebalances := [{node(), map()}], evacuations := [{node(), map()}]}. global_status() -> - Nodes = mria_mnesia:running_nodes(), + Nodes = emqx:running_nodes(), {RebalanceResults, _} = emqx_node_rebalance_status_proto_v1:rebalance_status(Nodes), Rebalances = [ {Node, coordinator_rebalance(Status)} diff --git a/apps/emqx_node_rebalance/test/emqx_node_rebalance_status_SUITE.erl b/apps/emqx_node_rebalance/test/emqx_node_rebalance_status_SUITE.erl new file mode 100644 index 000000000..167c37d8c --- /dev/null +++ b/apps/emqx_node_rebalance/test/emqx_node_rebalance_status_SUITE.erl @@ -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, []) + ). From f174cb656c28a1c790448193b5c04de59dec6666 Mon Sep 17 00:00:00 2001 From: Ilya Averyanov Date: Wed, 5 Jul 2023 15:38:41 +0300 Subject: [PATCH 2/2] fix(rebalance): fix swagger examples in api-doc --- .../src/emqx_dashboard_swagger.erl | 46 ++++++++++--------- .../test/emqx_swagger_requestBody_SUITE.erl | 18 ++++++++ .../src/emqx_node_rebalance_api.erl | 35 ++++++++------ 3 files changed, 63 insertions(+), 36 deletions(-) diff --git a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl index 47acee58b..f829c8b08 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_swagger.erl @@ -897,15 +897,25 @@ typename_to_spec("json_binary()", _Mod) -> typename_to_spec("port_number()", _Mod) -> range("1..65535"); typename_to_spec(Name, Mod) -> - Spec = range(Name), - Spec1 = remote_module_type(Spec, Name, Mod), - Spec2 = typerefl_array(Spec1, Name, Mod), - Spec3 = integer(Spec2, Name), - Spec3 =:= nomatch andalso - throw({error, #{msg => <<"Unsupported Type">>, type => Name, module => Mod}}), - Spec3. + try_convert_to_spec(Name, Mod, [ + fun try_remote_module_type/2, + fun try_typerefl_array/2, + fun try_range/2, + fun try_integer/2 + ]). 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 %% 1..10 1..inf -inf..10 [MinStr, MaxStr] -> @@ -917,39 +927,33 @@ range(Name) -> end. %% Module:Type -remote_module_type(nomatch, Name, Mod) -> +try_remote_module_type(Name, Mod) -> case string:split(Name, ":") of [_Module, Type] -> typename_to_spec(Type, Mod); _ -> nomatch - end; -remote_module_type(Spec, _Name, _Mod) -> - Spec. + end. -%% [string()] or [integer()] or [xxx]. -typerefl_array(nomatch, Name, Mod) -> +%% [string()] or [integer()] or [xxx] or [xxx,...] +try_typerefl_array(Name, Mod) -> case string:trim(Name, leading, "[") of Name -> nomatch; Name1 -> - case string:trim(Name1, trailing, "]") of + case string:trim(Name1, trailing, ",.]") of Name1 -> notmatch; Name2 -> Schema = typename_to_spec(Name2, Mod), #{type => array, items => Schema} end - end; -typerefl_array(Spec, _Name, _Mod) -> - Spec. + end. %% integer(1) -integer(nomatch, Name) -> +try_integer(Name, _Mod) -> case string:to_integer(Name) of {Int, []} -> #{type => integer, enum => [Int], default => Int}; _ -> nomatch - end; -integer(Spec, _Name) -> - Spec. + end. add_integer_prop(Schema, Key, Value) -> case string:to_integer(Value) of diff --git a/apps/emqx_dashboard/test/emqx_swagger_requestBody_SUITE.erl b/apps/emqx_dashboard/test/emqx_swagger_requestBody_SUITE.erl index e8c79c57c..4bc0f4a7c 100644 --- a/apps/emqx_dashboard/test/emqx_swagger_requestBody_SUITE.erl +++ b/apps/emqx_dashboard/test/emqx_swagger_requestBody_SUITE.erl @@ -105,6 +105,20 @@ t_deprecated(_Config) -> 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) -> GoodRef = <<"#/components/schemas/emqx_swagger_requestBody_SUITE.good_ref">>, Spec = #{ @@ -829,6 +843,10 @@ fields(deprecated_ref) -> {tag1, mk(binary(), #{desc => <<"tag1">>, deprecated => {since, "4.3.0"}})}, {tag2, mk(binary(), #{desc => <<"tag2">>, deprecated => true})}, {tag3, mk(binary(), #{desc => <<"tag3">>, deprecated => false})} + ]; +fields(nonempty_list_ref) -> + [ + {list, mk(nonempty_list(binary()), #{})} ]. enable(type) -> boolean(); diff --git a/apps/emqx_node_rebalance/src/emqx_node_rebalance_api.erl b/apps/emqx_node_rebalance/src/emqx_node_rebalance_api.erl index 1d25bfb33..fb27c0a30 100644 --- a/apps/emqx_node_rebalance/src/emqx_node_rebalance_api.erl +++ b/apps/emqx_node_rebalance/src/emqx_node_rebalance_api.erl @@ -709,25 +709,30 @@ fields(global_status) -> rebalance_example() -> #{ - wait_health_check => <<"10s">>, - conn_evict_rate => 10, - sess_evict_rate => 20, - abs_conn_threshold => 10, - rel_conn_threshold => 1.5, - abs_sess_threshold => 10, - rel_sess_threshold => 1.5, - wait_takeover => <<"10s">>, - nodes => [<<"othernode@127.0.0.1">>] + rebalance => + #{ + wait_health_check => <<"10s">>, + conn_evict_rate => 10, + sess_evict_rate => 20, + abs_conn_threshold => 10, + rel_conn_threshold => 1.5, + abs_sess_threshold => 10, + rel_sess_threshold => 1.5, + wait_takeover => <<"10s">>, + nodes => [<<"othernode@127.0.0.1">>] + } }. rebalance_evacuation_example() -> #{ - wait_health_check => <<"10s">>, - conn_evict_rate => 100, - sess_evict_rate => 100, - redirect_to => <<"othernode:1883">>, - wait_takeover => <<"10s">>, - migrate_to => [<<"othernode@127.0.0.1">>] + evacuation => #{ + wait_health_check => <<"10s">>, + conn_evict_rate => 100, + sess_evict_rate => 100, + redirect_to => <<"othernode:1883">>, + wait_takeover => <<"10s">>, + migrate_to => [<<"othernode@127.0.0.1">>] + } }. local_status_response_schema() ->