Bindy DNS Controller - Testing Guide
Complete guide for testing the Bindy DNS Controller, including unit tests and integration tests with Kind (Kubernetes in Docker).
Quick Start
# Unit tests (fast, no Kubernetes required)
make test
# Integration tests (automated with Kind cluster)
make kind-integration-test
# View results
# Unit: 62 tests passing
# Integration: All 8 DNS record types + infrastructure tests
Table of Contents
Test Overview
Test Results
Unit Tests: 62 PASSING ✅
test result: ok. 62 passed; 0 failed; 0 ignored
Integration Tests: Automated with Kind
- Kubernetes connectivity ✅
- CRD verification ✅
- All 8 DNS record types ✅
- Resource lifecycle ✅
Test Structure
bindy/
├── src/
│ ├── crd_tests.rs # CRD structure tests (28 tests)
│ └── reconcilers/
│ └── tests.rs # Bind9Manager tests (34 tests)
├── tests/
│ ├── simple_integration.rs # Rust integration tests
│ ├── integration_test.sh # Full integration test suite
│ └── common/mod.rs # Shared test utilities
└── deploy/
├── kind-deploy.sh # Deploy to Kind cluster
├── kind-test.sh # Basic functional tests
└── kind-cleanup.sh # Cleanup Kind cluster
Unit Tests
Unit tests run locally without Kubernetes (< 1 second).
Running Unit Tests
# All unit tests
make test
# or
cargo test
# Specific module
cargo test crd_tests::
cargo test bind9::tests::
# With output
cargo test -- --nocapture
Unit Test Coverage (62 tests)
CRD Tests (28 tests)
- Label selectors and matching
- SOA record structure
- DNSZone specs (primary/secondary)
- All DNS record types (A, AAAA, CNAME, MX, TXT, NS, SRV, CAA)
- Bind9Instance configurations
- DNSSEC settings
Bind9Manager Tests (34 tests)
- Zone file creation
- Email formatting for DNS
- All DNS record types (with/without TTL)
- Secondary zone configuration
- Zone lifecycle (create, exists, delete)
- Edge cases and workflows
Integration Tests
Integration tests run against Kind (Kubernetes in Docker) clusters.
Prerequisites
# Docker
docker --version # 20.10+
# Kind
kind --version # 0.20.0+
brew install kind # macOS
# kubectl
kubectl version --client # 1.24+
Running Integration Tests
Full Integration Suite (Recommended)
make kind-integration-test
This automatically:
- Creates Kind cluster (if needed)
- Builds and deploys controller
- Runs all integration tests
- Cleans up test resources
Step-by-Step
# 1. Deploy to Kind
make kind-deploy
# 2. Run functional tests
make kind-test
# 3. Run comprehensive integration tests
make kind-integration-test
# 4. View logs
make kind-logs
# 5. Cleanup
make kind-cleanup
Integration Test Coverage
Rust Integration Tests
test_kubernetes_connectivity- Cluster accesstest_crds_installed- CRD verificationtest_create_and_cleanup_namespace- Namespace lifecycle
Full Integration Suite (integration_test.sh)
- Bind9Instance creation
- DNSZone creation
- A Record (IPv4)
- AAAA Record (IPv6)
- CNAME Record
- MX Record
- TXT Record
- NS Record
- SRV Record
- CAA Record
Expected Output
🧪 Running Bindy Integration Tests
✅ Using existing cluster 'bindy-test'
1️⃣ Running Rust integration tests...
test test_kubernetes_connectivity ... ok
test test_crds_installed ... ok
test test_create_and_cleanup_namespace ... ok
2️⃣ Running functional tests with kubectl...
Testing Bind9Instance creation...
Testing DNSZone creation...
Testing all DNS record types...
3️⃣ Verifying resources...
✓ Bind9Instance created
✓ DNSZone created
✓ arecord created
✓ aaaarecord created
✓ cnamerecord created
✓ mxrecord created
✓ txtrecord created
✓ nsrecord created
✓ srvrecord created
✓ caarecord created
✅ All integration tests passed!
Makefile Targets
Test Targets
make test # Run unit tests
make test-lib # Library tests only
make test-integration # Rust integration tests
make test-all # Unit + Rust integration tests
make test-cov # Coverage report (HTML)
make test-cov-view # Generate and open coverage
Kind Targets
make kind-create # Create Kind cluster
make kind-deploy # Deploy controller
make kind-test # Basic functional tests
make kind-integration-test # Full integration suite
make kind-logs # View controller logs
make kind-cleanup # Delete cluster
Other Targets
make lint # Run clippy and fmt check
make format # Format code
make build # Build release binary
make docker-build # Build Docker image
Troubleshooting
Unit Tests
Tests fail to compile
cargo clean
cargo test
Specific test fails
cargo test test_name -- --nocapture
Integration Tests
“Cluster not found”
# Auto-created by integration test, or:
./deploy/kind-deploy.sh
“Controller not ready”
# Check status
kubectl get pods -n dns-system
# View logs
kubectl logs -n dns-system -l app=bindy
# Redeploy
./deploy/kind-deploy.sh
“CRDs not installed”
# Check CRDs
kubectl get crds | grep bindy.firestoned.io
# Install
kubectl apply -k deploy/crds
Resource creation fails
# Controller logs
kubectl logs -n dns-system -l app=bindy --tail=50
# Resource status
kubectl describe bind9instance <name> -n dns-system
# Events
kubectl get events -n dns-system --sort-by='.lastTimestamp'
Manual Cleanup
# Delete test resources
kubectl delete bind9instances,dnszones,arecords,aaaarecords,cnamerecords,mxrecords,txtrecords,nsrecords,srvrecords,caarecords --all -n dns-system
# Delete cluster
kind delete cluster --name bindy-test
# Clean build
cargo clean
CI/CD Integration
GitHub Actions
Current PR workflow (.github/workflows/pr.yaml):
- Lint (formatting, clippy)
- Test (unit tests)
- Build (stable, beta)
- Docker (build and push to ghcr.io)
- Security audit
- Coverage
Add Integration Tests
integration-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install Kind
run: |
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
- name: Run Integration Tests
run: |
chmod +x tests/integration_test.sh
./tests/integration_test.sh
Test Development
Writing Unit Tests
Add to src/crd_tests.rs or src/reconcilers/tests.rs:
#![allow(unused)]
fn main() {
#[test]
fn test_my_feature() {
// Arrange
let (_temp_dir, manager) = create_test_manager();
// Act
let result = manager.my_operation();
// Assert
assert!(result.is_ok());
}
}
Writing Integration Tests
Add to tests/simple_integration.rs:
#![allow(unused)]
fn main() {
#[tokio::test]
#[ignore] // Always mark as ignored
async fn test_my_scenario() {
let client = match get_kube_client_or_skip().await {
Some(c) => c,
None => return, // Skip if no cluster
};
// Test code here
}
}
Using Test Helpers
From tests/common/mod.rs:
#![allow(unused)]
fn main() {
use common::*;
let client = setup_dns_test_environment("my-test-ns").await?;
create_bind9_instance(&client, "ns", "dns", None).await?;
wait_for_ready(Duration::from_secs(10)).await;
cleanup_test_namespace(&client, "ns").await?;
}
Performance Testing
Coverage
make test-cov-view
# Opens coverage/tarpaulin-report.html
Load Testing
# Create many resources
for i in {1..100}; do
kubectl apply -f - <<EOF
apiVersion: bindy.firestoned.io/v1alpha1
kind: ARecord
metadata:
name: test-${i}
namespace: dns-system
spec:
zone: example.com
name: host-${i}
ipv4Address: "192.0.2.${i}"
EOF
done
# Monitor
kubectl top pod -n dns-system
Best Practices
Unit Tests
- Test one thing at a time
- Fast (< 1s each)
- No external dependencies
- Descriptive names
Integration Tests
- Always use
#[ignore] - Check cluster connectivity first
- Unique namespaces
- Always cleanup
- Good error messages
General
- Run
cargo fmtbefore committing - Run
cargo clippyto catch issues - Keep tests updated
- Document complex scenarios
Additional Resources
- Rust Testing
- Kube-rs Examples
- Kind Docs
- BIND9 Docs
- TEST_SUMMARY.md - Quick reference
Support
- GitHub Issues: https://github.com/firestoned/bindy/issues
- Controller logs:
make kind-logs - Test with output:
cargo test -- --nocapture