2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-10-12 08:12:33 +00:00

test(provtest): assert what the renderers produced, not that they ran

The kickstart template carried no directive, so mkinstall rendered it
correctly by doing nothing; it now carries a #TABLE: per node and an
#INCLUDE:, and the fetched autoinst is asserted to hold the expanded
values and no directive or #INCLUDEBAD:.

The postscripts listing is walked as a node walks it: a name taken out
of the index, then that leaf fetched -- Indexes and the alias are
separate directives, and a tree listed but unreadable fails every
postscript at once.

And the kernel and initrd the config names are fetched over both
transports and compared by sha256.
This commit is contained in:
Daniel Hilst
2026-09-11 12:02:14 -03:00
parent 1a7386e978
commit 378ba7eba1
2 changed files with 124 additions and 4 deletions
@@ -410,16 +410,26 @@ EOF
}
# The template mkinstall renders into /install/autoinst/<node>: P-35 fetches the
# rendered result, so a finished file would not do.
# rendered result, so a finished file would not do. It carries a directive of
# each kind the renderer has to handle -- a #TABLE: read per node, an #INCLUDE:
# of a second file -- because a template with none of them is rendered correctly
# by doing nothing at all, and the HTTP stage asserts what came out.
fabricate_template() {
local path=$1
write_file "$path" <<'EOF'
local path=$1 include
include="$(dirname "$path")/provtest-include.tmpl"
write_file "$include" <<'EOF'
provtest_included yes
EOF
write_file "$path" <<EOF
# provtest kickstart template. Rendered by mkinstall, fetched by the wire cases,
# never installed.
install
text
reboot
rootpw --iscrypted *
provtest_xcatmaster #TABLE:noderes:\$NODE:xcatmaster#
provtest_arch #TABLE:nodetype:\$NODE:arch#
#INCLUDE:$include#
%post
#XCAT_KICKSTART_POST__
%end
@@ -925,14 +935,18 @@ do_run_http() {
# `set root=http,` line only grub2 writes.
select="-s install-tree -s tftp-tree-over-http -s urls-the-node-was-given"
select="$select -s outside-the-aliases -s postscripts-listing"
# The kernel and initrd are named on a `linux`/`initrd` line, which only the
# grub2 loaders write; an xnba script names its kernel in its own form and
# the xnba case asserts that one.
case "$(node_netboot)" in
grub2-http)
select="$select -s boot-images-over-http"
if [ "$port" = 80 ]; then
select="$select -s default-port-the-node-was-told"
else
select="$select -s port-the-node-was-told"
fi ;;
*) stage_skip "$NODE is set with $(node_netboot), whose config names no port, so the port half of P-39 is left out" ;;
*) stage_skip "$NODE is set with $(node_netboot), whose config names no port and no kernel line, so the port half of P-39 and the boot images are left out" ;;
esac
# shellcheck disable=SC2086
@@ -943,6 +957,7 @@ do_run_http() {
--set knownfile="$(node_config_rel)" \
--set installpath="autoinst/$NODE" \
--set repofile="repodata/repomd.xml" \
--set master="$SRV_IP" --set arch="$NODE_ARCH" \
conf/http.conf
}
+105
View File
@@ -11,6 +11,7 @@
# --set node=provtestcn --set httpport=80 --set otherport=8080 \
# --set hexip=0A63010B --set knownfile=boot/grub2/grub.cfg-0A63010B \
# --set installpath=autoinst/provtestcn --set repofile=repodata/repomd.xml \
# --set master=10.99.1.1 --set arch=x86_64 \
# conf/http.conf
[defaults]
@@ -31,6 +32,26 @@ path = /install/%(installpath)s
assert =
status == 200
size > 0
# The file is what mkinstall rendered, not the template it rendered from.
# The caller's template carries a #TABLE: directive for each value below and
# an #INCLUDE: of a second file; an installer handed the unrendered form
# fails at the first line it does not understand, and one handed an empty
# expansion installs with no repository and no address.
text matches ^provtest_xcatmaster %(master)s$
text matches ^provtest_arch %(arch)s$
text matches ^provtest_included yes$
[step leftover]
type = extract
from = $autoinst.text
# Template.pm substitutes every directive in one pass (Template.pm:297, 375-385),
# so one still in the file is one nothing recognised. #INCLUDEBAD: is what
# includefile writes in place of a file it could not open (Template.pm:1551) --
# a rendered kickstart that names it is one an installer will read to the end
# and then stop.
pattern = #(?:TABLE|TABLEBLANKOKAY|INCLUDE|INCLUDEBAD|CRYPT|ENV|XCATVAR):
assert =
matched == no
# --- P-33 -------------------------------------------------------------------
@@ -99,6 +120,69 @@ url = $repourl.value/%(repofile)s
assert =
status == 200
# --- P-33, P-34, for the two files a node actually boots ---------------------
[scenario boot-images-over-http]
description = The kernel and initrd the node was told to fetch are served over HTTP, byte for byte
[step imageconfig]
type = tftp
path = %(knownfile)s
port = 69
assert =
size > 0
[step kernelpath]
type = extract
from = $imageconfig.text
# grub2 writes the tftp root's own prefix into the path when the protocol is
# http (grub2.pm:274-277), which is exactly the alias the web server publishes
# that tree under -- so the same capture serves both fetches below.
pattern = ^\s*linux(?:efi|16)?\s+/?(?:tftpboot/)?(\S+)
assert =
matched == yes
[step kerneltftp]
type = tftp
path = $kernelpath.value
port = 69
assert =
size > 0
[step kernelhttp]
type = http
path = /tftpboot/$kernelpath.value
# Not the same claim as the tftp tree being served: this is the file the node
# was told to boot, fetched the way the node will fetch it. A truncated or
# stale copy behind the web server is a kernel that will not decompress, and
# nothing on the management node notices.
assert =
status == 200
size > 0
sha256 == $kerneltftp.sha256
[step initrdpath]
type = extract
from = $imageconfig.text
pattern = ^\s*initrd(?:efi|16)?\s+/?(?:tftpboot/)?(\S+)
assert =
matched == yes
[step initrdtftp]
type = tftp
path = $initrdpath.value
port = 69
assert =
size > 0
[step initrdhttp]
type = http
path = /tftpboot/$initrdpath.value
assert =
status == 200
size > 0
sha256 == $initrdtftp.sha256
# --- P-37 -------------------------------------------------------------------
[scenario outside-the-aliases]
@@ -128,6 +212,27 @@ assert =
status == 200
size > 0
[step scriptname]
type = extract
from = $listing.text
# The first entry that is a plain relative name: Apache's index also carries the
# sort links (`?C=N;O=D`), the parent (`/install/`) and any subdirectory, which
# ends in a slash. Taking a name out of the listing rather than naming one here
# is what makes the fetch below a walk of the tree the node sees.
pattern = <a href="([A-Za-z][\w.-]*)"
assert =
matched == yes
[step script]
type = http
path = /install/postscripts/$scriptname.value
# A listing is not an assertion that anything under it is served: Indexes and
# the alias are separate directives, and a tree listed but not readable is a
# node whose postscripts all fail at once.
assert =
status == 200
size > 0
# --- P-39 -------------------------------------------------------------------
[scenario port-the-node-was-told]