Issue
In a ci/cd environment, i want to be able to update or downgrade a package to a specific version. To do this with yum, one needs to know the already installed version of a packge, eg one can use yum install
to install a new package or update to a newer version. yum downgrade
can be used to replace it with an earlier version.
Is there a way to use one command to install a specific version of a package?
Background: We continuously add new package versions to our yum channel on artifactory, so our yum channel doesn't really reflect a stable
state. One should be able to install or downgrade a specific package with one yum install <package_name>-<package_version>
Solution
UPDATE#2 (please see below for older answers)
Now going with the following approach:
- check the already installed version
- if the specified version is already installed, do nothing
- if a newer version is installed, do a
yum downgrade
- else, do a
yum install
(which also updates)
install-utils.sh:
#!/usr/bin/env bash
EXIT_FAILURE=1
function get_installed_version() {
pkg_name=$("rpm -q --queryformat \
'%{NAME}-%{VERSION}-%{RELEASE}' ${pkg_name}" | tail -1)
[ $? -ne 0 ] && pkg_name=""
echo ${pkg_name}
}
function is_version_newer() {
[[ $1 != $(echo -e "$1\n$2" | sort -V | head -1) ]]
}
function install_package(){
local pkg_name="$1"
local pkg_ver_rel="$2"
local pkg_full_name="${pkg_name}-${pkg_ver_rel}"
echo "Package to install: $pkg_full_name"
installed_pkg="$(get_installed_version $pkg_name)"
echo "Package version installed: $installed_pkg"
if [[ "$installed_pkg" == "$pkg_full_name" ]]; then
echo "Requested package version '$pkg_full_name' is " \
"already installed. Nothing to do."
elif is_version_newer "$installed_pkg" "$pkg_full_name"; then
echo "Downgrading to $pkg_full_name ..."
yum -y downgrade $pkg_full_name \
&& echo "Successfully downgraded to $pkg_full_name" \
|| { echo "Failed to downgrade to $pkg_full_name"; exit $EXIT_FAILURE; }
else
echo "Installing $pkg_full_name ..."
yum -y install $pkg_full_name \
&& echo "Successfully installed package $pkg_full_name" \
|| { echo "Failed to install $pkg_full_name"; exit $EXIT_FAILURE; }
fi
}
OLDER UPDATE: The (below answer) is not a good approach. Reason: Often, the version to be installed is not fully specified. So instead of giving 'version
-release
-architecture
-epoch
' (where architecture
and epoch
may be omitted) there is only the version
specified, meaning: The latest available package for version
shall be used. (eg. see this answer to "What's the rule for the Name-Version-Release of RPM?"). The approach given here will lead to an implicit downgrade to the last but one available version.
For example, one wants to install version: '0.11.1', which is already installed with version: 0.11.1-1. And available upstream is '0.11.1-SNAPSHOT20171030093532' and '0.11.1-2'. The install will update to the newest '0.11.1-2', but that would not match with the pkg_full_name
, so a yum downgrade
is performed, which let's the package manager select the snapshot version to be installed.
INITIAL ANSWER
For now, my best guess is to use some combination of yum install
, '(check installed version)' and yum downgrade
if it is not the specified version.
Eg:
pkg_name="somepackage"
pkg_full_name="somepackage-1.0.4-SNAPSHOT20171027143208"
echo "Installing $pkg_full_name ..."
yum -y install $pkg_full_name || \
{ echo "Failed to install $pkg_full_name"; exit 1; }
installed_package=$(rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}' ${pkg_name})
if [ "${installed_package}" != "${pkg_full_name}" ]; then
sudo yum -y downgrade $pkg_full_name || \
{ echo "Failed to downgrade to $pkg_full_name"; exit 1; }
fi
echo "Successfully installed package $pkg_full_name"
Answered By - huch Answer Checked By - Candace Johnson (WPSolving Volunteer)