Skip to content
This repository was archived by the owner on Oct 10, 2025. It is now read-only.

Commit 10592d0

Browse files
committed
feat: [#14] Complete integration test refactoring and verification
- Fixed integration test script git archive extraction logic - Added .env file transfer to VM in integration test setup - Updated API endpoint testing to use correct authentication tokens - Fixed test endpoints to use nginx proxy (port 80) instead of internal ports - Updated integration testing guide with successful test results and critical details - Added authentication requirements and correct API usage examples - Documented network architecture and port access patterns Integration tests now pass completely: ✅ VM deployment and SSH access ✅ Docker services (MySQL, Tracker, Prometheus, Grafana, Nginx) ✅ API endpoints with authentication (health check, stats API) ✅ UDP tracker ports (6868, 6969) listening ✅ Monitoring services health checks This completes the 12-factor app refactoring with working end-to-end validation.
1 parent a0456e8 commit 10592d0

File tree

3 files changed

+116
-54
lines changed

3 files changed

+116
-54
lines changed

docs/guides/integration-testing-guide.md

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,60 +1543,77 @@ This guide provides a complete integration testing workflow that:
15431543

15441544
### Integration Testing Results Summary
15451545

1546+
**INTEGRATION TESTS NOW PASS COMPLETELY!**
1547+
15461548
This guide provides a complete integration testing workflow that:
15471549

15481550
1. **Creates fresh infrastructure** in ~3-5 minutes
1549-
2. **Generates configuration files** from templates (~2 seconds)
1551+
2. **Generates configuration files** from templates (~2 seconds)
15501552
3. **Refreshes OpenTofu state** to detect VM IP (~3 seconds)
15511553
4. **Waits for cloud-init** to complete (~2-3 minutes)
15521554
5. **Runs comprehensive tests** covering all services (~3-5 minutes)
15531555
6. **Performs external smoke testing** using official Torrust client tools (~2-3 minutes)
15541556
7. **Verifies end-to-end functionality** of the Torrust Tracker
15551557
8. **Cleans up resources** when complete (~1 minute)
15561558

1557-
### Successful Test Results
1559+
**Total Time**: ~8-12 minutes for complete cycle
1560+
1561+
### ✅ Successful Test Results (Latest Run)
1562+
1563+
During the most recent testing cycle, the following components were validated successfully:
1564+
1565+
#### Infrastructure Tests
1566+
1567+
-**VM Access**: SSH connectivity working at `192.168.122.54`
1568+
-**Docker Installation**: Docker 28.3.1 and Docker Compose V2.38.1 working
1569+
-**Service Health**: All containers running with healthy status
1570+
1571+
#### Service Deployment
15581572

1559-
During this testing cycle, the following components were validated:
1573+
-**MySQL**: Database running healthy with proper credentials
1574+
-**Tracker**: Torrust Tracker running with all endpoints active
1575+
-**Prometheus**: Metrics collection working
1576+
-**Grafana**: Dashboard service healthy (version 11.4.0)
1577+
-**Nginx Proxy**: Reverse proxy routing working correctly
15601578

1561-
#### ✅ Infrastructure Tests
1579+
#### API and Endpoint Tests
15621580

1563-
- VM deployment and configuration
1564-
- Cloud-init provisioning
1565-
- SSH connectivity and authentication
1566-
- Docker and Docker Compose installation
1581+
- **Health Check API**: `{"status":"Ok"}` via nginx proxy on port 80
1582+
- **Statistics API**: Full stats JSON with admin token authentication
1583+
- **UDP Tracker Ports**: 6868 and 6969 listening on both IPv4 and IPv6
1584+
- **Monitoring Services**: Grafana and Prometheus both healthy
15671585

1568-
#### ✅ Service Integration Tests
1586+
#### Final Test Output
15691587

1570-
- All Docker services startup (tracker, mysql, prometheus, grafana, nginx)
1571-
- Service health checks and inter-service communication
1572-
- Environment configuration and secrets management
1588+
```console
1589+
[SUCCESS] All integration tests passed!
1590+
```
15731591

1574-
#### ✅ API and Endpoint Tests
1592+
### Critical Configuration Details
15751593

1576-
- Health check API: `{"status":"Ok"}`
1577-
- Stats API with authentication: Complete metrics data
1578-
- Nginx proxy configuration with correct headers
1594+
#### Authentication Requirements
15791595

1580-
#### ✅ External Smoke Tests (Official Client Tools)
1596+
- **Health Check API**: `/api/health_check` - No authentication required
1597+
- **Stats API**: `/api/v1/stats` - **Requires authentication token**
1598+
- **Admin Token**: `local-dev-admin-token-12345` (from `.env` file)
15811599

1582-
- **UDP Tracker (6868)**: `{"AnnounceIpv4": {"seeders": 2, "peers": ["192.168.122.1:17548"]}}`
1583-
- **UDP Tracker (6969)**: `{"AnnounceIpv4": {"seeders": 4, "peers": [...]}}`
1584-
- **HTTP Tracker (via proxy)**: `{"complete": 1, "interval": 120, "peers": []}`
1585-
- **Comprehensive Checker**: All operations (Setup, Connect, Announce, Scrape) successful
1600+
#### Correct API Testing Examples
15861601

1587-
#### ✅ Performance Validation
1602+
```bash
1603+
# Health check (no auth needed)
1604+
curl -s http://$VM_IP/api/health_check | jq .
15881605

1589-
- **UDP Response Time**: < 160ms
1590-
- **HTTP Response Time**: < 187ms
1591-
- **All protocols**: Sub-second response times under test load
1606+
# Stats API (auth required)
1607+
curl -s "http://$VM_IP/api/v1/stats?token=local-dev-admin-token-12345" | jq .
1608+
```
15921609

1593-
### Critical Configuration Fixes Applied
1610+
#### Network Architecture
15941611

1595-
During testing, several critical configuration issues were identified and resolved:
1612+
The deployment uses **nginx proxy** on port 80 that routes to internal services:
15961613

1597-
1. **Tracker Visibility**: Changed `private = true` to `private = false` in tracker.toml
1598-
2. **Nginx Proxy Headers**: Added missing `X-Forwarded-For` headers for HTTP tracker functionality
1599-
3. **Authentication Setup**: Validated admin token configuration for API access
1614+
- `/api/*` → routes to tracker service (internal port 1212)
1615+
- Internal Docker ports (1212, 7070, 9090) are NOT accessible from outside the VM
1616+
- UDP ports (6868, 6969) are directly exposed for tracker protocol
16001617

16011618
### Key Lessons Learned
16021619

infrastructure/scripts/validate-config.sh

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,45 @@ validate_environment_config() {
189189
log_info "Validating environment-specific configuration..."
190190

191191
case "${ENVIRONMENT}" in
192-
"local" | "production")
193-
# Both environments use the same sensible defaults
192+
"local")
193+
# Local environment allows public mode for integration testing
194+
if grep -q 'threshold = "info"' "${tracker_config}"; then
195+
[[ "${VERBOSE}" == "true" ]] && log_info "${ENVIRONMENT}: Info logging enabled"
196+
else
197+
log_error "${ENVIRONMENT}: Info logging not enabled"
198+
return 1
199+
fi
200+
201+
if grep -q 'on_reverse_proxy = true' "${tracker_config}"; then
202+
[[ "${VERBOSE}" == "true" ]] && log_info "${ENVIRONMENT}: Reverse proxy enabled"
203+
else
204+
log_error "${ENVIRONMENT}: Reverse proxy should be enabled"
205+
return 1
206+
fi
207+
208+
if grep -q 'private = false' "${tracker_config}"; then
209+
[[ "${VERBOSE}" == "true" ]] && log_info "${ENVIRONMENT}: Public tracker mode enabled (for integration testing)"
210+
else
211+
log_error "${ENVIRONMENT}: Public tracker mode should be enabled for integration testing"
212+
return 1
213+
fi
214+
215+
if grep -q 'driver = "mysql"' "${tracker_config}"; then
216+
[[ "${VERBOSE}" == "true" ]] && log_info "${ENVIRONMENT}: MySQL database configured"
217+
else
218+
log_error "${ENVIRONMENT}: MySQL database not configured"
219+
return 1
220+
fi
221+
222+
if grep -q 'external_ip = "0.0.0.0"' "${tracker_config}"; then
223+
[[ "${VERBOSE}" == "true" ]] && log_info "${ENVIRONMENT}: External IP set to 0.0.0.0"
224+
else
225+
log_warning "${ENVIRONMENT}: External IP not set to 0.0.0.0 (this may be intentional)"
226+
fi
227+
;;
228+
229+
"production")
230+
# Production environment requires private mode for security
194231
if grep -q 'threshold = "info"' "${tracker_config}"; then
195232
[[ "${VERBOSE}" == "true" ]] && log_info "${ENVIRONMENT}: Info logging enabled"
196233
else

infrastructure/tests/test-integration.sh

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,8 @@ setup_torrust_tracker() {
175175
return 1
176176
fi
177177

178-
# Extract archive on VM
179-
vm_exec "${vm_ip}" "cd /home/torrust/github/torrust && tar -xzf /tmp/$(basename "${temp_archive}") && mv torrust-tracker-demo torrust-tracker-demo-temp || true" "Extracting archive"
180-
vm_exec "${vm_ip}" "cd /home/torrust/github/torrust && mv torrust-tracker-demo-temp torrust-tracker-demo" "Moving to final location"
178+
# Extract archive on VM (git archive doesn't create parent directory)
179+
vm_exec "${vm_ip}" "cd /home/torrust/github/torrust && mkdir -p torrust-tracker-demo && cd torrust-tracker-demo && tar -xzf /tmp/$(basename "${temp_archive}")" "Extracting archive"
181180
vm_exec "${vm_ip}" "rm -f /tmp/$(basename "${temp_archive}")" "Cleaning up archive"
182181

183182
# Clean up local temp file
@@ -223,7 +222,7 @@ setup_torrust_tracker() {
223222

224223
log_success "Installation script completed successfully"
225224

226-
# Step 5: Copy the configured storage folder to the VM
225+
# Step 5: Copy the configured storage folder and .env file to the VM
227226
log_info "Copying configured storage folder to VM..."
228227

229228
# Ensure storage directory exists and has proper structure
@@ -241,6 +240,15 @@ setup_torrust_tracker() {
241240
return 1
242241
fi
243242

243+
# Copy .env file to VM
244+
log_info "Copying .env file to VM..."
245+
if ! scp -o StrictHostKeyChecking=no \
246+
"${PROJECT_ROOT}/application/.env" \
247+
"torrust@${vm_ip}:/home/torrust/github/torrust/torrust-tracker-demo/application/.env"; then
248+
log_error "Failed to copy .env file to VM"
249+
return 1
250+
fi
251+
244252
# Verify critical configuration files exist on VM
245253
log_info "Verifying configuration files on VM..."
246254

@@ -307,25 +315,25 @@ test_tracker_endpoints() {
307315
local vm_ip
308316
vm_ip=$(get_vm_ip)
309317

310-
# Test HTTP API endpoint
318+
# Test HTTP API endpoint through nginx proxy using Host header
311319
log_info "Testing HTTP API endpoint..."
312-
if vm_exec "${vm_ip}" "curl -f -s http://localhost:7070/api/v1/stats" "Checking HTTP API"; then
320+
if vm_exec "${vm_ip}" "curl -f -s -H 'Host: tracker.torrust-demo.com' http://localhost:80/api/health_check" "Checking HTTP API"; then
313321
log_success "HTTP API is responding"
314322
else
315323
log_error "HTTP API is not responding"
316324
return 1
317325
fi
318326

319-
# Test metrics endpoint
320-
log_info "Testing metrics endpoint..."
321-
if vm_exec "${vm_ip}" "curl -f -s http://localhost:1212/metrics" "Checking metrics endpoint"; then
322-
log_success "Metrics endpoint is responding"
327+
# Test tracker statistics API
328+
log_info "Testing tracker statistics API..."
329+
if vm_exec "${vm_ip}" "curl -f -s -H 'Host: tracker.torrust-demo.com' 'http://localhost:80/api/v1/stats?token=local-dev-admin-token-12345'" "Checking statistics API"; then
330+
log_success "Statistics API is responding"
323331
else
324-
log_error "Metrics endpoint is not responding"
332+
log_error "Statistics API is not responding"
325333
return 1
326334
fi
327335

328-
# Test if UDP ports are listening
336+
# Test if UDP ports are listening (these are directly exposed)
329337
log_info "Testing UDP tracker ports..."
330338
if vm_exec "${vm_ip}" "ss -ul | grep -E ':6868|:6969'" "Checking UDP ports"; then
331339
log_success "UDP tracker ports are listening"
@@ -343,21 +351,21 @@ test_monitoring() {
343351
local vm_ip
344352
vm_ip=$(get_vm_ip)
345353

346-
# Test Prometheus
347-
log_info "Testing Prometheus..."
348-
if vm_exec "${vm_ip}" "curl -f -s http://localhost:9090/-/healthy" "Checking Prometheus health"; then
349-
log_success "Prometheus is healthy"
354+
# Test Grafana through nginx proxy using Host header
355+
log_info "Testing Grafana..."
356+
if vm_exec "${vm_ip}" "curl -f -s -H 'Host: grafana.torrust-demo.com' http://localhost:80/api/health" "Checking Grafana health"; then
357+
log_success "Grafana is healthy"
350358
else
351-
log_error "Prometheus is not healthy"
359+
log_error "Grafana is not healthy"
352360
return 1
353361
fi
354362

355-
# Test Grafana
356-
log_info "Testing Grafana..."
357-
if vm_exec "${vm_ip}" "curl -f -s http://localhost:3100/api/health" "Checking Grafana health"; then
358-
log_success "Grafana is healthy"
363+
# Test Prometheus directly (no proxy configuration for Prometheus in current setup)
364+
log_info "Testing Prometheus..."
365+
if vm_exec "${vm_ip}" "docker exec prometheus wget -qO- http://localhost:9090/-/healthy" "Checking Prometheus health"; then
366+
log_success "Prometheus is healthy"
359367
else
360-
log_error "Grafana is not healthy"
368+
log_error "Prometheus is not healthy"
361369
return 1
362370
fi
363371

0 commit comments

Comments
 (0)