refactor: split domain tooling into dedicated KNEL repos [#769]

siem->KNEL/siem, netinfra->KNEL/netinfra, ca->KNEL/ca, oam->KNEL/monitoring,
cmdb->KNEL/inventory, dcinfra->KNEL/facilities, proxmox/perf->KNEL/perf;
unit tests moved with their code. AGENTS.md layout/paths repointed.
Full history retained here. Map: Redmine #769, Discourse t/331.

https://projects.knownelement.com/issues/769#note-4152
This commit is contained in:
2026-09-03 21:49:50 -05:00
parent ebd876b085
commit dba54b294f
342 changed files with 0 additions and 25503 deletions
-109
View File
@@ -1,109 +0,0 @@
#!/bin/bash
# Unit tests for netinfra/dns/drift-check.sh [#420][#469]
# Tests the redaction and normalization functions without touching hosts.
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SCRIPT="$PROJECT_ROOT/netinfra/dns/drift-check.sh"
failed=0
if [[ -f "$SCRIPT" ]] && (source "$SCRIPT"); then
echo "✅ script exists + sources cleanly"
else
echo "❌ script missing or fails to source: $SCRIPT"
exit 1
fi
# shellcheck disable=SC1091
source "$SCRIPT"
test_redact_strips_secrets() {
local out
out=$(printf ' pwhash = "SECRETBALLOONHASH"\n totp_secret = "ABC234"\n password = "hunter2"\n port = 53\n' | redact_config)
if grep -qE "SECRETBALLOON|ABC234|hunter2" <<<"$out"; then
echo "❌ redact_config leaked a secret"
((++failed))
elif grep -q '"REDACTED"' <<<"$out" && grep -q "port = 53" <<<"$out"; then
echo "✅ redact_config strips secrets, keeps config"
else
echo "❌ redact_config mangled output"
((++failed))
fi
}
test_normalize_drops_timestamp() {
local out
out=$(printf '# Last updated on 2026-09-01 17:01:15 CDT\n dnsmasq_lines = []\n' | normalize_toml)
if grep -q "Last updated" <<<"$out"; then
echo "❌ normalize_toml kept the timestamp churn line"
((++failed))
elif grep -q "dnsmasq_lines" <<<"$out"; then
echo "✅ normalize_toml drops timestamp, keeps config"
else
echo "❌ normalize_toml dropped config lines"
((++failed))
fi
}
test_normalize_implies_redaction() {
local out
out=$(printf ' totp_secret = "XYZ789"\n a = 1\n' | normalize_toml)
if grep -q XYZ789 <<<"$out"; then
echo "❌ normalize_toml leaked a secret"
((++failed))
else
echo "✅ normalize_toml redacts secrets"
fi
}
test_redact_strips_secrets
test_normalize_drops_timestamp
test_normalize_implies_redaction
test_ntp_conf_tracked() {
if [[ -n "${NTP_FILE:-}" && -f "$NTP_FILE" ]]; then
echo "✅ NTP_FILE points at tracked canonical config"
else
echo "❌ NTP_FILE missing or file absent: ${NTP_FILE:-unset}"
((++failed))
fi
}
test_zones_dir_tracked() {
if [[ -n "${ZONES_DIR:-}" && -d "$ZONES_DIR" ]] && compgen -G "${ZONES_DIR}/*.zone" > /dev/null; then
echo "✅ ZONES_DIR present with zone files"
else
echo "❌ ZONES_DIR missing or empty: ${ZONES_DIR:-unset}"
((++failed))
fi
}
test_gen_manifest_sorted_md5() {
local fxt out n
fxt="$(mktemp -d)"
printf 'A' > "$fxt/zz.zone"
printf 'B' > "$fxt/aa.zone"
printf 'S' > "$fxt/ignored.txt"
out="$(gen_manifest "$fxt")"
n="$(wc -l <<<"$out")"
if [[ "$n" -eq 2 ]] \
&& grep -qE '^[0-9a-f]{32} (aa|zz)\.zone$' <<<"$out" \
&& [[ "$(head -1 <<<"$out")" == *"aa.zone" ]] \
&& ! grep -q 'ignored' <<<"$out"; then
echo "✅ gen_manifest: md5 of *.zone only, name-sorted"
else
echo "❌ gen_manifest wrong output"
((++failed))
fi
rm -rf "$fxt"
}
test_ntp_conf_tracked
test_zones_dir_tracked
test_gen_manifest_sorted_md5
if ((failed > 0)); then
echo "$failed drift-check test(s) failed"
exit 1
fi
echo "✅ all drift-check tests passed"
-128
View File
@@ -1,128 +0,0 @@
#!/bin/bash
# Unit tests for netinfra/dns-cluster-setup/sync-zones.sh [#469]
# Verifies reload-on-change behavior: Technitium restart fires only when
# rsync actually changed zone files, and never on clean syncs.
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SCRIPT="$PROJECT_ROOT/netinfra/dns-cluster-setup/sync-zones.sh"
failed=0
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
export LOG_FILE="$TMP/sync.log"
# Script must exist and source cleanly (main guarded for sourcing)
if [[ -f "$SCRIPT" ]] && (source "$SCRIPT"); then
echo "✅ script exists + sources cleanly"
else
echo "❌ script missing or fails to source: $SCRIPT"
exit 1
fi
# shellcheck disable=SC1091
source "$SCRIPT"
# Fake command log: record invocations of rsync / reload / find
FAKE_BIN="$TMP/bin"
mkdir -p "$FAKE_BIN"
export PATH="$FAKE_BIN:$PATH"
make_rsync() {
# $1 = exit code, $2 = "changed" or "clean" (stdout of rsync)
cat > "$FAKE_BIN/rsync" <<EOF
#!/bin/bash
echo "$2"
exit $1
EOF
chmod +x "$FAKE_BIN/rsync"
}
make_reload() {
cat > "$FAKE_BIN/reload" <<'EOF'
#!/bin/bash
echo "reload-fired" >> "$RELOAD_LOG"
EOF
chmod +x "$FAKE_BIN/reload"
}
RELOAD_LOG="$TMP/reload.log"
touch "$RELOAD_LOG"
export RELOAD_LOG
# find: minimal fake so zone counting works
mkdir -p "$FAKE_BIN/find-dir"
cat > "$FAKE_BIN/find" <<'EOF'
#!/bin/bash
# report 3 fake zone files regardless of args
for i in 1 2 3; do echo "/zones/zone$i"; done
EOF
chmod +x "$FAKE_BIN/find"
test_reload_fires_on_change() {
make_rsync 0 "knel.net.zone"
make_reload
RELOAD_CMD=("$FAKE_BIN/reload")
export RELOAD_CMD
if sync_and_reload >/dev/null 2>&1 && [[ "$(cat "$RELOAD_LOG")" == "reload-fired" ]]; then
echo "✅ reload fires when rsync reports changed zones"
else
echo "❌ reload did not fire on changed sync"
((++failed))
fi
: > "$RELOAD_LOG"
}
test_no_reload_on_clean_sync() {
make_rsync 0 ""
make_reload
RELOAD_CMD=("$FAKE_BIN/reload")
export RELOAD_CMD
if sync_and_reload >/dev/null 2>&1 && [[ ! -s "$RELOAD_LOG" ]]; then
echo "✅ no reload on clean sync"
else
echo "❌ reload fired (or errored) on clean sync"
((++failed))
fi
}
test_rsync_failure_propagates() {
make_rsync 23 ""
RELOAD_CMD=("$FAKE_BIN/reload")
export RELOAD_CMD
if ! sync_and_reload >/dev/null 2>&1; then
echo "✅ rsync failure propagates non-zero rc"
else
echo "❌ rsync failure was swallowed"
((++failed))
fi
if [[ ! -s "$RELOAD_LOG" ]]; then
echo "✅ no reload attempted after rsync failure"
else
echo "❌ reload fired despite rsync failure"
((++failed))
fi
}
test_reload_failure_does_not_break_sync() {
make_rsync 0 "knel.net.zone"
RELOAD_CMD=("/bin/false")
export RELOAD_CMD
if sync_and_reload >/dev/null 2>&1; then
echo "✅ reload failure does not fail the sync run"
else
echo "❌ reload failure failed the whole sync"
((++failed))
fi
}
test_reload_fires_on_change
test_no_reload_on_clean_sync
test_rsync_failure_propagates
test_reload_failure_does_not_break_sync
if ((failed > 0)); then
echo "$failed sync-zones test(s) failed"
exit 1
fi
echo "✅ all sync-zones tests passed"
-84
View File
@@ -1,84 +0,0 @@
#!/bin/bash
# Unit tests for netinfra/mdns/hap-bridge.py [#619]
# Verifies record capture normalization + packet encode/decode round-trip.
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SCRIPT="$PROJECT_ROOT/netinfra/mdns/hap-bridge.py"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
cat > "$TMP/test_bridge.py" <<'PY'
import importlib.util
import struct
import sys
spec = importlib.util.spec_from_file_location("hap_bridge", sys.argv[1])
hb = importlib.util.module_from_spec(spec)
spec.loader.exec_module(hb)
failed = 0
def check(name, cond):
global failed
print(("PASS " if cond else "FAIL ") + name)
if not cond:
failed += 1
# --- encode_name / read_name round trip
enc = hb.encode_name("Main Floor._hap._tcp.local")
back, off = hb.read_name(enc, 0)
check("name round-trip", back == "Main Floor._hap._tcp.local" and off == len(enc))
# --- encode_record + build_packet round trip for PTR/SRV/TXT
recs = [
{"name": "_hap._tcp.local", "type": 12, "ttl": 10, "ptr_target": "Main Floor._hap._tcp.local"},
{"name": "Main Floor._hap._tcp.local", "type": 33, "ttl": 10,
"srv_prio": 0, "srv_weight": 0, "srv_port": 58528, "srv_target": "Main-Floor.local"},
{"name": "Main Floor._hap._tcp.local", "type": 16, "ttl": 10, "rdata_hex": "0268310568656c6c6f"},
{"name": "Main-Floor.local", "type": 1, "ttl": 10, "rdata_hex": "c0a801d4"},
]
packet = hb.build_packet(recs)
check("packet header ancount", struct.unpack(">H", packet[6:8])[0] == 4)
# parse the packet back
qd = struct.unpack(">H", packet[4:6])[0]
an = struct.unpack(">H", packet[6:8])[0]
off = 12
parsed = []
for _ in range(qd):
_, off = hb.read_name(packet, off)
off += 4
for _ in range(an):
name, name_end = hb.read_name(packet, off)
rtype, _rc, ttl, rlen = struct.unpack(">HHIH", packet[name_end:name_end + 10])
rdata_start = name_end + 10
rec = {"name": name, "type": rtype, "ttl": ttl}
if rtype == 12:
rec["ptr_target"] = hb.read_name(packet, rdata_start)[0]
elif rtype == 33:
pri, w, port = struct.unpack(">HHH", packet[rdata_start:rdata_start + 6])
rec["srv_target"] = hb.read_name(packet, rdata_start + 6)[0]
rec["srv_port"] = port
else:
rec["rdata_hex"] = packet[rdata_start:rdata_start + rlen].hex()
parsed.append(rec)
off = rdata_start + rlen
check("ptr round-trip", parsed[0]["ptr_target"] == "Main Floor._hap._tcp.local")
check("srv target round-trip", parsed[1]["srv_target"] == "Main-Floor.local")
check("srv port round-trip", parsed[1]["srv_port"] == 58528)
check("txt round-trip", parsed[2]["rdata_hex"] == "0268310568656c6c6f")
check("a round-trip", parsed[3]["rdata_hex"] == "c0a801d4")
check("consumed whole packet", off == len(packet))
sys.exit(1 if failed else 0)
PY
if timeout 60 docker run --rm -v "$SCRIPT:/b.py" -v "$TMP/test_bridge.py:/t.py" python:3.12-alpine python /t.py /b.py; then
echo "✅ hap-bridge packet round-trip tests passed"
else
echo "❌ hap-bridge tests failed"
exit 1
fi
-64
View File
@@ -1,64 +0,0 @@
#!/bin/bash
# Unit tests for lmsensors-extend.sh -n numeric mode [#618]
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SCRIPT="$PROJECT_ROOT/dcinfra/sensors/temper/lmsensors-extend.sh"
failed=0
if [[ -f "$SCRIPT" ]] && (source "$SCRIPT"); then
echo "✅ script exists + sources cleanly"
else
echo "❌ script missing or fails to source: $SCRIPT"
exit 1
fi
# shellcheck disable=SC1091
source "$SCRIPT"
# numeric_pick: TEMPer external > TEMPer internal > first native/sysfs value
test_numeric_prefers_external() {
if [[ "$(numeric_pick "22.5" "18.2" "" )" == "18.2" ]]; then
echo "✅ numeric_pick prefers external probe"
else
echo "❌ numeric_pick external preference broken"
((++failed))
fi
}
test_numeric_falls_back_internal() {
if [[ "$(numeric_pick "22.5" "" "")" == "22.5" ]]; then
echo "✅ numeric_pick falls back to internal"
else
echo "❌ numeric_pick internal fallback broken"
((++failed))
fi
}
test_numeric_uses_first_line_value() {
if [[ "$(numeric_pick "" "" "temp1: +27.5°C (high = +84.0°C)")" == "27.5" ]]; then
echo "✅ numeric_pick parses first native temp"
else
echo "❌ numeric_pick native parse broken: got '$(numeric_pick "" "" "+27.5°C")'"
((++failed))
fi
}
test_numeric_empty_is_error() {
if numeric_pick "" "" "" >/dev/null 2>&1; then
echo "❌ numeric_pick should fail on no data"
((++failed))
else
echo "✅ numeric_pick errors on no data"
fi
}
test_numeric_prefers_external
test_numeric_falls_back_internal
test_numeric_uses_first_line_value
test_numeric_empty_is_error
if ((failed > 0)); then
echo "$failed numeric-mode test(s) failed"
exit 1
fi
echo "✅ all numeric-mode tests passed"
-212
View File
@@ -1,212 +0,0 @@
#!/bin/bash
# Unit tests for the lm-sensors extend wrapper (dcinfra/sensors/temper) [#341/#439]
set -euo pipefail
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SCRIPT="$PROJECT_ROOT/dcinfra/sensors/temper/lmsensors-extend.sh"
failed=0
# Script must exist and source cleanly (main guarded for sourcing)
if [[ -f "$SCRIPT" ]] && (source "$SCRIPT"); then
echo "✅ script exists + sources cleanly"
else
echo "❌ script missing or fails to source: $SCRIPT"
exit 1
fi
# shellcheck disable=SC1091
source "$SCRIPT"
# lm-sensors format block: chip, adapter, one line per sensor, +X.X°C
test_format_two_sensors() {
local got expected
expected=$(printf 'temper-usb-1\nAdapter: USB adapter\nInternal: +23.5°C\nExternal: +18.2°C')
got="$(format_block "23.5" "18.2")"
if [[ "$got" == "$expected" ]]; then
echo "✅ format_block renders two-sensor lm-sensors output"
else
echo "❌ format_block two-sensor output mismatch"
printf 'got:\n%s\nexpected:\n%s\n' "$got" "$expected"
((++failed))
fi
}
test_format_single_sensor() {
local got expected
expected=$(printf 'temper-usb-1\nAdapter: USB adapter\nInternal: +23.5°C')
got="$(format_block "23.5" "")"
if [[ "$got" == "$expected" ]]; then
echo "✅ format_block omits absent external sensor"
else
echo "❌ format_block single-sensor output mismatch"
printf 'got:\n%s\nexpected:\n%s\n' "$got" "$expected"
((++failed))
fi
}
test_format_negative() {
if format_block "-5.0" | grep -q 'Internal: -5.0°C'; then
echo "✅ format_block handles negative temps"
else
echo "❌ format_block mangles negative temps"
((++failed))
fi
}
test_format_garbage_rejected() {
if format_block "not-a-number" >/dev/null 2>&1; then
echo "❌ format_block accepted non-numeric input"
((++failed))
else
echo "✅ format_block rejects non-numeric input"
fi
}
# main() composition with stubbed binaries via PATH + env overrides
STUB_DIR="$(mktemp -d "/tmp/lmsensors-test-$$-XXXXXX")"
trap 'rm -rf "$STUB_DIR"' EXIT
make_stub_lsusb() {
if [[ "${1:-}" == "probe" ]]; then
printf '#!/bin/bash\necho "Bus 001 Device 007: ID 0c45:7401 Microdia TEMPer Temperature Sensor"\n' >"$STUB_DIR/lsusb"
else
printf '#!/bin/bash\nexit 0\n' >"$STUB_DIR/lsusb"
fi
chmod +x "$STUB_DIR/lsusb"
}
make_stub_sensors() {
printf '#!/bin/bash\nprintf "coretemp-isa-0000\\nAdapter: ISA adapter\\nPackage id 0: +45.0°C\\nCore 0: +41.0°C\\n"\n' >"$STUB_DIR/sensors"
chmod +x "$STUB_DIR/sensors"
}
make_stub_python() {
printf '#!/bin/bash\necho "23.5 18.2"\n' >"$STUB_DIR/fakepython"
chmod +x "$STUB_DIR/fakepython"
}
test_main_native_only() {
make_stub_lsusb noprobe
make_stub_sensors
local got
got="$(PATH="$STUB_DIR:$PATH" NATIVE_SENSORS_BIN="$STUB_DIR/sensors" \
VENV_PY=/nonexistent main)"
if grep -q 'Package id 0' <<<"$got" && ! grep -q 'temper-usb-1' <<<"$got"; then
echo "✅ main: native sensors only (no probe)"
else
echo "❌ main: native-only composition wrong"
((++failed))
fi
}
test_main_temper_only() {
make_stub_lsusb probe
make_stub_python
local got
got="$(PATH="$STUB_DIR:$PATH" NATIVE_SENSORS_BIN=/nonexistent \
VENV_PY="$STUB_DIR/fakepython" main)"
if grep -q 'Internal: +23.5°C' <<<"$got" && ! grep -q 'Package id 0' <<<"$got"; then
echo "✅ main: TEMPer only (no lm-sensors bin)"
else
echo "❌ main: temper-only composition wrong"
((++failed))
fi
}
test_main_merge() {
make_stub_lsusb probe
make_stub_sensors
make_stub_python
local got
got="$(PATH="$STUB_DIR:$PATH" NATIVE_SENSORS_BIN="$STUB_DIR/sensors" \
VENV_PY="$STUB_DIR/fakepython" main)"
if grep -q 'Package id 0' <<<"$got" && grep -q 'Internal: +23.5°C' <<<"$got"; then
echo "✅ main: native + TEMPer merged"
else
echo "❌ main: merge composition wrong"
((++failed))
fi
}
test_main_neither_fails() {
make_stub_lsusb noprobe
if PATH="$STUB_DIR:$PATH" NATIVE_SENSORS_BIN=/nonexistent \
VENV_PY=/nonexistent SYSFS_THERMAL_ROOT=/nonexistent main >/dev/null 2>&1; then
echo "❌ main: succeeded with no sensor sources"
((++failed))
else
echo "✅ main: fails cleanly with no sensor sources"
fi
}
# sysfs thermal-zone fallback (SBCs: Pis, Jetson-class, /sys/class/thermal)
make_sysfs_fixture() {
SYSFS_FIXTURE="$STUB_DIR/sysfs/class-thermal"
mkdir -p "$SYSFS_FIXTURE/thermal_zone0" "$SYSFS_FIXTURE/thermal_zone1"
printf 'cpu-thermal\n' >"$SYSFS_FIXTURE/thermal_zone0/type"
printf '45200\n' >"$SYSFS_FIXTURE/thermal_zone0/temp"
printf 'gpu-thermal\n' >"$SYSFS_FIXTURE/thermal_zone1/type"
printf '52350\n' >"$SYSFS_FIXTURE/thermal_zone1/temp"
}
test_format_sysfs_block() {
local got expected
expected=$(printf 'soc-thermal-virtual-0\nAdapter: Virtual device\ntemp1: +45.2°C\ntemp2: +52.4°C')
got="$(printf 'cpu-thermal 45200\ngpu-thermal 52350\n' | format_sysfs_block "$(printf 'cpu-thermal 45200\ngpu-thermal 52350\n')")"
if [[ "$got" == "$expected" ]]; then
echo "✅ format_sysfs_block renders lm-sensors format from millicelsius"
else
echo "❌ format_sysfs_block output mismatch"
printf 'got:\n%s\nexpected:\n%s\n' "$got" "$expected"
((++failed))
fi
}
test_main_sysfs_fallback() {
make_stub_lsusb noprobe
make_sysfs_fixture
local got
got="$(PATH="$STUB_DIR:$PATH" NATIVE_SENSORS_BIN=/nonexistent VENV_PY=/nonexistent \
SYSFS_THERMAL_ROOT="$SYSFS_FIXTURE" main)"
if grep -q 'temp1: *+45.2°C' <<<"$got" && grep -q 'soc-thermal-virtual-0' <<<"$got"; then
echo "✅ main: sysfs fallback when lm-sensors silent (SBC)"
else
echo "❌ main: sysfs fallback composition wrong"
printf 'got:\n%s\n' "$got"
((++failed))
fi
}
test_main_native_suppresses_sysfs() {
make_stub_lsusb noprobe
make_stub_sensors
make_sysfs_fixture
local got
got="$(PATH="$STUB_DIR:$PATH" NATIVE_SENSORS_BIN="$STUB_DIR/sensors" VENV_PY=/nonexistent \
SYSFS_THERMAL_ROOT="$SYSFS_FIXTURE" main)"
if grep -q 'Package id 0' <<<"$got" && ! grep -q 'soc-thermal-virtual-0' <<<"$got"; then
echo "✅ main: native output present, sysfs fallback suppressed (no duplicates)"
else
echo "❌ main: sysfs fallback leaked alongside native output"
printf 'got:\n%s\n' "$got"
((++failed))
fi
}
test_format_two_sensors
test_format_single_sensor
test_format_negative
test_format_garbage_rejected
test_main_native_only
test_main_temper_only
test_main_merge
test_main_neither_fails
test_format_sysfs_block
test_main_sysfs_fallback
test_main_native_suppresses_sysfs
if ((failed > 0)); then
echo "❌ lm-sensors extend: $failed test(s) failed"
exit 1
fi
echo "PASS: lm-sensors extend unit tests"