diff --git a/crates/miroir-core/src/peer_discovery.rs b/crates/miroir-core/src/peer_discovery.rs index f7c8110..3b0deee 100644 --- a/crates/miroir-core/src/peer_discovery.rs +++ b/crates/miroir-core/src/peer_discovery.rs @@ -117,7 +117,7 @@ impl PeerDiscovery { /// Refresh the peer set by performing an SRV lookup (plan §14.5). /// - /// This resolves `_miroir._tcp...svc.cluster.local` + /// This resolves `_http._tcp...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 { 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); + } + } } diff --git a/tests/verify_p6_2_peer_discovery.sh b/tests/verify_p6_2_peer_discovery.sh new file mode 100755 index 0000000..6c0862c --- /dev/null +++ b/tests/verify_p6_2_peer_discovery.sh @@ -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 ✓ ==="