hack/run-kubernetes-sandbox-cpu-time_test.bats
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bats
# Regression coverage for the sandbox node CPU time capture in
# hack/e2e-chainsaw/_lib/run-kubernetes.sh. cozytest.sh ends an @test block at
# the first bare closing brace, so command mocks stay at top level.
#
# What this capture answers, and why nothing beside it answers the same thing:
# the worker captures describe a cgroup, so they can say what the tenant worker
# was allowed and what it consumed, and they are blind to the layer under the
# sandbox. A guest that is runnable and never scheduled looks from the cgroup
# like a guest that asked for nothing. Whether the sandbox node itself was given
# its turn is recorded in one place only -- the steal column of its own
# /proc/stat -- and the kubelet endpoints this tree already reads do not carry
# it. So the failure this suite guards against is not a wrong number; it is an
# empty directory, which reads as a sandbox that lost no time while nothing was
# ever asked.
load test_helper
kubectl_calls=/dev/null
kubectl_rows='srv1|192.0.2.11'
kubectl_list_rc=0
kubectl_list_stderr=
talosctl_calls=/dev/null
talosctl_rc=0
talosctl_stderr=
talosctl_output='cpu 10 0 5 900 1 0 0 7 4000 0
cpu0 10 0 5 900 1 0 0 7 4000 0'
timeout_calls=/dev/null
timeout_fail_node=
kubectl() {
printf '%s\n' "$*" >>"${kubectl_calls}"
[ -z "${kubectl_list_stderr}" ] || printf '%s\n' "${kubectl_list_stderr}" >&2
[ "${kubectl_list_rc}" -eq 0 ] || return "${kubectl_list_rc}"
# Quoted, or the mock decides the shape of the answer before the code under
# test sees it: jsonpath puts a dual-stack node's two addresses in one field,
# separated by a space, and an unquoted expansion splits that into two rows
# here -- which is exactly the input the walk has a branch for, and the branch
# would then be unreachable from this suite.
[ -z "${kubectl_rows}" ] || printf '%s\n' "${kubectl_rows}"
return 0
}
talosctl() {
printf '%s\n' "$*" >>"${talosctl_calls}"
[ -z "${talosctl_stderr}" ] || printf '%s\n' "${talosctl_stderr}" >&2
# Output before the status, because a read cut off part way has already
# written what it managed to read. A mock that returned first could only ever
# produce empty-plus-failure, leaving the arm that labels a partial capture
# unreachable in tests while being the likeliest one in production.
[ -z "${talosctl_output}" ] || printf '%s\n' "${talosctl_output}"
return "${talosctl_rc}"
}
timeout() {
local command_rc=0
printf '%s\n' "$*" >>"${timeout_calls}"
# Return 97 rather than running the command when the wrapper is not the
# bounded form: a read that lost its ceiling must not pass as a read.
[ "${1:-}" = -k ] || return 97
shift 3
"$@" || command_rc=$?
if [ -n "${timeout_fail_node}" ]; then
case " $* " in
*"${timeout_fail_node}"*) return 124 ;;
esac
fi
return "${command_rc}"
}
assert_file_contains() {
local needle="$1"
local file="$2"
if [ ! -f "${file}" ]; then
printf 'expected %s to exist so it could be checked for: %s\n' "${file}" "${needle}" >&2
return 1
fi
case "$(cat "${file}")" in
*"${needle}"*) return 0 ;;
esac
printf 'expected %s to contain: %s\n' "${file}" "${needle}" >&2
return 1
}
assert_file_lacks_pattern() {
local pattern="$1"
local file="$2"
# A missing file must fail rather than vacuously pass: a bare `! grep -q`
# succeeds on an unreadable path, which is indistinguishable from "the file
# exists and does not carry the label".
if [ ! -f "${file}" ]; then
printf 'expected %s to exist so it could be checked for: %s\n' "${file}" "${pattern}" >&2
return 1
fi
# Branched on awk's exact status. awk exits 1 for "no line matched" and 2 for
# "I could not evaluate this"; folded together, a negative assertion is
# satisfied by its own matcher giving up, which is the direction that goes
# green and stays green.
local _rc=0
awk -v pattern="${pattern}" '$0 ~ pattern { found = 1 } END { exit found ? 0 : 1 }' "${file}" || _rc=$?
case "${_rc}" in
0)
printf 'expected %s not to match: %s\n' "${file}" "${pattern}" >&2
return 1
;;
1) return 0 ;;
*)
printf 'awk could not evaluate pattern %s against %s\n' "${pattern}" "${file}" >&2
return 1
;;
esac
}
# The function under test redirects a command's stderr into a report file and
# decides which artifact to write from it. cozytest.sh runs under `set -x`, so
# the tracer's own line for that command lands on the very stderr being
# redirected, and every assertion about those files would be reading the
# tracer. Call through this wrapper so the sinks hold what production writes.
run_capture() {
local _rc=0
( set +x; cozy_capture_sandbox_node_cpu_time "${1:-1}" ) || _rc=$?
return "${_rc}"
}
stage() {
COZY_REPORT_DIR="$1/report"
COZY_SNAPSHOT_NAME=steal-smoke
printf 'context: e2e\n' >"$1/talosconfig"
export TALOSCONFIG="$1/talosconfig"
}
@test "the node's own CPU accounting is read over the Talos API" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
run_capture
# The endpoint and the node are both the address, because the e2e talosconfig
# carries no endpoints: one without the other reaches nothing at all.
assert_file_contains '-e 192.0.2.11 -n 192.0.2.11 read /proc/stat' "$talosctl_calls"
capture="$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.txt"
assert_file_contains 'cpu 10 0 5 900 1 0 0 7 4000 0' "$capture"
assert_file_lacks_pattern 'unknown' "$capture"
assert_file_lacks_pattern 'incomplete' "$capture"
rm -rf "$tmp"
}
@test "the column legend travels with the numbers" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
run_capture
# /proc/stat carries no header, and the two columns that matter here sit next
# to each other: steal is the eighth number after the label and guest is the
# ninth. Guest is large on a node running VMs and is already counted inside
# user, so reading the ninth as the eighth turns a fraction of a percent into
# twenty-odd -- which has already happened once against these nodes. The
# legend is what stops the next reader repeating it, and it is only useful
# where the numbers are.
capture="$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.txt"
assert_file_contains 'The eighth number is steal and the ninth is guest' "$capture"
# The pairing instruction rides with the legend, on the one arm that holds a
# whole reading, and so does the claim that counters were sampled inside the
# brackets -- the stamp itself only says when the read was attempted.
assert_file_contains 'subtracting this node file from its sibling' "$capture"
assert_file_contains 'counters were sampled somewhere inside each read' "$capture"
rm -rf "$tmp"
}
@test "each reading records when it was taken" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
run_capture
# Here the stamp is the only timing there is. A cAdvisor row carries its own
# sample time; a /proc/stat row carries none, so without this the gap between
# two readings of a node is unrecoverable from the artifact and a steal rate
# would have to be computed from a number the block does not promise.
capture="$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.txt"
assert_file_contains 'read attempted from' "$capture"
# Both ends, for the reason the sibling suite states: one stamp hides the read
# duration inside the interval, and that duration is the variable this
# collector is deployed against.
stamp=$(sed -n 's/.*read attempted from \([0-9][0-9]*\) to \([0-9][0-9]*\) epoch seconds.*/\1 \2/p' "$capture")
if [ -z "$stamp" ]; then
echo "expected a bare epoch stamp in $capture" >&2
cat "$capture" >&2
return 1
fi
rm -rf "$tmp"
}
@test "each read is bounded and keeps its exit code" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
run_capture
# An unbounded read here would hold the whole diagnostics block against a node
# whose Talos API is up but wedged, and the phase budget bounds when a read
# may START, never how long one already running may take. Named by their verbs
# rather than by the bound, because both carry the same one and a bare check
# for it would be satisfied twice by whichever read survived.
assert_file_contains '-k 5 20 kubectl get nodes' "$timeout_calls"
assert_file_contains '-k 5 20 talosctl' "$timeout_calls"
assert_file_contains '--request-timeout=20s' "$kubectl_calls"
assert_file_contains '[capture exit code: 0]' \
"$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.txt"
rm -rf "$tmp"
}
@test "a lowered read budget moves both of this collector's bounds" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
# Set after sourcing, which is how a caller and a test both set it. A value
# read only at assignment time would reach `timeout` unchecked here.
COZY_DIAG_READ_TIMEOUT=4
run_capture
assert_file_contains '-k 5 4 kubectl get nodes' "$timeout_calls"
assert_file_contains '-k 5 4 talosctl' "$timeout_calls"
assert_file_contains '--request-timeout=4s' "$kubectl_calls"
rm -rf "$tmp"
}
@test "a zero read budget is corrected rather than disabling the bound" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
# `timeout -k 5 0` disables the timeout outright, so a zero assigned after
# sourcing would restore the unbounded read this bound exists to remove.
COZY_DIAG_READ_TIMEOUT=0
run_capture
assert_file_lacks_pattern '^-k 5 0 ' "$timeout_calls"
assert_file_contains "-k 5 $COZY_DIAG_READ_TIMEOUT_DEFAULT talosctl" "$timeout_calls"
rm -rf "$tmp"
}
@test "no talosctl on PATH is recorded rather than left as an empty directory" {
# A subprocess with a stripped PATH, because this file mocks `talosctl` as a
# shell function and `command -v` finds functions -- the arm cannot be reached
# from inside a test body. Same device the sibling suites use, and the PATH is
# staged rather than emptied: the collector shells out before it gets to the
# check, so an empty PATH would fail this for the wrong reason and read as the
# arm being broken.
tmp=$(mktemp -d)
mkdir -p "$tmp/bin"
for c in mkdir grep mv rm; do
for d in /bin /usr/bin /usr/local/bin /opt/homebrew/bin; do
if [ -x "$d/$c" ]; then
ln -sf "$d/$c" "$tmp/bin/$c"
break
fi
done
if [ ! -x "$tmp/bin/$c" ]; then
echo "FAIL: could not stage $c in the stripped PATH; the check below would be vacuous" >&2
return 1
fi
done
if [ -e "$tmp/bin/talosctl" ]; then
echo "FAIL: talosctl leaked into the stripped PATH; this test would prove nothing" >&2
return 1
fi
printf 'context: e2e\n' >"$tmp/talosconfig"
rc=0
# Assigned inside the subprocess rather than in front of it: bash resolves the
# command name with the PATH the assignment sets, so `PATH=... bash` cannot
# find bash itself.
out=$(bash -c '
set -eu
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
COZY_REPORT_DIR='"$tmp"'/report
COZY_SNAPSHOT_NAME=steal-smoke
TALOSCONFIG='"$tmp"'/talosconfig
PATH='"$tmp"'/bin
cozy_capture_sandbox_node_cpu_time 1
' 2>&1) || rc=$?
printf '%s\n' "$out" >"$tmp/out"
[ "$rc" -ne 0 ]
marker="$tmp/report/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/COLLECTION-FAILED.txt"
assert_file_contains 'talosctl is not on PATH' "$marker"
# The distinction the marker exists for, spelled out in the artifact: a tool
# that was never run says nothing about the nodes, and the reading a missing
# file invites is that they lost no time.
assert_file_contains 'not a reading that they lost no time' "$marker"
rm -rf "$tmp"
}
@test "no talosconfig is recorded as a config that was missing, not as a node that refused" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
export TALOSCONFIG="$tmp/absent"
rc=0
run_capture || rc=$?
[ "$rc" -ne 0 ]
assert_file_contains 'no sandbox talosconfig at' \
"$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/COLLECTION-FAILED.txt"
# And nothing was asked, so no per-node file may claim otherwise.
[ ! -f "$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.txt" ]
rm -rf "$tmp"
}
@test "a node listing that failed is not reported as a cluster with no nodes" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
kubectl_list_rc=1
kubectl_list_stderr='error: You must be logged in to the server (Unauthorized)'
rc=0
run_capture || rc=$?
[ "$rc" -ne 0 ]
marker="$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/COLLECTION-FAILED.txt"
assert_file_contains 'failed to list sandbox nodes' "$marker"
# The status alone names none of the ways a listing fails -- Unauthorized, a
# refused connection and an unrecognised kind are all exit 1 -- so the stderr
# that says which is kept.
assert_file_contains 'Unauthorized' "$marker"
rm -rf "$tmp"
}
@test "a warning on a successful listing is kept apart from a failure" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
# kubectl writes deprecation and partial-result warnings on stderr with a zero
# exit, so which file stderr lands in is decided by the status and not by
# something having been written.
kubectl_list_stderr='Warning: v1 Node is deprecated'
dir="$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1"
run_capture
assert_file_contains 'Warning: v1 Node is deprecated' "$dir/READ-WARNINGS.txt"
[ ! -f "$dir/COLLECTION-FAILED.txt" ]
rm -rf "$tmp"
}
@test "a node with no InternalIP says why it was not asked" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
kubectl_rows='srv1|'
run_capture
# An absent file would be the same artifact as a node that was never listed.
# The Talos API is reached on that address, so its absence is the reason this
# node carries no numbers, and the reason is what the file holds.
assert_file_contains 'reports no InternalIP' \
"$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.txt"
rm -rf "$tmp"
}
@test "a dual-stack node is one node, dialled on its first address" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
# jsonpath emits every matching address into the same field, space separated,
# so a node with an IPv4 and an IPv6 InternalIP arrives as one row carrying
# two addresses. Both halves of that are wrong if taken literally: the pair
# concatenated is not an address to dial, and the second one is not a node.
kubectl_rows='srv1|192.0.2.11 2001:db8::11
srv2|192.0.2.12 2001:db8::12
srv3|192.0.2.13 2001:db8::13
srv4|192.0.2.14 2001:db8::14'
run_capture
assert_file_contains '-e 192.0.2.11 -n 192.0.2.11 read /proc/stat' "$talosctl_calls"
assert_file_lacks_pattern '2001:db8' "$talosctl_calls"
# And the count in the truncation marker is nodes, not addresses. The marker
# exists to say a short listing was truncated rather than small, so a total
# that counts each node twice is the one number in it that must not be wrong.
assert_file_contains 'capture stopped after 3 nodes; 4 were listed in total' \
"$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/COLLECTION-TRUNCATED.txt"
rm -rf "$tmp"
}
@test "a node whose read timed out does not stop the next node" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
kubectl_rows='srv1|192.0.2.11
srv2|192.0.2.12'
timeout_fail_node=192.0.2.11
run_capture
dir="$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1"
assert_file_contains '[capture exit code: 124]' "$dir/srv1.txt"
assert_file_contains 'cpu 10 0 5 900 1 0 0 7 4000 0' "$dir/srv2.txt"
rm -rf "$tmp"
}
@test "a read that never answered is recorded as unread, not as a node that lost nothing" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
talosctl_rc=1
talosctl_output=
talosctl_stderr='rpc error: code = Unavailable desc = connection error'
run_capture
capture="$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.txt"
assert_file_contains 'is unknown: the Talos API was not read' "$capture"
# This file holds no counters at all, so a reader following a pairing
# instruction here would subtract nothing from a healthy sibling and read that
# sibling's whole cumulative value as the delta -- steal inflated to the node's
# entire uptime, manufacturing the finding this collector looks for.
assert_file_lacks_pattern 'subtracting this node file from its sibling' "$capture"
# Nor may the stamp assert that anything was sampled between its two instants.
# When the read was attempted is true on every arm; that counters exist inside
# that bracket is exactly what this arm has just denied, and two consecutive
# lines contradicting each other is the reading failure this tree is written
# against.
assert_file_lacks_pattern 'counters were sampled' "$capture"
assert_file_contains 'read attempted from' "$capture"
# The note has to name a file that exists. There is no bare read-error.log in
# the directory -- each is named for its node, and the walk writes one per
# node -- so a note pointing at the bare name sends the reader after an
# artifact that was never written, which is the same harm as silence reported
# as an answer, one indirection out.
assert_file_contains 'beside this file, named for the same node' "$capture"
assert_file_contains 'connection error' \
"$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.read-error.log"
rm -rf "$tmp"
}
@test "a read killed without a word does not point at a file that was never written" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
# `timeout` SIGKILLs its child, so the dominant failure arrives non-zero with
# nothing on either stream. A note naming an error log here sends the reader
# after evidence that does not exist.
talosctl_rc=1
talosctl_output=
talosctl_stderr=
run_capture
capture="$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.txt"
assert_file_contains 'died without a word on either stream' "$capture"
[ ! -f "$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.read-error.log" ]
rm -rf "$tmp"
}
@test "a read cut off part way is marked incomplete rather than presented whole" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
# Output arrived and the read still failed, which is what a stream cut off
# part way through looks like. Read as complete, its numbers are a smaller
# total over the same interval -- a steal figure biased toward zero, in the
# direction that ends the investigation.
talosctl_rc=124
run_capture
capture="$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.txt"
assert_file_contains 'these counters are incomplete' "$capture"
# And the legend, which is a statement about a complete row, must not be
# attached to one that was truncated.
assert_file_lacks_pattern 'eighth number is steal' "$capture"
# Nor the instruction to pair it. A difference taken against a prefix
# understates the counter by whatever the read did not return, which for steal
# is the direction that says the node was given every turn it asked for.
assert_file_lacks_pattern 'subtracting this node file from its sibling' "$capture"
rm -rf "$tmp"
}
@test "a read that succeeded and returned nothing is not filed as a reading" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
talosctl_output=
run_capture
capture="$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv1.txt"
assert_file_contains 'the read succeeded and returned nothing' "$capture"
rm -rf "$tmp"
}
@test "the walk is capped and names both counts when it stops" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
kubectl_rows='srv1|192.0.2.11
srv2|192.0.2.12
srv3|192.0.2.13
srv4|192.0.2.14'
run_capture
# A short listing otherwise reads as a small cluster rather than a truncated
# walk, so a cap that fired is recorded with both counts.
assert_file_contains 'capture stopped after 3 nodes; 4 were listed in total' \
"$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/COLLECTION-TRUNCATED.txt"
[ ! -f "$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/srv4.txt" ]
rm -rf "$tmp"
}
@test "a cluster within the cap leaves no truncation marker" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
run_capture
[ ! -f "$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1/COLLECTION-TRUNCATED.txt" ]
rm -rf "$tmp"
}
@test "the sample number decides which reading a file belongs to" {
. hack/e2e-chainsaw/_lib/run-kubernetes.sh
tmp=$(mktemp -d)
kubectl_calls="$tmp/kubectl.calls"
talosctl_calls="$tmp/talosctl.calls"
timeout_calls="$tmp/timeout.calls"
stage "$tmp"
run_capture 2
# The pair is the instrument and the counters are cumulative, so a second
# reading written over the first leaves one file and no interval -- collected,
# and unable to answer the question it was collected for.
assert_file_contains 'cpu 10 0 5 900 1 0 0 7 4000 0' \
"$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-2/srv1.txt"
[ ! -d "$COZY_REPORT_DIR/snapshots/steal-smoke/sandbox-host-cpu-time/sample-1" ]
rm -rf "$tmp"
}