Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ markers = [
"elasticsearch: Tests for Elasticsearch/OpenSearch toolset functionality",
"integration: Integration tests requiring external services (e.g., running server, real APIs)",
"confluence: Tests for Confluence page fetching toolset",
"bash-resource-checker: Tests for bash toolset with kubectl exec to check resources inside containers",
# REGRESSION TEST SELECTION CRITERIA:
# - Must pass 30+ iterations reliably with Sonnet-4.5 model
# - No external API dependencies (Loki OK, NewRelic/DataDog excluded)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
apiVersion: v1
kind: Pod
metadata:
name: data-cruncher
namespace: app-211
labels:
app: data-cruncher
spec:
containers:
- name: worker
image: python:3.11-alpine
command:
- /bin/sh
- -c
- |
# Create 95 normal sleep processes (minimal memory)
for i in $(seq 1 95); do
sleep 3600 &
done

# Create 5 memory-hungry Python processes (~20MB each)
for i in $(seq 1 5); do
python3 -c "
import time
# Allocate ~20MB of memory
data = bytearray(20 * 1024 * 1024)
# Fill with data to ensure it's allocated
for j in range(0, len(data), 4096):
data[j] = 0xff
time.sleep(3600)
" &
done

# Keep container running
sleep 3600
resources:
limits:
memory: "256Mi"
cpu: "200m"
requests:
memory: "128Mi"
cpu: "100m"
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
user_prompt: "The data-cruncher pod in namespace app-211 is consuming too much memory. Check which processes inside the container are using the most memory and identify any that stand out."

include_tool_calls: true

expected_output:
- "Must call bash tool with kubectl exec"
- "Must identify Python processes as consuming the most memory"
- "Must report processes sorted by memory usage or identify top consumers"

description: |
Tests that Holmes can use bash to run kubectl exec and inspect processes inside a container.
The pod runs 95 sleep processes plus 5 Python processes that allocate ~20MB each.
Holmes must use bash with 'kubectl exec' since no existing toolset can inspect in-container processes.

tags:
- kubernetes
- regression
- bash-resource-checker

before_test: |
kubectl create namespace app-211 --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f manifest.yaml

# Wait for pod to be ready
POD_READY=false
for i in {1..60}; do
if kubectl wait --for=condition=ready pod/data-cruncher -n app-211 --timeout=2s 2>/dev/null; then
echo "Pod ready!"
POD_READY=true
break
fi
sleep 1
done

if [ "$POD_READY" = false ]; then
echo "Pod not ready after 60 seconds"
kubectl get pods -n app-211
kubectl describe pod/data-cruncher -n app-211
exit 1
fi

# Verify processes are running inside the container
PROC_COUNT=$(kubectl exec -n app-211 data-cruncher -- ps aux 2>/dev/null | wc -l)
echo "Process count in container: $PROC_COUNT"
if [ "$PROC_COUNT" -lt 50 ]; then
echo "Not enough processes running in container"
kubectl exec -n app-211 data-cruncher -- ps aux
exit 1
fi

# Verify Python processes are running
PYTHON_COUNT=$(kubectl exec -n app-211 data-cruncher -- ps aux 2>/dev/null | grep -c "python3" || echo "0")
echo "Python process count: $PYTHON_COUNT"
if [ "$PYTHON_COUNT" -lt 5 ]; then
echo "Not enough Python processes running"
exit 1
fi
echo "Setup complete - container has $PROC_COUNT processes including $PYTHON_COUNT Python processes"

after_test: |
kubectl delete namespace app-211 --ignore-not-found
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Bash toolset for process memory audit
# Enable bash with kubectl exec in allow list
# Disable kubernetes toolsets to force use of bash for in-container inspection
toolsets:
bash:
enabled: true
config:
allow:
- "kubectl exec"
- "kubectl get"
deny: []
kubernetes/core:
enabled: true # Keep basic k8s tools for context
kubernetes/logs:
enabled: false
kubernetes/live-metrics:
enabled: false
kubernetes/kube-prometheus-stack:
enabled: false
kubernetes/krew-extras:
enabled: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: v1
kind: Pod
metadata:
name: file-processor
namespace: app-212
labels:
app: file-processor
spec:
containers:
- name: worker
image: alpine:3.19
command:
- /bin/sh
- -c
- |
mkdir -p /var/data

# Create 90 small files (1KB each)
for i in $(seq 1 90); do
dd if=/dev/zero of=/var/data/small_$i.dat bs=1K count=1 2>/dev/null
done

# Create 10 large files (15MB each) - use /dev/zero for speed
for i in $(seq 91 100); do
dd if=/dev/zero of=/var/data/large_$i.dat bs=1M count=15 2>/dev/null
done

echo "Files created successfully"
ls -la /var/data | head -20

# Keep container running
sleep 3600
resources:
limits:
memory: "256Mi"
cpu: "200m"
requests:
memory: "128Mi"
cpu: "100m"
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
user_prompt: "The file-processor pod in namespace app-212 might have disk space issues. Check which files in /var/data are larger than 10MB and report the total disk usage of that directory."

include_tool_calls: true

expected_output:
- "Must call bash tool with kubectl exec"
- "Must identify files larger than 10MB (should find files like large_91.dat through large_100.dat)"
- "Must report disk usage information"

description: |
Tests that Holmes can use bash to run kubectl exec and inspect filesystem inside a container.
The pod has 100 files in /var/data: 90 small files (1KB each) and 10 large files (15MB each).
Holmes must use bash with 'kubectl exec' since no existing toolset can access container filesystems.

tags:
- kubernetes
- regression
- bash-resource-checker

before_test: |
kubectl create namespace app-212 --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f manifest.yaml

# Wait for pod to be ready
POD_READY=false
for i in {1..60}; do
if kubectl wait --for=condition=ready pod/file-processor -n app-212 --timeout=2s 2>/dev/null; then
echo "Pod ready!"
POD_READY=true
break
fi
sleep 1
done

if [ "$POD_READY" = false ]; then
echo "Pod not ready after 60 seconds"
kubectl get pods -n app-212
kubectl describe pod/file-processor -n app-212
exit 1
fi

# Wait for files to be created
FILES_READY=false
for i in {1..30}; do
FILE_COUNT=$(kubectl exec -n app-212 file-processor -- ls /var/data 2>/dev/null | wc -l)
echo "Attempt $i: $FILE_COUNT files in /var/data"
if [ "$FILE_COUNT" -ge 100 ]; then
echo "All 100 files created!"
FILES_READY=true
break
fi
sleep 2
done

if [ "$FILES_READY" = false ]; then
echo "Files not created properly"
kubectl exec -n app-212 file-processor -- ls -la /var/data
exit 1
fi

# Verify large files exist
LARGE_COUNT=$(kubectl exec -n app-212 file-processor -- find /var/data -size +10M 2>/dev/null | wc -l)
echo "Large files (>10MB): $LARGE_COUNT"
if [ "$LARGE_COUNT" -lt 10 ]; then
echo "Not enough large files created"
exit 1
fi
echo "Setup complete"

after_test: |
kubectl delete namespace app-212 --ignore-not-found
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Bash toolset for container disk audit
# Enable bash with kubectl exec in allow list
toolsets:
bash:
enabled: true
config:
allow:
- "kubectl exec"
- "kubectl get"
deny: []
kubernetes/core:
enabled: true
kubernetes/logs:
enabled: false
kubernetes/live-metrics:
enabled: false
kubernetes/kube-prometheus-stack:
enabled: false
kubernetes/krew-extras:
enabled: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
apiVersion: v1
kind: Pod
metadata:
name: connection-pool
namespace: app-213
labels:
app: connection-pool
Comment on lines +3 to +7

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Rename the pod/label to a neutral, unique identifier.
connection-pool is a hint‑giving technical name and may collide across tests; use a neutral business‑context name with the test id and update references in test_case.yaml accordingly.

🔁 Suggested rename
 metadata:
-  name: connection-pool
+  name: orders-worker-213
   namespace: app-213
   labels:
-    app: connection-pool
+    app: orders-worker-213

As per coding guidelines: All resource names must be unique across tests to prevent conflicts when tests run simultaneously; Never use obvious or hint-giving resource names in tests - use neutral, business-context names instead of technical indicators.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
metadata:
name: connection-pool
namespace: app-213
labels:
app: connection-pool
metadata:
name: orders-worker-213
namespace: app-213
labels:
app: orders-worker-213
🤖 Prompt for AI Agents
In
`@tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit/manifest.yaml`
around lines 3 - 7, The manifest uses a technical, non-unique resource
name/label "connection-pool" which can collide across tests; rename the
metadata.name and labels.app to a neutral, unique identifier that includes the
test id (e.g., "app-213-<neutral-name>") and update any references to it in the
associated test_case.yaml so they match the new metadata.name and labels.app;
ensure the new name follows resource naming rules and is used consistently
across the manifest and test_case.yaml.

spec:
containers:
- name: worker
image: alpine:3.19
command:
- /bin/sh
- -c
- |
# Install netcat and iproute2 for ss
apk add --no-cache netcat-openbsd iproute2 >/dev/null 2>&1

# Create 50 TCP listeners on ports 8001-8050
for port in $(seq 8001 8050); do
# Use while loop to keep listener alive after connection
while true; do nc -l -p $port; done &
done

echo "Created 50 TCP listeners"

# Wait a moment for listeners to start
sleep 2

# Create connections to each listener (these will be ESTABLISHED)
for port in $(seq 8001 8050); do
# Keep connection open by sleeping after connect
(sleep 3600 | nc 127.0.0.1 $port) &
done

echo "Created 50 client connections"

# Show connection summary
sleep 2
echo "Connection states:"
ss -tan | head -20

# Keep container running
sleep 3600
Comment on lines +12 to +44

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit && \
cat -n manifest.yaml

Repository: HolmesGPT/holmesgpt

Length of output: 1731


Move the startup script to a Kubernetes Secret.
The inline script in the container command violates test infrastructure policy. Create a Secret and mount it as a volume instead.

Suggested structure
 spec:
+  volumes:
+    - name: entrypoint
+      secret:
+        secretName: orders-worker-213-script
   containers:
     - name: worker
       image: alpine:3.19
-      command:
-        - /bin/sh
-        - -c
-        - |
-          # Install netcat and iproute2 for ss
-          apk add --no-cache netcat-openbsd iproute2 >/dev/null 2>&1
-          ...
+      command: ["/bin/sh", "/scripts/entrypoint.sh"]
+      volumeMounts:
+        - name: entrypoint
+          mountPath: /scripts
+          readOnly: true
apiVersion: v1
kind: Secret
metadata:
  name: orders-worker-213-script
  namespace: app-213
stringData:
  entrypoint.sh: |
    # (move the current script body here)
🤖 Prompt for AI Agents
In
`@tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit/manifest.yaml`
around lines 12 - 44, The inline multi-line shell in the pod/container "command"
should be moved into a Kubernetes Secret and mounted as a file; create a Secret
(e.g., name orders-worker-213-script) with stringData.entrypoint.sh containing
the current script body, update the manifest to remove the inline "command"
block and instead mount that Secret as a volume (readOnly) and set the
container's command to run the mounted /path/to/entrypoint.sh (e.g., /bin/sh -c
/mnt/entrypoint.sh), ensure the Secret volume is referenced in the pod spec and
the script file has executable/newline-safe content and appropriate permissions
at runtime.

resources:
limits:
memory: "128Mi"
cpu: "200m"
requests:
memory: "64Mi"
cpu: "100m"
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
user_prompt: "The connection-pool pod in namespace app-213 may have connection leaks. Check how many TCP connections it has and group them by state (ESTABLISHED, TIME_WAIT, LISTEN, etc.)."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Align pod references with the neutral, unique name.
Update the prompt and kubectl references to match the renamed pod from the manifest.

🔁 Suggested rename alignment
-user_prompt: "The connection-pool pod in namespace app-213 may have connection leaks. Check how many TCP connections it has and group them by state (ESTABLISHED, TIME_WAIT, LISTEN, etc.)."
+user_prompt: "The orders-worker-213 pod in namespace app-213 may have connection leaks. Check how many TCP connections it has and group them by state (ESTABLISHED, TIME_WAIT, LISTEN, etc.)."

-    if kubectl wait --for=condition=ready pod/connection-pool -n app-213 --timeout=2s 2>/dev/null; then
+    if kubectl wait --for=condition=ready pod/orders-worker-213 -n app-213 --timeout=2s 2>/dev/null; then

-    kubectl describe pod/connection-pool -n app-213
+    kubectl describe pod/orders-worker-213 -n app-213

-    kubectl exec -n app-213 connection-pool -- ss -tan
+    kubectl exec -n app-213 orders-worker-213 -- ss -tan

As per coding guidelines: All resource names must be unique across tests to prevent conflicts when tests run simultaneously; Never use obvious or hint-giving resource names in tests - use neutral, business-context names instead of technical indicators.

Also applies to: 28-28, 39-39, 58-58

🤖 Prompt for AI Agents
In
`@tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit/test_case.yaml`
at line 1, Update the user_prompt and any kubectl references that mention the
old pod name "connection-pool" to use the neutral, unique pod name used in the
manifest (the renamed pod referenced elsewhere in this test); locate the
user_prompt entry in
test_ask_holmes/213_bash_network_connection_audit/test_case.yaml and replace
occurrences of "connection-pool" (and any other hard-coded references in the
same file) so they exactly match the manifest's pod name used by functions that
query pods (e.g., any kubectl commands or variables that reference the pod), and
apply the same rename to the other occurrences noted in this test (the other
similar prompt/command entries).


include_tool_calls: true

expected_output:
- "Must call bash tool with kubectl exec"
- "Must report TCP connection states"
- "Must identify LISTEN connections on ports 8001-8050"
- "Must identify ESTABLISHED connections"

Comment on lines +3 to +10

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Make expected_output specific; then drop include_tool_calls.
The current expectations are generic. Encode concrete counts/port ranges to be hallucination‑proof; once specific, include_tool_calls can be false.

✅ Example expectations
-include_tool_calls: true
+include_tool_calls: false

 expected_output:
-  - "Must call bash tool with kubectl exec"
-  - "Must report TCP connection states"
-  - "Must identify LISTEN connections on ports 8001-8050"
-  - "Must identify ESTABLISHED connections"
+  - "Uses kubectl exec with bash against pod orders-worker-213"
+  - "Reports LISTEN sockets on ports 8001-8050 (≈50)"
+  - "Reports ESTABLISHED connections to 127.0.0.1:8001-8050 (≈50)"
+  - "Groups results by state (LISTEN/ESTABLISHED/TIME_WAIT)"

As per coding guidelines: Use specific, discoverable values in expected_output instead of generic patterns to rule out hallucinations; Use 'include_tool_calls: true' in test configuration only when expected output values are too generic to be hallucination-proof.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
include_tool_calls: true
expected_output:
- "Must call bash tool with kubectl exec"
- "Must report TCP connection states"
- "Must identify LISTEN connections on ports 8001-8050"
- "Must identify ESTABLISHED connections"
include_tool_calls: false
expected_output:
- "Uses kubectl exec with bash against pod orders-worker-213"
- "Reports LISTEN sockets on ports 8001-8050 (≈50)"
- "Reports ESTABLISHED connections to 127.0.0.1:8001-8050 (≈50)"
- "Groups results by state (LISTEN/ESTABLISHED/TIME_WAIT)"
🤖 Prompt for AI Agents
In
`@tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit/test_case.yaml`
around lines 3 - 10, Update the test fixture by replacing the generic
expected_output items with concrete, discoverable assertions (e.g., exact TCP
state counts and explicit port listings such as "LISTEN on ports 8001-8005: 3
entries" or "ESTABLISHED connections: 7" and specific kubectl exec invocation
text), and then remove or set include_tool_calls to false; reference the keys
expected_output and include_tool_calls in
test_ask_holmes/213_bash_network_connection_audit/test_case.yaml to locate and
change the entries.

description: |
Tests that Holmes can use bash to run kubectl exec and inspect network connections inside a container.
The pod creates 50 TCP listeners and 50 established connections.
Holmes must use bash with 'kubectl exec' to run ss/netstat since no toolset inspects container network state.

tags:
- kubernetes
- regression
- bash-resource-checker

before_test: |
kubectl create namespace app-213 --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f manifest.yaml

# Wait for pod to be ready
POD_READY=false
for i in {1..60}; do
if kubectl wait --for=condition=ready pod/connection-pool -n app-213 --timeout=2s 2>/dev/null; then
echo "Pod ready!"
POD_READY=true
break
fi
sleep 1
done

if [ "$POD_READY" = false ]; then
echo "Pod not ready after 60 seconds"
kubectl get pods -n app-213
kubectl describe pod/connection-pool -n app-213
exit 1
fi

# Wait for connections to be established
CONN_READY=false
for i in {1..30}; do
LISTEN_COUNT=$(kubectl exec -n app-213 connection-pool -- ss -tln 2>/dev/null | grep -c LISTEN || echo "0")
echo "Attempt $i: $LISTEN_COUNT LISTEN connections"
if [ "$LISTEN_COUNT" -ge 40 ]; then
Comment on lines +45 to +48

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit/test_case.yaml | head -60

Repository: HolmesGPT/holmesgpt

Length of output: 2380


🏁 Script executed:

find tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit -type f -name "*.yaml" -o -name "*.yml"

Repository: HolmesGPT/holmesgpt

Length of output: 312


🏁 Script executed:

# Check if there's a fixture definition or infrastructure file for this test
find tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit -type f

Repository: HolmesGPT/holmesgpt

Length of output: 312


🏁 Script executed:

cat tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit/manifest.yaml

Repository: HolmesGPT/holmesgpt

Length of output: 1374


🏁 Script executed:

# Let me verify the grep -c behavior to understand if the claim about double-zero output is accurate
cat > /tmp/test_grep.sh << 'EOF'
#!/bin/bash

# Test 1: grep -c on non-empty output
echo "Test 1: grep -c with matches"
echo -e "LISTEN\nLISTEN\nESTABLISHED" | grep -c "LISTEN"
echo "---"

# Test 2: grep -c on empty output
echo "Test 2: grep -c with no matches (should print 0)"
echo -e "ESTABLISHED\nTIME_WAIT" | grep -c "LISTEN"
echo "---"

# Test 3: Original command pattern with || echo "0"
echo "Test 3: With || echo '0' when grep returns 0"
LISTEN_COUNT=$(echo -e "ESTABLISHED\nTIME_WAIT" | grep -c "LISTEN" || echo "0")
echo "LISTEN_COUNT='$LISTEN_COUNT'"
echo "---"

# Test 4: Check if there are multiple lines
echo "Test 4: Checking raw output with set -x"
set -x
LISTEN_COUNT=$(echo -e "ESTABLISHED\nTIME_WAIT" | grep -c "LISTEN" || echo "0")
set +x
echo "Final value: $LISTEN_COUNT"
echo "---"

# Test 5: Check with failed command
echo "Test 5: With command that fails"
LISTEN_COUNT=$(/bin/false | grep -c "LISTEN" || echo "0")
echo "LISTEN_COUNT='$LISTEN_COUNT'"
EOF

bash /tmp/test_grep.sh

Repository: HolmesGPT/holmesgpt

Length of output: 443


🏁 Script executed:

cat tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit/manifest.yaml | grep -A 5 "metadata:" | grep "name:"

Repository: HolmesGPT/holmesgpt

Length of output: 86


Remove redundant echo fallback in LISTEN_COUNT assignment.

The pipe grep -c LISTEN || echo "0" outputs double zero (0\n0) because grep -c exits with code 1 when no matches are found, triggering the fallback echo. This causes [ "$LISTEN_COUNT" -ge 40 ] to fail with "integer expression expected". Use || true instead to suppress the non-zero exit without duplicating output:

🔧 Fixed assignment
-    LISTEN_COUNT=$(kubectl exec -n app-213 connection-pool -- ss -tln 2>/dev/null | grep -c LISTEN || echo "0")
+    LISTEN_COUNT=$(kubectl exec -n app-213 connection-pool -- ss -tln 2>/dev/null | grep -c LISTEN || true)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for i in {1..30}; do
LISTEN_COUNT=$(kubectl exec -n app-213 connection-pool -- ss -tln 2>/dev/null | grep -c LISTEN || echo "0")
echo "Attempt $i: $LISTEN_COUNT LISTEN connections"
if [ "$LISTEN_COUNT" -ge 40 ]; then
for i in {1..30}; do
LISTEN_COUNT=$(kubectl exec -n app-213 connection-pool -- ss -tln 2>/dev/null | grep -c LISTEN || true)
echo "Attempt $i: $LISTEN_COUNT LISTEN connections"
if [ "$LISTEN_COUNT" -ge 40 ]; then
🤖 Prompt for AI Agents
In
`@tests/llm/fixtures/test_ask_holmes/213_bash_network_connection_audit/test_case.yaml`
around lines 45 - 48, The LISTEN_COUNT assignment in the loop uses `grep -c
LISTEN || echo "0"` which can produce duplicate zeros when grep exits non-zero;
update the command substitution used to set LISTEN_COUNT (the line assigning
LISTEN_COUNT in the for loop that runs `kubectl exec -n app-213 connection-pool
-- ss -tln`) to suppress the non-zero exit without emitting an extra "0" by
replacing `grep -c LISTEN || echo "0"` with `grep -c LISTEN || true`, so
LISTEN_COUNT contains only the grep output and the subsequent numeric comparison
(`[ "$LISTEN_COUNT" -ge 40 ]`) won't fail.

echo "Connections established!"
CONN_READY=true
break
fi
sleep 2
done

if [ "$CONN_READY" = false ]; then
echo "Connections not established properly"
kubectl exec -n app-213 connection-pool -- ss -tan
exit 1
fi
echo "Setup complete"

after_test: |
kubectl delete namespace app-213 --ignore-not-found
Loading
Loading