Skip to content

Commit 81be148

Browse files
authored
feat(orchestrator): include orchestrator namespaces in namespace-inspect (#149)
* feat(orchestrator): include orchestrator namespaces in namespace-inspect When orchestrator resources are detected (Serverless operators, Knative namespaces, SonataFlowPlatform CRs, SonataFlow workflows), gather_orchestrator now writes their namespaces to a detected-namespaces.txt file. gather_namespace-inspect reads this file during auto-detection and merges those namespaces into the inspection list, giving deeper diagnostic coverage of orchestrator infrastructure. When the user explicitly specifies --namespaces, only those namespaces are inspected — orchestrator namespaces are not appended, respecting the user's explicit scope. Assisted-by: Claude * fix(namespace-inspect): defer exit until after orchestrator namespace merge Move the empty-namespaces exit check to after orchestrator namespaces are merged, so clusters with only orchestrator components (and no direct RHDH deployments) are still inspected. Assisted-by: Claude * fix(tests): resolve ShellCheck SC2016 warnings in test grep patterns Simplify grep patterns in orchestrator and namespace-inspect tests to avoid escaped dollar signs inside single quotes, which ShellCheck flags as unexpanded expressions. Assisted-by: Claude * fix(namespace-inspect): normalize namespaces before deduplication Orchestrator namespaces read from detected-namespaces.txt were deduplicated before whitespace trimming, allowing entries like " foo " and "foo" to both appear in the final list. This caused redundant oc adm inspect targets and inflated timeouts. Normalize each namespace (trim whitespace) immediately upon reading, both for orchestrator entries and existing entries during comparison. Replace the post-merge trim-only loop with a full cleanup pass that trims, removes empty entries, and deduplicates the entire array. Assisted-by: Claude * fix(orchestrator): stop creating empty detected-namespaces.txt The script unconditionally truncated detected-namespaces.txt at startup, leaving an empty file when no orchestrator components were found. This can confuse users and downstream tools inspecting the output artifacts. Remove the eager truncation (`: > "$ORCH_NAMESPACES_FILE"`). All writes already use append (>>), so the file is created naturally on the first detected namespace. gather_namespace-inspect already guards with `[[ -s file ]]`, so file absence is handled correctly. Assisted-by: Claude * test(namespace-inspect): replace grep-based tests with runtime behavior tests The previous tests only grepped for strings in the script source, which validated code presence but not runtime behavior. Replace them with tests that actually execute the script against mock binaries (oc, kubectl, helm, jq) and verify the resulting oc adm inspect arguments. New tests cover: - Deduplication of orchestrator namespaces with whitespace variants - Explicit --namespaces mode ignoring orchestrator namespaces - Empty detected-namespaces.txt producing no extra namespaces - Absent detected-namespaces.txt handled gracefully - Merging auto-detected and orchestrator namespaces without duplicates - Whitespace-only lines in detected-namespaces.txt being ignored Assisted-by: Claude
1 parent d11a697 commit 81be148

4 files changed

Lines changed: 332 additions & 9 deletions

File tree

collection-scripts/gather_namespace-inspect

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,6 @@ else
7777
# Combine and deduplicate
7878
all_namespaces=$(echo -e "${helm_namespaces}\n${standalone_namespaces}\n${cr_namespaces}\n${operator_namespaces}" | grep -v '^$' | sort | uniq || echo "")
7979

80-
if [[ -z "$all_namespaces" ]]; then
81-
log_warn "No RHDH deployments found in cluster"
82-
echo "No RHDH namespaces detected" > "$inspect_dir/no-namespaces.txt"
83-
exit 0
84-
fi
85-
8680
# Convert to array
8781
while IFS= read -r ns; do
8882
[[ -n "$ns" ]] && namespaces_to_inspect+=("$ns")
@@ -94,10 +88,53 @@ else
9488
fi
9589
fi
9690

97-
# Trim whitespace from namespace names
98-
for i in "${!namespaces_to_inspect[@]}"; do
99-
namespaces_to_inspect[$i]=$(echo "${namespaces_to_inspect[$i]}" | xargs)
91+
# Add orchestrator-related namespaces when auto-detecting (not when user specifies --namespaces)
92+
if [[ -z "${RHDH_TARGET_NAMESPACES:-}" ]]; then
93+
orch_ns_file="$BASE_COLLECTION_PATH/orchestrator/detected-namespaces.txt"
94+
if [[ -s "$orch_ns_file" ]]; then
95+
log_info "Adding orchestrator-related namespaces to inspection..."
96+
while IFS= read -r orch_ns; do
97+
orch_ns=$(echo "$orch_ns" | xargs)
98+
[[ -z "$orch_ns" ]] && continue
99+
already_included=false
100+
for existing_ns in "${namespaces_to_inspect[@]:-}"; do
101+
existing_ns=$(echo "$existing_ns" | xargs)
102+
if [[ "$existing_ns" == "$orch_ns" ]]; then
103+
already_included=true
104+
break
105+
fi
106+
done
107+
if [[ "$already_included" != "true" ]]; then
108+
namespaces_to_inspect+=("$orch_ns")
109+
log_info "Added orchestrator namespace: $orch_ns"
110+
fi
111+
done < "$orch_ns_file"
112+
fi
113+
fi
114+
115+
if [[ ${#namespaces_to_inspect[@]} -eq 0 ]]; then
116+
log_warn "No RHDH deployments or orchestrator components found in cluster"
117+
echo "No namespaces detected" > "$inspect_dir/no-namespaces.txt"
118+
exit 0
119+
fi
120+
121+
# Trim whitespace, remove empty entries, and deduplicate
122+
declare -a cleaned_namespaces=()
123+
for ns in "${namespaces_to_inspect[@]}"; do
124+
ns=$(echo "$ns" | xargs)
125+
[[ -z "$ns" ]] && continue
126+
already_present=false
127+
for existing in "${cleaned_namespaces[@]:-}"; do
128+
if [[ "$existing" == "$ns" ]]; then
129+
already_present=true
130+
break
131+
fi
132+
done
133+
if [[ "$already_present" != "true" ]]; then
134+
cleaned_namespaces+=("$ns")
135+
fi
100136
done
137+
namespaces_to_inspect=("${cleaned_namespaces[@]:-}")
101138

102139
log_info "Found ${#namespaces_to_inspect[@]} namespace(s) to inspect: ${namespaces_to_inspect[*]}"
103140

collection-scripts/gather_orchestrator

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ ensure_directory "$orchestrator_dir"
1818
# Flag to track if any Orchestrator components were found
1919
orchestrator_detected=false
2020

21+
# File to track orchestrator-related namespaces for gather_namespace-inspect
22+
# Created lazily on first write; gather_namespace-inspect uses [[ -s file ]] so absence is fine
23+
ORCH_NAMESPACES_FILE="$orchestrator_dir/detected-namespaces.txt"
24+
2125
# ============================================================================
2226
# Serverless Operators Detection and Collection
2327
# ============================================================================
@@ -33,6 +37,7 @@ function gather_serverless_operators() {
3337
if $KUBECTL_CMD get namespace "$serverless_ns" >/dev/null 2>&1; then
3438
log_info "\tFound OpenShift Serverless namespace: $serverless_ns"
3539
orchestrator_detected=true
40+
echo "$serverless_ns" >> "$ORCH_NAMESPACES_FILE"
3641

3742
local serverless_ns_dir="$serverless_dir/ns=$serverless_ns"
3843
ensure_directory "$serverless_ns_dir"
@@ -72,6 +77,7 @@ function gather_serverless_operators() {
7277
if $KUBECTL_CMD get namespace "$logic_ns" >/dev/null 2>&1; then
7378
log_info "\tFound OpenShift Serverless Logic namespace: $logic_ns"
7479
orchestrator_detected=true
80+
echo "$logic_ns" >> "$ORCH_NAMESPACES_FILE"
7581

7682
local logic_ns_dir="$serverless_dir/ns=$logic_ns"
7783
ensure_directory "$logic_ns_dir"
@@ -194,6 +200,8 @@ function gather_sonataflow_platforms() {
194200
sfp_name=$(echo "$sfp_info" | cut -d'/' -f2)
195201
fi
196202

203+
[[ -n "$sfp_ns" ]] && echo "$sfp_ns" >> "$ORCH_NAMESPACES_FILE"
204+
197205
log_info "--> Processing SonataFlowPlatform $sfp_name in namespace $sfp_ns"
198206

199207
local sfp_cr_dir="$sfp_dir/ns=$sfp_ns/$sfp_name"
@@ -264,6 +272,8 @@ function gather_sonataflow_workflows() {
264272
wf_name=$(echo "$wf_info" | cut -d'/' -f2)
265273
fi
266274

275+
[[ -n "$wf_ns" ]] && echo "$wf_ns" >> "$ORCH_NAMESPACES_FILE"
276+
267277
local ns_dir="$sfw_dir/ns=$wf_ns"
268278

269279
# Collect per-namespace workflow list once
@@ -320,6 +330,7 @@ function gather_knative_resources() {
320330
# Check knative-serving namespace for resources
321331
if $KUBECTL_CMD get namespace knative-serving >/dev/null 2>&1; then
322332
orchestrator_detected=true
333+
echo "knative-serving" >> "$ORCH_NAMESPACES_FILE"
323334
local serving_dir="$knative_dir/knative-serving"
324335
ensure_directory "$serving_dir"
325336

@@ -337,6 +348,7 @@ function gather_knative_resources() {
337348
# Check knative-eventing namespace for resources
338349
if $KUBECTL_CMD get namespace knative-eventing >/dev/null 2>&1; then
339350
orchestrator_detected=true
351+
echo "knative-eventing" >> "$ORCH_NAMESPACES_FILE"
340352
local eventing_dir="$knative_dir/knative-eventing"
341353
ensure_directory "$eventing_dir"
342354

@@ -422,6 +434,13 @@ gather_orchestrator_crds
422434
gather_sonataflow_platforms
423435
gather_sonataflow_workflows
424436
gather_knative_resources
437+
438+
# Deduplicate the detected namespaces file
439+
if [[ -s "$ORCH_NAMESPACES_FILE" ]]; then
440+
sort -u -o "$ORCH_NAMESPACES_FILE" "$ORCH_NAMESPACES_FILE"
441+
log_info "Orchestrator namespaces for namespace-inspect: $(tr '\n' ',' < "$ORCH_NAMESPACES_FILE" | sed 's/,$//')"
442+
fi
443+
425444
generate_orchestrator_summary
426445

427446
if [[ "$orchestrator_detected" == "true" ]]; then

tests/namespace-inspect.bats

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#!/usr/bin/env bats
2+
# Tests for gather_namespace-inspect script
3+
4+
load 'test_helper'
5+
6+
setup() {
7+
setup_test_environment
8+
export BASE_COLLECTION_PATH="${TEST_TMPDIR}"
9+
10+
# Create a mock bin directory and prepend it to PATH
11+
export MOCK_BIN="${TEST_TMPDIR}/mock-bin"
12+
mkdir -p "$MOCK_BIN"
13+
14+
# File where mock oc captures inspect arguments
15+
export OC_INSPECT_ARGS="${TEST_TMPDIR}/oc-inspect-args.txt"
16+
17+
# Mock oc: captures "adm inspect" args, no-ops everything else
18+
cat > "$MOCK_BIN/oc" << 'MOCK_OC'
19+
#!/usr/bin/env bash
20+
if [[ "${1:-}" == "adm" && "${2:-}" == "inspect" ]]; then
21+
shift 2
22+
echo "$@" > "$OC_INSPECT_ARGS"
23+
exit 0
24+
fi
25+
if [[ "${1:-}" == "version" ]]; then
26+
echo "Client Version: v4.15.0"
27+
exit 0
28+
fi
29+
echo ""
30+
exit 0
31+
MOCK_OC
32+
chmod +x "$MOCK_BIN/oc"
33+
34+
# Mock kubectl: returns empty results for all queries
35+
# Distinguishes "-o json" (needs valid JSON for jq) from "-o jsonpath=..." (needs empty string)
36+
cat > "$MOCK_BIN/kubectl" << 'MOCK_KUBECTL'
37+
#!/usr/bin/env bash
38+
if [[ "${1:-}" == "version" ]]; then
39+
echo "Client Version: v1.30.0"
40+
exit 0
41+
fi
42+
for arg in "$@"; do
43+
case "$arg" in
44+
json) echo '{"items":[]}'; exit 0 ;;
45+
jsonpath=*) exit 0 ;;
46+
esac
47+
done
48+
exit 0
49+
MOCK_KUBECTL
50+
chmod +x "$MOCK_BIN/kubectl"
51+
52+
# Mock helm: returns empty JSON array
53+
cat > "$MOCK_BIN/helm" << 'MOCK_HELM'
54+
#!/usr/bin/env bash
55+
echo "[]"
56+
exit 0
57+
MOCK_HELM
58+
chmod +x "$MOCK_BIN/helm"
59+
60+
# Mock jq: use real jq if available, otherwise provide minimal stub
61+
if command -v jq &>/dev/null; then
62+
ln -sf "$(command -v jq)" "$MOCK_BIN/jq"
63+
else
64+
cat > "$MOCK_BIN/jq" << 'MOCK_JQ'
65+
#!/usr/bin/env bash
66+
echo ""
67+
exit 0
68+
MOCK_JQ
69+
chmod +x "$MOCK_BIN/jq"
70+
fi
71+
72+
export PATH="$MOCK_BIN:$PATH"
73+
export KUBECTL_CMD="kubectl"
74+
}
75+
76+
teardown() {
77+
teardown_test_environment
78+
}
79+
80+
# ============================================================================
81+
# Script existence and basic tests
82+
# ============================================================================
83+
84+
@test "gather_namespace-inspect script exists" {
85+
[ -f "${SCRIPTS_DIR}/gather_namespace-inspect" ]
86+
}
87+
88+
@test "gather_namespace-inspect script is executable" {
89+
[ -x "${SCRIPTS_DIR}/gather_namespace-inspect" ]
90+
}
91+
92+
@test "gather_namespace-inspect sources common.sh" {
93+
run grep -q "source.*common.sh" "${SCRIPTS_DIR}/gather_namespace-inspect"
94+
[ "$status" -eq 0 ]
95+
}
96+
97+
# ============================================================================
98+
# Orchestrator namespace integration tests (runtime behavior)
99+
# ============================================================================
100+
101+
@test "gather_namespace-inspect auto-detect deduplicates orchestrator namespaces with whitespace variants" {
102+
mkdir -p "$BASE_COLLECTION_PATH/orchestrator"
103+
# Write duplicates, whitespace variants, and blank lines
104+
cat > "$BASE_COLLECTION_PATH/orchestrator/detected-namespaces.txt" << 'EOF'
105+
orch-ns1
106+
orch-ns1
107+
orch-ns2
108+
109+
orch-ns2
110+
orch-ns1
111+
EOF
112+
113+
run "${SCRIPTS_DIR}/gather_namespace-inspect"
114+
[ "$status" -eq 0 ]
115+
116+
# oc adm inspect should have been called
117+
[ -f "$OC_INSPECT_ARGS" ]
118+
119+
# Each namespace should appear exactly once
120+
local args
121+
args=$(cat "$OC_INSPECT_ARGS")
122+
local count_ns1 count_ns2
123+
count_ns1=$(echo "$args" | grep -o 'namespace/orch-ns1' | wc -l)
124+
count_ns2=$(echo "$args" | grep -o 'namespace/orch-ns2' | wc -l)
125+
[ "$count_ns1" -eq 1 ]
126+
[ "$count_ns2" -eq 1 ]
127+
}
128+
129+
@test "gather_namespace-inspect explicit namespaces mode ignores orchestrator namespaces" {
130+
export RHDH_TARGET_NAMESPACES="explicit-ns1,explicit-ns2"
131+
132+
mkdir -p "$BASE_COLLECTION_PATH/orchestrator"
133+
echo "orch-ns1" > "$BASE_COLLECTION_PATH/orchestrator/detected-namespaces.txt"
134+
135+
run "${SCRIPTS_DIR}/gather_namespace-inspect"
136+
[ "$status" -eq 0 ]
137+
[ -f "$OC_INSPECT_ARGS" ]
138+
139+
local args
140+
args=$(cat "$OC_INSPECT_ARGS")
141+
[[ "$args" == *"namespace/explicit-ns1"* ]]
142+
[[ "$args" == *"namespace/explicit-ns2"* ]]
143+
[[ "$args" != *"namespace/orch-ns1"* ]]
144+
}
145+
146+
@test "gather_namespace-inspect empty detected-namespaces.txt does not add namespaces" {
147+
mkdir -p "$BASE_COLLECTION_PATH/orchestrator"
148+
: > "$BASE_COLLECTION_PATH/orchestrator/detected-namespaces.txt"
149+
150+
run "${SCRIPTS_DIR}/gather_namespace-inspect"
151+
[ "$status" -eq 0 ]
152+
153+
# With no helm/operator/CR results and an empty orch file, no namespaces are detected
154+
[ -f "$BASE_COLLECTION_PATH/namespace-inspect/no-namespaces.txt" ]
155+
[[ ! -f "$OC_INSPECT_ARGS" ]]
156+
}
157+
158+
@test "gather_namespace-inspect absent detected-namespaces.txt does not add namespaces" {
159+
# Don't create the orchestrator directory at all
160+
run "${SCRIPTS_DIR}/gather_namespace-inspect"
161+
[ "$status" -eq 0 ]
162+
163+
[ -f "$BASE_COLLECTION_PATH/namespace-inspect/no-namespaces.txt" ]
164+
[[ ! -f "$OC_INSPECT_ARGS" ]]
165+
}
166+
167+
@test "gather_namespace-inspect merges auto-detected and orchestrator namespaces without duplicates" {
168+
# Make kubectl return a namespace for the operator detection query
169+
cat > "$MOCK_BIN/kubectl" << 'MOCK_KUBECTL'
170+
#!/usr/bin/env bash
171+
if [[ "${1:-}" == "version" ]]; then
172+
echo "Client Version: v1.30.0"
173+
exit 0
174+
fi
175+
if [[ "$*" == *"app=rhdh-operator"* ]]; then
176+
echo "operator-ns"
177+
exit 0
178+
fi
179+
for arg in "$@"; do
180+
case "$arg" in
181+
json) echo '{"items":[]}'; exit 0 ;;
182+
jsonpath=*) exit 0 ;;
183+
esac
184+
done
185+
exit 0
186+
MOCK_KUBECTL
187+
chmod +x "$MOCK_BIN/kubectl"
188+
189+
mkdir -p "$BASE_COLLECTION_PATH/orchestrator"
190+
# Include operator-ns as a duplicate and a new orch-only namespace
191+
printf '%s\n' "operator-ns" "orch-ns1" > "$BASE_COLLECTION_PATH/orchestrator/detected-namespaces.txt"
192+
193+
run "${SCRIPTS_DIR}/gather_namespace-inspect"
194+
[ "$status" -eq 0 ]
195+
[ -f "$OC_INSPECT_ARGS" ]
196+
197+
local args
198+
args=$(cat "$OC_INSPECT_ARGS")
199+
local count_operator count_orch
200+
count_operator=$(echo "$args" | grep -o 'namespace/operator-ns' | wc -l)
201+
count_orch=$(echo "$args" | grep -o 'namespace/orch-ns1' | wc -l)
202+
[ "$count_operator" -eq 1 ]
203+
[ "$count_orch" -eq 1 ]
204+
}
205+
206+
@test "gather_namespace-inspect whitespace-only lines in detected-namespaces.txt are ignored" {
207+
mkdir -p "$BASE_COLLECTION_PATH/orchestrator"
208+
# File with only whitespace lines
209+
printf ' \n\t\n \n' > "$BASE_COLLECTION_PATH/orchestrator/detected-namespaces.txt"
210+
211+
run "${SCRIPTS_DIR}/gather_namespace-inspect"
212+
[ "$status" -eq 0 ]
213+
214+
# No valid namespaces, so no inspect should run
215+
[ -f "$BASE_COLLECTION_PATH/namespace-inspect/no-namespaces.txt" ]
216+
[[ ! -f "$OC_INSPECT_ARGS" ]]
217+
}

0 commit comments

Comments
 (0)