Skip to content

Commit

Permalink
Allow for a more flexible relup package location
Browse files Browse the repository at this point in the history
Instead of forcing the user to put the tarball package
with the expected name (<relname>.tar.gz)and in the
expected location (releases/<version>) symlink this
fixed file name to a tarball existing in one of three different
places (releases/, releases/<version>,
releases/<version>/<relname>.tar.gz).
  • Loading branch information
lrascao committed Oct 27, 2016
1 parent 89ab65a commit 50ca104
Showing 1 changed file with 89 additions and 38 deletions.
127 changes: 89 additions & 38 deletions priv/templates/install_upgrade_escript
Original file line number Diff line number Diff line change
Expand Up @@ -9,67 +9,118 @@
%% Unpack or upgrade to a new tar.gz release
main(["unpack", RelName, NameTypeArg, NodeName, Cookie, VersionArg]) ->
TargetNode = start_distribution(NodeName, NameTypeArg, Cookie),
WhichReleases = which_releases(TargetNode),
Version = parse_version(VersionArg),
case proplists:get_value(Version, WhichReleases) of
undefined ->
%% not installed, so unpack tarball:
?INFO("Release ~s not found, attempting to unpack releases/~s/~s.tar.gz~n",[Version,Version,RelName]),
ReleasePackage = Version ++ "/" ++ RelName,
case rpc:call(TargetNode, release_handler, unpack_release,
[ReleasePackage], ?TIMEOUT) of
{ok, Vsn} ->
?INFO("Unpacked successfully: ~p~n", [Vsn]);
{error, UnpackReason} ->
print_existing_versions(TargetNode),
?INFO("Unpack failed: ~p~n",[UnpackReason]),
erlang:halt(2)
end;
case unpack_release(RelName, TargetNode, Version) of
{ok, Vsn} ->
?INFO("Unpacked successfully: ~p~n", [Vsn]);
old ->
%% no need to unpack, has been installed previously
?INFO("Release ~s is marked old, switching to it.~n",[Version]);
?INFO("Release ~s is marked old.~n",[Version]);
unpacked ->
?INFO("Release ~s is already unpacked, now installing.~n",[Version]);
?INFO("Release ~s is already unpacked.~n",[Version]);
current ->
?INFO("Release ~s is already installed and current. Making permanent.~n",[Version]);
?INFO("Release ~s is already installed and current.~n",[Version]);
permanent ->
?INFO("Release ~s is already installed, and set permanent.~n",[Version])
?INFO("Release ~s is already installed and set permanent.~n",[Version]);
{error, Reason} ->
?INFO("Unpack failed: ~p~n",[Reason]),
print_existing_versions(TargetNode),
erlang:halt(2)
end;
main(["install", RelName, NameTypeArg, NodeName, Cookie, VersionArg]) ->
TargetNode = start_distribution(NodeName, NameTypeArg, Cookie),
WhichReleases = which_releases(TargetNode),
Version = parse_version(VersionArg),
case proplists:get_value(Version, WhichReleases) of
undefined ->
%% not installed, so unpack tarball:
?INFO("Release ~s not found, attempting to unpack releases/~s/~s.tar.gz~n",[Version,Version,RelName]),
ReleasePackage = Version ++ "/" ++ RelName,
case rpc:call(TargetNode, release_handler, unpack_release,
[ReleasePackage], ?TIMEOUT) of
{ok, Vsn} ->
?INFO("Unpacked successfully: ~p~n", [Vsn]),
install_and_permafy(TargetNode, RelName, Vsn);
{error, UnpackReason} ->
print_existing_versions(TargetNode),
?INFO("Unpack failed: ~p~n",[UnpackReason]),
erlang:halt(2)
end;
case unpack_release(RelName, TargetNode, Version) of
{ok, Vsn} ->
?INFO("Unpacked successfully: ~p~n", [Vsn]),
install_and_permafy(TargetNode, RelName, Vsn);
old ->
%% no need to unpack, has been installed previously
?INFO("Release ~s is marked old, switching to it.~n",[Version]),
install_and_permafy(TargetNode, RelName, Version);
unpacked ->
?INFO("Release ~s is already unpacked, now installing.~n",[Version]),
install_and_permafy(TargetNode, RelName, Version);
current -> %% installed and in-use, just needs to be permanent
?INFO("Release ~s is already installed and current. Making permanent.~n",[Version]),
current ->
?INFO("Release ~s is already installed and current, making permanent.~n",[Version]),
permafy(TargetNode, RelName, Version);
permanent ->
?INFO("Release ~s is already installed, and set permanent.~n",[Version])
?INFO("Release ~s is already installed and set permanent.~n",[Version]);
{error, Reason} ->
?INFO("Unpack failed: ~p~n",[Reason]),
print_existing_versions(TargetNode),
erlang:halt(2)
end;
main(_) ->
erlang:halt(1).

unpack_release(RelName, TargetNode, Version) ->
WhichReleases = which_releases(TargetNode),
case proplists:get_value(Version, WhichReleases) of
undefined ->
%% not installed, so unpack tarball:
%% look for a release package with the intended version in the following order:
%% releases/<relname>-<version>.tar.gz
%% releases/<version>/<relname>-<version>.tar.gz
%% releases/<version>/<relname>.tar.gz
ReleasePackage = find_and_link_release_package(Version, RelName),
?INFO("Release ~s not found, attempting to unpack ~s~n",
[Version, ReleasePackage]),
%% regardless of the location of the release package, we'll
%% always give release handle the same thing which is the symlink
ReleasePackageLink = filename:join(Version, RelName),
case rpc:call(TargetNode, release_handler, unpack_release,
[ReleasePackageLink], ?TIMEOUT) of
{ok, Vsn} -> {ok, Vsn};
{error, _} = Error -> Error
end;
Other -> Other
end.

%% look for a release package with the provided version in the following order:
%% releases/<relname>-<version>.tar.gz
%% releases/<version>/<relname>-<version>.tar.gz
%% releases/<version>/<relname>.tar.gz
find_and_link_release_package(Version, RelName) ->
%% this is the symlink name we'll create once
%% we've found where the actual release package is located
ReleaseLink = filename:join(["releases", Version,
RelName ++ ".tar.gz"]),
case first_value(fun filelib:is_file/1,
[filename:join(["releases",
RelName ++ "-" ++ Version ++ ".tar.gz"]),
filename:join(["releases", Version,
RelName ++ "-" ++ Version ++ ".tar.gz"]),
filename:join(["releases", Version,
RelName ++ ".tar.gz"])]) of
no_value ->
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;
{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)
%% 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 exists
ok = filelib:ensure_dir(filename:join([filename:dirname(ReleaseLink), "dummy"])),
%% create the symlink pointing to the full path name
ok = file:make_symlink(filename:absname(Filename), ReleaseLink),
Filename
end.

first_value(_Fun, []) -> no_value;
first_value(Fun, [Value | Rest]) ->
case Fun(Value) of
false ->
first_value(Fun, Rest);
true ->
{ok, Value}
end.

parse_version(V) when is_list(V) ->
hd(string:tokens(V,"/")).

Expand Down

0 comments on commit 50ca104

Please sign in to comment.