2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-21 23:28:19 +00:00

fix(xcat-core): go-xcat asks to remove packages that are not installed

GO_XCAT_UNINSTALL_LIST names every package go-xcat installs plus the ones xCAT
has stopped producing, so a node installed before they went away is still
cleaned up. uninstall_xcat handed that whole list to the package manager, and
most of it is not installed on any one node: apt answers "Unable to locate
package" for a name it does not know and go-xcat warns once per package, while
dnf answers "No match for argument" and fails the call when nothing matches.

installed_packages() asks the local package database which of them this system
has, and uninstall_xcat and uninstall_xcat_completely pass only those on. A
node with none of them installed calls the package manager not at all.

This is also what makes a retired name in the list free to keep.

go_xcat_uninstall_installed_only.t runs uninstall_xcat with rpm and dpkg-query
answering from a fake package database and remove_package shadowed, and reads
the argument list the package manager would have been given. A filter that
kept everything and a filter that kept nothing each fail three of its four
assertions.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
Daniel Hilst
2026-09-16 18:25:29 -03:00
parent 87974d91c4
commit 6edeafa438
2 changed files with 45 additions and 3 deletions
+41 -2
View File
@@ -2033,10 +2033,47 @@ function update_xcat()
install_packages "$@" "${install_list[@]}"
}
# $@ package names
# Prints the ones this system actually has. `go-xcat uninstall` names packages xCAT no
# longer produces, so that a node installed before they went away is still cleaned up.
# Handing those names to the package manager on a node that never had them costs a
# warning each on apt, and fails the whole call on dnf when none of them match.
function installed_packages_rpm()
{
type rpm >/dev/null 2>&1 || return 255
local package=""
for package in "$@"
do
rpm -q --quiet "${package}" && echo "${package}"
done
return 0
}
# $@ package names
function installed_packages_deb()
{
type dpkg-query >/dev/null 2>&1 || return 255
local package=""
for package in "$@"
do
[[ "$(dpkg-query --show '--showformat=${Status}' "${package}" 2>/dev/null)" \
= "install ok installed" ]] && echo "${package}"
done
return 0
}
function installed_packages()
{
function_dispatch "${FUNCNAME[0]}" "$@"
}
# $1 -y
function uninstall_xcat()
{
remove_package "$@" "${GO_XCAT_UNINSTALL_LIST[@]}"
local -a present=()
readarray -t present < <(installed_packages "${GO_XCAT_UNINSTALL_LIST[@]}")
[[ "${#present[@]}" -gt "0" ]] || return 0
remove_package "$@" "${present[@]}"
}
function kill_xcat()
@@ -2091,7 +2128,9 @@ function trash_xcat()
function uninstall_xcat_completely()
{
purge_package -y "${GO_XCAT_UNINSTALL_LIST[@]}"
local -a present=()
readarray -t present < <(installed_packages "${GO_XCAT_UNINSTALL_LIST[@]}")
[[ "${#present[@]}" -eq "0" ]] || purge_package -y "${present[@]}"
kill_xcat
trash_xcat
@@ -79,7 +79,10 @@ sub uninstall_args {
my $present = join ' ', @{$installed};
open my $fh, '>', $driver or die "$driver: $!";
print {$fh} "set -u\n";
print {$fh} "type() { return 1; }\n"; # the rpm branch of the lists
# An rpm host: dpkg is absent, so the lists take the rpm branch and the deb arm of the
# dispatch stands down. Shadowing `type` to fail for everything would stand both arms
# down and the filter would answer nothing, whatever it does.
print {$fh} "type() { case \"\$1\" in dpkg|dpkg-query|apt-get) return 1 ;; *) return 0 ;; esac; }\n";
print {$fh} $lists, "\n";
print {$fh} <<"BASH";
INSTALLED="$present"