From 9b5c7065f2766f7790a6808a72a346c356f0f869 Mon Sep 17 00:00:00 2001 From: zhongwencool Date: Wed, 14 Jun 2023 09:12:20 +0800 Subject: [PATCH] feat: conf reload support --replace|merge --- apps/emqx_authn/src/emqx_authn.erl | 5 ++- apps/emqx_authz/src/emqx_authz.erl | 4 +++ apps/emqx_conf/src/emqx_conf_cli.erl | 53 +++++++++++++++++++--------- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/apps/emqx_authn/src/emqx_authn.erl b/apps/emqx_authn/src/emqx_authn.erl index e717550f1..50287941e 100644 --- a/apps/emqx_authn/src/emqx_authn.erl +++ b/apps/emqx_authn/src/emqx_authn.erl @@ -26,7 +26,7 @@ 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"). @@ -162,3 +162,6 @@ authn_list(Authn) when is_map(Authn) -> merge_config(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). diff --git a/apps/emqx_authz/src/emqx_authz.erl b/apps/emqx_authz/src/emqx_authz.erl index 9fd6063e7..6f45a88b7 100644 --- a/apps/emqx_authz/src/emqx_authz.erl +++ b/apps/emqx_authz/src/emqx_authz.erl @@ -33,6 +33,7 @@ move/2, update/2, merge/1, + merge_local/2, authorize/5, %% for telemetry information get_enabled_authzs/0 @@ -127,6 +128,9 @@ lookup(Type) -> 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)) -> emqx_authz_utils:update_config( ?CONF_KEY_PATH, {?CMD_MOVE, type(Type), ?CMD_MOVE_BEFORE(type(Before))} diff --git a/apps/emqx_conf/src/emqx_conf_cli.erl b/apps/emqx_conf/src/emqx_conf_cli.erl index 6035c1ec6..4231149d6 100644 --- a/apps/emqx_conf/src/emqx_conf_cli.erl +++ b/apps/emqx_conf/src/emqx_conf_cli.erl @@ -55,8 +55,12 @@ conf(["load", Path]) -> load_config(Path, merge); conf(["cluster_sync" | 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"]) -> - reload_etc_conf_on_local_node(); + conf(["reload", "--merge"]); conf(_) -> emqx_ctl:usage(usage_conf() ++ usage_sync()). @@ -98,7 +102,10 @@ admins(_) -> 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 []", "Print in-use configs (including default values) under the given key."}, @@ -181,7 +188,7 @@ load_config(Path, ReplaceOrMerge) -> case check_config(RawConf) of ok -> 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) ); {error, ?UPDATE_READONLY_KEYS_PROHIBITED = Reason} -> @@ -205,18 +212,34 @@ load_config(Path, ReplaceOrMerge) -> {error, bad_hocon_file} 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)); -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)); -update_config(Key, NewConf, merge) -> +update_config_cluster(Key, NewConf, merge) -> Merged = merge_conf(Key, NewConf), 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, {ok, _}) -> emqx_ctl:print("load ~ts in cluster ok~n", [Key]); -check_res(Key, {error, Reason}) -> emqx_ctl:warning("load ~ts failed~n~p~n", [Key, Reason]). +-define(LOCAL_OPTIONS, #{rawconf_with_defaults => true, persistent => false}). +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) -> case check_keys_is_not_readonly(Conf) of @@ -244,13 +267,13 @@ check_config_schema(Conf) -> sorted_fold(Fold, Conf). %% @doc Reload etc/emqx.conf to runtime config except for the readonly config --spec reload_etc_conf_on_local_node() -> ok | {error, term()}. -reload_etc_conf_on_local_node() -> +-spec reload_etc_conf_on_local_node(replace | merge) -> ok | {error, term()}. +reload_etc_conf_on_local_node(ReplaceOrMerge) -> case load_etc_config_file() of {ok, RawConf} -> case filter_readonly_config(RawConf) of {ok, Reloaded} -> - reload_config(Reloaded); + reload_config(Reloaded, ReplaceOrMerge); {error, Error} -> emqx_ctl:warning("check config failed~n~p~n", [Error]), {error, Error} @@ -301,14 +324,12 @@ filter_readonly_config(Raw) -> {error, Error} end. -reload_config(AllConf) -> +reload_config(AllConf, ReplaceOrMerge) -> Fold = fun({Key, Conf}, Acc) -> - case emqx:update_config([Key], Conf, #{persistent => false}) of + case update_config_local(Key, Conf, ReplaceOrMerge) of {ok, _} -> - emqx_ctl:print("Reloaded ~ts config ok~n", [Key]), Acc; Error -> - emqx_ctl:warning("Reloaded ~ts config failed~n~p~n", [Key, Error]), ?SLOG(error, #{ msg => "failed_to_reload_etc_config", key => Key,