mirror of
https://github.com/cozystack/cozystack.git
synced 2026-10-26 13:07:04 +09:00
The shell translator rewrites test bodies and loses Bats reporting. The unit lane needs complete TAP results and JUnit reports without changing how live-cluster suites run. Sourced production helpers still need a dash pass, and unit test bodies need nounset without exporting shell options into subprocesses. Assisted-by: LLM Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
412 lines
20 KiB
Bash
412 lines
20 KiB
Bash
#!/usr/bin/env bats
|
|
# -----------------------------------------------------------------------------
|
|
# Unit tests for the in-sandbox Talos image cache manifest split and the
|
|
# importer-reachability contract it relies on.
|
|
#
|
|
# hack/e2e-talos-image-cache.yaml bundles four documents but they are applied in
|
|
# two phases: hack/e2e-install-cozystack.bats applies everything EXCEPT the
|
|
# CiliumClusterwideNetworkPolicy (its CRD does not exist before Cozystack is
|
|
# installed), and hack/e2e-chainsaw/_lib/talos-image-cache.sh applies ONLY that
|
|
# policy later, once Cilium is up. If a future document is added to the manifest
|
|
# and silently dropped from the pre-Cilium apply, or the Cilium document leaks
|
|
# into it (and errors on the missing CRD), the mirror breaks and e2e falls back
|
|
# to the flaky public factory. These tests pin that split.
|
|
#
|
|
# They also pin the load-bearing reachability invariant: the throwaway probe pod
|
|
# is a faithful proxy for a real CDI importer only if it carries the exact label
|
|
# and namespace the egress policy selects. If either side drifts, the probe can
|
|
# pass while real importers stay blocked (a false positive that makes CI worse).
|
|
#
|
|
# Finally they cover the decision itself, sourced from
|
|
# hack/e2e-chainsaw/_lib/talos-image-cache.sh (sourcing it has no cluster side
|
|
# effects — it only sets parameter defaults and defines functions). Two pure
|
|
# fragments are exercised directly: the strict 206 gate that decides whether
|
|
# tenants are pointed at the mirror at all, and the --overrides JSON builder
|
|
# whose silent breakage would drop every probe to the public factory. The
|
|
# kubectl orchestration around them is driven here too, against a throwaway
|
|
# `kubectl` and `timeout` placed on PATH — the decision of which factory a whole
|
|
# suite pulls from is worth pinning without waiting for a cluster.
|
|
#
|
|
# On PATH, not shell functions, and that is not a style choice: the lookup runs
|
|
# `timeout -k 5 40 kubectl …` wherever timeout is installed, and an external
|
|
# timeout binary execs a real file.
|
|
# A `kubectl() { … }` override is invisible to it, so the stub would never be
|
|
# reached, and a suite that stubs that way goes quietly vacuous. A stub on PATH
|
|
# is also the only way to assert how the real call was spelled, which matters
|
|
# for the flags the three-way answer depends on: the stub answers exit 0 with no
|
|
# output for an absence no matter what flags it is handed, while a real kubectl
|
|
# does that only with --ignore-not-found, so that flag is pinned by inspecting
|
|
# the recorded call rather than by the behaviour around it.
|
|
#
|
|
# Root cause + fix are from cozystack/cozystack#3254 (@lexfrei); this is the port
|
|
# to the Chainsaw layout (hack/e2e-chainsaw/_lib/).
|
|
#
|
|
# CI runs this file under Bats through `make bats-unit-tests`. It also remains
|
|
# compatible with the legacy `hack/cozytest.sh` translator, whose awk parser
|
|
# recognizes only @test blocks and a bare `}` on its own line. The tests avoid
|
|
# `run`, `$status`, setup(), and teardown() for that compatibility path and use
|
|
# direct shell assertions. mikefarah yq's document separators are stripped.
|
|
#
|
|
# Run with: bats hack/talos-image-cache_test.bats
|
|
# -----------------------------------------------------------------------------
|
|
|
|
load test_helper
|
|
|
|
@test "manifest documents partition into pre-Cilium apply plus the Cilium policy" {
|
|
manifest=hack/e2e-talos-image-cache.yaml
|
|
total=$(yq '.kind' "$manifest" | grep -vc '^---$')
|
|
excluded=$(yq 'select(.kind != "CiliumClusterwideNetworkPolicy") | .kind' "$manifest" | grep -vc '^---$')
|
|
selected=$(yq 'select(.kind == "CiliumClusterwideNetworkPolicy") | .kind' "$manifest" | grep -vc '^---$')
|
|
[ "$total" -eq 4 ]
|
|
[ "$excluded" -eq 3 ]
|
|
[ "$selected" -eq 1 ]
|
|
[ $((excluded + selected)) -eq "$total" ]
|
|
}
|
|
|
|
@test "pre-Cilium apply keeps Service, Deployment, ConfigMap and drops the Cilium policy" {
|
|
manifest=hack/e2e-talos-image-cache.yaml
|
|
kinds=$(yq 'select(.kind != "CiliumClusterwideNetworkPolicy") | .kind' "$manifest" | grep -v '^---$')
|
|
for want in Service Deployment ConfigMap; do
|
|
printf '%s\n' "$kinds" | grep -qx "$want" || { echo "pre-Cilium apply is missing $want" >&2; exit 1; }
|
|
done
|
|
if printf '%s\n' "$kinds" | grep -qx CiliumClusterwideNetworkPolicy; then
|
|
echo "CiliumClusterwideNetworkPolicy leaked into the pre-Cilium apply" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
@test "point-of-use apply selects exactly the Cilium policy" {
|
|
manifest=hack/e2e-talos-image-cache.yaml
|
|
kinds=$(yq 'select(.kind == "CiliumClusterwideNetworkPolicy") | .kind' "$manifest" | grep -v '^---$')
|
|
[ "$kinds" = "CiliumClusterwideNetworkPolicy" ]
|
|
}
|
|
|
|
@test "range server records transfer outcome, bytes and duration" {
|
|
script=$(yq 'select(.kind == "ConfigMap") | .data."serve.py"' hack/e2e-talos-image-cache.yaml)
|
|
|
|
printf '%s\n' "$script" | python3 -c 'import sys; compile(sys.stdin.read(), "serve.py", "exec")'
|
|
printf '%s\n' "$script" | grep -Fq 'transfer-finished status=%s path=%s range=%s requested=%d sent=%d duration=%.3fs'
|
|
printf '%s\n' "$script" | grep -Fq 'time.monotonic() - started'
|
|
}
|
|
|
|
@test "egress policy selects the importer label and namespace the probe pod uses" {
|
|
manifest=hack/e2e-talos-image-cache.yaml
|
|
helper=hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
label=$(yq 'select(.kind == "CiliumClusterwideNetworkPolicy") | .spec.endpointSelector.matchLabels["k8s:cdi.kubevirt.io"]' "$manifest")
|
|
ns=$(yq 'select(.kind == "CiliumClusterwideNetworkPolicy") | .spec.endpointSelector.matchLabels["k8s:io.kubernetes.pod.namespace"]' "$manifest")
|
|
[ "$label" = "importer" ]
|
|
[ "$ns" = "tenant-test" ]
|
|
# The probe pod must carry the same label the policy selects, else it faces a
|
|
# different egress than a real importer and the guarantee breaks.
|
|
grep -q "cdi.kubevirt.io=importer" "$helper" || { echo "probe pod label drifted from the egress selector" >&2; exit 1; }
|
|
grep -q "TALOS_IMAGE_CACHE_PROBE_NS:-tenant-test" "$helper" || { echo "probe namespace drifted from the egress selector" >&2; exit 1; }
|
|
}
|
|
|
|
@test "egress rule targets the mirror pod's own identity" {
|
|
manifest=hack/e2e-talos-image-cache.yaml
|
|
target=$(yq 'select(.kind == "CiliumClusterwideNetworkPolicy") | .spec.egress[0].toEndpoints[0].matchLabels["k8s:app.kubernetes.io/name"]' "$manifest")
|
|
target_ns=$(yq 'select(.kind == "CiliumClusterwideNetworkPolicy") | .spec.egress[0].toEndpoints[0].matchLabels["k8s:io.kubernetes.pod.namespace"]' "$manifest")
|
|
mirror=$(yq 'select(.kind == "Deployment") | .spec.template.metadata.labels["app.kubernetes.io/name"]' "$manifest")
|
|
mirror_ns=$(yq 'select(.kind == "Deployment") | .metadata.namespace' "$manifest")
|
|
[ "$target" = "talos-image-cache" ]
|
|
[ "$target_ns" = "kube-system" ]
|
|
# The allow's destination must equal the mirror Deployment's own pod label and
|
|
# namespace, otherwise the hole is punched toward nothing: moving the mirror
|
|
# would leave these tests green while importers could no longer reach it.
|
|
[ "$target" = "$mirror" ]
|
|
[ "$target_ns" = "$mirror_ns" ]
|
|
}
|
|
|
|
@test "strict 206 gate selects the mirror on a byte-range success" {
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
if ! _talos_image_cache_probe_succeeded "code=206"; then
|
|
echo "expected a 206 probe result to select the mirror" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
@test "strict 206 gate finds the marker inside surrounding probe output" {
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
out=$(printf 'pod/talos-image-cache-probe created\ncode=206\npod "talos-image-cache-probe" deleted\n')
|
|
if ! _talos_image_cache_probe_succeeded "$out"; then
|
|
echo "expected 206 to be found in multi-line attach output" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
@test "strict 206 gate falls back on range-less, unreachable, empty and unrelated output" {
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
# A plain 200 means the mirror answered without range support; 000 means curl
|
|
# never connected. Both fall back to the public factory, as does output that
|
|
# carried no result marker at all (an attach stream lost with no logs to recover).
|
|
for bad in "code=200" "code=000" "code=404" "" "error: pods not found"; do
|
|
if _talos_image_cache_probe_succeeded "$bad"; then
|
|
echo "expected non-206 output to fall back to the public factory: [$bad]" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
_stub_kubectl_dir() {
|
|
# Build a throwaway PATH entry whose `kubectl get deploy ... -o name` fails
|
|
# its first $2 invocations and then answers with $3 on stdout (empty for a
|
|
# genuine absence). $1 is the scratch dir. printf, not a heredoc: cozytest.sh
|
|
# translates the file with awk and would read a @test or a bare `}` inside a
|
|
# heredoc as real syntax.
|
|
mkdir -p "$1/bin"
|
|
printf '%s\n' \
|
|
'#!/bin/sh' \
|
|
'printf "%s\n" "$*" >> "$STUB_CALLS"' \
|
|
'n=$(cat "$STUB_COUNTER")' \
|
|
'n=$((n + 1))' \
|
|
'printf "%s" "$n" > "$STUB_COUNTER"' \
|
|
'if [ "$n" -le "$STUB_FAILS" ]; then' \
|
|
' echo "error: the server was unable to return a response" >&2' \
|
|
' exit 1' \
|
|
'fi' \
|
|
'printf "%s" "$STUB_OUT"' \
|
|
> "$1/bin/kubectl"
|
|
chmod +x "$1/bin/kubectl"
|
|
# A transparent `timeout` that records how it was invoked and then runs the
|
|
# command anyway, so a test can pin the wrapper without changing what the
|
|
# wrapped call does. Same idiom as hack/run-kubernetes-serial-console_test.bats.
|
|
# With STUB_TIMEOUT_RC set it instead exits that status without running the
|
|
# command and without printing, which is what a real kill looks like from the
|
|
# caller's side: the wrapper says nothing and the command never reaches the
|
|
# point where it would have.
|
|
printf '%s\n' \
|
|
'#!/bin/sh' \
|
|
'printf "%s\n" "$*" >> "$STUB_TIMEOUT_CALLS"' \
|
|
'if [ -n "$STUB_TIMEOUT_RC" ]; then exit "$STUB_TIMEOUT_RC"; fi' \
|
|
'while [ $# -gt 0 ] && [ "$1" != kubectl ]; do shift; done' \
|
|
'exec "$@"' \
|
|
> "$1/bin/timeout"
|
|
chmod +x "$1/bin/timeout"
|
|
printf '0' > "$1/counter"
|
|
: > "$1/calls"
|
|
: > "$1/timeout.calls"
|
|
export STUB_COUNTER="$1/counter" STUB_CALLS="$1/calls" \
|
|
STUB_TIMEOUT_CALLS="$1/timeout.calls" STUB_FAILS="$2" STUB_OUT="$3" \
|
|
STUB_TIMEOUT_RC=""
|
|
PATH="$1/bin:$PATH"
|
|
}
|
|
|
|
@test "deployment lookup reports present when the mirror answers with a name" {
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
d=$(mktemp -d)
|
|
_TALOS_IMAGE_CACHE_QUERY_DELAY=0
|
|
_stub_kubectl_dir "$d" 0 'deployment.apps/talos-image-cache'
|
|
state=$(_talos_image_cache_deploy_state)
|
|
rm -rf "$d"
|
|
[ "$state" = present ]
|
|
}
|
|
|
|
@test "deployment lookup reports absent only on an empty answer the apiserver actually gave" {
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
d=$(mktemp -d)
|
|
_TALOS_IMAGE_CACHE_QUERY_DELAY=0
|
|
# --ignore-not-found: a real absence is exit 0 with no output. This is the
|
|
# one outcome allowed to turn the whole suite toward the public factory.
|
|
_stub_kubectl_dir "$d" 0 ''
|
|
state=$(_talos_image_cache_deploy_state)
|
|
# The flag has to be pinned by inspection, because the stub gives exit 0 and
|
|
# no output whether or not the call asks for it. Drop it from the real call
|
|
# and kubectl reports a genuine absence as an error instead: `absent` becomes
|
|
# a state production can never reach, while this test keeps passing.
|
|
flagged=$(grep -c -- '--ignore-not-found' "$d/calls" || true)
|
|
rm -rf "$d"
|
|
[ "$state" = absent ]
|
|
[ "$flagged" = 1 ]
|
|
}
|
|
|
|
@test "deployment lookup reports unknown when the apiserver never answers" {
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
d=$(mktemp -d)
|
|
_TALOS_IMAGE_CACHE_QUERY_DELAY=0
|
|
# Every attempt refused. Reading this as "absent" is the defect: a blip would
|
|
# send every tenant worker in the suite to the public factory.
|
|
_stub_kubectl_dir "$d" 99 'deployment.apps/talos-image-cache'
|
|
state=$(_talos_image_cache_deploy_state)
|
|
rm -rf "$d"
|
|
[ "$state" = unknown ]
|
|
}
|
|
|
|
@test "deployment lookup rides out a blip and reports what a later attempt found" {
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
d=$(mktemp -d)
|
|
_TALOS_IMAGE_CACHE_QUERY_DELAY=0
|
|
_stub_kubectl_dir "$d" 1 'deployment.apps/talos-image-cache'
|
|
state=$(_talos_image_cache_deploy_state)
|
|
tries=$(cat "$d/counter")
|
|
rm -rf "$d"
|
|
[ "$state" = present ]
|
|
[ "$tries" = 2 ]
|
|
}
|
|
|
|
@test "every attempt at the lookup carries a request deadline" {
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
d=$(mktemp -d)
|
|
_TALOS_IMAGE_CACHE_QUERY_DELAY=0
|
|
_stub_kubectl_dir "$d" 99 'deployment.apps/talos-image-cache'
|
|
state=$(_talos_image_cache_deploy_state)
|
|
# kubectl's --request-timeout defaults to 0, so a connection that
|
|
# establishes and then stalls hangs with no deadline, and re-asking would
|
|
# multiply that hang instead of riding out a blip. The flag alone is not a
|
|
# wall-clock bound either — kubectl retries discovery several times over
|
|
# before it gives up — so each attempt needs the wrapper as well. The last
|
|
# count pins the number of attempts, not their duration.
|
|
bounded=$(grep -c -- '--request-timeout=30s' "$d/calls" || true)
|
|
# The wall-clock bound is deliberately above the request deadline beside it:
|
|
# level with it, the kill lands first every time and --request-timeout can
|
|
# never fire, which is how the one silent failure mode stays silent.
|
|
wrapped=$(grep -c '^-k 5 40 kubectl ' "$d/timeout.calls" || true)
|
|
total=$(grep -c . "$d/calls" || true)
|
|
rm -rf "$d"
|
|
[ "$state" = unknown ]
|
|
[ "$total" = 3 ]
|
|
[ "$bounded" = 3 ]
|
|
[ "$wrapped" = 3 ]
|
|
}
|
|
|
|
@test "a present mirror routes the decision into the reachability probe" {
|
|
d=$(mktemp -d)
|
|
_TALOS_IMAGE_FACTORY_DECISION_FILE="$d/decision"
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
_TALOS_IMAGE_CACHE_QUERY_DELAY=0
|
|
_stub_kubectl_dir "$d" 0 'deployment.apps/talos-image-cache'
|
|
set +x
|
|
url=$(resolve_talos_image_factory_url 2>"$d/err")
|
|
err=$(cat "$d/err")
|
|
rm -rf "$d"
|
|
# The state token is a contract between this helper and its two readers.
|
|
# Drift on the resolve side is the worst case there is: the present branch
|
|
# would fall through to "not deployed", cache an empty URL, and send every
|
|
# tenant worker in the suite to the public factory — the very harm the
|
|
# three-way answer exists to prevent, with every other test still green.
|
|
[ -z "$url" ]
|
|
printf '%s' "$err" | grep -q 'Available but a tenant-scoped probe' || { echo "a present mirror must reach the probe, not the not-deployed branch: [$err]" >&2; exit 1; }
|
|
}
|
|
|
|
@test "an undecidable lookup warns and is not cached for the rest of the suite" {
|
|
d=$(mktemp -d)
|
|
_TALOS_IMAGE_FACTORY_DECISION_FILE="$d/decision"
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
_TALOS_IMAGE_CACHE_QUERY_DELAY=0
|
|
_stub_kubectl_dir "$d" 99 'deployment.apps/talos-image-cache'
|
|
# cozytest.sh runs each test under `set -x`, and xtrace shares the stderr
|
|
# this captures. Off for the call, so the assertions below read what the
|
|
# function said rather than an echo of the commands it ran, and left off
|
|
# afterwards: a test that turns it back on and then fails wedges `bats`
|
|
# instead of reporting, which costs a reader the failure they came for.
|
|
set +x
|
|
url=$(resolve_talos_image_factory_url 2>"$d/err")
|
|
cached=no
|
|
if [ -f "$d/decision" ]; then cached=yes; fi
|
|
err=$(cat "$d/err")
|
|
rm -rf "$d"
|
|
# Falling back for this one caller is fine; pinning that fallback for every
|
|
# later tenant test on the strength of a failed question is not.
|
|
[ -z "$url" ]
|
|
[ "$cached" = no ]
|
|
printf '%s' "$err" | grep -q 'could not determine' || { echo "an undecidable lookup must say so: [$err]" >&2; exit 1; }
|
|
# And it must say why. "could not determine" alone leaves an operator with a
|
|
# new silent failure in place of the old one: refused, Unauthorized and
|
|
# timed-out all read the same until kubectl's own message reaches the log.
|
|
printf '%s' "$err" | grep -q 'the server was unable to return a response' || { echo "the reason the lookup failed must reach the log: [$err]" >&2; exit 1; }
|
|
}
|
|
|
|
@test "a lookup killed by the wall-clock bound still accounts for itself" {
|
|
d=$(mktemp -d)
|
|
_TALOS_IMAGE_FACTORY_DECISION_FILE="$d/decision"
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
_TALOS_IMAGE_CACHE_QUERY_DELAY=0
|
|
_stub_kubectl_dir "$d" 0 'deployment.apps/talos-image-cache'
|
|
# The stall this loop exists for, and the one case where nobody speaks:
|
|
# `timeout` prints nothing when it fires, and the kubectl it killed never
|
|
# reached the point where it would have printed either. The sibling test
|
|
# below pins the reason on a kubectl that failed loudly, which every stub
|
|
# does by default -- so without this case "the reason reaches the log" is
|
|
# pinned only where it was never in doubt.
|
|
export STUB_TIMEOUT_RC=124
|
|
set +x
|
|
url=$(resolve_talos_image_factory_url 2>"$d/err")
|
|
err=$(cat "$d/err")
|
|
spoke=$(grep -c . "$d/calls" || true)
|
|
rm -rf "$d"
|
|
[ -z "$url" ]
|
|
# kubectl never ran, so anything the warning points at has to come from the
|
|
# lookup itself. Drop this and the case degrades into the sibling below.
|
|
[ "$spoke" = 0 ]
|
|
printf '%s' "$err" | grep -q 'the last one exited 124' || { echo "a lookup cut off by its own bound must say so: [$err]" >&2; exit 1; }
|
|
}
|
|
|
|
@test "a genuine absence still resolves once and stays cached" {
|
|
d=$(mktemp -d)
|
|
_TALOS_IMAGE_FACTORY_DECISION_FILE="$d/decision"
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
_TALOS_IMAGE_CACHE_QUERY_DELAY=0
|
|
_stub_kubectl_dir "$d" 0 ''
|
|
set +x
|
|
url=$(resolve_talos_image_factory_url 2>"$d/err")
|
|
cached=no
|
|
if [ -f "$d/decision" ]; then cached=yes; fi
|
|
err=$(cat "$d/err")
|
|
rm -rf "$d"
|
|
[ -z "$url" ]
|
|
[ "$cached" = yes ]
|
|
printf '%s' "$err" | grep -q 'not deployed' || { echo "a real absence must report itself as such: [$err]" >&2; exit 1; }
|
|
}
|
|
|
|
@test "with timeout off PATH the lookup still asks instead of answering unknown" {
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
d=$(mktemp -d)
|
|
_TALOS_IMAGE_CACHE_QUERY_DELAY=0
|
|
_stub_kubectl_dir "$d" 0 'deployment.apps/talos-image-cache'
|
|
rm -f "$d/bin/timeout"
|
|
# Everything the kubectl stub itself needs, staged from known directories so
|
|
# the stripped PATH below loses `timeout` and nothing else. Resolved this way
|
|
# rather than through `command -v` for the reason the same idiom gives in
|
|
# hack/run-kubernetes-node-join_test.bats: a name mocked as a shell function
|
|
# answers with the function and no link gets made.
|
|
for c in cat sleep; do
|
|
for p in /bin /usr/bin /usr/local/bin /opt/homebrew/bin; do
|
|
if [ -x "$p/$c" ]; then ln -sf "$p/$c" "$d/bin/$c"; break; fi
|
|
done
|
|
done
|
|
if [ ! -x "$d/bin/cat" ]; then
|
|
echo "could not stage a real cat in the stripped PATH; the check below would be vacuous" >&2
|
|
rm -rf "$d"
|
|
exit 1
|
|
fi
|
|
# Stripped for the call and restored right after: the assertions below need a
|
|
# `grep` this PATH deliberately does not have.
|
|
oldpath=$PATH
|
|
PATH="$d/bin"
|
|
state=$(_talos_image_cache_deploy_state)
|
|
PATH=$oldpath
|
|
wrapped=$(grep -c . "$d/timeout.calls" || true)
|
|
rm -rf "$d"
|
|
# Calling the wrapper anyway when it is not installed makes every attempt
|
|
# exit 127, and three of those read as an apiserver that never answered: a
|
|
# missing local binary would pin the whole suite to the public factory while
|
|
# every message blamed the cluster. Asserting the state rather than the exit
|
|
# is what distinguishes the two — 127 lands on `unknown`, not on an error.
|
|
[ "$state" = present ]
|
|
[ "$wrapped" = 0 ]
|
|
}
|
|
|
|
@test "probe overrides builder emits valid JSON with the image, command and restricted PSA" {
|
|
. hack/e2e-chainsaw/_lib/talos-image-cache.sh
|
|
img=example.invalid/img:tag
|
|
cmd='curl -s -o /dev/null -w code=%{http_code} -r 0-0 http://talos-image-cache.kube-system.svc/x.raw.xz'
|
|
json=$(_talos_image_cache_probe_overrides "$img" "$cmd")
|
|
# Invalid JSON would make every probe fail and silently drop CI back to the
|
|
# public factory, so parse it rather than pattern-match it.
|
|
printf '%s' "$json" | yq -p=json -o=json '.' >/dev/null
|
|
[ "$(printf '%s' "$json" | yq -p=json '.spec.containers[0].name')" = "c" ]
|
|
[ "$(printf '%s' "$json" | yq -p=json '.spec.containers[0].image')" = "$img" ]
|
|
[ "$(printf '%s' "$json" | yq -p=json '.spec.containers[0].command[2]')" = "$cmd" ]
|
|
[ "$(printf '%s' "$json" | yq -p=json '.spec.securityContext.runAsNonRoot')" = "true" ]
|
|
[ "$(printf '%s' "$json" | yq -p=json '.spec.containers[0].securityContext.allowPrivilegeEscalation')" = "false" ]
|
|
}
|