P6.2: Fix peer discovery DNS SRV service name and add test

- Fix SRV lookup to use `_http._tcp` instead of `_miroir._tcp` (matches headless Service port name)
- Add filter to skip empty strings when extracting pod names from SRV targets
- Add test coverage for SRV target pod name extraction
- Add verification script for P6.2 peer discovery metrics

The peer discovery implementation was already complete with:
- Headless Service template (miroir-headless.yaml)
- Downward API env vars (POD_NAME, POD_NAMESPACE, POD_IP) in Deployment
- Background refresh loop in main.rs
- miroir_peer_pod_count metric in middleware.rs

This commit fixes the SRV service name and adds robustness.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-05-23 02:29:17 -04:00
parent 5f9ee20eeb
commit e6cdd05f30
2 changed files with 100 additions and 4 deletions

View file

@ -117,7 +117,7 @@ impl PeerDiscovery {
/// Refresh the peer set by performing an SRV lookup (plan §14.5).
///
/// This resolves `_miroir._tcp.<service>.<namespace>.svc.cluster.local`
/// This resolves `_http._tcp.<service>.<namespace>.svc.cluster.local`
/// and extracts pod names from the returned targets. Uses the system
/// DNS resolver configuration from /etc/resolv.conf for maximum
/// compatibility across different Kubernetes distributions.
@ -126,7 +126,7 @@ impl PeerDiscovery {
#[cfg(feature = "peer-discovery")]
pub async fn refresh(&self) -> Result<PeerSet> {
let srv_name = format!(
"_miroir._tcp.{}.{}.svc.cluster.local",
"_http._tcp.{}.{}.svc.cluster.local",
self.service_name, self.namespace
);
@ -156,8 +156,8 @@ impl PeerDiscovery {
let target = srv.target().to_string();
// Remove trailing dot if present
let target = target.strip_suffix('.').unwrap_or(&target);
// Split and take first component
target.split('.').next().map(|s| s.to_string())
// Split and take first component, skip empty strings
target.split('.').next().filter(|s| !s.is_empty()).map(|s| s.to_string())
})
.collect();
@ -202,4 +202,25 @@ mod tests {
assert!(!set.is_empty());
assert_eq!(set.len(), 3);
}
#[test]
fn test_srv_target_pod_name_extraction() {
// Test that pod names are correctly extracted from SRV target strings.
// SRV records return targets like:
// "miroir-miroir-0.miroir-headless.default.svc.cluster.local."
// We extract the first component as the pod name.
let test_cases = vec![
("miroir-miroir-0.miroir-headless.default.svc.cluster.local", Some("miroir-miroir-0")),
("miroir-miroir-1.miroir-headless.default.svc.cluster.local.", Some("miroir-miroir-1")),
("miroir-miroir-2.miroir-headless.production.svc.cluster.local", Some("miroir-miroir-2")),
("invalid", Some("invalid")),
("", None), // Empty string returns None after filter
];
for (target, expected) in test_cases {
let result = target.strip_suffix('.').unwrap_or(target).split('.').next().filter(|s| !s.is_empty());
assert_eq!(result, expected, "Failed for target: {}", target);
}
}
}

View file

@ -0,0 +1,75 @@
#!/bin/bash
# Verification script for P6.2 Peer Discovery
# Tests that peer discovery is properly configured and the miroir_peer_pod_count metric exists
set -e
ADMIN_KEY="${MIROIR_ADMIN_API_KEY:-admin123}"
BASE_URL="${MIROIR_BASE_URL:-http://localhost:7700}"
METRICS_URL="${MIROIR_METRICS_URL:-http://localhost:9090}"
echo "=== P6.2 Peer Discovery Verification ==="
echo ""
echo "1. Checking miroir_peer_pod_count metric exists..."
METRICS=$(curl -s "${METRICS_URL}/metrics" 2>/dev/null || echo "")
if [ -z "$METRICS" ]; then
echo " ❌ FAILED: Could not connect to ${METRICS_URL}/metrics"
exit 1
fi
if echo "$METRICS" | grep -q "^miroir_peer_pod_count"; then
echo " ✓ miroir_peer_pod_count metric exists"
else
echo " ❌ FAILED: miroir_peer_pod_count metric not found"
exit 1
fi
echo ""
echo "2. Checking miroir_leader metric exists..."
if echo "$METRICS" | grep -q "^miroir_leader"; then
echo " ✓ miroir_leader metric exists"
else
echo " ❌ FAILED: miroir_leader metric not found"
exit 1
fi
echo ""
echo "3. Checking miroir_owned_shards_count metric exists..."
if echo "$METRICS" | grep -q "^miroir_owned_shards_count"; then
echo " ✓ miroir_owned_shards_count metric exists"
else
echo " ❌ FAILED: miroir_owned_shards_count metric not found"
exit 1
fi
echo ""
echo "4. Verifying POD_NAME env var is set (if running in K8s)..."
POD_NAME="${POD_NAME:-unknown}"
if [ "$POD_NAME" != "unknown" ]; then
echo " ✓ POD_NAME=$POD_NAME"
else
echo " ⚠ POD_NAME not set (not running in Kubernetes)"
fi
echo ""
echo "5. Verifying POD_NAMESPACE env var is set (if running in K8s)..."
POD_NAMESPACE="${POD_NAMESPACE:-unknown}"
if [ "$POD_NAMESPACE" != "unknown" ]; then
echo " ✓ POD_NAMESPACE=$POD_NAMESPACE"
else
echo " ⚠ POD_NAMESPACE not set (not running in Kubernetes)"
fi
echo ""
echo "6. Checking peer_discovery configuration..."
# The peer_discovery config is internal, but we can check the log for the refresh loop starting
# For local dev, peer discovery may be disabled if POD_NAME=unknown
if [ "$POD_NAME" = "unknown" ]; then
echo " peer discovery disabled (not running in Kubernetes)"
else
echo " ✓ peer discovery should be enabled (POD_NAME is set)"
fi
echo ""
echo "=== P6.2 Peer Discovery Verification Complete ✓ ==="