Files
cozystack/hack/testdata/install-wait/wait-nesting.sh
Aleksei Sviridkin 5fe595d4c0 test(e2e): hold the tenant-cluster install wait to an ordering rule
A test that creates a tenant Kubernetes cluster cannot END while that
release is still installing. A Helm release cannot be uninstalled
mid-install, and for this kind the install can outlive the fast
assertions: the kind carries helm-install-disable-wait, which drops
the wait on the main resources but not on the chart's blocking
post-install hook. A test that asserts and ends hands the remainder of
the install to teardown, where it is reported red on a step that tests
nothing.

The rule is about ending, not about touching the cluster at all. The
hook polls for the admin kubeconfig in the modes that have one, and
that Secret is what the test needs to reach the tenant API, so
bringing up a worker or waiting on a child release happens while the
parent is still installing. Reading mid-install is fine.

run-kubernetes.sh already does the right thing: it waits for the
parent release to reach Ready before the tenant-cluster assertions.
Nothing held it there. This adds the guard that does, and states the
rule where the e2e conventions live.

The guard reads the script rather than Chainsaw fixtures, because no
fixture applies this kind and a guard walking apply.file would pass by
having nothing to check. A case asserts that this stays the only
script creating it, and the sweep behind it keys on the apiVersion and
kind together so that an indented apply.resource block counts as a
creator too. It reads scripts and manifests only, and that rule is
pre-emptive rather than a response to what the root holds today: a
manifest quoted in prose or parked in a `.disabled` file creates no
cluster, and this repository writes the first shape in docs that lie
outside the root.

The rules it holds the script to -- what counts as a wait with teeth,
where in the body it has to stand, what may not switch errexit off
above it, and which call shapes count as an end-assertion -- are in
the file's header beside the code that enforces them, each with the
spellings it accepts and what it cannot see. How to size the budget is
derived once in the e2e conventions.

Nothing is added at the wait itself: hack/e2e-chainsaw/_lib is shared
by every Chainsaw suite, so a comment there escalates this change from
no e2e suites to the full suite, and the guard already reds on the
move it would have warned about.

Assisted-by: LLM
Signed-off-by: Aleksei Sviridkin <f@lex.la>
2026-09-11 09:06:19 +03:00

88 lines
3.0 KiB
Bash

#!/bin/sh
# Bodies for the nesting rule. Every function below writes the same wait the
# subject writes, so the identity matcher takes it in each of them; what
# differs is where the wait sits and whether the body parses at all.
cozy_wait_at_top() {
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
cozy_assert_tenant_reachable
}
cozy_wait_in_branch() {
if [ "$mode" = None ]; then
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
fi
cozy_assert_tenant_reachable
}
cozy_wait_in_loop() {
for _attempt in 1 2 3; do
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
done
}
# Two waits on the same release: the printed body carries no line numbers, so
# the one the caller asked about cannot be told from the other.
cozy_wait_twice() {
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
}
cozy_wait_in_case() {
case "$mode" in
None)
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
;;
esac
}
cozy_wait_in_until() {
until [ "$ready" = yes ]; do
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
done
}
# A subshell prints on the line that opens it, so the wait is not at the start
# of any printed line and the command matcher does not see it at all.
cozy_wait_in_subshell() {
( kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
)
}
cozy_wait_none() {
cozy_assert_tenant_reachable
}
cozy_wait_errexit_off() {
set +e
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
}
# `set -euo pipefail` is what this tree writes, so `set +euo pipefail` is what
# an author writes to undo it: the `e` is not the last letter of the flag.
cozy_wait_errexit_combined() {
set +euo pipefail
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
}
cozy_wait_errexit_after() {
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
set +e
}
# Closes with a command on the brace line. The range helper ends a body at a
# `}` in column 0, so this reaches the extractor looking like a definition,
# and what stands after the brace runs if the text is sourced. The witness
# says whether it did; unset, it writes nowhere.
cozy_wait_tail() {
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
}; printf 'ran\n' >"${COZY_TAIL_WITNESS:-/dev/null}"
# Deliberately missing its `fi`, which is what a body truncated at a brace
# inside a heredoc looks like to the shell. Last in the file so the unbalanced
# `if` cannot be read as covering the definitions below it.
cozy_wait_broken() {
if [ "$mode" = None ]; then
kubectl wait hr -n tenant-test "kubernetes-${test_name}" --timeout=5m --for=condition=ready
}