mirror of
https://github.com/xcat2/xcat-dep.git
synced 2026-10-17 01:00:35 +00:00
Merge master into fix/openeuler-ppc64le-net-dns
Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
@@ -23,7 +23,14 @@ jobs:
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
apt-utils bats createrepo-c dpkg-dev gnupg \
|
||||
libfile-slurper-perl \
|
||||
libparallel-forkmanager-perl libperl-critic-perl rpm rpm2cpio cpio
|
||||
libparallel-forkmanager-perl libperl-critic-perl rpm rpm2cpio cpio \
|
||||
grub-common ca-certificates
|
||||
|
||||
- name: Install the arm64-efi grub modules
|
||||
# t/aarch64_target.t runs the spec's own grub2-mkimage command, and it skips without
|
||||
# the arm64-efi modules -- a skip exactly where the suite runs. The script reads them
|
||||
# from the runner's own suite through apt's signed metadata.
|
||||
run: sudo ./install-grub-arm64-modules.sh
|
||||
|
||||
- name: Run static checks
|
||||
run: |
|
||||
@@ -75,6 +82,8 @@ jobs:
|
||||
prove -v -It/lib t/genesis_openembedded_release.t
|
||||
sudo -E prove -v -It/lib t/genesis_openembedded_consumer.t
|
||||
prove -v t/riscv64_perl_cell.t
|
||||
prove -v t/aarch64_target.t
|
||||
prove -v t/aarch64_cross_build.t
|
||||
sudo -E prove -v -It/lib t/common-repo-gate.t
|
||||
prove -v t/openeuler.t
|
||||
prove -v t/openeuler_mock_template_include.t
|
||||
@@ -85,6 +94,7 @@ jobs:
|
||||
prove -v -Ilib t/openeuler_native_trust_dbpath.t
|
||||
prove -v -Ilib t/openeuler_native_cpio_scan.t
|
||||
bats t/verify-xcatsn-install.bats
|
||||
bats t/install-grub-arm64-modules.bats
|
||||
|
||||
# Ubuntu's AppArmor policy blocks these unprivileged test namespaces.
|
||||
- name: Run native packaging tests
|
||||
|
||||
@@ -395,6 +395,17 @@ tracked prebuilt EFI payload and `syslinux-xcat` installs the prebuilt bootloade
|
||||
release tarball, so the noarch rpms carry the same payload as the ppc64le build. aarch64 is not
|
||||
part of the `--finalize-xcat-dep` cross-arch genesis copy.
|
||||
|
||||
`aarch64` also builds on an x86_64 host. mock applies `--forcearch=aarch64` to the
|
||||
`alma+epel-10-aarch64` config when the host is not aarch64, so the chroot runs aarch64 binaries
|
||||
through `qemu-aarch64-static` and produces aarch64 rpms. The host needs that emulator and its
|
||||
`binfmt_misc` handler; without them mock warns at the start of the build and the chroot cannot run
|
||||
its own rpm scriptlets. EL packages no `qemu-user-static`, so take the static binary from a Fedora
|
||||
container, as the riscv64 host prerequisites do.
|
||||
|
||||
A cross-build is slower than a native one and is otherwise the same build: the rpms and the
|
||||
repository cell carry the target architecture, not the host one, and the step timeout is the
|
||||
emulated bound.
|
||||
|
||||
# riscv64 (EL10): cross-building on an x86_64 host
|
||||
|
||||
There is no riscv64 build host in the xCAT build farm and no EPEL for riscv64, so the
|
||||
|
||||
+34
-1
@@ -25,7 +25,7 @@ our @EXPORT_OK = qw(
|
||||
cross_copy_genesis finalize_xcat_dep bump_dep_release_suffix
|
||||
createrepo_c_cmd sign_and_index_repo
|
||||
build_mock_uniqueext rpm_in_cell resolve_mock_cfg mock_chroot_uid mock_result_dirs
|
||||
make_traversable_path
|
||||
make_traversable_path epel_target_profile epel_cell_path cell_lock_path
|
||||
native_owner_command NATIVE_BUILD_GID
|
||||
openeuler_build_target openeuler_repo_subdir
|
||||
recover_common_repository
|
||||
@@ -896,6 +896,39 @@ sub recover_common_repository {
|
||||
return 1;
|
||||
}
|
||||
|
||||
# epel_target_profile($target, $host_arch): the EL release, the rpm architecture, and whether
|
||||
# mock cross-builds, for one EPEL target name on one build host. Returns undef for a name that is
|
||||
# not an EPEL target, so the caller keeps its own error.
|
||||
#
|
||||
# The target name carries the architecture of the rpms it produces, and that architecture decides
|
||||
# the repository cell the build deploys to. A host of another architecture cross-builds the target
|
||||
# through mock's own --forcearch and qemu-user; the rpms are still the target's architecture.
|
||||
sub epel_target_profile {
|
||||
my ($target, $host_arch) = @_;
|
||||
return undef unless defined $target && defined $host_arch;
|
||||
my ($rel, $arch) = $target =~ /epel-(\d+)-(.+)\z/;
|
||||
return undef unless defined $rel && defined $arch;
|
||||
return { rel => $rel, arch => $arch, forcearch => ($arch eq $host_arch ? 0 : 1) };
|
||||
}
|
||||
|
||||
# epel_cell_path($repo_dep, $profile): the repository cell an EPEL target deploys,
|
||||
# <repo-dep>/rh<rel>/<arch>, from the profile epel_target_profile returns.
|
||||
#
|
||||
# The deploy, the carry-over and the cell lock all take the path from here, so the lock covers the
|
||||
# directory the deploy writes. Two targets share a lock exactly when they share a cell.
|
||||
sub epel_cell_path {
|
||||
my ($repo_dep, $profile) = @_;
|
||||
return undef unless defined $repo_dep && $profile;
|
||||
return "$repo_dep/rh$profile->{rel}/$profile->{arch}";
|
||||
}
|
||||
|
||||
# cell_lock_path($cell): the lock of a repository cell <dir>/<arch> sits beside it, as
|
||||
# <dir>/.<arch>.lock, because the deploy replaces the cell directory itself.
|
||||
sub cell_lock_path {
|
||||
my ($cell) = @_;
|
||||
return dirname($cell) . '/.' . basename($cell) . '.lock';
|
||||
}
|
||||
|
||||
# resolve_mock_cfg($os_id, $rel, $arch[, $cfg_dir]): the mock config for EL release $rel on this
|
||||
# host, <id>+epel-<rel>-<arch>. /etc/os-release says 'almalinux' where mock-core-configs names the
|
||||
# file 'alma', so the short form is tried too. $cfg_dir defaults to /etc/mock.
|
||||
|
||||
Executable
+154
@@ -0,0 +1,154 @@
|
||||
#!/bin/bash
|
||||
# Install the arm64-efi GRUB modules, so a host grub-mkimage can build the AArch64
|
||||
# network loader of grub2-xcat.spec. Ubuntu ships them only in grub-efi-arm64-bin,
|
||||
# which is Architecture: arm64 and does not install on an amd64 host. The deb is read
|
||||
# through apt's signed metadata, unpacked in a temporary directory, and only the
|
||||
# module files are copied out.
|
||||
#
|
||||
# grub-mkimage embeds kernel.img and resolves moddep.lst from the module directory,
|
||||
# so the modules must come from the GRUB version of the host tool.
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: install-grub-arm64-modules.sh [-d DESTDIR] [-s SUITE] [-m MIRROR]
|
||||
|
||||
-d DESTDIR where the modules go (default /usr/lib/grub/arm64-efi)
|
||||
-s SUITE suite to read (default: VERSION_CODENAME of /etc/os-release)
|
||||
-m MIRROR apt mirror (default https://ports.ubuntu.com/ubuntu-ports)
|
||||
|
||||
apt verifies the suite InRelease signature with the host keyring, and the deb hash
|
||||
against that signed index. The deb is unpacked under ${TMPDIR:-/tmp} and removed on
|
||||
exit. Nothing else from it is installed.
|
||||
EOF
|
||||
}
|
||||
|
||||
PACKAGE=grub-efi-arm64-bin
|
||||
MODULE_PATH=usr/lib/grub/arm64-efi
|
||||
MIRROR_DEFAULT=https://ports.ubuntu.com/ubuntu-ports
|
||||
|
||||
# Prints the GRUB upstream version of the host image builder, e.g. 2.12.
|
||||
# EL names the tool grub2-mkimage and Debian names it grub-mkimage.
|
||||
host_grub_version() {
|
||||
local tool out
|
||||
for tool in grub2-mkimage grub-mkimage; do
|
||||
command -v "$tool" >/dev/null 2>&1 || continue
|
||||
out=$("$tool" --version 2>/dev/null) || continue
|
||||
# "grub-mkimage (GRUB) 2.12-1ubuntu7.3"
|
||||
out=${out##* }
|
||||
echo "${out%%-*}"
|
||||
return 0
|
||||
done
|
||||
echo "no grub2-mkimage and no grub-mkimage on PATH" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
# The upstream version of a deb version: no epoch, no distribution revision.
|
||||
upstream_version() {
|
||||
local v=${1#*:}
|
||||
echo "${v%%-*}"
|
||||
}
|
||||
|
||||
# apt-get against a private state tree, so the host dpkg architecture and the host
|
||||
# sources stay as they are. An unsigned or stale index fails here.
|
||||
apt_get() {
|
||||
local root=$1
|
||||
shift
|
||||
apt-get \
|
||||
-o Dir::State="$root/state" \
|
||||
-o Dir::State::status="$root/status" \
|
||||
-o Dir::Cache="$root/cache" \
|
||||
-o Dir::Etc::SourceList="$root/sources.list" \
|
||||
-o Dir::Etc::SourceParts="$root/none" \
|
||||
-o Dir::Etc::Preferences="$root/none/preferences" \
|
||||
-o Dir::Etc::PreferencesParts="$root/none" \
|
||||
-o APT::Architecture=arm64 \
|
||||
-o APT::Architectures=arm64 \
|
||||
-o APT::Sandbox::User=root \
|
||||
-o Acquire::AllowInsecureRepositories=false \
|
||||
-o APT::Get::AllowUnauthenticated=false \
|
||||
"$@"
|
||||
}
|
||||
|
||||
main() {
|
||||
local dest=/usr/lib/grub/arm64-efi suite='' mirror=$MIRROR_DEFAULT opt
|
||||
OPTIND=1
|
||||
while getopts 'd:s:m:h' opt; do
|
||||
case $opt in
|
||||
d) dest=$OPTARG ;;
|
||||
s) suite=$OPTARG ;;
|
||||
m) mirror=$OPTARG ;;
|
||||
h) usage; return 0 ;;
|
||||
*) usage >&2; return 2 ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
if (( $# != 0 )); then
|
||||
usage >&2
|
||||
return 2
|
||||
fi
|
||||
if [[ -z $suite ]]; then
|
||||
suite=$(. /etc/os-release 2>/dev/null && echo "$VERSION_CODENAME")
|
||||
fi
|
||||
if [[ -z $suite ]]; then
|
||||
echo "no suite: /etc/os-release names no VERSION_CODENAME, give -s" >&2
|
||||
return 2
|
||||
fi
|
||||
|
||||
local want
|
||||
want=$(host_grub_version) || return 1
|
||||
|
||||
local root
|
||||
root=$(mktemp -d "${TMPDIR:-/tmp}/grub-arm64.XXXXXX") || return 1
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '$root'" EXIT
|
||||
mkdir -p "$root/state/lists/partial" "$root/cache/archives/partial" "$root/none" "$root/deb" || return 1
|
||||
: > "$root/status"
|
||||
printf 'deb [arch=arm64] %s %s main\n' "$mirror" "$suite" > "$root/sources.list" || return 1
|
||||
|
||||
if ! apt_get "$root" update; then
|
||||
echo "FAIL: apt-get update of $mirror $suite failed" >&2
|
||||
return 1
|
||||
fi
|
||||
if ! (cd "$root/deb" && apt_get "$root" download "$PACKAGE"); then
|
||||
echo "FAIL: apt-get download $PACKAGE from $suite failed" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local deb
|
||||
deb=$(find "$root/deb" -maxdepth 1 -name "${PACKAGE}_*_arm64.deb" | sort | head -1)
|
||||
if [[ -z $deb ]]; then
|
||||
echo "FAIL: apt downloaded no $PACKAGE deb" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local got
|
||||
got=$(dpkg-deb -f "$deb" Version) || return 1
|
||||
got=$(upstream_version "$got")
|
||||
if [[ $got != "$want" ]]; then
|
||||
echo "FAIL: $PACKAGE is GRUB $got and the host image builder is GRUB $want" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
dpkg-deb -x "$deb" "$root/x" || return 1
|
||||
if [[ ! -d $root/x/$MODULE_PATH ]]; then
|
||||
echo "FAIL: $PACKAGE carries no $MODULE_PATH" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# The modules, moddep.lst and kernel.img, and none of the documentation or the
|
||||
# prebuilt images under monolithic/ that the deb also carries.
|
||||
install -d "$dest" || return 1
|
||||
find "$root/x/$MODULE_PATH" -maxdepth 1 -type f -exec install -m 0644 -t "$dest" {} + || return 1
|
||||
|
||||
local count
|
||||
count=$(find "$dest" -maxdepth 1 -name '*.mod' | wc -l)
|
||||
if (( count == 0 )) || [[ ! -f $dest/kernel.img || ! -f $dest/moddep.lst ]]; then
|
||||
echo "FAIL: $dest has no modules, no kernel.img or no moddep.lst" >&2
|
||||
return 1
|
||||
fi
|
||||
echo "PASS: $count arm64-efi modules of GRUB $got in $dest, from ${deb##*/}"
|
||||
}
|
||||
|
||||
if [[ ${BASH_SOURCE[0]} == "$0" ]]; then
|
||||
main "$@"
|
||||
fi
|
||||
+10
-15
@@ -19,7 +19,7 @@ use FindBin qw($RealBin);
|
||||
use lib $RealBin, "$RealBin/lib";
|
||||
use XCAT::NFSLock ();
|
||||
use MockBuildUtils qw(sh_quote print_step version_matches required_pkgs rpm_in_cell resolve_mock_cfg
|
||||
NATIVE_BUILD_GID
|
||||
NATIVE_BUILD_GID epel_target_profile epel_cell_path cell_lock_path
|
||||
carry_over_rpms rpm_name rpm_arch rpm_source_rpm rpm_digests_ok
|
||||
install_deps_packages install_deps_command missing_perl_modules
|
||||
read_manifest derive_target_from_repo_path
|
||||
@@ -1179,13 +1179,16 @@ sub target_profile {
|
||||
epel => 0,
|
||||
};
|
||||
}
|
||||
my ($rel) = $target =~ /epel-(\d+)-/;
|
||||
die "Could not parse EL release from target '$target'\n" unless defined $rel;
|
||||
# The target name, not the host, decides the architecture of the rpms and so the repository
|
||||
# cell they deploy to. A host of another architecture cross-builds the target through mock's
|
||||
# own --forcearch, which is what gives the emulated build its own step timeout below.
|
||||
my $epel = epel_target_profile($target, $host_arch);
|
||||
die "Could not parse EL release from target '$target'\n" unless $epel;
|
||||
return {
|
||||
rel => $rel,
|
||||
arch => $host_arch,
|
||||
rel => $epel->{rel},
|
||||
arch => $epel->{arch},
|
||||
noarch_cfg => $target,
|
||||
forcearch => 0,
|
||||
forcearch => $epel->{forcearch},
|
||||
epel => 1,
|
||||
dep_builders => [qw(elilo-xcat grub2-xcat ipmitool-xcat syslinux-xcat goconserver conserver-xcat xnba-undi ipxe-xcat)],
|
||||
# xCAT Requires all of these on every arch, and every one of them builds natively on
|
||||
@@ -2490,15 +2493,7 @@ sub target_cell {
|
||||
my ($target) = @_;
|
||||
my $native = openeuler_repo_subdir($target);
|
||||
return "$repo_dep/$native" if defined $native;
|
||||
my $profile = target_profile($target);
|
||||
return "$repo_dep/rh$profile->{rel}/$profile->{arch}";
|
||||
}
|
||||
|
||||
# The lock of a repository cell <dir>/<arch> sits beside it, as <dir>/.<arch>.lock: the deploy
|
||||
# replaces the cell directory itself.
|
||||
sub cell_lock_path {
|
||||
my ($cell) = @_;
|
||||
return dirname($cell) . '/.' . basename($cell) . '.lock';
|
||||
return epel_cell_path($repo_dep, target_profile($target));
|
||||
}
|
||||
|
||||
# Release locks on every exit path, but only from the process that acquired them.
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env perl
|
||||
# An EPEL target names the architecture of the rpms it produces, and that architecture decides
|
||||
# the repository cell the build deploys to. A build host whose own architecture differs
|
||||
# cross-builds the target through mock's --forcearch and qemu-user; the rpms are still the
|
||||
# target's architecture.
|
||||
#
|
||||
# alma+epel-10-aarch64 built on an x86_64 host reported arch=x86_64, so target_cell resolved to
|
||||
# rh10/x86_64 and the aarch64 build would have replaced the x86_64 cell of the published
|
||||
# repository with aarch64 rpms. It also reported forcearch=0, which left the emulated build with
|
||||
# the native step timeout.
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin qw($RealBin);
|
||||
use Test::More;
|
||||
|
||||
use lib $RealBin, "$RealBin/..";
|
||||
use MockBuildUtils qw(epel_target_profile epel_cell_path cell_lock_path);
|
||||
|
||||
# A cross-built target: the rpms and the cell are the target's architecture, not the host's.
|
||||
{
|
||||
my $p = epel_target_profile('alma+epel-10-aarch64', 'x86_64');
|
||||
ok($p, 'alma+epel-10-aarch64 is an EPEL target') or done_testing, exit;
|
||||
is($p->{rel}, '10', 'EL release 10');
|
||||
is($p->{arch}, 'aarch64', 'the rpm architecture is the target architecture, not the host one');
|
||||
is($p->{forcearch}, 1, 'an x86_64 host cross-builds it');
|
||||
}
|
||||
|
||||
# The same target on its own architecture is a native build.
|
||||
{
|
||||
my $p = epel_target_profile('alma+epel-10-aarch64', 'aarch64');
|
||||
is($p->{arch}, 'aarch64', 'a native aarch64 build still produces aarch64 rpms');
|
||||
is($p->{forcearch}, 0, 'and does not cross-build');
|
||||
}
|
||||
|
||||
# Every target that builds today keeps the answer it has today: same arch, no cross-build.
|
||||
for my $case (['alma+epel-10-x86_64', 'x86_64', '10'],
|
||||
['alma+epel-9-x86_64', 'x86_64', '9'],
|
||||
['alma+epel-8-x86_64', 'x86_64', '8'],
|
||||
['alma+epel-10-ppc64le', 'ppc64le', '10'],
|
||||
['alma+epel-9-ppc64le', 'ppc64le', '9'],
|
||||
['alma+epel-8-ppc64le', 'ppc64le', '8'])
|
||||
{
|
||||
my ($target, $host, $rel) = @$case;
|
||||
my $p = epel_target_profile($target, $host);
|
||||
is($p->{rel}, $rel, "$target on $host: EL release $rel");
|
||||
is($p->{arch}, $host, "$target on $host: builds natively for $host");
|
||||
is($p->{forcearch}, 0, "$target on $host: no cross-build");
|
||||
}
|
||||
|
||||
# The two EL10 targets deploy to different cells, so they take different cell locks. With the
|
||||
# architecture taken from the host, both resolved to rh10/x86_64 and to one lock: the aarch64 build
|
||||
# on xcat-master held .x86_64.lock, and the x86_64 build of the same run waited out its 100 retries
|
||||
# and exited before it built anything (xcat-dep-build-el10-x86_64 builds 92 and 93).
|
||||
{
|
||||
my $repo = '/repo/yum/xcat-dep';
|
||||
my %cell = map { $_ => epel_cell_path($repo, epel_target_profile("alma+epel-10-$_", 'x86_64')) }
|
||||
qw(x86_64 aarch64);
|
||||
is($cell{aarch64}, "$repo/rh10/aarch64", 'the aarch64 target deploys to the aarch64 cell');
|
||||
is($cell{x86_64}, "$repo/rh10/x86_64", 'the x86_64 target deploys to the x86_64 cell');
|
||||
isnt(cell_lock_path($cell{aarch64}), cell_lock_path($cell{x86_64}),
|
||||
'the two EL10 targets of one host take different cell locks');
|
||||
is(cell_lock_path($cell{aarch64}), "$repo/rh10/.aarch64.lock",
|
||||
'a cell lock sits beside its cell');
|
||||
}
|
||||
|
||||
# A name that is not an EPEL target is refused, so the caller can keep its own error. The
|
||||
# forcearch and openEuler targets are resolved before this sub is reached.
|
||||
for my $not (qw(rocky-10-riscv64-xcat openeuler-24.03sp4-x86_64 noble)) {
|
||||
is(epel_target_profile($not, 'x86_64'), undef, "'$not' is not an EPEL target");
|
||||
}
|
||||
|
||||
done_testing;
|
||||
+8
-2
@@ -130,11 +130,17 @@ my $grub_spec = slurp($grub_spec_file);
|
||||
# build does not carry, or efi_uga, makes grub2-mkimage fail.
|
||||
SKIP: {
|
||||
my $moddir = '/usr/lib/grub/arm64-efi';
|
||||
skip 'grub2-mkimage or the arm64-efi grub modules are not installed', 4
|
||||
unless -d $moddir && system('command -v grub2-mkimage >/dev/null 2>&1') == 0;
|
||||
# Debian and Ubuntu name the tool grub-mkimage and EL names it grub2-mkimage. The CI
|
||||
# runner is Ubuntu, so looking only for the EL name skips the checks exactly where the
|
||||
# suite runs, which measures nothing.
|
||||
my ($mkimage) = grep { system("command -v $_ >/dev/null 2>&1") == 0 }
|
||||
qw(grub2-mkimage grub-mkimage);
|
||||
skip 'no grub2-mkimage or grub-mkimage, or the arm64-efi grub modules are not installed', 4
|
||||
unless -d $moddir && $mkimage;
|
||||
skip 'no grub2-mkimage command in the spec', 4 if $cmd eq '';
|
||||
my $tmp = tempdir(CLEANUP => 1);
|
||||
my $run = $cmd;
|
||||
$run =~ s/\Agrub2-mkimage\b/$mkimage/;
|
||||
$run =~ s/(?<=\s-o\s)\S+/$tmp\/grubaa64.efi/;
|
||||
is(system("$run >/dev/null 2>&1"), 0, "the spec's grub2-mkimage command succeeds");
|
||||
my $image = '';
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/env bats
|
||||
# Unit tests for install-grub-arm64-modules.sh. apt-get, dpkg-deb and the grub
|
||||
# image builder are shell functions here, so no archive is read and the modules
|
||||
# land only under BATS_TEST_TMPDIR.
|
||||
|
||||
setup() {
|
||||
source "$BATS_TEST_DIRNAME/../install-grub-arm64-modules.sh"
|
||||
export TMPDIR=$BATS_TEST_TMPDIR
|
||||
CALLS=$BATS_TEST_TMPDIR/calls
|
||||
DEST=$BATS_TEST_TMPDIR/dest
|
||||
DEB_VERSION=2.12-1ubuntu7
|
||||
TOOL_VERSION=2.12-1ubuntu7.3
|
||||
DEB_HAS_MODULES=1
|
||||
}
|
||||
|
||||
# Both names, because the loop takes whichever the host has and a developer host
|
||||
# may carry the real EL one.
|
||||
grub2-mkimage() {
|
||||
echo "grub2-mkimage (GRUB) $TOOL_VERSION"
|
||||
}
|
||||
|
||||
grub-mkimage() {
|
||||
echo "grub-mkimage (GRUB) $TOOL_VERSION"
|
||||
}
|
||||
|
||||
apt-get() {
|
||||
echo "apt-get $*" >>"$CALLS"
|
||||
local list
|
||||
list=$(printf '%s\n' "$@" | sed -nE 's/^Dir::Etc::SourceList=//p')
|
||||
[ -z "$list" ] || cp "$list" "$BATS_TEST_TMPDIR/sources.list.seen"
|
||||
case " $* " in
|
||||
*" download "*)
|
||||
# apt-get download writes the deb into the working directory.
|
||||
: >"grub-efi-arm64-bin_${DEB_VERSION}_arm64.deb"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# A deb tree with the module directory, the documentation and the prebuilt images
|
||||
# the real grub-efi-arm64-bin carries.
|
||||
dpkg-deb() {
|
||||
echo "dpkg-deb $*" >>"$CALLS"
|
||||
case $1 in
|
||||
-f) echo "$DEB_VERSION" ;;
|
||||
-x)
|
||||
local out=$3 mod=$3/usr/lib/grub/arm64-efi
|
||||
if [[ $out != "$BATS_TEST_TMPDIR"/* ]]; then
|
||||
echo "dpkg-deb -x outside the temporary tree: $out" >&2
|
||||
return 1
|
||||
fi
|
||||
mkdir -p "$out/usr/share/doc/grub-efi-arm64-bin"
|
||||
: >"$out/usr/share/doc/grub-efi-arm64-bin/copyright"
|
||||
(( DEB_HAS_MODULES )) || return 0
|
||||
mkdir -p "$mod/monolithic"
|
||||
local m
|
||||
for m in normal linux tftp efinet; do : >"$mod/$m.mod"; done
|
||||
: >"$mod/kernel.img"
|
||||
: >"$mod/moddep.lst"
|
||||
: >"$mod/monolithic/grubnetaa64.efi"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
leftover_dirs() {
|
||||
find "$BATS_TEST_TMPDIR" -maxdepth 1 -name 'grub-arm64.*' | wc -l
|
||||
}
|
||||
|
||||
@test "an operand is a usage error" {
|
||||
run main noble
|
||||
[ "$status" -eq 2 ]
|
||||
[[ $output == Usage:* ]]
|
||||
}
|
||||
|
||||
@test "an unknown option is a usage error" {
|
||||
run main -z
|
||||
[ "$status" -eq 2 ]
|
||||
[[ $output == *Usage:* ]]
|
||||
}
|
||||
|
||||
@test "the upstream version of a deb version drops the epoch and the revision" {
|
||||
[ "$(upstream_version 1:2.12-1ubuntu7.3)" = 2.12 ]
|
||||
[ "$(upstream_version 2.06-104)" = 2.06 ]
|
||||
}
|
||||
|
||||
@test "the host GRUB version comes from the image builder on PATH" {
|
||||
[ "$(host_grub_version)" = 2.12 ]
|
||||
}
|
||||
|
||||
@test "no image builder on PATH stops the run before any download" {
|
||||
host_grub_version() { echo "no grub2-mkimage and no grub-mkimage on PATH" >&2; return 1; }
|
||||
run main -d "$DEST" -s noble
|
||||
[ "$status" -eq 1 ]
|
||||
[ ! -e "$CALLS" ]
|
||||
}
|
||||
|
||||
@test "apt reads the given suite and mirror, with authentication left on" {
|
||||
run main -d "$DEST" -s jammy -m https://mirror.example/ubuntu-ports
|
||||
[ "$status" -eq 0 ]
|
||||
grep -q -- '-o APT::Get::AllowUnauthenticated=false' "$CALLS"
|
||||
grep -q -- '-o Acquire::AllowInsecureRepositories=false' "$CALLS"
|
||||
grep -q -- '-o APT::Architectures=arm64' "$CALLS"
|
||||
grep -q 'apt-get .* update' "$CALLS"
|
||||
grep -q 'download grub-efi-arm64-bin' "$CALLS"
|
||||
# The suite and the mirror reach apt through its own sources.list, and the host
|
||||
# sources and dpkg architectures are never read or changed.
|
||||
local list
|
||||
list=$(sed -nE 's/.*-o Dir::Etc::SourceList=([^ ]+).*/\1/p' "$CALLS" | head -1)
|
||||
[ "$(cat "$BATS_TEST_TMPDIR/sources.list.seen")" = "deb [arch=arm64] https://mirror.example/ubuntu-ports jammy main" ]
|
||||
[[ $list == "$BATS_TEST_TMPDIR"/grub-arm64.*/sources.list ]]
|
||||
}
|
||||
|
||||
@test "only the module files are installed, and the temporary tree is removed" {
|
||||
run main -d "$DEST" -s noble
|
||||
[ "$status" -eq 0 ]
|
||||
[[ $output == "PASS: 4 arm64-efi modules of GRUB 2.12 in $DEST, from grub-efi-arm64-bin_2.12-1ubuntu7_arm64.deb" ]]
|
||||
[ -f "$DEST/normal.mod" ]
|
||||
[ -f "$DEST/kernel.img" ]
|
||||
[ -f "$DEST/moddep.lst" ]
|
||||
# Not the documentation, and not the prebuilt images of monolithic/.
|
||||
[ ! -e "$DEST/usr" ]
|
||||
[ ! -e "$DEST/monolithic" ]
|
||||
[ ! -e "$DEST/copyright" ]
|
||||
[ "$(find "$DEST" -mindepth 1 | wc -l)" -eq 6 ]
|
||||
[ "$(leftover_dirs)" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "a deb of another GRUB version than the host tool installs nothing" {
|
||||
DEB_VERSION=2.06-1ubuntu1
|
||||
run main -d "$DEST" -s noble
|
||||
[ "$status" -eq 1 ]
|
||||
[[ $output == *"grub-efi-arm64-bin is GRUB 2.06 and the host image builder is GRUB 2.12"* ]]
|
||||
[ ! -e "$DEST" ]
|
||||
[ "$(leftover_dirs)" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "a deb without the module directory installs nothing" {
|
||||
DEB_HAS_MODULES=0
|
||||
run main -d "$DEST" -s noble
|
||||
[ "$status" -eq 1 ]
|
||||
[[ $output == *"carries no usr/lib/grub/arm64-efi"* ]]
|
||||
[ ! -e "$DEST" ]
|
||||
}
|
||||
|
||||
@test "a failed apt-get update stops the run before the download" {
|
||||
apt-get() {
|
||||
echo "apt-get $*" >>"$CALLS"
|
||||
case " $* " in *" update "*) return 100 ;; esac
|
||||
}
|
||||
run main -d "$DEST" -s noble
|
||||
[ "$status" -eq 1 ]
|
||||
[[ $output == *"apt-get update of https://ports.ubuntu.com/ubuntu-ports noble failed"* ]]
|
||||
! grep -q 'download' "$CALLS"
|
||||
[ ! -e "$DEST" ]
|
||||
}
|
||||
|
||||
@test "a download that yields no deb is not reported as a success" {
|
||||
apt-get() { echo "apt-get $*" >>"$CALLS"; }
|
||||
run main -d "$DEST" -s noble
|
||||
[ "$status" -eq 1 ]
|
||||
[[ $output == *"apt downloaded no grub-efi-arm64-bin deb"* ]]
|
||||
[ ! -e "$DEST" ]
|
||||
}
|
||||
Reference in New Issue
Block a user