From e0e4517d9e1b1eae0bf3e527278a5ca3e31bf220 Mon Sep 17 00:00:00 2001 From: JimMoen Date: Fri, 17 May 2024 09:10:10 +0800 Subject: [PATCH] fix: ensure plugin config on boot --- .../src/emqx_mgmt_api_plugins.erl | 4 +- apps/emqx_plugins/src/emqx_plugins.erl | 46 +++++++++++++++++-- apps/emqx_plugins/src/emqx_plugins_serde.erl | 4 +- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/apps/emqx_management/src/emqx_mgmt_api_plugins.erl b/apps/emqx_management/src/emqx_mgmt_api_plugins.erl index 94b16320a..bda053dee 100644 --- a/apps/emqx_management/src/emqx_mgmt_api_plugins.erl +++ b/apps/emqx_management/src/emqx_mgmt_api_plugins.erl @@ -599,9 +599,9 @@ ensure_action(Name, restart) -> ok. %% for RPC plugin avro encoded config update -do_update_plugin_config(Name, AvroJsonMap, PluginConfigMap) -> +do_update_plugin_config(NameVsn, AvroJsonMap, PluginConfigMap) -> %% TODO: maybe use `PluginConfigMap` to validate config - emqx_plugins:put_config(Name, AvroJsonMap, PluginConfigMap). + emqx_plugins:put_config(NameVsn, AvroJsonMap, PluginConfigMap). %%-------------------------------------------------------------------- %% Helper functions diff --git a/apps/emqx_plugins/src/emqx_plugins.erl b/apps/emqx_plugins/src/emqx_plugins.erl index 108ef1386..dc8be43fa 100644 --- a/apps/emqx_plugins/src/emqx_plugins.erl +++ b/apps/emqx_plugins/src/emqx_plugins.erl @@ -659,7 +659,8 @@ ensure_exists_and_installed(NameVsn) -> case get_tar(NameVsn) of {ok, TarContent} -> ok = file:write_file(pkg_file_path(NameVsn), TarContent), - ok = do_ensure_installed(NameVsn); + ok = do_ensure_installed(NameVsn), + ok = ensure_avro_config(NameVsn); _ -> %% If not, try to get it from the cluster. do_get_from_cluster(NameVsn) @@ -1046,6 +1047,7 @@ maybe_create_config_dir(NameVsn) -> ConfigDir = plugin_config_dir(NameVsn), case filelib:ensure_path(ConfigDir) of ok -> + _ = maybe_copy_default_avro_config(NameVsn), ok; {error, Reason} -> ?SLOG(warning, #{ @@ -1056,6 +1058,37 @@ maybe_create_config_dir(NameVsn) -> {error, {mkdir_failed, ConfigDir, Reason}} end. +maybe_copy_default_avro_config(NameVsn) -> + Source = default_avro_config_file(NameVsn), + Destination = avro_config_file(NameVsn), + filelib:is_regular(Source) andalso + case file:copy(Source, Destination) of + {ok, _} -> + ok, + ensure_avro_config(NameVsn); + {error, Reason} -> + ?SLOG(warning, #{ + msg => "failed_to_copy_plugin_default_avro_config", + source => Source, + destination => Destination, + reason => Reason + }) + end. + +%% ensure_avro_config() -> +%% ok = for_plugins(fun(NameVsn) -> ensure_avro_config(NameVsn) end). + +ensure_avro_config(NameVsn) -> + case read_plugin_avro(NameVsn, #{read_mode => ?JSON_MAP}) of + {ok, AvroJsonMap} -> + {ok, Config} = decode_plugin_avro_config( + NameVsn, emqx_utils_json:encode(AvroJsonMap) + ), + put_config(NameVsn, AvroJsonMap, Config); + _ -> + ok + end. + %% @private Backup the current config to a file with a timestamp suffix and %% then save the new config to the config file. backup_and_write_avro_bin(NameVsn, AvroBin) -> @@ -1148,7 +1181,7 @@ plugin_dir(NameVsn) -> -spec plugin_config_dir(name_vsn()) -> string(). plugin_config_dir(NameVsn) -> - wrap_list_path(filename:join([plugin_dir(NameVsn), "data", "configs"])). + wrap_list_path(filename:join([emqx:data_dir(), "plugins", NameVsn])). %% Files -spec pkg_file_path(name_vsn()) -> string(). @@ -1161,15 +1194,20 @@ info_file_path(NameVsn) -> -spec avsc_file_path(name_vsn()) -> string(). avsc_file_path(NameVsn) -> - wrap_list_path(filename:join([plugin_dir(NameVsn), "config_schema.avsc"])). + wrap_list_path(filename:join([plugin_dir(NameVsn), "config", "config_schema.avsc"])). -spec avro_config_file(name_vsn()) -> string(). avro_config_file(NameVsn) -> wrap_list_path(filename:join([plugin_config_dir(NameVsn), "config.avro"])). +%% should only used when plugin installing +-spec default_avro_config_file(name_vsn()) -> string(). +default_avro_config_file(NameVsn) -> + wrap_list_path(filename:join([plugin_dir(NameVsn), "config", "config.avro"])). + -spec i18n_file_path(name_vsn()) -> string(). i18n_file_path(NameVsn) -> - wrap_list_path(filename:join([plugin_dir(NameVsn), "config_i18n.json"])). + wrap_list_path(filename:join([plugin_dir(NameVsn), "config", "config_i18n.json"])). -spec readme_file(name_vsn()) -> string(). readme_file(NameVsn) -> diff --git a/apps/emqx_plugins/src/emqx_plugins_serde.erl b/apps/emqx_plugins/src/emqx_plugins_serde.erl index fdc46e661..7328c33ff 100644 --- a/apps/emqx_plugins/src/emqx_plugins_serde.erl +++ b/apps/emqx_plugins/src/emqx_plugins_serde.erl @@ -151,10 +151,10 @@ terminate(_Reason, _State) -> -spec get_plugin_avscs() -> [{string(), string()}]. get_plugin_avscs() -> - Pattern = filename:join([emqx_plugins:install_dir(), "*", "config_schema.avsc"]), + Pattern = filename:join([emqx_plugins:install_dir(), "*", "config", "config_schema.avsc"]), lists:foldl( fun(AvscPath, AccIn) -> - [_, NameVsn | _] = lists:reverse(filename:split(AvscPath)), + [_, _, NameVsn | _] = lists:reverse(filename:split(AvscPath)), [{to_bin(NameVsn), AvscPath} | AccIn] end, _Acc0 = [],