From 1c74c83f5e83e5d38ee1ef691d0a202054e135a2 Mon Sep 17 00:00:00 2001 From: "Zaiming (Stone) Shi" Date: Fri, 22 Apr 2022 17:31:20 +0200 Subject: [PATCH] fix(license): print warning at start --- apps/emqx/src/emqx_tls_lib.erl | 19 ++++-- apps/emqx/test/emqx_common_test_helpers.erl | 9 +-- apps/emqx/test/emqx_config_handler_SUITE.erl | 4 +- lib-ee/emqx_license/include/emqx_license.hrl | 20 +++--- .../emqx_license/src/emqx_license_checker.erl | 68 ++++++++++++------- lib-ee/emqx_license/src/emqx_license_cli.erl | 17 +---- 6 files changed, 74 insertions(+), 63 deletions(-) diff --git a/apps/emqx/src/emqx_tls_lib.erl b/apps/emqx/src/emqx_tls_lib.erl index ffa13194f..9f0c80be2 100644 --- a/apps/emqx/src/emqx_tls_lib.erl +++ b/apps/emqx/src/emqx_tls_lib.erl @@ -322,7 +322,8 @@ delete_old_file(_New, Old) -> case is_generated_file(Old) andalso filelib:is_regular(Old) andalso file:delete(Old) of ok -> ok; - false -> %% the file is not generated by us, or it is already deleted + %% the file is not generated by us, or it is already deleted + false -> ok; {error, Reason} -> ?SLOG(error, #{msg => "failed_to_delete_ssl_file", file_path => Old, reason => Reason}) @@ -412,16 +413,21 @@ pem_dir(Dir) -> filename:join([emqx:mutable_certs_dir(), Dir]). is_hex_str(HexStr) -> - try is_hex_str2(ensure_str(HexStr)) - catch throw: not_hex -> false + try + is_hex_str2(ensure_str(HexStr)) + catch + throw:not_hex -> false end. is_hex_str2(HexStr) -> - _ = [case S of + _ = [ + case S of S when S >= $0, S =< $9 -> S; S when S >= $a, S =< $f -> S; _ -> throw(not_hex) - end || S <- HexStr], + end + || S <- HexStr + ], true. hex_str(Bin) -> @@ -457,8 +463,7 @@ do_drop_invalid_certs([Key | Keys], SSL) -> PemOrPath -> case is_pem(PemOrPath) orelse is_valid_pem_file(PemOrPath) of true -> do_drop_invalid_certs(Keys, SSL); - {error, _} -> - do_drop_invalid_certs(Keys, maps:without([Key], SSL)) + {error, _} -> do_drop_invalid_certs(Keys, maps:without([Key], SSL)) end end. diff --git a/apps/emqx/test/emqx_common_test_helpers.erl b/apps/emqx/test/emqx_common_test_helpers.erl index cda953a76..2169f42ba 100644 --- a/apps/emqx/test/emqx_common_test_helpers.erl +++ b/apps/emqx/test/emqx_common_test_helpers.erl @@ -488,8 +488,9 @@ is_tcp_server_available(Host, Port, Timeout) -> start_ekka() -> try mnesia_hook:module_info() of _ -> ekka:start() - catch _:_ -> - %% Falling back to using Mnesia DB backend. - application:set_env(mria, db_backend, mnesia), - ekka:start() + catch + _:_ -> + %% Falling back to using Mnesia DB backend. + application:set_env(mria, db_backend, mnesia), + ekka:start() end. diff --git a/apps/emqx/test/emqx_config_handler_SUITE.erl b/apps/emqx/test/emqx_config_handler_SUITE.erl index 72e3ed62f..ae34bee7a 100644 --- a/apps/emqx/test/emqx_config_handler_SUITE.erl +++ b/apps/emqx/test/emqx_config_handler_SUITE.erl @@ -223,7 +223,9 @@ t_callback_crash(_Config) -> Opts = #{rawconf_with_defaults => true}, ok = emqx_config_handler:add_handler(CrashPath, ?MODULE), Old = emqx:get_raw_config(CrashPath), - ?assertMatch({error, {config_update_crashed, _}}, emqx:update_config(CrashPath, <<"89%">>, Opts)), + ?assertMatch( + {error, {config_update_crashed, _}}, emqx:update_config(CrashPath, <<"89%">>, Opts) + ), New = emqx:get_raw_config(CrashPath), ?assertEqual(Old, New), ok = emqx_config_handler:remove_handler(CrashPath), diff --git a/lib-ee/emqx_license/include/emqx_license.hrl b/lib-ee/emqx_license/include/emqx_license.hrl index df40942ac..5cc7c6df0 100644 --- a/lib-ee/emqx_license/include/emqx_license.hrl +++ b/lib-ee/emqx_license/include/emqx_license.hrl @@ -9,20 +9,20 @@ -define(EVALUATION_LOG, "\n" - "================================================================================\n" - "This is an evaluation license that is restricted to 1000 concurrent connections.\n" - "If you already have a paid license, please apply it now.\n" - "Or you could visit https://emqx.com/apply-licenses/emqx to get a trial license.\n" - "================================================================================\n" + "========================================================================\n" + "Using an evaluation license limited to ~p concurrent connections.\n" + "Apply a license at https://emqx.com/apply-licenses/emqx.\n" + "Or contact EMQ customer services.\n" + "========================================================================\n" ). -define(EXPIRY_LOG, "\n" - "======================================================\n" - "Your license has expired.\n" - "Please visit https://emqx.com/apply-licenses/emqx or\n" - "contact customer services.\n" - "======================================================\n" + "========================================================================\n" + "License has been expired for ~p days.\n" + "Apply a new license at https://emqx.com/apply-licenses/emqx.\n" + "Or contact EMQ customer services.\n" + "========================================================================\n" ). -define(OFFICIAL, 1). diff --git a/lib-ee/emqx_license/src/emqx_license_checker.erl b/lib-ee/emqx_license/src/emqx_license_checker.erl index add2927e6..161e5a9cf 100644 --- a/lib-ee/emqx_license/src/emqx_license_checker.erl +++ b/lib-ee/emqx_license/src/emqx_license_checker.erl @@ -11,6 +11,7 @@ -define(CHECK_INTERVAL, 5000). -define(EXPIRY_ALARM_CHECK_INTERVAL, 24 * 60 * 60). +-define(OK(EXPR), try _ = begin EXPR end, ok catch _:_ -> ok end). -export([ start_link/1, @@ -18,7 +19,8 @@ update/1, dump/0, purge/0, - limits/0 + limits/0, + print_warnings/1 ]). %% gen_server callbacks @@ -78,7 +80,7 @@ init([LicenseFetcher, CheckInterval]) -> ?LICENSE_TAB = ets:new(?LICENSE_TAB, [ set, protected, named_table, {read_concurrency, true} ]), - #{} = check_license(License), + ok = print_warnings(check_license(License)), State0 = ensure_check_license_timer(#{ check_license_interval => CheckInterval, license => License @@ -90,7 +92,7 @@ init([LicenseFetcher, CheckInterval]) -> end. handle_call({update, License}, _From, State) -> - _ = expiry_early_alarm(License), + ok = expiry_early_alarm(License), {reply, check_license(License), State#{license => License}}; handle_call(dump, _From, #{license := License} = State) -> {reply, emqx_license_parser:dump(License), State}; @@ -109,7 +111,7 @@ handle_info(check_license, #{license := License} = State) -> ?tp(debug, emqx_license_checked, #{}), {noreply, NewState}; handle_info(check_expiry_alarm, #{license := License} = State) -> - _ = expiry_early_alarm(License), + ok = expiry_early_alarm(License), NewState = ensure_check_expiry_timer(State), {noreply, NewState}; handle_info(_Msg, State) -> @@ -138,21 +140,21 @@ cancel_timer(State, Key) -> check_license(License) -> DaysLeft = days_left(License), - NeedRestrict = need_restrict(License, DaysLeft), - Limits = limits(License, NeedRestrict), + IsOverdue = is_overdue(License, DaysLeft), + NeedRestriction = IsOverdue, + MaxConn = emqx_license_parser:max_connections(License), + Limits = limits(License, NeedRestriction), true = apply_limits(Limits), #{ - warn_evaluation => warn_evaluation(License, NeedRestrict), - warn_expiry => warn_expiry(License, NeedRestrict) + warn_evaluation => warn_evaluation(License, NeedRestriction, MaxConn), + warn_expiry => {(DaysLeft < 0), -DaysLeft} }. -warn_evaluation(License, false) -> - emqx_license_parser:customer_type(License) == ?EVALUATION_CUSTOMER; -warn_evaluation(_License, _NeedRestrict) -> +warn_evaluation(License, false, MaxConn) -> + {emqx_license_parser:customer_type(License) == ?EVALUATION_CUSTOMER, MaxConn}; +warn_evaluation(_License, _NeedRestrict, _Limits) -> false. -warn_expiry(_License, NeedRestrict) -> NeedRestrict. - limits(License, false) -> #{max_connections => emqx_license_parser:max_connections(License)}; limits(_License, true) -> #{max_connections => ?ERR_EXPIRED}. @@ -161,19 +163,20 @@ days_left(License) -> {DateNow, _} = calendar:universal_time(), calendar:date_to_gregorian_days(DateEnd) - calendar:date_to_gregorian_days(DateNow). -need_restrict(License, DaysLeft) -> +is_overdue(License, DaysLeft) -> CType = emqx_license_parser:customer_type(License), Type = emqx_license_parser:license_type(License), - DaysLeft < 0 andalso - (Type =/= ?OFFICIAL) orelse small_customer_over_expired(CType, DaysLeft). + small_customer_overdue(CType, DaysLeft) orelse + non_official_license_overdue(Type, DaysLeft). -small_customer_over_expired(?SMALL_CUSTOMER, DaysLeft) when - DaysLeft < ?EXPIRED_DAY --> - true; -small_customer_over_expired(_CType, _DaysLeft) -> - false. +%% small customers overdue 90 days after license expiry date +small_customer_overdue(?SMALL_CUSTOMER, DaysLeft) -> DaysLeft < ?EXPIRED_DAY; +small_customer_overdue(_CType, _DaysLeft) -> false. + +%% never restrict official license +non_official_license_overdue(?OFFICIAL, _) -> false; +non_official_license_overdue(_, DaysLeft) -> DaysLeft < 0. apply_limits(Limits) -> ets:insert(?LICENSE_TAB, {limits, Limits}). @@ -181,8 +184,23 @@ apply_limits(Limits) -> expiry_early_alarm(License) -> case days_left(License) < 30 of true -> - DateEnd = emqx_license_parser:expiry_date(License), - catch emqx_alarm:activate(license_expiry, #{expiry_at => DateEnd}); + {Y, M, D} = emqx_license_parser:expiry_date(License), + Date = iolist_to_binary(io_lib:format("~B~2..0B~2..0B", [Y, M, D])), + ?OK(emqx_alarm:activate(license_expiry, #{expiry_at => Date})); false -> - catch emqx_alarm:deactivate(license_expiry) + ?OK(emqx_alarm:deactivate(license_expiry)) end. + +print_warnings(Warnings) -> + ok = print_evaluation_warning(Warnings), + ok = print_expiry_warning(Warnings). + +print_evaluation_warning(#{warn_evaluation := {true, MaxConn}}) -> + io:format(?EVALUATION_LOG, [MaxConn]); +print_evaluation_warning(_) -> + ok. + +print_expiry_warning(#{warn_expiry := {true, Days}}) -> + io:format(?EXPIRY_LOG, [Days]); +print_expiry_warning(_) -> + ok. diff --git a/lib-ee/emqx_license/src/emqx_license_cli.erl b/lib-ee/emqx_license/src/emqx_license_cli.erl index 7eccdf79a..9d618db67 100644 --- a/lib-ee/emqx_license/src/emqx_license_cli.erl +++ b/lib-ee/emqx_license/src/emqx_license_cli.erl @@ -66,19 +66,4 @@ unload() -> ok = emqx_ctl:unregister_command(license). print_warnings(Warnings) -> - ok = print_evaluation_warning(Warnings), - ok = print_expiry_warning(Warnings). - -%%------------------------------------------------------------------------------ -%% Private functions -%%------------------------------------------------------------------------------ - -print_evaluation_warning(#{warn_evaluation := true}) -> - ?PRINT_MSG(?EVALUATION_LOG); -print_evaluation_warning(_) -> - ok. - -print_expiry_warning(#{warn_expiry := true}) -> - ?PRINT_MSG(?EXPIRY_LOG); -print_expiry_warning(_) -> - ok. + emqx_license_checker:print_warnings(Warnings).