fix(plugins): read avsc file

This commit is contained in:
JimMoen 2024-04-24 15:24:38 +08:00
parent 8db5e51592
commit d06f410fd5
No known key found for this signature in database
3 changed files with 45 additions and 21 deletions

View File

@ -81,7 +81,9 @@
%% Defines %% Defines
-define(PLUGIN_PERSIS_CONFIG_KEY(NameVsn), {?MODULE, NameVsn}). -define(PLUGIN_PERSIS_CONFIG_KEY(NameVsn), {?MODULE, NameVsn}).
%% Types -define(RAW_BIN, binary).
-define(JSON_MAP, json_map).
%% "my_plugin-0.1.0" %% "my_plugin-0.1.0"
-type name_vsn() :: binary() | string(). -type name_vsn() :: binary() | string().
%% the parse result of the JSON info file %% the parse result of the JSON info file
@ -590,30 +592,36 @@ do_read_plugin(NameVsn) ->
do_read_plugin2(NameVsn, #{}). do_read_plugin2(NameVsn, #{}).
do_read_plugin2(NameVsn, Option) -> do_read_plugin2(NameVsn, Option) ->
do_read_plugin3(NameVsn, info_file(NameVsn), Option). do_read_plugin3(NameVsn, info_file_path(NameVsn), Option).
do_read_plugin3(NameVsn, InfoFilePath, Options) -> do_read_plugin3(NameVsn, InfoFilePath, Options) ->
{ok, PlainMap} = (read_file_fun(InfoFilePath, "bad_info_file"))(), {ok, PlainMap} = (read_file_fun(InfoFilePath, "bad_info_file", #{read_mode => ?JSON_MAP}))(),
Info0 = check_plugin(PlainMap, NameVsn, InfoFilePath), Info0 = check_plugin(PlainMap, NameVsn, InfoFilePath),
Info1 = plugins_readme(NameVsn, Options, Info0), Info1 = plugins_readme(NameVsn, Options, Info0),
plugin_status(NameVsn, Info1). plugin_status(NameVsn, Info1).
read_plugin_avsc(NameVsn) -> read_plugin_avsc(NameVsn) ->
read_plugin_avsc(NameVsn, #{read_mode => ?JSON_MAP}).
read_plugin_avsc(NameVsn, Options) ->
tryit( tryit(
atom_to_list(?FUNCTION_NAME), atom_to_list(?FUNCTION_NAME),
read_file_fun(schema_file(NameVsn), "bad_avsc_file") read_file_fun(avsc_file_path(NameVsn), "bad_avsc_file", Options)
). ).
read_plugin_i18n(NameVsn) -> read_plugin_i18n(NameVsn) ->
read_plugin_i18n(NameVsn, #{read_mode => ?JSON_MAP}).
read_plugin_i18n(NameVsn, Options) ->
tryit( tryit(
atom_to_list(?FUNCTION_NAME), atom_to_list(?FUNCTION_NAME),
read_file_fun(i18n_file(NameVsn), "bad_i18n_file") read_file_fun(i18n_file_path(NameVsn), "bad_i18n_file", Options)
). ).
read_plugin_avro(NameVsn) -> read_plugin_avro(NameVsn) ->
read_plugin_avro(NameVsn, #{read_mode => ?RAW_BIN}).
read_plugin_avro(NameVsn, Options) ->
tryit( tryit(
atom_to_list(?FUNCTION_NAME), atom_to_list(?FUNCTION_NAME),
read_file_fun(schema_file(NameVsn), "bad_avro_file") read_file_fun(avro_config_file(NameVsn), "bad_avro_file", Options)
). ).
ensure_exists_and_installed(NameVsn) -> ensure_exists_and_installed(NameVsn) ->
@ -1000,15 +1008,22 @@ maybe_post_op_after_install(NameVsn) ->
ok. ok.
maybe_load_config_schema(NameVsn) -> maybe_load_config_schema(NameVsn) ->
case read_plugin_avsc(NameVsn) of filelib:is_regular(avsc_file_path(NameVsn)) andalso
{ok, Avsc} -> do_load_config_schema(NameVsn).
case emqx_plugins_serde:add_schema(NameVsn, Avsc) of
do_load_config_schema(NameVsn) ->
case read_plugin_avsc(NameVsn, #{read_mode => ?RAW_BIN}) of
{ok, AvscBin} ->
case emqx_plugins_serde:add_schema(NameVsn, AvscBin) of
ok -> ok; ok -> ok;
{error, already_exists} -> ok; {error, already_exists} -> ok;
{error, Reason} -> {error, Reason} {error, _Reason} -> ok
end; end;
{error, Reason} -> {error, Reason} ->
?SLOG(warning, Reason) ?SLOG(warning, #{
msg => "failed_to_read_plugin_avsc", reason => Reason, name_vsn => NameVsn
}),
ok
end. end.
maybe_create_config_dir(NameVsn) -> maybe_create_config_dir(NameVsn) ->
@ -1020,14 +1035,23 @@ maybe_create_config_dir(NameVsn) ->
write_avro_bin(NameVsn, AvroBin) -> write_avro_bin(NameVsn, AvroBin) ->
ok = file:write_file(avro_config_file(NameVsn), AvroBin). ok = file:write_file(avro_config_file(NameVsn), AvroBin).
read_file_fun(Path, ErrMsg) -> read_file_fun(Path, ErrMsg, #{read_mode := ?RAW_BIN}) ->
fun() ->
case file:read_file(Path) of
{ok, Bin} ->
{ok, Bin};
{error, Reason} ->
ErrMeta = #{error_msg => ErrMsg, reason => Reason},
throw(ErrMeta)
end
end;
read_file_fun(Path, ErrMsg, #{read_mode := ?JSON_MAP}) ->
fun() -> fun() ->
case hocon:load(Path, #{format => richmap}) of case hocon:load(Path, #{format => richmap}) of
{ok, RichMap} -> {ok, RichMap} ->
{ok, hocon_maps:ensure_plain(RichMap)}; {ok, hocon_maps:ensure_plain(RichMap)};
{error, Reason} -> {error, Reason} ->
ErrMeta = #{error_msg => ErrMsg, reason => Reason}, ErrMeta = #{error_msg => ErrMsg, reason => Reason},
?SLOG(warning, ErrMeta),
throw(ErrMeta) throw(ErrMeta)
end end
end. end.
@ -1043,16 +1067,16 @@ plugin_config_dir(NameVsn) ->
pkg_file(NameVsn) -> pkg_file(NameVsn) ->
filename:join([install_dir(), bin([NameVsn, ".tar.gz"])]). filename:join([install_dir(), bin([NameVsn, ".tar.gz"])]).
info_file(NameVsn) -> info_file_path(NameVsn) ->
filename:join([plugin_dir(NameVsn), "release.json"]). filename:join([plugin_dir(NameVsn), "release.json"]).
schema_file(NameVsn) -> avsc_file_path(NameVsn) ->
filename:join([plugin_dir(NameVsn), "config_schema.avsc"]). filename:join([plugin_dir(NameVsn), "config_schema.avsc"]).
avro_config_file(NameVsn) -> avro_config_file(NameVsn) ->
filename:join([plugin_config_dir(NameVsn), "config.avro"]). filename:join([plugin_config_dir(NameVsn), "config.avro"]).
i18n_file(NameVsn) -> i18n_file_path(NameVsn) ->
filename:join([plugin_dir(NameVsn), "i18n.json"]). filename:join([plugin_dir(NameVsn), "i18n.json"]).
readme_file(NameVsn) -> readme_file(NameVsn) ->

View File

@ -79,7 +79,7 @@ add_schema(Name, Avsc) ->
end. end.
get_schema(NameVsn) -> get_schema(NameVsn) ->
Path = emqx_plugins:schema_file(NameVsn), Path = emqx_plugins:avsc_file_path(NameVsn),
case read_avsc_file(Path) of case read_avsc_file(Path) of
{ok, Avsc} -> {ok, Avsc} ->
{ok, Avsc}; {ok, Avsc};
@ -129,7 +129,7 @@ handle_continue({build_serdes, SchemasMap}, State) ->
_ = build_serdes(SchemasMap), _ = build_serdes(SchemasMap),
{noreply, State}. {noreply, State}.
handle_call({build_serdes, {NameVsn, Avsc}}, _From, State) -> handle_call({build_serdes, NameVsn, Avsc}, _From, State) ->
BuildRes = do_build_serde(NameVsn, Avsc), BuildRes = do_build_serde(NameVsn, Avsc),
{reply, BuildRes, State}; {reply, BuildRes, State};
handle_call(_Call, _From, State) -> handle_call(_Call, _From, State) ->

View File

@ -49,7 +49,7 @@ read_plugin_test() ->
with_rand_install_dir( with_rand_install_dir(
fun(_Dir) -> fun(_Dir) ->
NameVsn = "bar-5", NameVsn = "bar-5",
InfoFile = emqx_plugins:info_file(NameVsn), InfoFile = emqx_plugins:info_file_path(NameVsn),
FakeInfo = FakeInfo =
"name=bar, rel_vsn=\"5\", rel_apps=[justname_no_vsn]," "name=bar, rel_vsn=\"5\", rel_apps=[justname_no_vsn],"
"description=\"desc bar\"", "description=\"desc bar\"",
@ -90,7 +90,7 @@ delete_package_test() ->
meck_emqx(), meck_emqx(),
with_rand_install_dir( with_rand_install_dir(
fun(_Dir) -> fun(_Dir) ->
File = emqx_plugins:pkg_file("a-1"), File = emqx_plugins:pkg_file_path("a-1"),
ok = write_file(File, "a"), ok = write_file(File, "a"),
ok = emqx_plugins:delete_package("a-1"), ok = emqx_plugins:delete_package("a-1"),
%% delete again should be ok %% delete again should be ok
@ -108,7 +108,7 @@ purge_test() ->
meck_emqx(), meck_emqx(),
with_rand_install_dir( with_rand_install_dir(
fun(_Dir) -> fun(_Dir) ->
File = emqx_plugins:info_file("a-1"), File = emqx_plugins:info_file_path("a-1"),
Dir = emqx_plugins:plugin_dir("a-1"), Dir = emqx_plugins:plugin_dir("a-1"),
ok = filelib:ensure_dir(File), ok = filelib:ensure_dir(File),
?assertMatch({ok, _}, file:read_file_info(Dir)), ?assertMatch({ok, _}, file:read_file_info(Dir)),