mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-10-20 22:55:40 +00:00
test(ubuntu): exercise live-media imports and warnings
Replace source-text assertions with real media imports in an isolated filesystem and database. Run the native fixture before the package build in CI.
This commit is contained in:
@@ -9,7 +9,7 @@ jobs:
|
||||
- name: Refresh package indexes
|
||||
run: sudo apt-get update
|
||||
- name: Install dependencies
|
||||
run: sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests bats bubblewrap gawk mawk rpm rsyslog build-essential fakeroot reprepro devscripts debhelper libcapture-tiny-perl libfile-slurper-perl libjson-perl libyaml-pp-perl libparallel-forkmanager-perl libsoap-lite-perl libdbi-perl libcgi-pm-perl quilt openssh-server dpkg looptools genometools software-properties-common grub-common grub-efi-amd64-bin squashfs-tools pigz
|
||||
run: sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests bats bubblewrap cpio gawk mawk rpm rsyslog build-essential fakeroot reprepro devscripts debhelper libcapture-tiny-perl libfile-slurper-perl libjson-perl libyaml-pp-perl libparallel-forkmanager-perl libsoap-lite-perl libdbi-perl libdbd-sqlite3-perl libcgi-pm-perl quilt openssh-server dpkg looptools genometools software-properties-common grub-common grub-efi-amd64-bin squashfs-tools pigz
|
||||
- name: Enable postscript test namespaces
|
||||
run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
|
||||
- name: Install lifecycle test dependencies
|
||||
@@ -19,6 +19,9 @@ jobs:
|
||||
- name: Prepare xCAT syslog directory
|
||||
if: ${{ !cancelled() }}
|
||||
run: sudo install -d -o syslog -g adm -m 0750 /var/log/xcat
|
||||
- name: Run Ubuntu image fixture tests
|
||||
if: ${{ !cancelled() }}
|
||||
run: prove xCAT-test/native/ubuntu_live_media_guardrails.t
|
||||
- name: Run tests
|
||||
if: ${{ !cancelled() }}
|
||||
run: perl github_action_xcat_test.pl
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package XCAT::Test::UbuntuImage;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Capture::Tiny qw(capture_merged);
|
||||
use File::Basename qw(dirname);
|
||||
use File::Path qw(make_path);
|
||||
use File::Slurper qw(read_binary write_binary);
|
||||
use File::Temp qw(tempdir);
|
||||
use XCAT::Test::File qw(repo_path);
|
||||
|
||||
sub new {
|
||||
my ($class) = @_;
|
||||
for my $tool (qw(bwrap timeout cpio gzip perl)) {
|
||||
die "Ubuntu image tests require $tool\n"
|
||||
unless grep { -x "$_/$tool" } qw(/usr/bin /bin /usr/sbin /sbin);
|
||||
}
|
||||
my $self = bless { root => tempdir(CLEANUP => 1) }, $class;
|
||||
make_path(map { "$self->{root}/$_" } qw(etc install tmp work/bin work/db));
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub write {
|
||||
my ($self, $file, $content) = @_;
|
||||
my $path = "$self->{root}/$file";
|
||||
make_path(dirname($path));
|
||||
write_binary($path, $content);
|
||||
return $path;
|
||||
}
|
||||
|
||||
sub read {
|
||||
my ($self, $file) = @_;
|
||||
return read_binary("$self->{root}/$file");
|
||||
}
|
||||
|
||||
sub run {
|
||||
my ($self, @command) = @_;
|
||||
my $root = $self->{root};
|
||||
my @sandbox = (
|
||||
'bwrap', '--unshare-all', '--die-with-parent', '--new-session',
|
||||
'--tmpfs', '/',
|
||||
(map { ('--ro-bind', $_, $_) } grep { -d $_ } qw(/usr /bin /sbin /lib /lib64)),
|
||||
'--dev', '/dev', '--proc', '/proc', '--dir', '/run', '--dir', '/sys',
|
||||
'--dir', '/opt',
|
||||
'--bind', "$root/etc", '/etc', '--bind', "$root/install", '/install',
|
||||
'--bind', "$root/tmp", '/tmp', '--bind', "$root/work", '/work',
|
||||
'--ro-bind', repo_path('.'), '/repo', '--chdir', '/work',
|
||||
'--setenv', 'PATH', '/work/bin:/usr/bin:/bin:/usr/sbin:/sbin',
|
||||
'--setenv', 'LC_ALL', 'C', '--setenv', 'XCATROOT', '/repo',
|
||||
'--setenv', 'XCATCFG', 'SQLite:/work/db',
|
||||
'--setenv', 'PERL5LIB', '/repo/perl-xCAT:/repo/xCAT-server/lib/perl',
|
||||
);
|
||||
push @sandbox, '--ro-bind', '/etc/alternatives', '/etc/alternatives'
|
||||
if -d '/etc/alternatives';
|
||||
my ($output, $status) = capture_merged {
|
||||
local %ENV = (PATH => '/usr/bin:/bin:/usr/sbin:/sbin');
|
||||
system(@sandbox, 'timeout', '45', @command);
|
||||
$?;
|
||||
};
|
||||
return ($status, $output);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,26 @@
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use File::Slurper qw(write_binary);
|
||||
use JSON::PP qw(encode_json);
|
||||
use xCAT::Table;
|
||||
|
||||
my $plugin = '/repo/xCAT-server/lib/xcat/plugins/debian.pm';
|
||||
require $plugin;
|
||||
|
||||
my $site = xCAT::Table->new('site', -create => 1);
|
||||
$site->setAttribs({ key => 'installdir' }, { value => '/install' });
|
||||
$site->close();
|
||||
|
||||
my @responses;
|
||||
my $detected = xCAT_plugin::debian::is_ubuntu_live_media('/work/media');
|
||||
xCAT_plugin::debian::process_request(
|
||||
{ command => ['copycd'], arg => ['-m', '/work/media', '-o'] },
|
||||
sub { push @responses, @_ },
|
||||
);
|
||||
my $osdistro = xCAT::Table->new('osdistro');
|
||||
my $row = $osdistro->getAttribs({ osdistroname => 'ubuntu24.04-x86_64' },
|
||||
qw(arch dirpaths type));
|
||||
$osdistro->close();
|
||||
write_binary('/work/result.json', encode_json({ detected => $detected,
|
||||
responses => \@responses, osdistro => $row }));
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use JSON::PP qw(decode_json);
|
||||
use Test::More;
|
||||
use XCAT::Test::UbuntuImage;
|
||||
|
||||
plan skip_all => 'Linux filesystem namespaces are required' unless $^O eq 'linux';
|
||||
|
||||
for my $case (
|
||||
['install-source metadata', ['casper/install-sources.yaml'], 1],
|
||||
['squashfs payload', ['casper/ubuntu-server.squashfs'], 1],
|
||||
['both live markers', ['casper/install-sources.yaml', 'casper/root.squashfs'], 1],
|
||||
['ordinary installer', ['install/vmlinuz'], 0],
|
||||
['casper without a live marker', ['casper/vmlinuz'], 0],
|
||||
['similarly named files', ['casper/root.squashfs.bak', 'casper/install-sources.yml'], 0],
|
||||
['marker outside casper', ['casper/vmlinuz', 'install-sources.yaml', 'root.squashfs'], 0],
|
||||
) {
|
||||
my ($name, $files, $live) = @$case;
|
||||
subtest $name => sub {
|
||||
my $image = XCAT::Test::UbuntuImage->new();
|
||||
$image->write('work/media/.disk/info', "Ubuntu-Server 24.04 LTS \"Noble Numbat\" - Release amd64 (20240423)\n");
|
||||
$image->write('work/media/README.diskdefines', "#define DISKNUM 1\n");
|
||||
$image->write('work/media/dists/noble/Release', "Suite: noble\n");
|
||||
$image->write("work/media/$_", "fixture $_\n") for @$files;
|
||||
my ($status, $output) = $image->run('perl',
|
||||
'/repo/xCAT-test/native/fixtures/ubuntu_image/media.pl');
|
||||
is($status, 0, 'copycd request completes') or diag($output);
|
||||
return unless $status == 0;
|
||||
my $result = decode_json($image->read('work/result.json'));
|
||||
is_deeply([grep { $_->{error} || ($_->{data} || '') =~ /^Error/ }
|
||||
@{ $result->{responses} }], [], 'import reports no errors');
|
||||
is_deeply($result->{osdistro}, { arch => 'x86_64', type => 'Linux',
|
||||
dirpaths => '/install/ubuntu24.04/x86_64' }, 'import records the copied distribution');
|
||||
is($result->{detected}, $live, 'media classification matches its contents');
|
||||
my @warnings = map { @{ $_->{warning} || [] } } @{ $result->{responses} };
|
||||
is(scalar @warnings, $live, 'only live media produces a package-source warning');
|
||||
if ($live) {
|
||||
like($warnings[0], qr/not a complete Ubuntu apt package mirror/,
|
||||
'warning explains the live media limitation');
|
||||
like($warnings[0], qr/linuximage\.pkgdir.*linuximage\.otherpkgdir.*HTTP\/HTTPS/,
|
||||
'warning identifies configurable package sources');
|
||||
}
|
||||
ok(grep({ ($_->{data} || '') eq 'Media copy operation successful' }
|
||||
@{ $result->{responses} }), 'request reports a successful import');
|
||||
for my $file (@$files) {
|
||||
is($image->read("install/ubuntu24.04/x86_64/$file"), "fixture $file\n",
|
||||
"$file reaches the copied media");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
done_testing();
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use Test::More;
|
||||
|
||||
use XCAT::Test::File qw(slurp_repo_file);
|
||||
|
||||
my $debian_pm = slurp_repo_file('xCAT-server/lib/xcat/plugins/debian.pm');
|
||||
like( $debian_pm, qr/sub is_ubuntu_live_media/, 'copycds can detect Ubuntu live media' );
|
||||
like( $debian_pm, qr/casper\/install-sources\.yaml/, 'copycds recognizes Subiquity install source metadata' );
|
||||
like( $debian_pm, qr/casper\/\*\.squashfs/, 'copycds recognizes live squashfs media' );
|
||||
like( $debian_pm, qr/not a complete Ubuntu apt package mirror/, 'copycds warns that Ubuntu live media is not a complete apt mirror' );
|
||||
like( $debian_pm, qr/linuximage\.pkgdir.*linuximage\.otherpkgdir.*HTTP\/HTTPS Ubuntu apt repository/s, 'copycds warning points to explicit package source attributes' );
|
||||
|
||||
my $genimage = slurp_repo_file('xCAT-server/share/xcat/netboot/ubuntu/genimage');
|
||||
unlike( $genimage, qr{http://archive\.ubuntu\.com/ubuntu/}, 'Ubuntu genimage does not implicitly use the public amd64 archive' );
|
||||
unlike( $genimage, qr{http://ports\.ubuntu\.com/ubuntu-ports/}, 'Ubuntu genimage does not implicitly use the public ports archive' );
|
||||
like( $genimage, qr{\$aptcmd2 = "--verbose --arch \$uarch \$dist \$rootimg_dir file://\$srcdir"}, 'Ubuntu genimage uses copied local media when no explicit mirror is configured' );
|
||||
like( $genimage, qr/copied Ubuntu media.*complete local Ubuntu apt mirror.*HTTP\/HTTPS Ubuntu apt repository/s, 'Ubuntu genimage gives an actionable package source error' );
|
||||
like( $genimage, qr{\@pkgdir_internet.*?\$aptcmd2 = "--verbose --arch \$uarch \$dist \$rootimg_dir \$mirrorurl"}s, 'Ubuntu genimage still honors an explicit mirror configured in pkgdir' );
|
||||
|
||||
my $copycds_doc = slurp_repo_file('docs/source/guides/admin-guides/references/man8/copycds.8.rst');
|
||||
like( $copycds_doc, qr/Ubuntu live-server media.*not a complete Ubuntu apt package mirror/s, 'copycds documentation explains Ubuntu live media package limits' );
|
||||
|
||||
my $linuximage_doc = slurp_repo_file('docs/source/guides/admin-guides/references/man5/linuximage.5.rst');
|
||||
like( $linuximage_doc, qr/Ubuntu live-server media copied by copycds is not a complete apt package mirror.*HTTP\/HTTPS Ubuntu apt repository/, 'linuximage documentation explains Ubuntu live media package limits' );
|
||||
|
||||
my $osimage_doc = slurp_repo_file('docs/source/guides/admin-guides/references/man7/osimage.7.rst');
|
||||
like( $osimage_doc, qr/Ubuntu live-server media copied by copycds is not a complete apt package mirror.*HTTP\/HTTPS Ubuntu apt repository/, 'osimage documentation explains Ubuntu live media package limits' );
|
||||
|
||||
done_testing();
|
||||
Reference in New Issue
Block a user