mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-09-05 12:37:54 +00:00
e4cc04a455
Signed-off-by: Vinícius Ferrão <2031761+viniciusferrao@users.noreply.github.com>
251 lines
7.7 KiB
Perl
251 lines
7.7 KiB
Perl
#!/usr/bin/env perl
|
|
use strict;
|
|
use warnings;
|
|
|
|
use File::Copy qw(copy);
|
|
use File::Path qw(make_path);
|
|
use File::Slurper qw(read_text write_text);
|
|
use File::Spec;
|
|
use File::Temp qw(tempdir);
|
|
use FindBin;
|
|
use lib "$FindBin::Bin/../lib";
|
|
use Test::More;
|
|
|
|
use XCAT::Test::File qw(repo_path);
|
|
|
|
my $postscripts = repo_path(File::Spec->catdir('xCAT', 'postscripts'));
|
|
my $library = File::Spec->catfile( $postscripts, 'xcatpkgutils.sh' );
|
|
my $loader = File::Spec->catfile( $postscripts, 'xcatpkgutils-loader.sh' );
|
|
|
|
my $tmpdir = tempdir( CLEANUP => 1 );
|
|
my $dnf_first = File::Spec->catdir( $tmpdir, 'dnf-first' );
|
|
my $yum_only = File::Spec->catdir( $tmpdir, 'yum-only' );
|
|
my $neither = File::Spec->catdir( $tmpdir, 'neither' );
|
|
make_path( $dnf_first, $yum_only, $neither );
|
|
write_executable( File::Spec->catfile( $dnf_first, 'dnf' ), "#!/bin/sh\n" );
|
|
write_executable( File::Spec->catfile( $dnf_first, 'yum' ), "#!/bin/sh\n" );
|
|
write_executable( File::Spec->catfile( $yum_only, 'yum' ), "#!/bin/sh\n" );
|
|
|
|
SKIP: {
|
|
skip 'the shared discovery helper is introduced by the production commit', 3
|
|
unless helper_available();
|
|
is_deeply(
|
|
[ run_helper($dnf_first) ],
|
|
[ 0, "dnf\n" ],
|
|
'dnf is preferred when both RPM package managers are executable'
|
|
);
|
|
is_deeply(
|
|
[ run_helper($yum_only) ],
|
|
[ 0, "yum\n" ],
|
|
'yum is used when dnf is unavailable'
|
|
);
|
|
is_deeply(
|
|
[ run_helper($neither) ],
|
|
[ 1, '' ],
|
|
'discovery fails without output when neither package manager is executable'
|
|
);
|
|
}
|
|
|
|
my $caller_dir = File::Spec->catdir( $tmpdir, 'callers' );
|
|
my $test_bin = File::Spec->catdir( $caller_dir, 'bin' );
|
|
make_path($test_bin);
|
|
stage_callers($caller_dir);
|
|
write_executable( File::Spec->catfile( $test_bin, 'logger' ), "#!/bin/sh\nexit 0\n" );
|
|
write_executable( File::Spec->catfile( $test_bin, 'mount' ), "#!/bin/sh\nexit 1\n" );
|
|
write_executable(
|
|
File::Spec->catfile( $test_bin, 'uname' ),
|
|
"#!/bin/sh\nprintf '%s\\n' Linux\n"
|
|
);
|
|
write_executable( File::Spec->catfile( $test_bin, 'dpkg' ), "#!/bin/sh\nexit 1\n" );
|
|
write_executable(
|
|
File::Spec->catfile( $test_bin, 'rpm' ),
|
|
<<'SH'
|
|
#!/bin/sh
|
|
case "$*" in
|
|
--version) exit 0 ;;
|
|
-q\ zypper)
|
|
[ "$XCAT_PM_SCENARIO" = zypper ] && exit 0
|
|
exit 1
|
|
;;
|
|
esac
|
|
if [ -n "${XCAT_RPM_TRACE:-}" ]; then
|
|
printf '%s\n' "$*" >> "$XCAT_RPM_TRACE"
|
|
exit 0
|
|
fi
|
|
exit 1
|
|
SH
|
|
);
|
|
write_executable( File::Spec->catfile( $test_bin, 'dnf' ), "#!/bin/sh\nexit 0\n" );
|
|
write_executable( File::Spec->catfile( $test_bin, 'yum' ), "#!/bin/sh\nexit 0\n" );
|
|
write_executable( File::Spec->catfile( $test_bin, 'zypper' ), "#!/bin/sh\nexit 0\n" );
|
|
|
|
my $bash_env = File::Spec->catfile( $caller_dir, 'bash-env.sh' );
|
|
# Fake only the absolute executable probes; the staged callers and library stay unchanged.
|
|
write_text(
|
|
$bash_env,
|
|
<<'SH'
|
|
function [
|
|
{
|
|
case "$1:$2:$XCAT_PM_SCENARIO" in
|
|
-x:/usr/bin/dnf:dnf) return 0 ;;
|
|
-x:/usr/bin/dnf:*) return 1 ;;
|
|
-x:/usr/bin/yum:dnf|-x:/usr/bin/yum:yum) return 0 ;;
|
|
-x:/usr/bin/yum:*) return 1 ;;
|
|
esac
|
|
builtin [ "$@"
|
|
}
|
|
|
|
exit()
|
|
{
|
|
if builtin [ -n "${XCAT_PM_STATE_TRACE:-}" ]; then
|
|
printf '%s|%s|%s|%s|%s\n' "${yumcmd:-}" "${hasrpm:-}" "${hasyum:-}" \
|
|
"${haszypper:-}" "${supdatecommand:-}" \
|
|
> "$XCAT_PM_STATE_TRACE"
|
|
fi
|
|
builtin exit "$@"
|
|
}
|
|
SH
|
|
);
|
|
|
|
my %common_env = (
|
|
ARCH => 'x86_64',
|
|
BASH_ENV => $bash_env,
|
|
INSTALLDIR => 'INSTALLDIR',
|
|
NFSSERVER => 'package-test-server',
|
|
NODE => 'node1',
|
|
OSVER => 'rocky9',
|
|
PATH => "$test_bin:$ENV{PATH}",
|
|
);
|
|
|
|
for my $scenario (
|
|
[ dnf => 'dnf||||' ],
|
|
[ yum => 'yum||||' ],
|
|
)
|
|
{
|
|
my ( $name, $expected_state ) = @{$scenario};
|
|
my ( $status, $output, $state ) = run_caller( 'ospkgs', $name );
|
|
is( $status, 0, "ospkgs completes with $name" ) or diag($output);
|
|
is( $state, $expected_state, "ospkgs selects $name" );
|
|
}
|
|
|
|
my ( $ospkgs_status, $ospkgs_output, $ospkgs_state ) =
|
|
run_caller( 'ospkgs', 'neither' );
|
|
is( $ospkgs_status, 1, 'ospkgs still stops when neither dnf nor yum is available' );
|
|
is( $ospkgs_state, '||||', 'ospkgs leaves package-manager state empty on failure' );
|
|
like(
|
|
$ospkgs_output,
|
|
qr/^Please install yum or dnf on node1\.$/m,
|
|
'ospkgs retains its package-manager installation error'
|
|
);
|
|
|
|
for my $scenario (
|
|
[ dnf => 'dnf|1|1|0|rpm -Uvh --replacepkgs' ],
|
|
[ yum => 'yum|1|1|0|rpm -Uvh --replacepkgs' ],
|
|
[ zypper => '|1|0|1|rpm -Uvh --replacepkgs' ],
|
|
[ rpm => '|1|0|0|rpm -Uvh --replacepkgs' ],
|
|
)
|
|
{
|
|
my ( $name, $expected_state ) = @{$scenario};
|
|
my ( $status, $output, $state ) = run_caller( 'otherpkgs', $name );
|
|
is( $status, 0, "otherpkgs completes with the $name discovery outcome" )
|
|
or diag($output);
|
|
is( $state, $expected_state, "otherpkgs retains the $name discovery outcome" );
|
|
}
|
|
|
|
like(
|
|
read_text( File::Spec->catfile( $caller_dir, 'otherpkgs-rpm-command.trace' ) ),
|
|
qr/^-Uvh --replacepkgs package-test\*$/m,
|
|
'otherpkgs executes its raw RPM installation fallback'
|
|
);
|
|
|
|
done_testing();
|
|
|
|
sub run_helper {
|
|
my ($directory) = @_;
|
|
return run_command(
|
|
'/bin/sh', '-c', '. "$1"; xcat_find_rpm_package_manager "$2"',
|
|
'package-manager-discovery-test', $library, $directory
|
|
);
|
|
}
|
|
|
|
sub helper_available {
|
|
return system(
|
|
'/bin/sh', '-c',
|
|
'. "$1"; command -v xcat_find_rpm_package_manager >/dev/null 2>&1',
|
|
'package-manager-discovery-test', $library
|
|
) == 0;
|
|
}
|
|
|
|
sub run_caller {
|
|
my ( $caller, $scenario ) = @_;
|
|
my $trace = File::Spec->catfile( $caller_dir, "$caller-$scenario.trace" );
|
|
local %ENV = ( %ENV, %common_env );
|
|
$ENV{XCAT_PM_SCENARIO} = $scenario;
|
|
$ENV{XCAT_PM_STATE_TRACE} = $trace;
|
|
|
|
my @arguments;
|
|
if ( $caller eq 'ospkgs' ) {
|
|
delete @ENV{qw(OTHERPKGS OTHERPKGS_INDEX UPDATENODE)};
|
|
$ENV{OSPKGS} = 'package-test';
|
|
@arguments = ('--keeprepo');
|
|
} else {
|
|
delete @ENV{qw(OSPKGS OTHERPKGS)};
|
|
$ENV{OSVER} = 'custom9';
|
|
if ( $scenario eq 'rpm' ) {
|
|
$ENV{OTHERPKGS1} = 'package-test';
|
|
$ENV{OTHERPKGS_INDEX} = 1;
|
|
$ENV{XCAT_RPM_TRACE} = File::Spec->catfile(
|
|
$caller_dir, 'otherpkgs-rpm-command.trace'
|
|
);
|
|
} else {
|
|
delete @ENV{qw(OTHERPKGS1 XCAT_RPM_TRACE)};
|
|
$ENV{OTHERPKGS_INDEX} = 0;
|
|
}
|
|
$ENV{UPDATENODE} = 1;
|
|
}
|
|
|
|
my ( $status, $output ) = run_command(
|
|
File::Spec->catfile( $caller_dir, $caller ), @arguments
|
|
);
|
|
my $state = read_text($trace);
|
|
chomp($state);
|
|
return ( $status, $output, $state );
|
|
}
|
|
|
|
sub stage_callers {
|
|
my ($directory) = @_;
|
|
for my $source (
|
|
$library, $loader,
|
|
map { File::Spec->catfile( $postscripts, $_ ) } qw(ospkgs otherpkgs)
|
|
)
|
|
{
|
|
my $filename = ( File::Spec->splitpath($source) )[2];
|
|
my $destination = File::Spec->catfile( $directory, $filename );
|
|
copy( $source, $destination )
|
|
or die "Unable to stage $source as $destination: $!";
|
|
chmod 0755, $destination
|
|
or die "Unable to make $destination executable: $!";
|
|
}
|
|
}
|
|
|
|
sub write_executable {
|
|
my ( $path, $contents ) = @_;
|
|
write_text( $path, $contents );
|
|
chmod 0755, $path or die "Unable to make $path executable: $!";
|
|
}
|
|
|
|
sub run_command {
|
|
my (@command) = @_;
|
|
my $pid = open( my $pipe, '-|' );
|
|
die "Unable to fork for @command: $!" unless defined($pid);
|
|
if ( $pid == 0 ) {
|
|
open( STDERR, '>&', STDOUT ) or die "Unable to merge stderr: $!";
|
|
exec { $command[0] } @command;
|
|
die "Unable to execute @command: $!";
|
|
}
|
|
|
|
my $output = do { local $/; <$pipe> } // '';
|
|
close($pipe);
|
|
return ( $? >> 8, $output );
|
|
}
|