Merge pull request #8034 from emqx/update_relup_script
fix: porting the install_upgrade.escript from v4.4
This commit is contained in:
commit
ea09ad6403
|
@ -22,7 +22,8 @@
|
|||
|
||||
[shell emqx]
|
||||
!cd $PACKAGE_PATH
|
||||
!tar -zxf ${PROFILE}-$(echo $old_vsn | sed -r 's/[v|e]//g')-*-ubuntu20.04-amd64.tar.gz
|
||||
mkdir -p emqx
|
||||
!tar -C emqx -zxf ${PROFILE}-$(echo $old_vsn | sed -r 's/[v|e]//g')-*-ubuntu20.04-amd64.tar.gz
|
||||
?SH-PROMPT
|
||||
|
||||
!cd emqx
|
||||
|
|
|
@ -179,7 +179,8 @@ jobs:
|
|||
working-directory: source
|
||||
run: |
|
||||
pkg_name=$(find _packages/${{ matrix.profile }} -mindepth 1 -maxdepth 1 -iname \*.tar.gz)
|
||||
tar -zxf $pkg_name
|
||||
mkdir -p emqx
|
||||
tar -C emqx -zxf $pkg_name
|
||||
# gsed -i '/emqx_telemetry/d' ./emqx/data/loaded_plugins
|
||||
./emqx/bin/emqx start || cat emqx/log/erlang.log.1
|
||||
ready='no'
|
||||
|
|
|
@ -197,7 +197,8 @@ jobs:
|
|||
- name: test
|
||||
run: |
|
||||
pkg_name=$(find _packages/${{ matrix.profile }} -mindepth 1 -maxdepth 1 -iname \*.tar.gz)
|
||||
tar -zxf $pkg_name
|
||||
mkdir -p emqx
|
||||
tar -C emqx -zxf $pkg_name
|
||||
# gsed -i '/emqx_telemetry/d' ./emqx/data/loaded_plugins
|
||||
./emqx/bin/emqx start || cat emqx/log/erlang.log.1
|
||||
ready='no'
|
||||
|
|
|
@ -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.
|
|
@ -4,7 +4,11 @@
|
|||
%% ex: ft=erlang ts=4 sw=4 et
|
||||
|
||||
-define(TIMEOUT, 300000).
|
||||
-define(INFO(Fmt,Args), io:format(Fmt++"~n",Args)).
|
||||
-define(INFO(Fmt,Args), io:format(standard_io, Fmt++"~n",Args)).
|
||||
-define(ERROR(Fmt,Args), io:format(standard_error, "ERROR: "++Fmt++"~n",Args)).
|
||||
-define(SEMVER_RE, <<"^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(-[a-zA-Z\\d][-a-zA-Z.\\d]*)?(\\+[a-zA-Z\\d][-a-zA-Z.\\d]*)?$">>).
|
||||
|
||||
-mode(compile).
|
||||
|
||||
main([Command0, DistInfoStr | CommandArgs]) ->
|
||||
%% convert the distribution info arguments string to an erlang term
|
||||
|
@ -52,6 +56,7 @@ unpack(_, Args) ->
|
|||
install({RelName, NameTypeArg, NodeName, Cookie}, Opts) ->
|
||||
TargetNode = start_distribution(NodeName, NameTypeArg, Cookie),
|
||||
Version = proplists:get_value(version, Opts),
|
||||
validate_target_version(Version, TargetNode),
|
||||
case unpack_release(RelName, TargetNode, Version) of
|
||||
{ok, Vsn} ->
|
||||
?INFO("Unpacked successfully: ~p.", [Vsn]),
|
||||
|
@ -142,9 +147,10 @@ parse_arguments([VersionStr|Rest], Acc) ->
|
|||
parse_arguments(Rest, [{version, Version}] ++ Acc).
|
||||
|
||||
unpack_release(RelName, TargetNode, Version) ->
|
||||
StartScriptExists = filelib:is_dir(filename:join(["releases", Version, "start.boot"])),
|
||||
WhichReleases = which_releases(TargetNode),
|
||||
case proplists:get_value(Version, WhichReleases) of
|
||||
undefined ->
|
||||
Res when Res =:= undefined; (Res =:= unpacked andalso not StartScriptExists) ->
|
||||
%% not installed, so unpack tarball:
|
||||
%% look for a release package with the intended version in the following order:
|
||||
%% releases/<relname>-<version>.tar.gz
|
||||
|
@ -159,16 +165,43 @@ unpack_release(RelName, TargetNode, Version) ->
|
|||
case rpc:call(TargetNode, release_handler, unpack_release,
|
||||
[ReleasePackageLink], ?TIMEOUT) of
|
||||
{ok, Vsn} -> {ok, Vsn};
|
||||
{error, {existing_release, Vsn}} ->
|
||||
%% sometimes the user may have removed the release/<vsn> dir
|
||||
%% for an `unpacked` release, then we need to re-unpack it from
|
||||
%% the .tar ball
|
||||
untar_for_unpacked_release(str(RelName), Vsn),
|
||||
{ok, Vsn};
|
||||
{error, _} = Error -> Error
|
||||
end
|
||||
end;
|
||||
Other -> Other
|
||||
Other ->
|
||||
Other
|
||||
end.
|
||||
|
||||
%% 1. look for a release package tarball with the provided version in the following order:
|
||||
%% releases/<relname>-<version>.tar.gz
|
||||
%% releases/<version>/<relname>-<version>.tar.gz
|
||||
%% releases/<version>/<relname>.tar.gz
|
||||
untar_for_unpacked_release(RelName, Vsn) ->
|
||||
{ok, Root} = file:get_cwd(),
|
||||
RelDir = filename:join([Root, "releases"]),
|
||||
%% untar the .tar file, so release/<vsn> will be created
|
||||
Tar = filename:join([RelDir, Vsn, RelName ++ ".tar.gz"]),
|
||||
extract_tar(Root, Tar),
|
||||
|
||||
%% create RELEASE file
|
||||
RelFile = filename:join([RelDir, Vsn, RelName ++ ".rel"]),
|
||||
release_handler:create_RELEASES(Root, RelFile),
|
||||
|
||||
%% Clean release
|
||||
_ = file:delete(Tar),
|
||||
_ = file:delete(RelFile).
|
||||
|
||||
extract_tar(Cwd, Tar) ->
|
||||
case erl_tar:extract(Tar, [keep_old_files, {cwd, Cwd}, compressed]) of
|
||||
ok -> ok;
|
||||
{error, {Name, Reason}} -> % New erl_tar (R3A).
|
||||
throw({error, {cannot_extract_file, Name, Reason}})
|
||||
end.
|
||||
|
||||
%% 1. look for a release package tarball with the provided version:
|
||||
%% releases/<relname>-*<version>*.tar.gz
|
||||
%% 2. create a symlink from a fixed location (ie. releases/<version>/<relname>.tar.gz)
|
||||
%% to the release package tarball found in 1.
|
||||
%% 3. return a tuple with the paths to the release package and
|
||||
|
@ -184,47 +217,38 @@ find_and_link_release_package(Version, RelName) ->
|
|||
%% we've found where the actual release package is located
|
||||
ReleaseLink = filename:join(["releases", Version,
|
||||
RelNameStr ++ ".tar.gz"]),
|
||||
TarBalls = [
|
||||
filename:join(["releases",
|
||||
RelNameStr ++ "-" ++ Version ++ ".tar.gz"]),
|
||||
filename:join(["releases", Version,
|
||||
RelNameStr ++ "-" ++ Version ++ ".tar.gz"]),
|
||||
filename:join(["releases", Version,
|
||||
RelNameStr ++ ".tar.gz"])
|
||||
],
|
||||
case first_value(fun filelib:is_file/1, TarBalls) of
|
||||
no_value ->
|
||||
TarBalls = filename:join(["releases", RelNameStr ++ "-*" ++ Version ++ "*.tar.gz"]),
|
||||
case filelib:wildcard(TarBalls) of
|
||||
[] ->
|
||||
{undefined, undefined};
|
||||
%% no need to create the link since the release package we
|
||||
%% found is located in the same place as the link would be
|
||||
{ok, Filename} when is_list(Filename) andalso
|
||||
Filename =:= ReleaseLink ->
|
||||
{Filename, ReleaseHandlerPackageLink};
|
||||
{ok, Filename} when is_list(Filename) ->
|
||||
%% we now have the location of the release package, however
|
||||
%% release handler expects a fixed nomenclature (<relname>.tar.gz)
|
||||
[Filename] when is_list(Filename) ->
|
||||
%% the release handler expects a fixed nomenclature (<relname>.tar.gz)
|
||||
%% so give it just that by creating a symlink to the tarball
|
||||
%% we found.
|
||||
%% make sure that the dir where we're creating the link in exists
|
||||
ok = filelib:ensure_dir(filename:join([filename:dirname(ReleaseLink), "dummy"])),
|
||||
%% create the symlink pointing to the full path name of the
|
||||
%% release package we found
|
||||
case file:make_symlink(filename:absname(Filename), ReleaseLink) of
|
||||
ok ->
|
||||
ok;
|
||||
{error, eperm} -> % windows!
|
||||
{ok,_} = file:copy(filename:absname(Filename), ReleaseLink)
|
||||
end,
|
||||
{Filename, ReleaseHandlerPackageLink}
|
||||
make_symlink_or_copy(filename:absname(Filename), ReleaseLink),
|
||||
{Filename, ReleaseHandlerPackageLink};
|
||||
Files ->
|
||||
?ERROR("Found more than one package for version: '~s', "
|
||||
"files: ~p", [Version, Files]),
|
||||
erlang:halt(47)
|
||||
end.
|
||||
|
||||
first_value(_Fun, []) -> no_value;
|
||||
first_value(Fun, [Value | Rest]) ->
|
||||
case Fun(Value) of
|
||||
false ->
|
||||
first_value(Fun, Rest);
|
||||
true ->
|
||||
{ok, Value}
|
||||
make_symlink_or_copy(Filename, ReleaseLink) ->
|
||||
case file:make_symlink(Filename, ReleaseLink) of
|
||||
ok -> ok;
|
||||
{error, eexist} ->
|
||||
?INFO("Symlink ~p already exists, recreate it", [ReleaseLink]),
|
||||
ok = file:delete(ReleaseLink),
|
||||
make_symlink_or_copy(Filename, ReleaseLink);
|
||||
{error, Reason} when Reason =:= eperm; Reason =:= enotsup ->
|
||||
{ok, _} = file:copy(Filename, ReleaseLink);
|
||||
{error, Reason} ->
|
||||
?ERROR("Create symlink ~p failed, error: ~p", [ReleaseLink, Reason]),
|
||||
erlang:halt(47)
|
||||
end.
|
||||
|
||||
parse_version(V) when is_list(V) ->
|
||||
|
@ -246,7 +270,7 @@ check_and_install(TargetNode, Vsn) ->
|
|||
{ok, _OtherVsn, _Desc} ->
|
||||
ok;
|
||||
{error, Reason} ->
|
||||
?INFO("ERROR: release_handler:check_install_release failed: ~p.",[Reason]),
|
||||
?ERROR("Call release_handler:check_install_release failed: ~p.", [Reason]),
|
||||
erlang:halt(3)
|
||||
end,
|
||||
case rpc:call(TargetNode, release_handler, install_release,
|
||||
|
@ -259,18 +283,18 @@ check_and_install(TargetNode, Vsn) ->
|
|||
iolist_to_binary(
|
||||
[io_lib:format("* ~s\t~s~n",[V,S]) || {V,S} <- which_releases(TargetNode)]),
|
||||
?INFO("Installed versions:~n~s", [VerList]),
|
||||
?INFO("ERROR: Unable to revert to '~s' - not installed.", [Vsn]),
|
||||
?ERROR("Unable to revert to '~s' - not installed.", [Vsn]),
|
||||
erlang:halt(2);
|
||||
%% as described in http://erlang.org/doc/man/appup.html, when performing a relup
|
||||
%% with soft purge:
|
||||
%% If the value is soft_purge, release_handler:install_release/1
|
||||
%% returns {error,{old_processes,Mod}}
|
||||
{error, {old_processes, Mod}} ->
|
||||
?INFO("ERROR: unable to install '~s' - old processes still running code from module ~p",
|
||||
?ERROR("Unable to install '~s' - old processes still running code from module ~p",
|
||||
[Vsn, Mod]),
|
||||
erlang:halt(3);
|
||||
{error, Reason1} ->
|
||||
?INFO("ERROR: release_handler:install_release failed: ~p",[Reason1]),
|
||||
?ERROR("Call release_handler:install_release failed: ~p",[Reason1]),
|
||||
erlang:halt(4)
|
||||
end.
|
||||
|
||||
|
@ -287,8 +311,7 @@ permafy(TargetNode, RelName, Vsn) ->
|
|||
make_permanent, [Vsn], ?TIMEOUT),
|
||||
?INFO("Made release permanent: ~p", [Vsn]),
|
||||
%% upgrade/downgrade the scripts by replacing them
|
||||
Scripts = [RelNameStr, RelNameStr ++ "_ctl",
|
||||
"nodetool", "install_upgrade.escript"],
|
||||
Scripts = [RelNameStr, RelNameStr++"_ctl", "nodetool", "install_upgrade.escript"],
|
||||
[{ok, _} = file:copy(filename:join(["bin", File++"-"++Vsn]),
|
||||
filename:join(["bin", File]))
|
||||
|| File <- Scripts],
|
||||
|
@ -302,7 +325,7 @@ remove_release(TargetNode, Vsn) ->
|
|||
?INFO("Uninstalled Release: ~s", [Vsn]),
|
||||
ok;
|
||||
{error, Reason} ->
|
||||
?INFO("ERROR: release_handler:remove_release failed: ~p", [Reason]),
|
||||
?ERROR("Call release_handler:remove_release failed: ~p", [Reason]),
|
||||
erlang:halt(3)
|
||||
end.
|
||||
|
||||
|
@ -330,8 +353,7 @@ start_distribution(TargetNode, NameTypeArg, Cookie) ->
|
|||
MyNode = make_script_node(TargetNode),
|
||||
{ok, _Pid} = net_kernel:start([MyNode, get_name_type(NameTypeArg)]),
|
||||
erlang:set_cookie(node(), Cookie),
|
||||
case {net_kernel:connect_node(TargetNode),
|
||||
net_adm:ping(TargetNode)} of
|
||||
case {net_kernel:hidden_connect_node(TargetNode), net_adm:ping(TargetNode)} of
|
||||
{true, pong} ->
|
||||
ok;
|
||||
{_, pang} ->
|
||||
|
@ -344,7 +366,7 @@ start_distribution(TargetNode, NameTypeArg, Cookie) ->
|
|||
|
||||
make_script_node(Node) ->
|
||||
[Name, Host] = string:tokens(atom_to_list(Node), "@"),
|
||||
list_to_atom(lists:concat(["remsh_" ++ Name, "_upgrader_", os:getpid(), "@", Host])).
|
||||
list_to_atom(lists:concat(["remsh_", Name, "_upgrader_", os:getpid(), "@", Host])).
|
||||
|
||||
%% get name type from arg
|
||||
get_name_type(NameTypeArg) ->
|
||||
|
@ -359,3 +381,35 @@ erts_vsn() ->
|
|||
{ok, Str} = file:read_file(filename:join(["releases", "start_erl.data"])),
|
||||
[ErtsVsn, _] = string:tokens(binary_to_list(Str), " "),
|
||||
ErtsVsn.
|
||||
|
||||
validate_target_version(TargetVersion, TargetNode) ->
|
||||
CurrentVersion = current_release_version(TargetNode),
|
||||
case {get_major_minor_vsn(CurrentVersion), get_major_minor_vsn(TargetVersion)} of
|
||||
{{Major, Minor}, {Major, Minor}} -> ok;
|
||||
_ ->
|
||||
?ERROR("Cannot upgrade/downgrade from '~s' to '~s'~n"
|
||||
"Hot upgrade is only supported between patch releases.",
|
||||
[CurrentVersion, TargetVersion]),
|
||||
erlang:halt(48)
|
||||
end.
|
||||
|
||||
get_major_minor_vsn(Version) ->
|
||||
Parts = parse_semver(Version),
|
||||
[Major | Rem0] = Parts,
|
||||
[Minor | _Rem1] = Rem0,
|
||||
{Major, Minor}.
|
||||
|
||||
parse_semver(Version) ->
|
||||
case re:run(Version, ?SEMVER_RE, [{capture, all_but_first, binary}]) of
|
||||
{match, Parts} -> Parts;
|
||||
nomatch ->
|
||||
?ERROR("Invalid semantic version: '~s'~n", [Version]),
|
||||
erlang:halt(22)
|
||||
end.
|
||||
|
||||
str(A) when is_atom(A) ->
|
||||
atom_to_list(A);
|
||||
str(A) when is_binary(A) ->
|
||||
binary_to_list(A);
|
||||
str(A) when is_list(A) ->
|
||||
(A).
|
||||
|
|
27
build
27
build
|
@ -108,15 +108,19 @@ make_elixir_rel() {
|
|||
## extract previous version .tar.gz files to _build/$PROFILE/rel/emqx before making relup
|
||||
make_relup() {
|
||||
local rel_dir="_build/$PROFILE/rel/emqx"
|
||||
mkdir -p "${rel_dir}/lib"
|
||||
mkdir -p "${rel_dir}/releases"
|
||||
local name_pattern
|
||||
name_pattern="${PROFILE}-$(./pkg-vsn.sh "$PROFILE" --vsn_matcher)"
|
||||
name_pattern="${PROFILE}-$(./pkg-vsn.sh "$PROFILE" --vsn_matcher --long)"
|
||||
local releases=()
|
||||
while read -r tgzfile ; do
|
||||
local base_vsn
|
||||
base_vsn="$(echo "$tgzfile" | grep -oE "[0-9]+\.[0-9]+\.[0-9]+(-(alpha|beta)\.[0-9])?(-[0-9a-f]{8})?" | head -1)"
|
||||
tar -C "$rel_dir" -zxf ---keep-old-files "$tgzfile" emqx/releases emqx/lib
|
||||
base_vsn="$(echo "$tgzfile" | grep -oE "[0-9]+\.[0-9]+\.[0-9]+(-(alpha|beta|rc)\.[0-9])?(-[0-9a-f]{8})?" | head -1)"
|
||||
## we have to create tmp dir to untar old tgz, as `tar --skip-old-files` is not supported on all plantforms
|
||||
local tmp_dir
|
||||
tmp_dir="$(mktemp -d -t emqx.XXXXXXX)"
|
||||
tar -C "$tmp_dir" -zxf "$tgzfile"
|
||||
cp -npr "$tmp_dir/releases"/* "${rel_dir}/releases/" || true
|
||||
cp -npr "$tmp_dir/lib"/* "${rel_dir}/lib/" || true
|
||||
rm -rf "$tmp_dir"
|
||||
releases+=( "$base_vsn" )
|
||||
done < <("$FIND" _upgrade_base -maxdepth 1 -name "${name_pattern}.tar.gz" -type f)
|
||||
if [ ${#releases[@]} -eq 0 ]; then
|
||||
|
@ -171,20 +175,23 @@ 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)
|
||||
pushd "${tard}" >/dev/null
|
||||
tar -czf "${target_name}" emqx
|
||||
## 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}" -- *
|
||||
popd >/dev/null
|
||||
mv "${tard}/${target_name}" "${target}"
|
||||
case "$SYSTEM" in
|
||||
|
|
|
@ -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]).
|
|
@ -88,7 +88,8 @@ emqx_test(){
|
|||
local packagename="${PACKAGE_FILE_NAME}"
|
||||
case "$PKG_SUFFIX" in
|
||||
"tar.gz")
|
||||
tar -zxf "${PACKAGE_PATH}/${packagename}"
|
||||
mkdir -p "${PACKAGE_PATH}/emqx"
|
||||
tar -C "${PACKAGE_PATH}/emqx" -zxf "${PACKAGE_PATH}/${packagename}"
|
||||
export EMQX_ZONES__DEFAULT__MQTT__SERVER_KEEPALIVE=60
|
||||
export EMQX_MQTT__MAX_TOPIC_ALIAS=10
|
||||
export EMQX_LOG__CONSOLE_HANDLER__LEVEL=debug
|
||||
|
@ -231,7 +232,8 @@ relup_test(){
|
|||
pattern="$EMQX_NAME-$("$CODE_PATH"/pkg-vsn.sh "${EMQX_NAME}" --long --vsn_matcher)"
|
||||
while read -r pkg; do
|
||||
packagename=$(basename "${pkg}")
|
||||
tar -zxf "$packagename"
|
||||
mkdir -p emqx
|
||||
tar -C emqx -zxf "$packagename"
|
||||
if ! ./emqx/bin/emqx start; then
|
||||
cat emqx/log/erlang.log.1 || true
|
||||
cat emqx/log/emqx.log.1 || true
|
||||
|
|
|
@ -173,7 +173,7 @@ download_prev_release(Tag, #{binary_rel_url := {ok, URL0}, clone_url := Repo}) -
|
|||
Filename = filename:join(BaseDir, Dir),
|
||||
Script = "mkdir -p ${OUTFILE} &&
|
||||
wget -c -O ${OUTFILE}.tar.gz ${URL} &&
|
||||
tar -zxf ${OUTFILE} ${OUTFILE}.tar.gz",
|
||||
tar -zxf ${OUTFILE}.tar.gz -C ${OUTFILE}",
|
||||
Env = [{"TAG", Tag}, {"OUTFILE", Filename}, {"URL", URL}],
|
||||
bash(Script, Env),
|
||||
{ok, Filename}.
|
||||
|
|
Loading…
Reference in New Issue