Просмотр исходного кода

Merge pull request #13068 from zmstone/0517-fix-dynamic-license-usage-for-dashboard

fix(license): show dynamic max_connections for bc
Zaiming (Stone) Shi 1 год назад
Родитель
Сommit
c6ee37bacd

+ 12 - 3
apps/emqx_dashboard/test/emqx_dashboard_api_test_helpers.erl

@@ -25,6 +25,7 @@
     request/3,
     request/3,
     request/4,
     request/4,
     request/5,
     request/5,
+    request/6,
     multipart_formdata_request/3,
     multipart_formdata_request/3,
     multipart_formdata_request/4,
     multipart_formdata_request/4,
     host/0,
     host/0,
@@ -77,8 +78,11 @@ request(Username, Method, Url, Body) ->
     request(Username, <<"public">>, Method, Url, Body).
     request(Username, <<"public">>, Method, Url, Body).
 
 
 request(Username, Password, Method, Url, Body) ->
 request(Username, Password, Method, Url, Body) ->
+    request(Username, Password, Method, Url, Body, #{}).
+
+request(Username, Password, Method, Url, Body0, Headers) ->
     Request =
     Request =
-        case Body of
+        case Body0 of
             [] when
             [] when
                 Method =:= get orelse Method =:= put orelse
                 Method =:= get orelse Method =:= put orelse
                     Method =:= head orelse Method =:= delete orelse
                     Method =:= head orelse Method =:= delete orelse
@@ -86,8 +90,10 @@ request(Username, Password, Method, Url, Body) ->
             ->
             ->
                 {Url, [auth_header(Username, Password)]};
                 {Url, [auth_header(Username, Password)]};
             _ ->
             _ ->
-                {Url, [auth_header(Username, Password)], "application/json",
-                    emqx_utils_json:encode(Body)}
+                ContentType = maps:get("content-type", Headers, "application/json"),
+                HeadersList = maps:to_list(maps:without(["content-type"], Headers)),
+                Body = maybe_encode(Body0),
+                {Url, [auth_header(Username, Password) | HeadersList], ContentType, Body}
         end,
         end,
     ct:pal("Method: ~p, Request: ~p", [Method, Request]),
     ct:pal("Method: ~p, Request: ~p", [Method, Request]),
     case httpc:request(Method, Request, [], [{body_format, binary}]) of
     case httpc:request(Method, Request, [], [{body_format, binary}]) of
@@ -99,6 +105,9 @@ request(Username, Password, Method, Url, Body) ->
             {error, Reason}
             {error, Reason}
     end.
     end.
 
 
+maybe_encode(Body) when is_binary(Body) -> Body;
+maybe_encode(Body) -> emqx_utils_json:encode(Body).
+
 host() ->
 host() ->
     ?HOST.
     ?HOST.
 
 

+ 5 - 1
apps/emqx_license/src/emqx_license_checker.erl

@@ -119,7 +119,11 @@ handle_call({update, License}, _From, #{license := Old} = State) ->
     ok = log_new_license(Old, License),
     ok = log_new_license(Old, License),
     {reply, check_license(License), State1#{license => License}};
     {reply, check_license(License), State1#{license => License}};
 handle_call(dump, _From, #{license := License} = State) ->
 handle_call(dump, _From, #{license := License} = State) ->
-    {reply, emqx_license_parser:dump(License), State};
+    Dump0 = emqx_license_parser:dump(License),
+    %% resolve the current dynamic limit
+    MaybeDynamic = get_max_connections(License),
+    Dump = lists:keyreplace(max_connections, 1, Dump0, {max_connections, MaybeDynamic}),
+    {reply, Dump, State};
 handle_call(expiry_epoch, _From, #{license := License} = State) ->
 handle_call(expiry_epoch, _From, #{license := License} = State) ->
     ExpiryEpoch = date_to_expiry_epoch(emqx_license_parser:expiry_date(License)),
     ExpiryEpoch = date_to_expiry_epoch(emqx_license_parser:expiry_date(License)),
     {reply, ExpiryEpoch, State};
     {reply, ExpiryEpoch, State};

+ 7 - 1
apps/emqx_license/src/emqx_license_http_api.erl

@@ -149,7 +149,7 @@ error_msg(Code, Msg) ->
 '/license/setting'(get, _Params) ->
 '/license/setting'(get, _Params) ->
     {200, get_setting()};
     {200, get_setting()};
 '/license/setting'(put, #{body := Setting}) ->
 '/license/setting'(put, #{body := Setting}) ->
-    case emqx_license:update_setting(Setting) of
+    case update_setting(Setting) of
         {error, Error} ->
         {error, Error} ->
             ?SLOG(
             ?SLOG(
                 error,
                 error,
@@ -165,6 +165,12 @@ error_msg(Code, Msg) ->
             '/license/setting'(get, undefined)
             '/license/setting'(get, undefined)
     end.
     end.
 
 
+update_setting(Setting) when is_map(Setting) ->
+    emqx_license:update_setting(Setting);
+update_setting(_Setting) ->
+    %% TODO: EMQX-12401 content-type enforcement by framework
+    {error, "bad content-type"}.
+
 fields(key_license) ->
 fields(key_license) ->
     [lists:keyfind(key, 1, emqx_license_schema:fields(key_license))].
     [lists:keyfind(key, 1, emqx_license_schema:fields(key_license))].
 
 

+ 29 - 4
apps/emqx_license/test/emqx_license_http_api_SUITE.erl

@@ -57,7 +57,12 @@ end_per_testcase(_TestCase, _Config) ->
 %%------------------------------------------------------------------------------
 %%------------------------------------------------------------------------------
 
 
 request(Method, Uri, Body) ->
 request(Method, Uri, Body) ->
-    emqx_dashboard_api_test_helpers:request(<<"license_admin">>, Method, Uri, Body).
+    request(Method, Uri, Body, #{}).
+
+request(Method, Uri, Body, Headers) ->
+    emqx_dashboard_api_test_helpers:request(
+        <<"license_admin">>, <<"public">>, Method, Uri, Body, Headers
+    ).
 
 
 uri(Segments) ->
 uri(Segments) ->
     emqx_dashboard_api_test_helpers:uri(Segments).
     emqx_dashboard_api_test_helpers:uri(Segments).
@@ -229,24 +234,44 @@ t_license_setting(_Config) ->
 
 
 t_license_setting_bc(_Config) ->
 t_license_setting_bc(_Config) ->
     %% Create a BC license
     %% Create a BC license
-    Key = emqx_license_test_lib:make_license(#{customer_type => "3"}),
+    Key = emqx_license_test_lib:make_license(#{
+        customer_type => "3",
+        max_connections => "33"
+    }),
     Res = request(post, uri(["license"]), #{key => Key}),
     Res = request(post, uri(["license"]), #{key => Key}),
     ?assertMatch({ok, 200, _}, Res),
     ?assertMatch({ok, 200, _}, Res),
+    %% for bc customer, before setting dynamic limit,
+    %% the default limit is always 25, as if no license
+    ?assertMatch(#{<<"max_connections">> := 25}, request_dump()),
     %% get
     %% get
     GetRes = request(get, uri(["license", "setting"]), []),
     GetRes = request(get, uri(["license", "setting"]), []),
+    %% aslo check that the settings return correctly
     validate_setting(GetRes, <<"75%">>, <<"80%">>, 25),
     validate_setting(GetRes, <<"75%">>, <<"80%">>, 25),
     %% update
     %% update
     Low = <<"50%">>,
     Low = <<"50%">>,
     High = <<"55%">>,
     High = <<"55%">>,
-    UpdateRes = request(put, uri(["license", "setting"]), #{
+    Settings = #{
         <<"connection_low_watermark">> => Low,
         <<"connection_low_watermark">> => Low,
         <<"connection_high_watermark">> => High,
         <<"connection_high_watermark">> => High,
         <<"dynamic_max_connections">> => 26
         <<"dynamic_max_connections">> => 26
-    }),
+    },
+    UpdateRes = request(put, uri(["license", "setting"]), Settings),
+    %% assert it's changed to 26
     validate_setting(UpdateRes, Low, High, 26),
     validate_setting(UpdateRes, Low, High, 26),
+    ?assertMatch(#{<<"max_connections">> := 26}, request_dump()),
     ?assertEqual(26, emqx_config:get([license, dynamic_max_connections])),
     ?assertEqual(26, emqx_config:get([license, dynamic_max_connections])),
+    %% Try to set it beyond the limit, it's allowed, but no effect
+    Settings2 = Settings#{<<"dynamic_max_connections">> => 99999},
+    UpdateRes2 = request(put, uri(["license", "setting"]), Settings2),
+    validate_setting(UpdateRes2, Low, High, 99999),
+    ?assertMatch(#{<<"max_connections">> := 33}, request_dump()),
+    ?assertEqual(99999, emqx_config:get([license, dynamic_max_connections])),
     ok.
     ok.
 
 
+request_dump() ->
+    {ok, 200, DumpJson} = request(get, uri(["license"]), []),
+    emqx_utils_json:decode(DumpJson).
+
 validate_setting(Res, ExpectLow, ExpectHigh) ->
 validate_setting(Res, ExpectLow, ExpectHigh) ->
     ?assertMatch({ok, 200, _}, Res),
     ?assertMatch({ok, 200, _}, Res),
     {ok, 200, Payload} = Res,
     {ok, 200, Payload} = Res,