fix(relup): download to 4.4.0 failed with error bad_lib_vsn
This commit is contained in:
parent
bcd56d3db2
commit
a7791b6c58
|
@ -129,7 +129,7 @@ prod_overrides() ->
|
||||||
[{add, [ {erl_opts, [deterministic]}]}].
|
[{add, [ {erl_opts, [deterministic]}]}].
|
||||||
|
|
||||||
relup_deps(Profile, Vsn) ->
|
relup_deps(Profile, Vsn) ->
|
||||||
InjectCmd = "scripts/inject-relup.escript " ++ filename:join(["_build", Profile, "rel", "emqx", "releases", Vsn]),
|
InjectCmd = "scripts/inject-relup.escript " ++ filename:join(["_build", Profile, "rel", "emqx"]) ++ " " ++ Vsn,
|
||||||
{post_hooks,
|
{post_hooks,
|
||||||
[ {"(linux|darwin|solaris|freebsd|netbsd|openbsd)", relup, InjectCmd}
|
[ {"(linux|darwin|solaris|freebsd|netbsd|openbsd)", relup, InjectCmd}
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,80 +4,103 @@
|
||||||
|
|
||||||
-mode(compile).
|
-mode(compile).
|
||||||
|
|
||||||
-define(ERROR(FORMAT, ARGS), io:format(standard_error, "[inject-relup] " ++ FORMAT ++"~n", ARGS)).
|
-define(ERROR(FORMAT, ARGS), io:format(standard_error, "[inject-relup] " ++ FORMAT ++ "~n", ARGS)).
|
||||||
-define(INFO(FORMAT, ARGS), io:format(user, "[inject-relup] " ++ FORMAT ++"~n", ARGS)).
|
-define(INFO(FORMAT, ARGS), io:format(user, "[inject-relup] " ++ FORMAT ++ "~n", ARGS)).
|
||||||
|
|
||||||
usage() ->
|
usage() ->
|
||||||
"Usage: " ++ escript:script_name() ++ " <path-to-relup-file-or-dir>".
|
"Usage: " ++ escript:script_name() ++ " <path-to-release-dir> <release-vsn>".
|
||||||
|
|
||||||
main([DirOrFile]) ->
|
main([RelRootDir, CurrRelVsn]) ->
|
||||||
case filelib:is_dir(DirOrFile) of
|
case filelib:is_dir(filename:join([RelRootDir, "releases"])) andalso
|
||||||
true -> ok = inject_dir(DirOrFile);
|
filelib:is_dir(filename:join([RelRootDir, "lib"])) of
|
||||||
|
true ->
|
||||||
|
EmqxAppVsns = get_emqx_app_vsns(RelRootDir),
|
||||||
|
ok = inject_relup_file(RelRootDir, CurrRelVsn, EmqxAppVsns);
|
||||||
false ->
|
false ->
|
||||||
case filelib:is_regular(DirOrFile) of
|
?ERROR("not a valid root dir of release: ~p, for example: _build/emqx/rel/emqx",
|
||||||
true -> inject_file(DirOrFile);
|
[RelRootDir]),
|
||||||
false ->
|
|
||||||
?ERROR("not a valid file: ~p", [DirOrFile]),
|
|
||||||
erlang:halt(1)
|
erlang:halt(1)
|
||||||
end
|
|
||||||
end;
|
end;
|
||||||
main(_Args) ->
|
main(_Args) ->
|
||||||
?ERROR("~s", [usage()]),
|
?ERROR("~s", [usage()]),
|
||||||
erlang:halt(1).
|
erlang:halt(1).
|
||||||
|
|
||||||
inject_dir(Dir) ->
|
inject_relup_file(RelRootDir, CurrRelVsn, EmqxAppVsns) ->
|
||||||
RelupFiles = filelib:wildcard(filename:join([Dir, "**", "relup"])),
|
RelupFile = filename:join([RelRootDir, "releases", CurrRelVsn, "relup"]),
|
||||||
lists:foreach(fun inject_file/1, RelupFiles).
|
inject_file(RelupFile, EmqxAppVsns).
|
||||||
|
|
||||||
inject_file(File) ->
|
inject_file(File, EmqxAppVsns) ->
|
||||||
EmqxVsn = emqx_vsn_from_rel_file(File),
|
|
||||||
case file:script(File) of
|
case file:script(File) of
|
||||||
{ok, {CurrRelVsn, UpVsnRUs, DnVsnRUs}} ->
|
{ok, {CurrRelVsn, UpVsnRUs, DnVsnRUs}} ->
|
||||||
?INFO("injecting instructions to: ~p", [File]),
|
?INFO("injecting instructions to: ~p", [File]),
|
||||||
UpdatedContent = {CurrRelVsn, inject_relup_instrs(up, EmqxVsn, CurrRelVsn, UpVsnRUs),
|
UpdatedContent = {CurrRelVsn,
|
||||||
inject_relup_instrs(down, EmqxVsn, CurrRelVsn, DnVsnRUs)},
|
inject_relup_instrs(up, EmqxAppVsns, CurrRelVsn, UpVsnRUs),
|
||||||
ok = file:write_file(File, term_to_text(UpdatedContent));
|
inject_relup_instrs(down, EmqxAppVsns, CurrRelVsn, DnVsnRUs)},
|
||||||
|
file:write_file(File, term_to_text(UpdatedContent));
|
||||||
{ok, _BadFormat} ->
|
{ok, _BadFormat} ->
|
||||||
?ERROR("bad formatted relup file: ~p", [File]),
|
?ERROR("bad formatted relup file: ~p", [File]),
|
||||||
error({bad_relup_format, File});
|
error({bad_relup_format, File});
|
||||||
|
{error, enoent} ->
|
||||||
|
?INFO("relup file not found: ~p", [File]),
|
||||||
|
ok;
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
?ERROR("read relup file ~p failed: ~p", [File, Reason]),
|
?ERROR("read relup file ~p failed: ~p", [File, Reason]),
|
||||||
error({read_relup_error, Reason})
|
error({read_relup_error, Reason})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
inject_relup_instrs(Type, EmqxVsn, CurrRelVsn, RUs) ->
|
inject_relup_instrs(Type, EmqxAppVsns, CurrRelVsn, RUs) ->
|
||||||
[{Vsn, Desc, append_emqx_relup_instrs(Type, EmqxVsn, CurrRelVsn, Vsn, Instrs)}
|
lists:map(fun
|
||||||
|| {Vsn, Desc, Instrs} <- RUs].
|
({Vsn, "(relup-injected) " ++ _ = Desc, Instrs}) -> %% already injected
|
||||||
|
{Vsn, Desc, Instrs};
|
||||||
|
({Vsn, Desc, Instrs}) ->
|
||||||
|
{Vsn, "(relup-injected) " ++ Desc,
|
||||||
|
append_emqx_relup_instrs(Type, EmqxAppVsns, CurrRelVsn, Vsn, Instrs)}
|
||||||
|
end, RUs).
|
||||||
|
|
||||||
%% The `{apply, emqx_relup, post_release_upgrade, []}` will be appended to the end of
|
%% The `{apply, emqx_relup, post_release_upgrade, []}` will be appended to the end of
|
||||||
%% the instruction lists.
|
%% the instruction lists.
|
||||||
append_emqx_relup_instrs(Type, EmqxVsn, CurrRelVsn, Vsn, Instrs) ->
|
append_emqx_relup_instrs(up, EmqxAppVsns, CurrRelVsn, FromRelVsn, Instrs) ->
|
||||||
CallbackFun = relup_callback_func(Type),
|
{EmqxVsn, true} = maps:get(CurrRelVsn, EmqxAppVsns),
|
||||||
Extra = #{}, %% we may need some extended args
|
Extra = #{}, %% we may need some extended args
|
||||||
case lists:reverse(Instrs) of
|
|
||||||
[{apply, {emqx_relup, CallbackFun, _}} | _] ->
|
|
||||||
Instrs;
|
|
||||||
RInstrs ->
|
|
||||||
Instrs2 = lists:reverse(
|
|
||||||
[ {apply, {emqx_relup, CallbackFun, [CurrRelVsn, Vsn, Extra]}}
|
|
||||||
, {load, {emqx_relup, brutal_purge, soft_purge}}
|
|
||||||
| RInstrs]),
|
|
||||||
%% we have to put 'load_object_code' before 'point_of_no_return'
|
%% we have to put 'load_object_code' before 'point_of_no_return'
|
||||||
%% so here we simply put it to the beginning
|
%% so here we simply put it to the beginning
|
||||||
[{load_object_code, {emqx, EmqxVsn, [emqx_relup]}} | Instrs2]
|
Instrs0 = [ {load_object_code, {emqx, EmqxVsn, [emqx_relup]}}
|
||||||
|
| Instrs],
|
||||||
|
Instrs0 ++
|
||||||
|
[ {load, {emqx_relup, brutal_purge, soft_purge}}
|
||||||
|
, {apply, {emqx_relup, post_release_upgrade, [FromRelVsn, Extra]}}
|
||||||
|
];
|
||||||
|
|
||||||
|
append_emqx_relup_instrs(down, EmqxAppVsns, _CurrRelVsn, ToRelVsn, Instrs) ->
|
||||||
|
Extra = #{}, %% we may need some extended args
|
||||||
|
case maps:get(ToRelVsn, EmqxAppVsns) of
|
||||||
|
{EmqxVsn, true} ->
|
||||||
|
Instrs0 = [ {load_object_code, {emqx, EmqxVsn, [emqx_relup]}}
|
||||||
|
| Instrs],
|
||||||
|
Instrs0 ++
|
||||||
|
[ {apply, {emqx_relup, post_release_downgrade, [ToRelVsn, Extra]}}
|
||||||
|
, {load, {emqx_relup, brutal_purge, soft_purge}}
|
||||||
|
];
|
||||||
|
{_EmqxVsn, false} ->
|
||||||
|
Instrs ++
|
||||||
|
[ {apply, {emqx_relup, post_release_downgrade, [ToRelVsn, Extra]}}
|
||||||
|
, {remove, {emqx_relup, brutal_purge, soft_purge}}
|
||||||
|
]
|
||||||
end.
|
end.
|
||||||
|
|
||||||
relup_callback_func(up) -> post_release_upgrade;
|
get_emqx_app_vsns(RelRootDir) ->
|
||||||
relup_callback_func(down) -> post_release_downgrade.
|
RelFiles = filelib:wildcard(filename:join([RelRootDir, "releases", "*", "emqx.rel"])),
|
||||||
|
lists:foldl(fun(RelFile, AppVsns) ->
|
||||||
|
{ok, RelVsn, EmqxVsn} = read_emqx_vsn_from_rel_file(RelFile),
|
||||||
|
AppVsns#{RelVsn => {EmqxVsn, has_relup_module(RelRootDir, EmqxVsn)}}
|
||||||
|
end, #{}, RelFiles).
|
||||||
|
|
||||||
emqx_vsn_from_rel_file(RelupFile) ->
|
read_emqx_vsn_from_rel_file(RelFile) ->
|
||||||
RelDir = filename:dirname(RelupFile),
|
|
||||||
RelFile = filename:join([RelDir, "emqx.rel"]),
|
|
||||||
case file:script(RelFile) of
|
case file:script(RelFile) of
|
||||||
{ok, {release, {_RelName, _RelVsn}, _Erts, Apps}} ->
|
{ok, {release, {_RelName, RelVsn}, _Erts, Apps}} ->
|
||||||
case lists:keysearch(emqx, 1, Apps) of
|
case lists:keysearch(emqx, 1, Apps) of
|
||||||
{value, {emqx, EmqxVsn}} ->
|
{value, {emqx, EmqxVsn}} ->
|
||||||
EmqxVsn;
|
{ok, RelVsn, EmqxVsn};
|
||||||
false ->
|
false ->
|
||||||
error({emqx_vsn_cannot_found, RelFile})
|
error({emqx_vsn_cannot_found, RelFile})
|
||||||
end;
|
end;
|
||||||
|
@ -87,5 +110,17 @@ emqx_vsn_from_rel_file(RelupFile) ->
|
||||||
?ERROR("read .rel file ~p failed: ~p", [RelFile, Reason])
|
?ERROR("read .rel file ~p failed: ~p", [RelFile, Reason])
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
has_relup_module(RelRootDir, EmqxVsn) ->
|
||||||
|
AppFile = filename:join([RelRootDir, "lib", "emqx-" ++ EmqxVsn, "ebin", "emqx.app"]),
|
||||||
|
case file:script(AppFile) of
|
||||||
|
{ok, {application, emqx, AppInfo}} ->
|
||||||
|
{value, {_, EmqxVsn}} = lists:keysearch(vsn, 1, AppInfo), %% assert
|
||||||
|
{value, {_, Modules}} = lists:keysearch(modules, 1, AppInfo),
|
||||||
|
lists:member(emqx_relup, Modules);
|
||||||
|
{error, Reason} ->
|
||||||
|
?ERROR("read .app file ~p failed: ~p", [AppFile, Reason]),
|
||||||
|
error({read_app_file_error, AppFile, Reason})
|
||||||
|
end.
|
||||||
|
|
||||||
term_to_text(Term) ->
|
term_to_text(Term) ->
|
||||||
io_lib:format("~p.", [Term]).
|
io_lib:format("~p.", [Term]).
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
-module(emqx_relup).
|
-module(emqx_relup).
|
||||||
|
|
||||||
-export([ post_release_upgrade/3
|
-export([ post_release_upgrade/2
|
||||||
, post_release_downgrade/3
|
, post_release_downgrade/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
post_release_upgrade(_CurrRelVsn, _FromVsn, _) ->
|
%% what to do after upgraded from a old release vsn.
|
||||||
|
post_release_upgrade(_FromRelVsn, _) ->
|
||||||
reload_components().
|
reload_components().
|
||||||
|
|
||||||
post_release_downgrade(_CurrRelVsn, _ToVsn, _) ->
|
%% what to do after downgraded to a old release vsn.
|
||||||
|
post_release_downgrade(_ToRelVsn, _) ->
|
||||||
reload_components().
|
reload_components().
|
||||||
|
|
||||||
-ifdef(EMQX_ENTERPRISE).
|
-ifdef(EMQX_ENTERPRISE).
|
||||||
|
|
Loading…
Reference in New Issue