feat: conf reload support --replace|merge

This commit is contained in:
zhongwencool 2023-06-14 09:12:20 +08:00
parent 095fb040c0
commit 9b5c7065f2
3 changed files with 45 additions and 17 deletions

View File

@ -26,7 +26,7 @@
get_enabled_authns/0 get_enabled_authns/0
]). ]).
-export([merge_config/1, import_config/1]). -export([merge_config/1, merge_config_local/2, import_config/1]).
-include("emqx_authn.hrl"). -include("emqx_authn.hrl").
@ -162,3 +162,6 @@ authn_list(Authn) when is_map(Authn) ->
merge_config(AuthNs) -> merge_config(AuthNs) ->
emqx_authn_api:update_config([?CONF_NS_ATOM], {merge_authenticators, AuthNs}). emqx_authn_api:update_config([?CONF_NS_ATOM], {merge_authenticators, AuthNs}).
merge_config_local(AuthNs, Opts) ->
emqx:update_config([?CONF_NS_ATOM], {merge_authenticators, AuthNs}, Opts).

View File

@ -33,6 +33,7 @@
move/2, move/2,
update/2, update/2,
merge/1, merge/1,
merge_local/2,
authorize/5, authorize/5,
%% for telemetry information %% for telemetry information
get_enabled_authzs/0 get_enabled_authzs/0
@ -127,6 +128,9 @@ lookup(Type) ->
merge(NewConf) -> merge(NewConf) ->
emqx_authz_utils:update_config(?ROOT_KEY, {?CMD_MERGE, NewConf}). emqx_authz_utils:update_config(?ROOT_KEY, {?CMD_MERGE, NewConf}).
merge_local(NewConf, Opts) ->
emqx:update_config(?ROOT_KEY, {?CMD_MERGE, NewConf}, Opts).
move(Type, ?CMD_MOVE_BEFORE(Before)) -> move(Type, ?CMD_MOVE_BEFORE(Before)) ->
emqx_authz_utils:update_config( emqx_authz_utils:update_config(
?CONF_KEY_PATH, {?CMD_MOVE, type(Type), ?CMD_MOVE_BEFORE(type(Before))} ?CONF_KEY_PATH, {?CMD_MOVE, type(Type), ?CMD_MOVE_BEFORE(type(Before))}

View File

@ -55,8 +55,12 @@ conf(["load", Path]) ->
load_config(Path, merge); load_config(Path, merge);
conf(["cluster_sync" | Args]) -> conf(["cluster_sync" | Args]) ->
admins(Args); admins(Args);
conf(["reload", "--merge"]) ->
reload_etc_conf_on_local_node(merge);
conf(["reload", "--replace"]) ->
reload_etc_conf_on_local_node(replace);
conf(["reload"]) -> conf(["reload"]) ->
reload_etc_conf_on_local_node(); conf(["reload", "--merge"]);
conf(_) -> conf(_) ->
emqx_ctl:usage(usage_conf() ++ usage_sync()). emqx_ctl:usage(usage_conf() ++ usage_sync()).
@ -98,7 +102,10 @@ admins(_) ->
usage_conf() -> usage_conf() ->
[ [
{"conf reload", "reload etc/emqx.conf on local node"}, {"conf reload --replace|--merge", "reload etc/emqx.conf on local node"},
{"", "The new configuration values will be overlaid on the existing values by default."},
{"", "use the --replace flag to replace existing values with the new ones instead."},
{"----------------------------------", "------------"},
{"conf show_keys", "print all the currently used configuration keys."}, {"conf show_keys", "print all the currently used configuration keys."},
{"conf show [<key>]", {"conf show [<key>]",
"Print in-use configs (including default values) under the given key."}, "Print in-use configs (including default values) under the given key."},
@ -181,7 +188,7 @@ load_config(Path, ReplaceOrMerge) ->
case check_config(RawConf) of case check_config(RawConf) of
ok -> ok ->
lists:foreach( lists:foreach(
fun({K, V}) -> update_config(K, V, ReplaceOrMerge) end, fun({K, V}) -> update_config_cluster(K, V, ReplaceOrMerge) end,
to_sorted_list(RawConf) to_sorted_list(RawConf)
); );
{error, ?UPDATE_READONLY_KEYS_PROHIBITED = Reason} -> {error, ?UPDATE_READONLY_KEYS_PROHIBITED = Reason} ->
@ -205,18 +212,34 @@ load_config(Path, ReplaceOrMerge) ->
{error, bad_hocon_file} {error, bad_hocon_file}
end. end.
update_config(?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME = Key, Conf, merge) -> update_config_cluster(?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME = Key, Conf, merge) ->
check_res(Key, emqx_authz:merge(Conf)); check_res(Key, emqx_authz:merge(Conf));
update_config(?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME = Key, Conf, merge) -> update_config_cluster(?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME = Key, Conf, merge) ->
check_res(Key, emqx_authn:merge_config(Conf)); check_res(Key, emqx_authn:merge_config(Conf));
update_config(Key, NewConf, merge) -> update_config_cluster(Key, NewConf, merge) ->
Merged = merge_conf(Key, NewConf), Merged = merge_conf(Key, NewConf),
check_res(Key, emqx_conf:update([Key], Merged, ?OPTIONS)); check_res(Key, emqx_conf:update([Key], Merged, ?OPTIONS));
update_config(Key, Value, replace) -> update_config_cluster(Key, Value, replace) ->
check_res(Key, emqx_conf:update([Key], Value, ?OPTIONS)). check_res(Key, emqx_conf:update([Key], Value, ?OPTIONS)).
check_res(Key, {ok, _}) -> emqx_ctl:print("load ~ts in cluster ok~n", [Key]); -define(LOCAL_OPTIONS, #{rawconf_with_defaults => true, persistent => false}).
check_res(Key, {error, Reason}) -> emqx_ctl:warning("load ~ts failed~n~p~n", [Key, Reason]). update_config_local(?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME = Key, Conf, merge) ->
check_res(node(), Key, emqx_authz:merge_local(Conf, ?LOCAL_OPTIONS));
update_config_local(?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME = Key, Conf, merge) ->
check_res(node(), Key, emqx_authn:merge_config_local(Conf, ?LOCAL_OPTIONS));
update_config_local(Key, NewConf, merge) ->
Merged = merge_conf(Key, NewConf),
check_res(node(), Key, emqx:update_config([Key], Merged, ?LOCAL_OPTIONS));
update_config_local(Key, Value, replace) ->
check_res(node(), Key, emqx:update_config([Key], Value, ?LOCAL_OPTIONS)).
check_res(Key, Res) -> check_res(cluster, Key, Res).
check_res(Mode, Key, {ok, _} = Res) ->
emqx_ctl:print("load ~ts in ~p ok~n", [Key, Mode]),
Res;
check_res(_Mode, Key, {error, Reason} = Res) ->
emqx_ctl:warning("load ~ts failed~n~p~n", [Key, Reason]),
Res.
check_config(Conf) -> check_config(Conf) ->
case check_keys_is_not_readonly(Conf) of case check_keys_is_not_readonly(Conf) of
@ -244,13 +267,13 @@ check_config_schema(Conf) ->
sorted_fold(Fold, Conf). sorted_fold(Fold, Conf).
%% @doc Reload etc/emqx.conf to runtime config except for the readonly config %% @doc Reload etc/emqx.conf to runtime config except for the readonly config
-spec reload_etc_conf_on_local_node() -> ok | {error, term()}. -spec reload_etc_conf_on_local_node(replace | merge) -> ok | {error, term()}.
reload_etc_conf_on_local_node() -> reload_etc_conf_on_local_node(ReplaceOrMerge) ->
case load_etc_config_file() of case load_etc_config_file() of
{ok, RawConf} -> {ok, RawConf} ->
case filter_readonly_config(RawConf) of case filter_readonly_config(RawConf) of
{ok, Reloaded} -> {ok, Reloaded} ->
reload_config(Reloaded); reload_config(Reloaded, ReplaceOrMerge);
{error, Error} -> {error, Error} ->
emqx_ctl:warning("check config failed~n~p~n", [Error]), emqx_ctl:warning("check config failed~n~p~n", [Error]),
{error, Error} {error, Error}
@ -301,14 +324,12 @@ filter_readonly_config(Raw) ->
{error, Error} {error, Error}
end. end.
reload_config(AllConf) -> reload_config(AllConf, ReplaceOrMerge) ->
Fold = fun({Key, Conf}, Acc) -> Fold = fun({Key, Conf}, Acc) ->
case emqx:update_config([Key], Conf, #{persistent => false}) of case update_config_local(Key, Conf, ReplaceOrMerge) of
{ok, _} -> {ok, _} ->
emqx_ctl:print("Reloaded ~ts config ok~n", [Key]),
Acc; Acc;
Error -> Error ->
emqx_ctl:warning("Reloaded ~ts config failed~n~p~n", [Key, Error]),
?SLOG(error, #{ ?SLOG(error, #{
msg => "failed_to_reload_etc_config", msg => "failed_to_reload_etc_config",
key => Key, key => Key,