Merge pull request #13269 from JimMoen/improve-plugin-behavior
fix: mark fresh install to cp the default configuration file directly
This commit is contained in:
commit
f9e17d6c25
|
@ -59,7 +59,6 @@
|
||||||
-define(VSN_WILDCARD, "-*.tar.gz").
|
-define(VSN_WILDCARD, "-*.tar.gz").
|
||||||
|
|
||||||
-define(CONTENT_PLUGIN, plugin).
|
-define(CONTENT_PLUGIN, plugin).
|
||||||
-define(CONTENT_CONFIG, config).
|
|
||||||
|
|
||||||
namespace() ->
|
namespace() ->
|
||||||
"plugins".
|
"plugins".
|
||||||
|
@ -411,7 +410,7 @@ upload_install(post, #{body := #{<<"plugin">> := Plugin}}) when is_map(Plugin) -
|
||||||
%% File bin is too large, we use rpc:multicall instead of cluster_rpc:multicall
|
%% File bin is too large, we use rpc:multicall instead of cluster_rpc:multicall
|
||||||
NameVsn = string:trim(FileName, trailing, ".tar.gz"),
|
NameVsn = string:trim(FileName, trailing, ".tar.gz"),
|
||||||
case emqx_plugins:describe(NameVsn) of
|
case emqx_plugins:describe(NameVsn) of
|
||||||
{error, #{error_msg := "bad_info_file", reason := {enoent, _}}} ->
|
{error, #{msg := "bad_info_file", reason := {enoent, _Path}}} ->
|
||||||
case emqx_plugins:parse_name_vsn(FileName) of
|
case emqx_plugins:parse_name_vsn(FileName) of
|
||||||
{ok, AppName, _Vsn} ->
|
{ok, AppName, _Vsn} ->
|
||||||
AppDir = filename:join(emqx_plugins:install_dir(), AppName),
|
AppDir = filename:join(emqx_plugins:install_dir(), AppName),
|
||||||
|
@ -467,12 +466,12 @@ do_install_package(FileName, Bin) ->
|
||||||
),
|
),
|
||||||
Reason =
|
Reason =
|
||||||
case hd(Filtered) of
|
case hd(Filtered) of
|
||||||
{error, #{error_msg := Reason0}} -> Reason0;
|
{error, #{msg := Reason0}} -> Reason0;
|
||||||
{error, #{reason := Reason0}} -> Reason0
|
{error, #{reason := Reason0}} -> Reason0
|
||||||
end,
|
end,
|
||||||
{400, #{
|
{400, #{
|
||||||
code => 'BAD_PLUGIN_INFO',
|
code => 'BAD_PLUGIN_INFO',
|
||||||
message => iolist_to_binary([Reason, ": ", FileName])
|
message => iolist_to_binary([bin(Reason), ": ", FileName])
|
||||||
}}
|
}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -565,8 +564,8 @@ install_package(FileName, Bin) ->
|
||||||
ok = filelib:ensure_dir(File),
|
ok = filelib:ensure_dir(File),
|
||||||
ok = file:write_file(File, Bin),
|
ok = file:write_file(File, Bin),
|
||||||
PackageName = string:trim(FileName, trailing, ".tar.gz"),
|
PackageName = string:trim(FileName, trailing, ".tar.gz"),
|
||||||
case emqx_plugins:ensure_installed(PackageName) of
|
case emqx_plugins:ensure_installed(PackageName, ?fresh_install) of
|
||||||
{error, #{reason := not_found}} = NotFound ->
|
{error, #{reason := plugin_not_found}} = NotFound ->
|
||||||
NotFound;
|
NotFound;
|
||||||
{error, Reason} = Error ->
|
{error, Reason} = Error ->
|
||||||
?SLOG(error, Reason#{msg => "failed_to_install_plugin"}),
|
?SLOG(error, Reason#{msg => "failed_to_install_plugin"}),
|
||||||
|
@ -597,6 +596,9 @@ delete_package(Name) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% for RPC plugin update
|
%% for RPC plugin update
|
||||||
|
%% TODO: catch thrown error to return 400
|
||||||
|
%% - plugin_not_found
|
||||||
|
%% - otp vsn assertion failed
|
||||||
ensure_action(Name, start) ->
|
ensure_action(Name, start) ->
|
||||||
_ = emqx_plugins:ensure_started(Name),
|
_ = emqx_plugins:ensure_started(Name),
|
||||||
_ = emqx_plugins:ensure_enabled(Name),
|
_ = emqx_plugins:ensure_enabled(Name),
|
||||||
|
@ -625,10 +627,9 @@ do_update_plugin_config(NameVsn, AvroJsonMap, AvroValue) ->
|
||||||
|
|
||||||
return(Code, ok) ->
|
return(Code, ok) ->
|
||||||
{Code};
|
{Code};
|
||||||
return(_, {error, #{error_msg := "bad_info_file", reason := {enoent, _} = Reason}}) ->
|
return(_, {error, #{msg := Msg, reason := {enoent, Path} = Reason}}) ->
|
||||||
{404, #{code => 'NOT_FOUND', message => readable_error_msg(Reason)}};
|
?SLOG(error, #{msg => Msg, reason => Reason}),
|
||||||
return(_, {error, #{error_msg := "bad_avro_config_file", reason := {enoent, _} = Reason}}) ->
|
{404, #{code => 'NOT_FOUND', message => iolist_to_binary([Path, " does not exist"])}};
|
||||||
{404, #{code => 'NOT_FOUND', message => readable_error_msg(Reason)}};
|
|
||||||
return(_, {error, Reason}) ->
|
return(_, {error, Reason}) ->
|
||||||
{400, #{code => 'PARAM_ERROR', message => readable_error_msg(Reason)}}.
|
{400, #{code => 'PARAM_ERROR', message => readable_error_msg(Reason)}}.
|
||||||
|
|
||||||
|
@ -728,6 +729,10 @@ format_plugin_avsc_and_i18n(_NameVsn) ->
|
||||||
#{avsc => null, i18n => null}.
|
#{avsc => null, i18n => null}.
|
||||||
-endif.
|
-endif.
|
||||||
|
|
||||||
|
bin(A) when is_atom(A) -> atom_to_binary(A, utf8);
|
||||||
|
bin(L) when is_list(L) -> list_to_binary(L);
|
||||||
|
bin(B) when is_binary(B) -> B.
|
||||||
|
|
||||||
% running_status: running loaded, stopped
|
% running_status: running loaded, stopped
|
||||||
%% config_status: not_configured disable enable
|
%% config_status: not_configured disable enable
|
||||||
plugin_status(#{running_status := running}) -> running;
|
plugin_status(#{running_status := running}) -> running;
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
-define(plugin_conf_not_found, plugin_conf_not_found).
|
-define(plugin_conf_not_found, plugin_conf_not_found).
|
||||||
-define(plugin_without_config_schema, plugin_without_config_schema).
|
-define(plugin_without_config_schema, plugin_without_config_schema).
|
||||||
|
-define(fresh_install, fresh_install).
|
||||||
|
-define(normal, normal).
|
||||||
|
|
||||||
-type schema_name() :: binary().
|
-type schema_name() :: binary().
|
||||||
-type avsc_path() :: string().
|
-type avsc_path() :: string().
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
-export([
|
-export([
|
||||||
ensure_installed/0,
|
ensure_installed/0,
|
||||||
ensure_installed/1,
|
ensure_installed/1,
|
||||||
|
ensure_installed/2,
|
||||||
ensure_uninstalled/1,
|
ensure_uninstalled/1,
|
||||||
ensure_enabled/1,
|
ensure_enabled/1,
|
||||||
ensure_enabled/2,
|
ensure_enabled/2,
|
||||||
|
@ -169,19 +170,27 @@ ensure_installed(NameVsn) ->
|
||||||
case read_plugin_info(NameVsn, #{}) of
|
case read_plugin_info(NameVsn, #{}) of
|
||||||
{ok, _} ->
|
{ok, _} ->
|
||||||
ok,
|
ok,
|
||||||
_ = maybe_ensure_plugin_config(NameVsn);
|
_ = maybe_ensure_plugin_config(NameVsn, ?normal);
|
||||||
{error, _} ->
|
{error, _} ->
|
||||||
ok = purge(NameVsn),
|
ok = purge(NameVsn),
|
||||||
case ensure_exists_and_installed(NameVsn) of
|
case ensure_exists_and_installed(NameVsn) of
|
||||||
ok ->
|
ok ->
|
||||||
maybe_post_op_after_installed(NameVsn),
|
maybe_post_op_after_installed(NameVsn, ?normal),
|
||||||
_ = maybe_ensure_plugin_config(NameVsn),
|
|
||||||
ok;
|
ok;
|
||||||
{error, _Reason} = Err ->
|
{error, _Reason} = Err ->
|
||||||
Err
|
Err
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
ensure_installed(NameVsn, ?fresh_install = Mode) ->
|
||||||
|
case ensure_exists_and_installed(NameVsn) of
|
||||||
|
ok ->
|
||||||
|
maybe_post_op_after_installed(NameVsn, Mode),
|
||||||
|
ok;
|
||||||
|
{error, _Reason} = Err ->
|
||||||
|
Err
|
||||||
|
end.
|
||||||
|
|
||||||
%% @doc Ensure files and directories for the given plugin are being deleted.
|
%% @doc Ensure files and directories for the given plugin are being deleted.
|
||||||
%% If a plugin is running, or enabled, an error is returned.
|
%% If a plugin is running, or enabled, an error is returned.
|
||||||
-spec ensure_uninstalled(name_vsn()) -> ok | {error, any()}.
|
-spec ensure_uninstalled(name_vsn()) -> ok | {error, any()}.
|
||||||
|
@ -189,12 +198,12 @@ ensure_uninstalled(NameVsn) ->
|
||||||
case read_plugin_info(NameVsn, #{}) of
|
case read_plugin_info(NameVsn, #{}) of
|
||||||
{ok, #{running_status := RunningSt}} when RunningSt =/= stopped ->
|
{ok, #{running_status := RunningSt}} when RunningSt =/= stopped ->
|
||||||
{error, #{
|
{error, #{
|
||||||
error_msg => "bad_plugin_running_status",
|
msg => "bad_plugin_running_status",
|
||||||
hint => "stop_the_plugin_first"
|
hint => "stop_the_plugin_first"
|
||||||
}};
|
}};
|
||||||
{ok, #{config_status := enabled}} ->
|
{ok, #{config_status := enabled}} ->
|
||||||
{error, #{
|
{error, #{
|
||||||
error_msg => "bad_plugin_config_status",
|
msg => "bad_plugin_config_status",
|
||||||
hint => "disable_the_plugin_first"
|
hint => "disable_the_plugin_first"
|
||||||
}};
|
}};
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -279,9 +288,9 @@ ensure_started(NameVsn) ->
|
||||||
case do_ensure_started(NameVsn) of
|
case do_ensure_started(NameVsn) of
|
||||||
ok ->
|
ok ->
|
||||||
ok;
|
ok;
|
||||||
{error, Reason} ->
|
{error, ReasonMap} ->
|
||||||
?SLOG(alert, Reason#{msg => "failed_to_start_plugin"}),
|
?SLOG(error, ReasonMap#{msg => "failed_to_start_plugin"}),
|
||||||
{error, Reason}
|
{error, ReasonMap}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc Stop all plugins before broker stops.
|
%% @doc Stop all plugins before broker stops.
|
||||||
|
@ -374,7 +383,7 @@ list() ->
|
||||||
{ok, Info} ->
|
{ok, Info} ->
|
||||||
{true, Info};
|
{true, Info};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?SLOG(warning, Reason),
|
?SLOG(warning, Reason#{msg => "failed_to_read_plugin_info"}),
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
@ -402,7 +411,10 @@ decode_plugin_config_map(NameVsn, AvroJsonMap) ->
|
||||||
do_decode_plugin_config_map(NameVsn, AvroJsonMap)
|
do_decode_plugin_config_map(NameVsn, AvroJsonMap)
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
?SLOG(debug, #{name_vsn => NameVsn, plugin_with_avro_schema => false}),
|
?SLOG(debug, #{
|
||||||
|
msg => "plugin_without_config_schema",
|
||||||
|
name_vsn => NameVsn
|
||||||
|
}),
|
||||||
{ok, ?plugin_without_config_schema}
|
{ok, ?plugin_without_config_schema}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -537,13 +549,13 @@ do_ensure_installed(NameVsn) ->
|
||||||
end;
|
end;
|
||||||
{error, {_, enoent}} ->
|
{error, {_, enoent}} ->
|
||||||
{error, #{
|
{error, #{
|
||||||
error_msg => "failed_to_extract_plugin_package",
|
msg => "failed_to_extract_plugin_package",
|
||||||
path => TarGz,
|
path => TarGz,
|
||||||
reason => not_found
|
reason => plugin_tarball_not_found
|
||||||
}};
|
}};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{error, #{
|
{error, #{
|
||||||
error_msg => "bad_plugin_package",
|
msg => "bad_plugin_package",
|
||||||
path => TarGz,
|
path => TarGz,
|
||||||
reason => Reason
|
reason => Reason
|
||||||
}}
|
}}
|
||||||
|
@ -600,7 +612,7 @@ add_new_configured(Configured, {Action, NameVsn}, Item) ->
|
||||||
{Front, Rear} = lists:splitwith(SplitFun, Configured),
|
{Front, Rear} = lists:splitwith(SplitFun, Configured),
|
||||||
Rear =:= [] andalso
|
Rear =:= [] andalso
|
||||||
throw(#{
|
throw(#{
|
||||||
error_msg => "position_anchor_plugin_not_configured",
|
msg => "position_anchor_plugin_not_configured",
|
||||||
hint => "maybe_install_and_configure",
|
hint => "maybe_install_and_configure",
|
||||||
name_vsn => NameVsn
|
name_vsn => NameVsn
|
||||||
}),
|
}),
|
||||||
|
@ -664,12 +676,13 @@ do_ensure_started(NameVsn) ->
|
||||||
ok ->
|
ok ->
|
||||||
Plugin = do_read_plugin(NameVsn),
|
Plugin = do_read_plugin(NameVsn),
|
||||||
ok = load_code_start_apps(NameVsn, Plugin);
|
ok = load_code_start_apps(NameVsn, Plugin);
|
||||||
{error, plugin_not_found} ->
|
{error, #{reason := Reason} = ReasonMap} ->
|
||||||
?SLOG(error, #{
|
?SLOG(error, #{
|
||||||
error_msg => "plugin_not_found",
|
msg => "failed_to_start_plugin",
|
||||||
name_vsn => NameVsn
|
name_vsn => NameVsn,
|
||||||
|
reason => Reason
|
||||||
}),
|
}),
|
||||||
ok
|
{error, ReasonMap}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
).
|
).
|
||||||
|
@ -682,10 +695,12 @@ tryit(WhichOp, F) ->
|
||||||
try
|
try
|
||||||
F()
|
F()
|
||||||
catch
|
catch
|
||||||
throw:ReasonMap ->
|
throw:ReasonMap when is_map(ReasonMap) ->
|
||||||
%% thrown exceptions are known errors
|
%% thrown exceptions are known errors
|
||||||
%% translate to a return value without stacktrace
|
%% translate to a return value without stacktrace
|
||||||
{error, ReasonMap};
|
{error, ReasonMap};
|
||||||
|
throw:Reason ->
|
||||||
|
{error, #{reason => Reason}};
|
||||||
error:Reason:Stacktrace ->
|
error:Reason:Stacktrace ->
|
||||||
%% unexpected errors, log stacktrace
|
%% unexpected errors, log stacktrace
|
||||||
?SLOG(warning, #{
|
?SLOG(warning, #{
|
||||||
|
@ -769,18 +784,18 @@ do_get_from_cluster(NameVsn) ->
|
||||||
ok = do_ensure_installed(NameVsn);
|
ok = do_ensure_installed(NameVsn);
|
||||||
{error, NodeErrors} when Nodes =/= [] ->
|
{error, NodeErrors} when Nodes =/= [] ->
|
||||||
ErrMeta = #{
|
ErrMeta = #{
|
||||||
error_msg => "failed_to_copy_plugin_from_other_nodes",
|
msg => "failed_to_copy_plugin_from_other_nodes",
|
||||||
name_vsn => NameVsn,
|
name_vsn => NameVsn,
|
||||||
node_errors => NodeErrors,
|
node_errors => NodeErrors,
|
||||||
reason => not_found
|
reason => plugin_not_found
|
||||||
},
|
},
|
||||||
?SLOG(error, ErrMeta),
|
?SLOG(error, ErrMeta),
|
||||||
{error, ErrMeta};
|
{error, ErrMeta};
|
||||||
{error, _} ->
|
{error, _} ->
|
||||||
ErrMeta = #{
|
ErrMeta = #{
|
||||||
error_msg => "no_nodes_to_copy_plugin_from",
|
msg => "no_nodes_to_copy_plugin_from",
|
||||||
name_vsn => NameVsn,
|
name_vsn => NameVsn,
|
||||||
reason => not_found
|
reason => plugin_not_found
|
||||||
},
|
},
|
||||||
?SLOG(error, ErrMeta),
|
?SLOG(error, ErrMeta),
|
||||||
{error, ErrMeta}
|
{error, ErrMeta}
|
||||||
|
@ -791,6 +806,11 @@ get_plugin_tar_from_any_node([], _NameVsn, Errors) ->
|
||||||
get_plugin_tar_from_any_node([Node | T], NameVsn, Errors) ->
|
get_plugin_tar_from_any_node([Node | T], NameVsn, Errors) ->
|
||||||
case emqx_plugins_proto_v1:get_tar(Node, NameVsn, infinity) of
|
case emqx_plugins_proto_v1:get_tar(Node, NameVsn, infinity) of
|
||||||
{ok, _} = Res ->
|
{ok, _} = Res ->
|
||||||
|
?SLOG(debug, #{
|
||||||
|
msg => "get_plugin_tar_from_cluster_successfully",
|
||||||
|
node => Node,
|
||||||
|
name_vsn => NameVsn
|
||||||
|
}),
|
||||||
Res;
|
Res;
|
||||||
Err ->
|
Err ->
|
||||||
get_plugin_tar_from_any_node(T, NameVsn, [{Node, Err} | Errors])
|
get_plugin_tar_from_any_node(T, NameVsn, [{Node, Err} | Errors])
|
||||||
|
@ -805,6 +825,11 @@ get_plugin_config_from_any_node([Node | T], NameVsn, Errors) ->
|
||||||
)
|
)
|
||||||
of
|
of
|
||||||
{ok, _} = Res ->
|
{ok, _} = Res ->
|
||||||
|
?SLOG(debug, #{
|
||||||
|
msg => "get_plugin_config_from_cluster_successfully",
|
||||||
|
node => Node,
|
||||||
|
name_vsn => NameVsn
|
||||||
|
}),
|
||||||
Res;
|
Res;
|
||||||
Err ->
|
Err ->
|
||||||
get_plugin_config_from_any_node(T, NameVsn, [{Node, Err} | Errors])
|
get_plugin_config_from_any_node(T, NameVsn, [{Node, Err} | Errors])
|
||||||
|
@ -870,7 +895,7 @@ check_plugin(
|
||||||
catch
|
catch
|
||||||
_:_ ->
|
_:_ ->
|
||||||
throw(#{
|
throw(#{
|
||||||
error_msg => "bad_rel_apps",
|
msg => "bad_rel_apps",
|
||||||
rel_apps => Apps,
|
rel_apps => Apps,
|
||||||
hint => "A non-empty string list of app_name-app_vsn format"
|
hint => "A non-empty string list of app_name-app_vsn format"
|
||||||
})
|
})
|
||||||
|
@ -878,7 +903,7 @@ check_plugin(
|
||||||
Info;
|
Info;
|
||||||
false ->
|
false ->
|
||||||
throw(#{
|
throw(#{
|
||||||
error_msg => "name_vsn_mismatch",
|
msg => "name_vsn_mismatch",
|
||||||
name_vsn => NameVsn,
|
name_vsn => NameVsn,
|
||||||
path => FilePath,
|
path => FilePath,
|
||||||
name => Name,
|
name => Name,
|
||||||
|
@ -887,7 +912,7 @@ check_plugin(
|
||||||
end;
|
end;
|
||||||
check_plugin(_What, NameVsn, File) ->
|
check_plugin(_What, NameVsn, File) ->
|
||||||
throw(#{
|
throw(#{
|
||||||
error_msg => "bad_info_file_content",
|
msg => "bad_info_file_content",
|
||||||
mandatory_fields => [rel_vsn, name, rel_apps, description],
|
mandatory_fields => [rel_vsn, name, rel_apps, description],
|
||||||
name_vsn => NameVsn,
|
name_vsn => NameVsn,
|
||||||
path => File
|
path => File
|
||||||
|
@ -943,7 +968,7 @@ do_load_plugin_app(AppName, Ebin) ->
|
||||||
ok;
|
ok;
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
throw(#{
|
throw(#{
|
||||||
error_msg => "failed_to_load_plugin_beam",
|
msg => "failed_to_load_plugin_beam",
|
||||||
path => BeamFile,
|
path => BeamFile,
|
||||||
reason => Reason
|
reason => Reason
|
||||||
})
|
})
|
||||||
|
@ -958,7 +983,7 @@ do_load_plugin_app(AppName, Ebin) ->
|
||||||
ok;
|
ok;
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
throw(#{
|
throw(#{
|
||||||
error_msg => "failed_to_load_plugin_app",
|
msg => "failed_to_load_plugin_app",
|
||||||
name => AppName,
|
name => AppName,
|
||||||
reason => Reason
|
reason => Reason
|
||||||
})
|
})
|
||||||
|
@ -975,7 +1000,7 @@ start_app(App) ->
|
||||||
ok;
|
ok;
|
||||||
{error, {ErrApp, Reason}} ->
|
{error, {ErrApp, Reason}} ->
|
||||||
throw(#{
|
throw(#{
|
||||||
error_msg => "failed_to_start_plugin_app",
|
msg => "failed_to_start_plugin_app",
|
||||||
app => App,
|
app => App,
|
||||||
err_app => ErrApp,
|
err_app => ErrApp,
|
||||||
reason => Reason
|
reason => Reason
|
||||||
|
@ -1057,7 +1082,7 @@ stop_app(App) ->
|
||||||
?SLOG(debug, #{msg => "plugin_not_started", app => App}),
|
?SLOG(debug, #{msg => "plugin_not_started", app => App}),
|
||||||
ok = unload_moudle_and_app(App);
|
ok = unload_moudle_and_app(App);
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
throw(#{error_msg => "failed_to_stop_app", app => App, reason => Reason})
|
throw(#{msg => "failed_to_stop_app", app => App, reason => Reason})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
unload_moudle_and_app(App) ->
|
unload_moudle_and_app(App) ->
|
||||||
|
@ -1152,13 +1177,13 @@ for_plugins(ActionFun) ->
|
||||||
for_plugins_action_error_occurred,
|
for_plugins_action_error_occurred,
|
||||||
ErrMeta
|
ErrMeta
|
||||||
),
|
),
|
||||||
?SLOG(error, ErrMeta),
|
?SLOG(error, ErrMeta#{msg => "for_plugins_action_error_occurred"}),
|
||||||
ok
|
ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
maybe_post_op_after_installed(NameVsn0) ->
|
maybe_post_op_after_installed(NameVsn0, Mode) ->
|
||||||
NameVsn = wrap_to_list(NameVsn0),
|
NameVsn = wrap_to_list(NameVsn0),
|
||||||
_ = maybe_load_config_schema(NameVsn),
|
_ = maybe_load_config_schema(NameVsn, Mode),
|
||||||
ok = maybe_ensure_state(NameVsn).
|
ok = maybe_ensure_state(NameVsn).
|
||||||
|
|
||||||
maybe_ensure_state(NameVsn) ->
|
maybe_ensure_state(NameVsn) ->
|
||||||
|
@ -1183,13 +1208,13 @@ maybe_ensure_state(NameVsn) ->
|
||||||
end,
|
end,
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
maybe_load_config_schema(NameVsn) ->
|
maybe_load_config_schema(NameVsn, Mode) ->
|
||||||
AvscPath = avsc_file_path(NameVsn),
|
AvscPath = avsc_file_path(NameVsn),
|
||||||
_ =
|
_ =
|
||||||
with_plugin_avsc(NameVsn) andalso
|
with_plugin_avsc(NameVsn) andalso
|
||||||
filelib:is_regular(AvscPath) andalso
|
filelib:is_regular(AvscPath) andalso
|
||||||
do_load_config_schema(NameVsn, AvscPath),
|
do_load_config_schema(NameVsn, AvscPath),
|
||||||
_ = maybe_create_config_dir(NameVsn).
|
_ = maybe_create_config_dir(NameVsn, Mode).
|
||||||
|
|
||||||
do_load_config_schema(NameVsn, AvscPath) ->
|
do_load_config_schema(NameVsn, AvscPath) ->
|
||||||
case emqx_plugins_serde:add_schema(bin(NameVsn), AvscPath) of
|
case emqx_plugins_serde:add_schema(bin(NameVsn), AvscPath) of
|
||||||
|
@ -1198,11 +1223,11 @@ do_load_config_schema(NameVsn, AvscPath) ->
|
||||||
{error, _Reason} -> ok
|
{error, _Reason} -> ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
maybe_create_config_dir(NameVsn) ->
|
maybe_create_config_dir(NameVsn, Mode) ->
|
||||||
with_plugin_avsc(NameVsn) andalso
|
with_plugin_avsc(NameVsn) andalso
|
||||||
do_create_config_dir(NameVsn).
|
do_create_config_dir(NameVsn, Mode).
|
||||||
|
|
||||||
do_create_config_dir(NameVsn) ->
|
do_create_config_dir(NameVsn, Mode) ->
|
||||||
case plugin_config_dir(NameVsn) of
|
case plugin_config_dir(NameVsn) of
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
{error, {gen_config_dir_failed, Reason}};
|
{error, {gen_config_dir_failed, Reason}};
|
||||||
|
@ -1210,7 +1235,7 @@ do_create_config_dir(NameVsn) ->
|
||||||
case filelib:ensure_path(ConfigDir) of
|
case filelib:ensure_path(ConfigDir) of
|
||||||
ok ->
|
ok ->
|
||||||
%% get config from other nodes or get from tarball
|
%% get config from other nodes or get from tarball
|
||||||
_ = maybe_ensure_plugin_config(NameVsn),
|
_ = maybe_ensure_plugin_config(NameVsn, Mode),
|
||||||
ok;
|
ok;
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?SLOG(warning, #{
|
?SLOG(warning, #{
|
||||||
|
@ -1222,20 +1247,25 @@ do_create_config_dir(NameVsn) ->
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec maybe_ensure_plugin_config(name_vsn()) -> ok.
|
-spec maybe_ensure_plugin_config(name_vsn(), ?fresh_install | ?normal) -> ok.
|
||||||
maybe_ensure_plugin_config(NameVsn) ->
|
maybe_ensure_plugin_config(NameVsn, Mode) ->
|
||||||
maybe
|
maybe
|
||||||
true ?= with_plugin_avsc(NameVsn),
|
true ?= with_plugin_avsc(NameVsn),
|
||||||
_ = ensure_plugin_config(NameVsn)
|
_ = ensure_plugin_config({NameVsn, Mode})
|
||||||
else
|
else
|
||||||
_ -> ok
|
_ -> ok
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-spec ensure_plugin_config(name_vsn()) -> ok.
|
-spec ensure_plugin_config({name_vsn(), ?fresh_install | ?normal}) -> ok.
|
||||||
ensure_plugin_config(NameVsn) ->
|
ensure_plugin_config({NameVsn, ?normal}) ->
|
||||||
%% fetch plugin hocon config from cluster
|
ensure_plugin_config(NameVsn, [N || N <- mria:running_nodes(), N /= node()]);
|
||||||
Nodes = [N || N <- mria:running_nodes(), N /= node()],
|
ensure_plugin_config({NameVsn, ?fresh_install}) ->
|
||||||
ensure_plugin_config(NameVsn, Nodes).
|
?SLOG(debug, #{
|
||||||
|
msg => "default_plugin_config_used",
|
||||||
|
name_vsn => NameVsn,
|
||||||
|
hint => "fresh_install"
|
||||||
|
}),
|
||||||
|
cp_default_config_file(NameVsn).
|
||||||
|
|
||||||
-spec ensure_plugin_config(name_vsn(), list()) -> ok.
|
-spec ensure_plugin_config(name_vsn(), list()) -> ok.
|
||||||
ensure_plugin_config(NameVsn, []) ->
|
ensure_plugin_config(NameVsn, []) ->
|
||||||
|
@ -1255,8 +1285,6 @@ ensure_plugin_config(NameVsn, Nodes) ->
|
||||||
ensure_config_map(NameVsn);
|
ensure_config_map(NameVsn);
|
||||||
_ ->
|
_ ->
|
||||||
?SLOG(error, #{msg => "config_not_found_from_cluster", name_vsn => NameVsn}),
|
?SLOG(error, #{msg => "config_not_found_from_cluster", name_vsn => NameVsn}),
|
||||||
%% otherwise cp default hocon file
|
|
||||||
%% i.e. Clean installation
|
|
||||||
cp_default_config_file(NameVsn)
|
cp_default_config_file(NameVsn)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -1292,6 +1320,11 @@ ensure_config_map(NameVsn) ->
|
||||||
true ->
|
true ->
|
||||||
do_ensure_config_map(NameVsn, ConfigJsonMap);
|
do_ensure_config_map(NameVsn, ConfigJsonMap);
|
||||||
false ->
|
false ->
|
||||||
|
?SLOG(debug, #{
|
||||||
|
msg => "put_plugin_config_directly",
|
||||||
|
hint => "plugin_without_config_schema",
|
||||||
|
name_vsn => NameVsn
|
||||||
|
}),
|
||||||
put_config(NameVsn, ConfigJsonMap, ?plugin_without_config_schema)
|
put_config(NameVsn, ConfigJsonMap, ?plugin_without_config_schema)
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -1376,23 +1409,23 @@ prune_backup_files(Path) ->
|
||||||
Deletes
|
Deletes
|
||||||
).
|
).
|
||||||
|
|
||||||
read_file_fun(Path, ErrMsg, #{read_mode := ?RAW_BIN}) ->
|
read_file_fun(Path, Msg, #{read_mode := ?RAW_BIN}) ->
|
||||||
fun() ->
|
fun() ->
|
||||||
case file:read_file(Path) of
|
case file:read_file(Path) of
|
||||||
{ok, Bin} ->
|
{ok, Bin} ->
|
||||||
{ok, Bin};
|
{ok, Bin};
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
ErrMeta = #{error_msg => ErrMsg, reason => Reason},
|
ErrMeta = #{msg => Msg, reason => Reason},
|
||||||
throw(ErrMeta)
|
throw(ErrMeta)
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
read_file_fun(Path, ErrMsg, #{read_mode := ?JSON_MAP}) ->
|
read_file_fun(Path, Msg, #{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 = #{msg => Msg, reason => Reason},
|
||||||
throw(ErrMeta)
|
throw(ErrMeta)
|
||||||
end
|
end
|
||||||
end.
|
end.
|
||||||
|
|
|
@ -353,7 +353,7 @@ t_enable_disable(Config) ->
|
||||||
?assertEqual([#{name_vsn => NameVsn, enable => true}], emqx_plugins:configured()),
|
?assertEqual([#{name_vsn => NameVsn, enable => true}], emqx_plugins:configured()),
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
{error, #{
|
{error, #{
|
||||||
error_msg := "bad_plugin_config_status",
|
msg := "bad_plugin_config_status",
|
||||||
hint := "disable_the_plugin_first"
|
hint := "disable_the_plugin_first"
|
||||||
}},
|
}},
|
||||||
emqx_plugins:ensure_uninstalled(NameVsn)
|
emqx_plugins:ensure_uninstalled(NameVsn)
|
||||||
|
@ -381,7 +381,7 @@ t_bad_tar_gz(Config) ->
|
||||||
ok = file:write_file(FakeTarTz, "a\n"),
|
ok = file:write_file(FakeTarTz, "a\n"),
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
{error, #{
|
{error, #{
|
||||||
error_msg := "bad_plugin_package",
|
msg := "bad_plugin_package",
|
||||||
reason := eof
|
reason := eof
|
||||||
}},
|
}},
|
||||||
emqx_plugins:ensure_installed("fake-vsn")
|
emqx_plugins:ensure_installed("fake-vsn")
|
||||||
|
@ -389,8 +389,8 @@ t_bad_tar_gz(Config) ->
|
||||||
%% the plugin tarball can not be found on any nodes
|
%% the plugin tarball can not be found on any nodes
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
{error, #{
|
{error, #{
|
||||||
error_msg := "no_nodes_to_copy_plugin_from",
|
msg := "no_nodes_to_copy_plugin_from",
|
||||||
reason := not_found
|
reason := plugin_not_found
|
||||||
}},
|
}},
|
||||||
emqx_plugins:ensure_installed("nonexisting")
|
emqx_plugins:ensure_installed("nonexisting")
|
||||||
),
|
),
|
||||||
|
@ -463,7 +463,7 @@ t_bad_info_json(Config) ->
|
||||||
ok = write_info_file(Config, NameVsn, "bad-syntax"),
|
ok = write_info_file(Config, NameVsn, "bad-syntax"),
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
{error, #{
|
{error, #{
|
||||||
error_msg := "bad_info_file",
|
msg := "bad_info_file",
|
||||||
reason := {parse_error, _}
|
reason := {parse_error, _}
|
||||||
}},
|
}},
|
||||||
emqx_plugins:describe(NameVsn)
|
emqx_plugins:describe(NameVsn)
|
||||||
|
@ -471,7 +471,7 @@ t_bad_info_json(Config) ->
|
||||||
ok = write_info_file(Config, NameVsn, "{\"bad\": \"obj\"}"),
|
ok = write_info_file(Config, NameVsn, "{\"bad\": \"obj\"}"),
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
{error, #{
|
{error, #{
|
||||||
error_msg := "bad_info_file_content",
|
msg := "bad_info_file_content",
|
||||||
mandatory_fields := _
|
mandatory_fields := _
|
||||||
}},
|
}},
|
||||||
emqx_plugins:describe(NameVsn)
|
emqx_plugins:describe(NameVsn)
|
||||||
|
|
|
@ -57,7 +57,7 @@ read_plugin_test() ->
|
||||||
try
|
try
|
||||||
ok = write_file(InfoFile, FakeInfo),
|
ok = write_file(InfoFile, FakeInfo),
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
{error, #{error_msg := "bad_rel_apps"}},
|
{error, #{msg := "bad_rel_apps"}},
|
||||||
emqx_plugins:read_plugin_info(NameVsn, #{})
|
emqx_plugins:read_plugin_info(NameVsn, #{})
|
||||||
)
|
)
|
||||||
after
|
after
|
||||||
|
|
Loading…
Reference in New Issue