fix: porting emqx_relup.erl from 4.4
This commit is contained in:
parent
40ad23ee74
commit
3d7cab4288
|
@ -0,0 +1,42 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2017-2022 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqx_relup).
|
||||
|
||||
%% NOTE: DO NOT remove this `-include`.
|
||||
%% We use this to force this module to be upgraded every release.
|
||||
-include("emqx_release.hrl").
|
||||
|
||||
-export([
|
||||
post_release_upgrade/2,
|
||||
post_release_downgrade/2
|
||||
]).
|
||||
|
||||
-define(INFO(FORMAT), io:format("[emqx_relup] " ++ FORMAT ++ "~n")).
|
||||
-define(INFO(FORMAT, ARGS), io:format("[emqx_relup] " ++ FORMAT ++ "~n", ARGS)).
|
||||
|
||||
%% What to do after upgraded from an old release vsn.
|
||||
post_release_upgrade(FromRelVsn, _) ->
|
||||
?INFO("emqx has been upgraded from ~s to ~s!", [FromRelVsn, emqx_release:version()]),
|
||||
reload_components().
|
||||
|
||||
%% What to do after downgraded to an old release vsn.
|
||||
post_release_downgrade(ToRelVsn, _) ->
|
||||
?INFO("emqx has been downgraded from ~s to ~s!", [emqx_release:version(), ToRelVsn]),
|
||||
reload_components().
|
||||
|
||||
reload_components() ->
|
||||
ok.
|
8
build
8
build
|
@ -175,18 +175,20 @@ make_tgz() {
|
|||
target="${pkgpath}/${target_name}"
|
||||
|
||||
src_tarball="${relpath}/emqx-${PKG_VSN}.tar.gz"
|
||||
tard="tmp/emqx_untar_${PKG_VSN}"
|
||||
rm -rf "${tard}"
|
||||
tard="$(mktemp -d -t emqx.XXXXXXX)"
|
||||
mkdir -p "${tard}/emqx"
|
||||
mkdir -p "${pkgpath}"
|
||||
if [ ! -f "$src_tarball" ]; then
|
||||
log "ERROR: $src_tarball is not found"
|
||||
fi
|
||||
tar zxf "${src_tarball}" -C "${tard}/emqx"
|
||||
if [ -f "${tard}/emqx/releases/${PKG_VSN}/relup" ]; then
|
||||
./scripts/inject-relup.escript "${tard}/emqx/releases/${PKG_VSN}/relup"
|
||||
fi
|
||||
## try to be portable for tar.gz packages.
|
||||
## for DEB and RPM packages the dependencies are resoved by yum and apt
|
||||
cp_dyn_libs "${tard}/emqx"
|
||||
## create tar after change dir (for windows)
|
||||
## create tar after change dir
|
||||
## to avoid creating an extra level of 'emqx' dir in the .tar.gz file
|
||||
pushd "${tard}/emqx" >/dev/null
|
||||
tar -zcf "../${target_name}" -- *
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
#!/usr/bin/env escript
|
||||
|
||||
%% This script injects implicit relup instructions for emqx applications.
|
||||
|
||||
-mode(compile).
|
||||
|
||||
-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)).
|
||||
|
||||
usage() ->
|
||||
"Usage: " ++ escript:script_name() ++ " <path-to-relup-file>".
|
||||
|
||||
main([RelupFile]) ->
|
||||
ok = inject_relup_file(RelupFile);
|
||||
main(_Args) ->
|
||||
?ERROR("~s", [usage()]),
|
||||
erlang:halt(1).
|
||||
|
||||
inject_relup_file(File) ->
|
||||
case file:script(File) of
|
||||
{ok, {CurrRelVsn, UpVsnRUs, DnVsnRUs}} ->
|
||||
?INFO("Injecting instructions to: ~p", [File]),
|
||||
UpdatedContent = {CurrRelVsn,
|
||||
inject_relup_instrs(up, UpVsnRUs),
|
||||
inject_relup_instrs(down, DnVsnRUs)},
|
||||
file:write_file(File, term_to_text(UpdatedContent));
|
||||
{ok, _BadFormat} ->
|
||||
?ERROR("Bad formatted relup file: ~p", [File]),
|
||||
error({bad_relup_format, File});
|
||||
{error, enoent} ->
|
||||
?INFO("Cannot find relup file: ~p", [File]),
|
||||
ok;
|
||||
{error, Reason} ->
|
||||
?ERROR("Read relup file ~p failed: ~p", [File, Reason]),
|
||||
error({read_relup_error, Reason})
|
||||
end.
|
||||
|
||||
inject_relup_instrs(Type, RUs) ->
|
||||
lists:map(fun({Vsn, Desc, Instrs}) ->
|
||||
{Vsn, Desc, append_emqx_relup_instrs(Type, Vsn, Instrs)}
|
||||
end, RUs).
|
||||
|
||||
append_emqx_relup_instrs(up, FromRelVsn, Instrs0) ->
|
||||
{{UpExtra, _}, Instrs1} = filter_and_check_instrs(up, Instrs0),
|
||||
Instrs1 ++
|
||||
[ {load, {emqx_release, brutal_purge, soft_purge}}
|
||||
, {load, {emqx_relup, brutal_purge, soft_purge}}
|
||||
, {apply, {emqx_relup, post_release_upgrade, [FromRelVsn, UpExtra]}}
|
||||
];
|
||||
|
||||
append_emqx_relup_instrs(down, ToRelVsn, Instrs0) ->
|
||||
{{_, DnExtra}, Instrs1} = filter_and_check_instrs(down, Instrs0),
|
||||
%% NOTE: When downgrading, we apply emqx_relup:post_release_downgrade/2 before reloading
|
||||
%% or removing the emqx_relup module.
|
||||
Instrs2 = Instrs1 ++
|
||||
[ {load, {emqx_release, brutal_purge, soft_purge}}
|
||||
, {apply, {emqx_relup, post_release_downgrade, [ToRelVsn, DnExtra]}}
|
||||
, {load, {emqx_relup, brutal_purge, soft_purge}}
|
||||
],
|
||||
Instrs2.
|
||||
|
||||
filter_and_check_instrs(Type, Instrs) ->
|
||||
case filter_fetch_emqx_mods_and_extra(Instrs) of
|
||||
{_, DnExtra, _, _} when Type =:= up, DnExtra =/= undefined ->
|
||||
?ERROR("Got '{apply,{emqx_relup,post_release_downgrade,[_,Extra]}}'"
|
||||
" from the upgrade instruction list, should be 'post_release_upgrade'", []),
|
||||
error({instruction_not_found, load_object_code});
|
||||
{UpExtra, _, _, _} when Type =:= down, UpExtra =/= undefined ->
|
||||
?ERROR("Got '{apply,{emqx_relup,post_release_upgrade,[_,Extra]}}'"
|
||||
" from the downgrade instruction list, should be 'post_release_downgrade'", []),
|
||||
error({instruction_not_found, load_object_code});
|
||||
{_, _, [], _} ->
|
||||
?ERROR("Cannot find any 'load_object_code' instructions for app emqx", []),
|
||||
error({instruction_not_found, load_object_code});
|
||||
{UpExtra, DnExtra, EmqxMods, RemainInstrs} ->
|
||||
assert_mandatory_modules(Type, EmqxMods),
|
||||
{{UpExtra, DnExtra}, RemainInstrs}
|
||||
end.
|
||||
|
||||
filter_fetch_emqx_mods_and_extra(Instrs) ->
|
||||
lists:foldl(fun do_filter_and_get/2, {undefined, undefined, [], []}, Instrs).
|
||||
|
||||
%% collect modules for emqx app
|
||||
do_filter_and_get({load_object_code, {emqx, _AppVsn, Mods}} = Instr,
|
||||
{UpExtra, DnExtra, EmqxMods, RemainInstrs}) ->
|
||||
{UpExtra, DnExtra, EmqxMods ++ Mods, RemainInstrs ++ [Instr]};
|
||||
%% remove 'load' instrs for emqx_relup and emqx_release
|
||||
do_filter_and_get({load, {Mod, _, _}}, {UpExtra, DnExtra, EmqxMods, RemainInstrs})
|
||||
when Mod =:= emqx_relup; Mod =:= emqx_release ->
|
||||
{UpExtra, DnExtra, EmqxMods, RemainInstrs};
|
||||
%% remove 'remove' and 'purge' instrs for emqx_relup
|
||||
do_filter_and_get({remove, {emqx_relup, _, _}}, {UpExtra, DnExtra, EmqxMods, RemainInstrs}) ->
|
||||
{UpExtra, DnExtra, EmqxMods, RemainInstrs};
|
||||
do_filter_and_get({purge, [emqx_relup]}, {UpExtra, DnExtra, EmqxMods, RemainInstrs}) ->
|
||||
{UpExtra, DnExtra, EmqxMods, RemainInstrs};
|
||||
%% remove 'apply' instrs for upgrade, and collect the 'Extra' parameter
|
||||
do_filter_and_get({apply, {emqx_relup, post_release_upgrade, [_, UpExtra0]}},
|
||||
{_, DnExtra, EmqxMods, RemainInstrs}) ->
|
||||
{UpExtra0, DnExtra, EmqxMods, RemainInstrs};
|
||||
%% remove 'apply' instrs for downgrade, and collect the 'Extra' parameter
|
||||
do_filter_and_get({apply, {emqx_relup, post_release_downgrade, [_, DnExtra0]}},
|
||||
{UpExtra, _, EmqxMods, RemainInstrs}) ->
|
||||
{UpExtra, DnExtra0, EmqxMods, RemainInstrs};
|
||||
%% keep all other instrs unchanged
|
||||
do_filter_and_get(Instr, {UpExtra, DnExtra, EmqxMods, RemainInstrs}) ->
|
||||
{UpExtra, DnExtra, EmqxMods, RemainInstrs ++ [Instr]}.
|
||||
|
||||
assert_mandatory_modules(_, Mods) ->
|
||||
MandInstrs = [{load_module,emqx_release,brutal_purge,soft_purge,[]},
|
||||
{load_module,emqx_relup}],
|
||||
assert(lists:member(emqx_relup, Mods) andalso lists:member(emqx_release, Mods),
|
||||
"The following instructions are mandatory in every clause of the emqx.appup.src: ~p", [MandInstrs]).
|
||||
|
||||
assert(true, _, _) ->
|
||||
ok;
|
||||
assert(false, Msg, Args) ->
|
||||
?ERROR(Msg, Args),
|
||||
error(assert_failed).
|
||||
|
||||
term_to_text(Term) ->
|
||||
io_lib:format("~p.", [Term]).
|
Loading…
Reference in New Issue