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

test(packaging): query resolved RPM dependencies

This commit is contained in:
Vinícius Ferrão
2026-10-08 22:48:51 -03:00
parent e7c7babce0
commit dbbdcddcb2
5 changed files with 110 additions and 122 deletions
+3 -1
View File
@@ -17,12 +17,14 @@ jobs:
- name: Test Debian package lifecycle
run: prove -v xCAT-test/native/xcatd_debian_lifecycle.t xCAT-test/native/xcatd_restart_callers.t xCAT-test/native/apache_package_lifecycle.t xCAT-test/native/package_upgrade_logging.t
- name: Install package test dependencies
run: sudo apt-get install -y --no-install-recommends cpio createrepo-c rsync gnupg libxml-libxml-perl
run: sudo apt-get install -y --no-install-recommends cpio createrepo-c rsync gnupg libxml-libxml-perl python3-rpm
- name: Exercise probe package payloads
if: ${{ !cancelled() }}
run: prove xCAT-test/native/probe_package_payload.t
- name: Exercise release repositories
run: prove xCAT-test/native/release_repository.t
- name: Check parsed package relations
run: prove xCAT-test/native/package_relations.t
- name: Prepare xCAT syslog directory
if: ${{ !cancelled() }}
run: sudo install -d -o syslog -g adm -m 0750 /var/log/xcat
+100
View File
@@ -0,0 +1,100 @@
#!/usr/bin/env perl
use strict;
use warnings;
use File::Temp qw(tempdir);
use FindBin;
use lib "$FindBin::Bin/../lib";
use Test::More;
use XCAT::Test::File qw(repo_path);
use XCAT::Test::Package qw(run_in);
plan skip_all => 'requires Linux RPM tooling' unless $^O eq 'linux';
local %ENV = (%ENV, HOME => tempdir(CLEANUP => 1));
delete @ENV{qw(pcm fsm s390x)};
my @platforms = (
['EL7', 'rhel 7', 0], ['EL8', 'rhel 8', 1], ['EL9', 'rhel 9', 1],
['EL10', 'rhel 10', 1], ['Fedora', 'fedora 44', 1],
['SLES12', 'suse_version 1315', 0], ['SLES15', 'suse_version 1500', 1],
['openEuler', 'openEuler 2', 0],
);
my @images = map { "xCAT-genesis-openembedded-$_" } qw(x86_64 ppc64le riscv64 s390x);
my %legacy = (x86_64 => 'x86_64', ppc64le => 'ppc64', aarch64 => 'aarch64');
for my $platform (@platforms) {
my ($name, $macro, $weak) = @$platform;
for my $arch (qw(x86_64 ppc64le aarch64 riscv64 s390x)) {
for my $pkg (qw(xCAT xCATsn)) {
my $requires = query($pkg, $arch, $macro, '--requires');
my $recommends = query($pkg, $arch, $macro, '--recommends');
unlike($requires, qr/xCAT-genesis-openembedded-/, "$name $arch $pkg never requires optional images");
my @actual = sort grep { /^xCAT-genesis-openembedded-/ } split /\n/, $recommends;
is_deeply(\@actual, $weak ? [sort @images] : [], "$name $arch $pkg optional image recommendations");
my @scripts = grep { /^xCAT-genesis-scripts-/ } split /\n/, $requires;
is_deeply(\@scripts, $legacy{$arch}
? ["xCAT-genesis-scripts-$legacy{$arch} = 1:9.9.9-1"] : [],
"$name $arch $pkg required legacy Genesis scripts");
if ($arch eq 'riscv64') {
like($requires, $pkg eq 'xCAT' ? qr/^ipmitool-xcat >= 1\.8\.18-4$/m : qr/^ipmitool-xcat >= 1\.8\.17-1$/m,
"$name $pkg RISC-V IPMI dependency");
unlike($requires, qr/xCAT-genesis-scripts-|xnba-undi|syslinux-xcat|elilo-xcat|%\{/,
"$name $pkg RISC-V has no unavailable legacy payload or unresolved macro");
}
}
}
for my $s390 (0, 1) {
local $ENV{s390x} = $s390;
my $requires = query('xCAT-server', 'x86_64', $macro, '--requires');
like($requires, qr/^perl\(Digest::SHA\)$/m, "$name server s390x=$s390 requires Digest::SHA");
next if $s390;
my $recommends = query('xCAT-server', 'x86_64', $macro, '--recommends');
is(scalar(grep { $_ eq 'perl-DB_File' } split /\n/, $requires), $name eq 'EL10' ? 0 : 1,
"$name server hard DB_File dependency");
is(scalar(grep { $_ eq 'perl-DB_File' } split /\n/, $recommends), $name eq 'EL10' ? 1 : 0,
"$name server weak DB_File dependency");
like($requires, qr/^\Q$_\E$/m, "$name server keeps $_")
for qw(perl-Net-Telnet perl-Net-DNS perl-Crypt-CBC perl-Crypt-Rijndael);
}
}
for my $platform (@platforms) {
my ($name, $macro) = @$platform;
my ($rc, $filter, $err) = run_in(repo_path('.'), 'python3', '-c', <<'PY', repo_path('xCAT-server/xCAT-server.spec'), $macro);
import rpm, sys
for name in ('rhel', 'fedora', 'suse_version', 'openEuler'):
rpm.delMacro(name)
name, value = sys.argv[2].split()
rpm.addMacro(name, value)
rpm.addMacro('version', '9.9.9')
rpm.addMacro('release', '1')
rpm.addMacro('__requires_exclude', '^retained$')
rpm.spec(sys.argv[1])
print(rpm.expandMacro('%{?__requires_exclude}'))
PY
is($rc, 0, "$name parses server dependency generator policy") or BAIL_OUT($err);
chomp $filter;
ok('retained' =~ /$filter/, "$name keeps an inherited dependency filter");
is('perl(DB_File)' =~ /$filter/ ? 1 : 0, $name eq 'EL10' ? 1 : 0,
"$name automatic DB_File dependency exclusion");
unlike('perl(Digest::SHA)', qr/$filter/, "$name keeps automatic Digest::SHA dependencies");
}
for my $case (['Linux', 'rhel 8', 'iproute'], ['SUSE', 'suse_version 1500', 'iproute2']) {
my ($name, $macro, $provider) = @$case;
my $requires = query('xCAT-probe', 'x86_64', $macro, '--requires');
my @providers = grep { /^iproute2?$/ } split /\n/, $requires;
is_deeply(\@providers, [$provider], "$name probe socket tool provider");
}
done_testing();
sub query {
my ($package, $arch, $macro, $relation) = @_;
my $format = $relation eq '--requires'
? '[%{REQUIRENAME} %{REQUIREFLAGS:depflags} %{REQUIREVERSION}\n]'
: '[%{RECOMMENDNAME}\n]';
my ($rc, $out, $err) = run_in(repo_path('.'), 'rpmspec', '-q', '--target', $arch,
(map { ('--undefine', $_) } qw(rhel fedora suse_version openEuler)),
'--define', $macro, '--define', 'version 9.9.9', '--define', 'release 1',
'--qf', $format, repo_path("$package/$package.spec"));
BAIL_OUT("$package $arch $macro: $err") if $rc;
$out =~ s/[^\S\n]+$//mg;
return $out;
}
@@ -8,28 +8,6 @@ use Test::More;
use XCAT::Test::File qw(slurp_repo_file);
my $rpm_weak_dependencies = join(
"\n",
'%if 0%{?fedora} || 0%{?rhel} >= 8 || 0%{?suse_version} >= 1500',
'Recommends: xCAT-genesis-openembedded-x86_64',
'Recommends: xCAT-genesis-openembedded-ppc64le',
'Recommends: xCAT-genesis-openembedded-riscv64',
'Recommends: xCAT-genesis-openembedded-s390x',
'%endif',
);
my $rpm_spec = slurp_repo_file('xCAT/xCAT.spec');
like(
$rpm_spec,
qr/^\Q$rpm_weak_dependencies\E$/m,
'RPM weak dependencies stay inside their compatibility guard',
);
unlike(
$rpm_spec,
qr/^Requires:\s+xCAT-genesis-openembedded-/m,
'missing OpenEmbedded images do not block an RPM upgrade',
);
my $deb_control = slurp_repo_file('xCAT/debian/control');
like(
$deb_control,
@@ -57,13 +35,6 @@ unlike(
'missing OpenEmbedded images do not block a DEB upgrade',
);
my $sn_rpm_spec = slurp_repo_file('xCATsn/xCATsn.spec');
like(
$sn_rpm_spec,
qr/^\Q$rpm_weak_dependencies\E$/m,
'service-node weak dependencies stay inside their compatibility guard',
);
my $sn_deb_control = slurp_repo_file('xCATsn/debian/control');
like(
$sn_deb_control,
+1 -58
View File
@@ -7,66 +7,9 @@ use lib "$FindBin::Bin/../lib";
use lib "$FindBin::Bin/../../build-utils/lib";
use Test::More;
use XCAT::Test::File qw(repo_path slurp_repo_file);
use XCAT::Test::File qw(repo_path);
use XCAT::BuildUtils qw(targetarch_from_target);
# riscv64 packaging: the arch-named packages (xCAT, xCATsn) must resolve their
# architecture token and dependencies for riscv64, and the build scripts must
# know the riscv64 package names. The Genesis image comes from the OpenEmbedded
# packages, so there is no arch-named Genesis package to resolve here.
my $xcat = slurp_repo_file('xCAT/xCAT.spec');
my ($xcat_rv) = $xcat =~ /^%ifarch riscv64\n((?:#[^\n]*\n|Requires:[^\n]*\n)*)%endif$/m;
like( $xcat_rv || '', qr/^Requires: ipmitool-xcat >= 1\.8\.18-4$/m, 'xCAT.spec requires ipmitool-xcat on riscv64' );
unlike( $xcat_rv || '', qr/xnba-undi|syslinux-xcat|elilo-xcat/, 'xCAT.spec does not require the x86 PXE loaders on riscv64' );
# riscv64 has no legacy Genesis package: the requirement must disappear rather than
# resolve to an unsatisfiable name, and the OpenEmbedded image is recommended instead.
like( $xcat, qr/^%\{\?genesistarch:Requires: xCAT-genesis-scripts-%\{genesistarch\} = 1:%\{version\}-%\{release\}\}$/m, 'xCAT.spec asks for the legacy Genesis package only where the architecture has one' );
like( $xcat, qr/^Recommends: xCAT-genesis-openembedded-riscv64$/m, 'xCAT.spec recommends the RISC-V OpenEmbedded Genesis image' );
SKIP: {
my $rpmspec = qx(command -v rpmspec 2>/dev/null);
chomp($rpmspec);
skip 'rpmspec is not installed', 2 unless $rpmspec && -x $rpmspec;
my $spec = repo_path('xCAT/xCAT.spec');
open( my $requires_fh, '-|',
$rpmspec, '-q', '--target', 'riscv64', '--requires', $spec )
or BAIL_OUT("unable to run $rpmspec: $!");
my $requires = do { local $/; <$requires_fh> };
close($requires_fh)
or BAIL_OUT("rpmspec failed for $spec with status " . ($? >> 8));
unlike( $requires, qr/genesis-scripts/, 'a riscv64 build requires no legacy Genesis package' );
unlike( $requires, qr/\Q%{genesistarch}\E/, 'a riscv64 build leaves no unexpanded architecture macro' );
}
my $xcatsn = slurp_repo_file('xCATsn/xCATsn.spec');
my ($xcatsn_rv) = $xcatsn =~ /^%ifarch [^\n]*\briscv64\b[^\n]*\n((?:#[^\n]*\n|Requires:[^\n]*\n)*)%endif$/m;
like( $xcatsn_rv || '', qr/^Requires: ipmitool-xcat >= 1\.8\.17-1$/m, 'xCATsn.spec requires ipmitool-xcat on riscv64' );
like( $xcatsn, qr/^Recommends: xCAT-genesis-openembedded-riscv64$/m, 'xCATsn.spec recommends the RISC-V OpenEmbedded Genesis image' );
my $server = slurp_repo_file('xCAT-server/xCAT-server.spec');
like( $server, qr/^Recommends: perl-DB_File$/m, 'xCAT-server.spec recommends perl-DB_File on EL10 (riscv64 has no EPEL to provide it)' );
like(
$server,
qr/^%if 0%\{\?rhel\} >= 10\nRecommends: perl-DB_File\n/m,
'the weak perl-DB_File dependency is limited to EL10, where riscv64 has no EPEL',
);
like(
$server,
qr/^%else\nRequires: perl-DB_File\n%endif$/m,
'build hosts without weak dependencies keep the hard perl-DB_File requirement',
);
like(
$server,
qr/^%global __requires_exclude %\{\?__requires_exclude:%\{__requires_exclude\}\|\}\^perl\\\\\(DB_File\\\\\)\$$/m,
'xCAT-server.spec appends the generated perl(DB_File) requirement to the build root filter',
);
like( $server, qr/^Requires: perl-Net-Telnet perl-Net-DNS perl-Crypt-CBC perl-Crypt-Rijndael$/m, 'xCAT-server.spec keeps the other EL perl requires' );
my $architectures = repo_path('build-utils/rpm-architectures.sh');
is(system('sh', '-n', $architectures), 0, 'the shared build architecture data parses as POSIX shell');
open(
@@ -1,42 +1,14 @@
#!/usr/bin/env perl
use strict;
use warnings;
use File::Spec;
use FindBin;
use lib "$FindBin::Bin/../lib";
use Test::More;
use XCAT::Test::File qw(slurp_repo_file);
my $repo_root = File::Spec->rel2abs(
File::Spec->catdir( $FindBin::Bin, '..', '..' )
);
sub read_file {
my ($filename) = @_;
open( my $fh, '<', $filename )
or die "Unable to read $filename: $!";
my $content = do { local $/; <$fh> };
close($fh);
return $content;
}
my $rpm_spec = read_file(
File::Spec->catfile( $repo_root, 'xCAT-server', 'xCAT-server.spec' )
);
my @rpm_sha_requirements =
$rpm_spec =~ /^Requires:.*\bperl\(Digest::SHA\)(?:\s|$)/mg;
is(
scalar(@rpm_sha_requirements),
2,
'both RPM architecture branches require Digest::SHA',
);
my $debian_control = read_file(
File::Spec->catfile( $repo_root, 'xCAT-server', 'debian', 'control' )
);
like(
$debian_control,
qr/^Depends:.*\blibdigest-sha-perl\b/m,
'the Debian package requires Digest::SHA',
);
my $control = slurp_repo_file('xCAT-server/debian/control');
my ($server) = $control =~ /^Package: xcat-server\n(.*?)(?:\n\n|\z)/ms;
like($server // '', qr/^Depends:.*\blibdigest-sha-perl\b/m,
'the Debian server package requires Digest::SHA');
done_testing();