diff --git a/xCAT-test/bats/fixtures/go-xcat-common.sh b/xCAT-test/bats/fixtures/go-xcat-common.sh new file mode 100644 index 000000000..74e820ef3 --- /dev/null +++ b/xCAT-test/bats/fixtures/go-xcat-common.sh @@ -0,0 +1,18 @@ +#!/bin/bash +PATH="" +source /tmp/go-xcat || exit 70 +TMP_DIR=/tmp/fixture +GO_XCAT_DEFAULT_BASE_URL=https://repo.example.invalid +GO_XCAT_DEFAULT_INSTALL_PATH=/tmp/fixture/install + +yum() { printf '%s\n' "$*" >> /tmp/fixture/yum.log; } +download_file() +{ + printf '%s\n' "$1" >> /tmp/fixture/download.log + [ "$COMMON_PRESENT" = 1 ] || return 1 + printf '\n' > "$2" +} + +add_xcat_dep_common_repo_yum_or_zypper "$1" "$2" || exit $? +refresh_xcat_dep_repository_ids +printf '%s\n' "${GO_XCAT_DEP_REPOSITORY_IDS[*]}" > /tmp/fixture/ids diff --git a/xCAT-test/bats/go_xcat_common_repository.bats b/xCAT-test/bats/go_xcat_common_repository.bats index b49f4fce0..0a36d4ea3 100644 --- a/xCAT-test/bats/go_xcat_common_repository.bats +++ b/xCAT-test/bats/go_xcat_common_repository.bats @@ -4,119 +4,74 @@ load 'helpers/go_xcat' setup() { - go_xcat_require_source + [ "$(uname -s)" = Linux ] || skip 'repository checks require Linux namespaces' + GO_XCAT_SOURCE="${XCAT_TEST_GO_XCAT:-$(go_xcat_default_source)}" + [ -r "$GO_XCAT_SOURCE" ] || return 1 + [ -n "$BATS_TEST_TMPDIR" ] || return 1 + fixture="$BATS_TEST_TMPDIR/repository" + mkdir -p "$fixture/etc/yum.repos.d" + COMMON_PRESENT=1 } -run_common_repository_case() +configure_repository() { - local case_dir="$1" - local common_present="$2" - shift 2 - - mkdir -p "$case_dir" - export ADD_LOG="${case_dir}/add.log" - export COMMON_PRESENT="$common_present" - export DOWNLOAD_LOG="${case_dir}/download.log" - export ID_LOG="${case_dir}/id.log" - export TEST_TMP="$case_dir" - - go_xcat_load_functions \ - add_xcat_dep_common_repo_yum_or_zypper \ - xcat_dep_common_repo_configured \ - refresh_xcat_dep_repository_ids - - TMP_DIR="$TEST_TMP" - GO_XCAT_DEFAULT_BASE_URL=https://repo.example.invalid - GO_XCAT_DEP_REPOSITORY_IDS=(xcat-dep) - - yum() { :; } - - download_file() - { - printf '%s\n' "$1" >>"$DOWNLOAD_LOG" - [[ ${COMMON_PRESENT:-0} == 1 ]] || return 1 - : >"$2" - } - - add_repo_by_url_yum_or_zypper() - { - printf '%s %s\n' "$1" "$2" >>"$ADD_LOG" - } - - xcat_dep_common_repo_configured() - { - [[ -s "$ADD_LOG" ]] - } - - ( add_xcat_dep_common_repo_yum_or_zypper "$@" ) - refresh_xcat_dep_repository_ids - printf '%s\n' "${GO_XCAT_DEP_REPOSITORY_IDS[*]}" >"$ID_LOG" + bwrap --die-with-parent --unshare-net --ro-bind / / --dev /dev --proc /proc \ + --tmpfs /tmp --ro-bind "$BATS_TEST_DIRNAME/../.." /tmp/source \ + --ro-bind "$GO_XCAT_SOURCE" /tmp/go-xcat \ + --bind "$fixture" /tmp/fixture --bind "$fixture/etc" /etc \ + --setenv COMMON_PRESENT "$COMMON_PRESENT" --chdir /tmp/fixture \ + bash /tmp/source/xCAT-test/bats/fixtures/go-xcat-common.sh "$@" } -run_template_generation() -{ - local tmp_dir="$1" - local repo_log="$2" - - mkdir -p "$tmp_dir" - export REPO_LOG="$repo_log" - export TEST_TMP="$tmp_dir" - - go_xcat_load_functions add_repo_by_url_yum_or_zypper - - TMP_DIR="$TEST_TMP" - GO_XCAT_DEFAULT_INSTALL_PATH=/install/xcat - yum() { :; } - add_repo_by_file() { cp "$1" "$REPO_LOG"; } - - add_repo_by_url_yum_or_zypper \ - https://repo.example.invalid/xcat-dep/common xcat-dep-common optional -} - -@test "an available remote common repository is enabled" { - local case_dir="${BATS_TEST_TMPDIR}/remote-present" - - run run_common_repository_case "$case_dir" 1 "" latest - [ "$status" -eq 0 ] - [ "$(read_file_or_empty "${case_dir}/download.log")" = "https://repo.example.invalid/yum/latest/xcat-dep/common/repodata/repomd.xml" ] - [ "$(read_file_or_empty "${case_dir}/add.log")" = "https://repo.example.invalid/yum/latest/xcat-dep/common xcat-dep-common" ] - [ "$(read_file_or_empty "${case_dir}/id.log")" = "xcat-dep xcat-dep-common" ] +@test "an available remote common repository is installed and activated" { + run configure_repository '' latest + [ "$status" -eq 0 ] || { printf '%s\n' "$output"; return 1; } + [ "$(cat "$fixture/download.log")" = 'https://repo.example.invalid/yum/latest/xcat-dep/common/repodata/repomd.xml' ] + [ "$(cat "$fixture/ids")" = 'xcat-dep xcat-dep-common' ] + repo="$fixture/etc/yum.repos.d/xcat-dep-common.repo" + grep -Fxq '[xcat-dep-common]' "$repo" + grep -Fxq 'baseurl=https://repo.example.invalid/yum/latest/xcat-dep/common' "$repo" + grep -Fxq 'enabled=1' "$repo" + grep -Fxq 'skip_if_unavailable=1' "$repo" + grep -Fxq 'repo_gpgcheck=1' "$repo" + grep -Fxq 'gpgcheck=1' "$repo" + grep -Fxq 'gpgkey=https://repo.example.invalid/yum/latest/xcat-dep/common/repodata/repomd.xml.key' "$repo" + [ "$(cat "$fixture/yum.log")" = 'clean metadata' ] } @test "a release without the remote common repository remains usable" { - local case_dir="${BATS_TEST_TMPDIR}/remote-missing" - - run run_common_repository_case "$case_dir" 0 "" 2.18 + COMMON_PRESENT=0 + run configure_repository '' 2.18 [ "$status" -eq 0 ] - [ "$(read_file_or_empty "${case_dir}/add.log")" = "" ] - [ "$(read_file_or_empty "${case_dir}/id.log")" = "xcat-dep" ] + [ "$(cat "$fixture/ids")" = xcat-dep ] + [ ! -e "$fixture/etc/yum.repos.d/xcat-dep-common.repo" ] + [ ! -e "$fixture/yum.log" ] } @test "a custom repository file does not guess an unrelated common repository" { - local case_dir="${BATS_TEST_TMPDIR}/repo-file" - - run run_common_repository_case "$case_dir" 1 https://repo.example.invalid/custom/xcat-dep.repo latest + run configure_repository https://repo.example.invalid/custom/xcat-dep.repo latest [ "$status" -eq 0 ] - [ "$(read_file_or_empty "${case_dir}/download.log")" = "" ] - [ "$(read_file_or_empty "${case_dir}/add.log")" = "" ] + [ ! -e "$fixture/download.log" ] + [ ! -e "$fixture/etc/yum.repos.d/xcat-dep-common.repo" ] + [ "$(cat "$fixture/ids")" = xcat-dep ] } -@test "a local common repository is enabled beside the distribution repository" { - local local_root="${BATS_TEST_TMPDIR}/local-repository" - local case_dir="${BATS_TEST_TMPDIR}/local-present" - mkdir -p "${local_root}/common/repodata" - : >"${local_root}/common/repodata/repomd.xml" - - run run_common_repository_case "$case_dir" 0 "$local_root" latest - [ "$status" -eq 0 ] - [ "$(read_file_or_empty "${case_dir}/add.log")" = "${local_root}/common xcat-dep-common" ] +@test "a local common repository is installed beside the distribution repository" { + mkdir -p "$fixture/local/common/repodata" + printf '\n' > "$fixture/local/common/repodata/repomd.xml" + run configure_repository /tmp/fixture/local latest + [ "$status" -eq 0 ] || { printf '%s\n' "$output"; return 1; } + [ ! -e "$fixture/download.log" ] + [ "$(cat "$fixture/ids")" = 'xcat-dep xcat-dep-common' ] + grep -Fxq 'baseurl=file:///tmp/fixture/local/common' "$fixture/etc/yum.repos.d/xcat-dep-common.repo" } -@test "the optional common repository template tolerates outages and verifies metadata" { - local template_log="${BATS_TEST_TMPDIR}/generated-common.repo" - - run run_template_generation "$BATS_TEST_TMPDIR" "$template_log" +@test "an existing zypper common repository is retained without a new download" { + mkdir -p "$fixture/etc/zypp/repos.d" + printf '[xcat-dep-common]\n' > "$fixture/etc/zypp/repos.d/xcat-dep-common.repo" + COMMON_PRESENT=0 + run configure_repository '' latest [ "$status" -eq 0 ] - grep -Fxq 'skip_if_unavailable=1' "$template_log" - grep -Fxq 'repo_gpgcheck=1' "$template_log" + [ "$(cat "$fixture/ids")" = 'xcat-dep xcat-dep-common' ] + [ "$(cat "$fixture/etc/zypp/repos.d/xcat-dep-common.repo")" = '[xcat-dep-common]' ] } diff --git a/xCAT-test/bats/go_xcat_genesis_package_names.bats b/xCAT-test/bats/go_xcat_genesis_package_names.bats index 68913d0c2..5da69f552 100644 --- a/xCAT-test/bats/go_xcat_genesis_package_names.bats +++ b/xCAT-test/bats/go_xcat_genesis_package_names.bats @@ -13,31 +13,26 @@ load 'helpers/shell_source' setup() { - go_xcat_require_source + GO_XCAT_SOURCE="${XCAT_TEST_GO_XCAT:-$(go_xcat_default_source)}" + export GO_XCAT_SOURCE SCRIPTS_DEBIAN="$(repo_path 'xCAT-genesis-scripts/debian')" SPEC="$(repo_path 'xCAT-genesis-base/xCAT-genesis-base.spec')" - [ -d "$SCRIPTS_DEBIAN" ] || skip "$SCRIPTS_DEBIAN is required" - [ -r "$SPEC" ] || skip "$SPEC is required" + [ -r "$GO_XCAT_SOURCE" ] || return 1 + [ -d "$SCRIPTS_DEBIAN" ] || return 1 + [ -r "$SPEC" ] || return 1 export SCRIPTS_DEBIAN SPEC } -# Run the array definitions of go-xcat and print the two lists it built, one per line. package_lists() { - local want_dpkg="$1" list_body - list_body="$(awk ' - /^GO_XCAT_INSTALL_LIST=\(/ { copy = 1 } - /^PATH=/ { exit } - copy { print } - ' "$GO_XCAT_SOURCE")" - [ -n "$list_body" ] || { echo 'go-xcat package arrays not found' >&2; return 3; } + local want_dpkg="$1" ( if [ "$want_dpkg" = 1 ]; then dpkg() { :; } fi # A real dpkg on the build host would select the deb branch on every run. PATH="" - eval "$list_body" + source "$GO_XCAT_SOURCE" || exit 70 printf 'install %s\n' "${GO_XCAT_INSTALL_LIST[*]}" printf 'uninstall %s\n' "${GO_XCAT_UNINSTALL_LIST[*]}" ) diff --git a/xCAT-test/unit/destiny_genesis_architecture.t b/xCAT-test/unit/destiny_genesis_architecture.t index e98aa678d..4204757f0 100644 --- a/xCAT-test/unit/destiny_genesis_architecture.t +++ b/xCAT-test/unit/destiny_genesis_architecture.t @@ -5,27 +5,26 @@ use warnings; use File::Path qw(make_path); use File::Temp qw(tempdir); use FindBin; +use lib "$FindBin::Bin/../lib"; +use lib "$FindBin::Bin/../../perl-xCAT"; +use lib "$FindBin::Bin/../../xCAT-server/lib/perl"; use Test::More; - -my $source = "$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/destiny.pm"; -open(my $source_fh, '<', $source) or die "open $source: $!"; -my $content = do { local $/; <$source_fh> }; -close($source_fh) or die "close $source: $!"; - -my @routines; -for my $name (qw(_genesis_boot_arch _genesis_uses_power_console)) { - my ($routine) = $content =~ /^(sub \Q$name\E\s*\{.*?^\})/ms; - BAIL_OUT("could not extract $name from destiny.pm") unless $routine; - push(@routines, $routine); -} -eval join("\n", @routines); ## no critic (BuiltinFunctions::ProhibitStringyEval) -BAIL_OUT("could not load Genesis architecture helpers: $@") if $@; +use XCAT::Test::File qw(repo_path); my $tftp = tempdir(CLEANUP => 1); -make_path("$tftp/xcat"); +$ENV{XCATROOT} = repo_path('xCAT-server'); +$ENV{XCATCFG} = "$tftp/config"; +make_path("$tftp/xcat", $ENV{XCATCFG}); +require xCAT::TableUtils; +{ + no warnings qw(redefine once); + local *xCAT::TableUtils::get_site_attribute = sub { return (0); }; + local $INC{'xCAT_monitoring/monitorctrl.pm'} = __FILE__; + require(repo_path('xCAT-server/lib/xcat/plugins/destiny.pm')); +} is( - _genesis_boot_arch($tftp, 'ppc64le'), + xCAT_plugin::destiny::_genesis_boot_arch($tftp, 'ppc64le'), 'ppc64', 'ppc64le keeps the legacy POWER fallback when no exact image exists', ); @@ -35,7 +34,7 @@ open(my $marker_fh, '>', "$tftp/xcat/genesis.exact-arch.ppc64") close($marker_fh) or die "close exact POWER marker: $!"; is( - _genesis_boot_arch($tftp, 'ppc64le'), + xCAT_plugin::destiny::_genesis_boot_arch($tftp, 'ppc64le'), 'ppc64le', 'ppc64le does not fall back to a canonical big-endian ppc64 image', ); @@ -47,25 +46,21 @@ open(my $kernel_fh, '>', "$tftp/xcat/genesis.kernel.ppc64le") close($kernel_fh) or die "close exact POWER kernel: $!"; is( - _genesis_boot_arch($tftp, 'ppc64le'), + xCAT_plugin::destiny::_genesis_boot_arch($tftp, 'ppc64le'), 'ppc64le', 'ppc64le uses the exact OpenEmbedded boot artifact', ); is( - _genesis_boot_arch($tftp, 'ppc64el'), + xCAT_plugin::destiny::_genesis_boot_arch($tftp, 'ppc64el'), 'ppc64le', 'the Debian spelling resolves to the exact ppc64le artifact', ); -is(_genesis_boot_arch($tftp, 'x86_64'), 'x86_64', 'other architectures are unchanged'); +is(xCAT_plugin::destiny::_genesis_boot_arch($tftp, 'x86_64'), 'x86_64', 'other architectures are unchanged'); -ok(_genesis_uses_power_console('ppc64'), 'legacy POWER uses the hypervisor console'); -ok(_genesis_uses_power_console('ppc64le'), 'ppc64le uses the hypervisor console'); -ok(!_genesis_uses_power_console('x86_64'), 'x86_64 keeps the serial console path'); - -like( - $content, - qr/my \$arch = _genesis_boot_arch\(\$tftpdir, \$ent->\{arch\}\);/, - 'destiny applies the tested architecture selection to nodeset', -); +ok(xCAT_plugin::destiny::_genesis_uses_power_console('ppc64'), 'legacy POWER uses the hypervisor console'); +ok(xCAT_plugin::destiny::_genesis_uses_power_console('ppc64le'), 'ppc64le uses the hypervisor console'); +for my $arch (qw(x86_64 aarch64 s390x riscv64 ppc64el ppc64lex)) { + ok(!xCAT_plugin::destiny::_genesis_uses_power_console($arch), "$arch does not select a POWER console"); +} done_testing(); diff --git a/xCAT-test/unit/xcatconfig_genesis_openembedded.t b/xCAT-test/unit/xcatconfig_genesis_openembedded.t index 59c8fc3e7..360d97564 100644 --- a/xCAT-test/unit/xcatconfig_genesis_openembedded.t +++ b/xCAT-test/unit/xcatconfig_genesis_openembedded.t @@ -1,27 +1,39 @@ #!/usr/bin/env perl use strict; use warnings; +no warnings 'once'; use File::Path qw(make_path remove_tree); use File::Temp qw(tempdir); use FindBin; +use lib "$FindBin::Bin/../lib"; +use lib "$FindBin::Bin/../../perl-xCAT"; +use lib "$FindBin::Bin/../../xCAT-server/lib/perl"; use Test::More; +use XCAT::Test::File qw(repo_path); -my $source = "$FindBin::Bin/../../xCAT-server/sbin/xcatconfig"; -open(my $source_fh, '<', $source) or die "open $source: $!"; -my $content = do { local $/; <$source_fh> }; -close($source_fh) or die "close $source: $!"; - -my @routines; -for my $name (qw(_installed_genesis_architectures _genesis_architectures_to_build)) { - my ($routine) = $content =~ /^(sub \Q$name\E\s*\{.*?^\})/ms; - BAIL_OUT("could not extract $name from xcatconfig") unless $routine; - push(@routines, $routine); +BEGIN { + *CORE::GLOBAL::exit = sub { die bless { status => $_[0] || 0 }, 'XcatconfigTestExit'; }; } -eval join("\n", @routines); ## no critic (BuiltinFunctions::ProhibitStringyEval) -BAIL_OUT("could not load Genesis architecture helpers: $@") if $@; my $tmpdir = tempdir(CLEANUP => 1); +$ENV{XCATROOT} = repo_path('xCAT-server'); +$ENV{XCATCFG} = "$tmpdir/config"; +make_path($ENV{XCATCFG}); +my ($help, $error); +{ + local @ARGV = ('--help'); + open(my $out, '>', \$help) or die $!; + local *STDOUT = $out; + do(repo_path('xCAT-server/sbin/xcatconfig')); + $error = $@; +} +is(ref($error), 'XcatconfigTestExit', 'the complete CLI reaches its help exit'); +is(ref($error) ? $error->{status} : undef, 0, 'help exits successfully'); +like($help, qr/xcatconfig/, 'the complete CLI prints usage'); +die "Cannot load xcatconfig: $error" unless ref($error) eq 'XcatconfigTestExit' && !$error->{status}; +$::osname = 'Linux'; + make_path( "$tmpdir/share/xcat/netboot/genesis/ppc64/fs", "$tmpdir/share/xcat/netboot/genesis/x86_64/fs",