Skip to content

Commit cac64ce

Browse files
committed
feat(lab-03): FreePBX Advanced Features -- resource limits, AMI :5038, recordings/MOH/voicemail volumes
1 parent a6099ed commit cac64ce

3 files changed

Lines changed: 240 additions & 56 deletions

File tree

.github/workflows/ci.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,31 @@ jobs:
124124
- name: Cleanup
125125
if: always()
126126
run: docker compose -f docker/docker-compose.lan.yml down -v
127+
128+
lab-03-smoke:
129+
name: Lab 03 -- FreePBX Advanced Features (AMI + recordings + MOH volumes)
130+
runs-on: ubuntu-latest
131+
needs: validate
132+
continue-on-error: true
133+
steps:
134+
- uses: actions/checkout@v4
135+
- name: Install tools
136+
run: sudo apt-get install -y curl default-mysql-client netcat-openbsd
137+
- name: Validate advanced compose
138+
run: docker compose -f docker/docker-compose.advanced.yml config -q && echo "Advanced compose valid"
139+
- name: Start advanced stack
140+
run: docker compose -f docker/docker-compose.advanced.yml up -d
141+
- name: Wait for MariaDB
142+
run: timeout 120 bash -c 'until docker exec freepbx-a03-db mysqladmin ping -uroot -pRootLab03! --silent; do sleep 5; done'
143+
- name: Wait for Mailhog
144+
run: timeout 60 bash -c 'until curl -sf http://localhost:8620/api/v2/messages; do sleep 5; done'
145+
- name: Wait for FreePBX web
146+
run: timeout 300 bash -c 'until curl -sf http://localhost:8320/admin/config.php; do sleep 10; done'
147+
- name: Run Lab 10-03 test script
148+
run: bash tests/labs/test-lab-10-03.sh --no-cleanup
149+
- name: Collect logs on failure
150+
if: failure()
151+
run: docker compose -f docker/docker-compose.advanced.yml logs
152+
- name: Cleanup
153+
if: always()
154+
run: docker compose -f docker/docker-compose.advanced.yml down -v

docker/docker-compose.advanced.yml

Lines changed: 94 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,109 @@
1-
# Lab 03 — Advanced Features: freepbx with TLS, resource limits, logging
2-
---
1+
# Lab 03 — Advanced Features
2+
# Module 10: FreePBX/Asterisk VoIP PBX
3+
# External MariaDB + Mailhog + resource limits + recordings/MOH volumes
4+
# Web UI: http://localhost:8320/admin/
5+
# SIP: sip:localhost:5162
6+
# Mailhog: http://localhost:8620
7+
# AMI (mgr): localhost:5038
8+
9+
name: it-stack-freepbx-lab03
10+
311
services:
4-
freepbx:
12+
# ── External Database ─────────────────────────────────────────────────────────
13+
freepbx-a03-db:
14+
image: mariadb:10.11
15+
container_name: freepbx-a03-db
16+
restart: unless-stopped
17+
environment:
18+
MYSQL_ROOT_PASSWORD: RootLab03!
19+
MYSQL_DATABASE: asterisk
20+
MYSQL_USER: asterisk
21+
MYSQL_PASSWORD: AsteriskLab03!
22+
volumes:
23+
- freepbx-a03-db-data:/var/lib/mysql
24+
healthcheck:
25+
test: ["CMD", "mysqladmin", "ping", "-uroot", "-pRootLab03!", "--silent"]
26+
interval: 10s
27+
timeout: 5s
28+
retries: 10
29+
start_period: 30s
30+
deploy:
31+
resources:
32+
limits:
33+
cpus: "0.5"
34+
memory: 512M
35+
networks:
36+
- freepbx-a03-net
37+
38+
# ── SMTP Relay ────────────────────────────────────────────────────────────────
39+
freepbx-a03-mail:
40+
image: mailhog/mailhog:latest
41+
container_name: freepbx-a03-mail
42+
restart: unless-stopped
43+
ports:
44+
- "8620:8025"
45+
networks:
46+
- freepbx-a03-net
47+
48+
# ── FreePBX Application (Advanced) ───────────────────────────────────────────
49+
freepbx-a03-app:
550
image: tiredofit/freepbx:16
6-
container_name: it-stack-freepbx
51+
container_name: freepbx-a03-app
752
restart: unless-stopped
53+
depends_on:
54+
freepbx-a03-db:
55+
condition: service_healthy
56+
freepbx-a03-mail:
57+
condition: service_started
858
ports:
9-
- "5060:$firstPort"
59+
- "8320:80"
60+
- "5162:5060/udp"
61+
- "5162:5060/tcp"
62+
- "5038:5038"
1063
environment:
11-
- IT_STACK_ENV=lab-03-advanced
12-
- TLS_ENABLED=true
64+
DB_HOST: freepbx-a03-db
65+
DB_NAME: asterisk
66+
DB_USER: asterisk
67+
DB_PASS: AsteriskLab03!
68+
ADMIN_PASSWORD: Admin03!
69+
RTP_START: "18000"
70+
RTP_FINISH: "18100"
71+
SMTP_HOST: freepbx-a03-mail
72+
SMTP_PORT: "1025"
73+
# AMI manager interface
74+
AMI_ENABLED: "true"
75+
AMI_PORT: "5038"
76+
# Voicemail
77+
VOICEMAIL_DOMAIN: lab.local
78+
VOICEMAIL_FROM: voicemail@lab.local
1379
volumes:
14-
- freepbx_data:/var/lib/freepbx
15-
- ./certs:/etc/ssl/certs:ro
80+
- freepbx-a03-data:/var/www/html/admin/modules
81+
- freepbx-a03-recordings:/var/spool/asterisk/monitor
82+
- freepbx-a03-moh:/var/lib/asterisk/moh
83+
- freepbx-a03-voicemail:/var/spool/asterisk/voicemail
84+
- freepbx-a03-logs:/var/log
85+
healthcheck:
86+
test: ["CMD-SHELL", "curl -sf http://localhost/admin/config.php | grep -qi 'freepbx\\|asterisk\\|login'"]
87+
interval: 30s
88+
timeout: 15s
89+
retries: 10
90+
start_period: 180s
1691
deploy:
1792
resources:
1893
limits:
19-
cpus: "2.0"
20-
memory: G
21-
logging:
22-
driver: json-file
23-
options:
24-
max-size: "100m"
25-
max-file: "5"
94+
cpus: "1.0"
95+
memory: 1G
2696
networks:
27-
- it-stack-net
97+
- freepbx-a03-net
2898

2999
networks:
30-
it-stack-net:
100+
freepbx-a03-net:
31101
driver: bridge
32102

33103
volumes:
34-
freepbx_data:
104+
freepbx-a03-db-data:
105+
freepbx-a03-data:
106+
freepbx-a03-recordings:
107+
freepbx-a03-moh:
108+
freepbx-a03-voicemail:
109+
freepbx-a03-logs:

tests/labs/test-lab-10-03.sh

Lines changed: 118 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bash
22
# test-lab-10-03.sh — Lab 10-03: Advanced Features
33
# Module 10: FreePBX/Asterisk VoIP PBX
4-
# freepbx with TLS, resource limits, and production-grade configuration
4+
# Tests: resource limits + AMI interface + recordings/MOH/voicemail volumes + dialplan
55
set -euo pipefail
66

77
LAB_ID="10-03"
@@ -11,61 +11,142 @@ COMPOSE_FILE="docker/docker-compose.advanced.yml"
1111
PASS=0
1212
FAIL=0
1313

14-
# ── Colors ────────────────────────────────────────────────────────────────────
1514
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
1615
CYAN='\033[0;36m'; NC='\033[0m'
1716

18-
pass() { echo -e "${GREEN}[PASS]${NC} $1"; ((PASS++)); }
19-
fail() { echo -e "${RED}[FAIL]${NC} $1"; ((FAIL++)); }
20-
info() { echo -e "${CYAN}[INFO]${NC} $1"; }
21-
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
17+
pass() { echo -e "${GREEN}[PASS]${NC} $1"; ((PASS++)); }
18+
fail() { echo -e "${RED}[FAIL]${NC} $1"; ((FAIL++)); }
19+
section() { echo -e "\n${CYAN}── $1 ──${NC}"; }
20+
info() { echo -e "${CYAN}[INFO]${NC} $1"; }
2221

23-
echo -e "${CYAN}======================================${NC}"
22+
CLEANUP=true
23+
[[ "${1:-}" == "--no-cleanup" ]] && CLEANUP=false
24+
25+
cleanup() {
26+
if [[ "${CLEANUP}" == "true" ]]; then
27+
info "Cleaning up..."
28+
docker compose -f "${COMPOSE_FILE}" down -v --remove-orphans 2>/dev/null || true
29+
fi
30+
}
31+
trap cleanup EXIT
32+
33+
echo -e "${CYAN}========================================${NC}"
2434
echo -e "${CYAN} Lab ${LAB_ID}: ${LAB_NAME}${NC}"
2535
echo -e "${CYAN} Module: ${MODULE}${NC}"
26-
echo -e "${CYAN}======================================${NC}"
27-
echo ""
36+
echo -e "${CYAN}========================================${NC}"
2837

2938
# ── PHASE 1: Setup ────────────────────────────────────────────────────────────
30-
info "Phase 1: Setup"
39+
section "Phase 1: Setup"
3140
docker compose -f "${COMPOSE_FILE}" up -d
32-
info "Waiting 30s for ${MODULE} to initialize..."
33-
sleep 30
3441

3542
# ── PHASE 2: Health Checks ────────────────────────────────────────────────────
36-
info "Phase 2: Health Checks"
43+
section "Phase 2: Health Checks"
44+
45+
info "Waiting for MariaDB (up to 90s)..."
46+
for i in $(seq 1 18); do
47+
if docker exec freepbx-a03-db mysqladmin ping -uroot -pRootLab03! --silent 2>/dev/null; then
48+
pass "MariaDB healthy"; break
49+
fi
50+
[[ $i -eq 18 ]] && fail "MariaDB timed out"
51+
sleep 5
52+
done
53+
54+
info "Waiting for Mailhog (up to 60s)..."
55+
for i in $(seq 1 12); do
56+
if curl -sf http://localhost:8620/api/v2/messages > /dev/null 2>&1; then
57+
pass "Mailhog reachable on :8620"; break
58+
fi
59+
[[ $i -eq 12 ]] && fail "Mailhog not reachable on :8620"
60+
sleep 5
61+
done
62+
63+
info "Waiting for FreePBX web (up to 4 min)..."
64+
for i in $(seq 1 48); do
65+
if curl -sf http://localhost:8320/admin/config.php 2>/dev/null | grep -qi 'freepbx\|asterisk\|login'; then
66+
pass "FreePBX admin UI on :8320"; break
67+
fi
68+
[[ $i -eq 48 ]] && fail "FreePBX not reachable on :8320"
69+
sleep 5
70+
done
71+
72+
# ── PHASE 3: Functional Tests ─────────────────────────────────────────────────
73+
section "Phase 3: Functional Tests"
74+
75+
# Container states
76+
for cname in freepbx-a03-db freepbx-a03-mail freepbx-a03-app; do
77+
if docker inspect "${cname}" --format '{{.State.Status}}' 2>/dev/null | grep -q running; then
78+
pass "${cname} running"
79+
else
80+
fail "${cname} not running"
81+
fi
82+
done
3783

38-
if docker compose -f "${COMPOSE_FILE}" ps | grep -q "running\|Up"; then
39-
pass "Container is running"
84+
# AMI port accessible from host
85+
if nc -z localhost 5038 2>/dev/null; then
86+
pass "AMI port :5038 accessible"
4087
else
41-
fail "Container is not running"
88+
fail "AMI port :5038 not accessible"
4289
fi
4390

44-
# ── PHASE 3: Functional Tests ─────────────────────────────────────────────────
45-
info "Phase 3: Functional Tests (Lab 03 — Advanced Features)"
91+
# Asterisk core responding
92+
if docker exec freepbx-a03-app asterisk -rx "core show version" 2>/dev/null | grep -qi asterisk; then
93+
pass "Asterisk core show version responds"
94+
else
95+
fail "Asterisk core not responding"
96+
fi
4697

47-
# TODO: Add module-specific functional tests here
48-
# Example:
49-
# if curl -sf http://localhost:5060/health > /dev/null 2>&1; then
50-
# pass "Health endpoint responds"
51-
# else
52-
# fail "Health endpoint not reachable"
53-
# fi
98+
# Asterisk dialplan loaded
99+
CONTEXTS=$(docker exec freepbx-a03-app asterisk -rx "dialplan show" 2>/dev/null | grep -c "^==" || echo 0)
100+
if [[ "${CONTEXTS:-0}" -gt 0 ]]; then
101+
pass "Asterisk dialplan has ${CONTEXTS} contexts"
102+
else
103+
fail "Asterisk dialplan empty or not loaded"
104+
fi
54105

55-
warn "Functional tests for Lab 10-03 pending implementation"
106+
# Asterisk channels list
107+
if docker exec freepbx-a03-app asterisk -rx "core show channels" 2>/dev/null | grep -q 'active channel\|0 active'; then
108+
pass "Asterisk core show channels responds"
109+
else
110+
fail "Asterisk show channels failed"
111+
fi
56112

57-
# ── PHASE 4: Cleanup ──────────────────────────────────────────────────────────
58-
info "Phase 4: Cleanup"
59-
docker compose -f "${COMPOSE_FILE}" down -v --remove-orphans
60-
info "Cleanup complete"
113+
# Resource limits applied
114+
MEM_LIMIT=$(docker inspect freepbx-a03-app --format '{{.HostConfig.Memory}}' 2>/dev/null || echo 0)
115+
if [[ "${MEM_LIMIT:-0}" -gt 0 ]]; then
116+
pass "Memory limit set on freepbx-a03-app (${MEM_LIMIT} bytes)"
117+
else
118+
fail "No memory limit set on freepbx-a03-app"
119+
fi
120+
121+
# Advanced volumes exist
122+
for vol in freepbx-a03-recordings freepbx-a03-moh freepbx-a03-voicemail freepbx-a03-data freepbx-a03-logs; do
123+
if docker volume ls --format '{{.Name}}' | grep -q "${vol}"; then
124+
pass "Volume ${vol} exists"
125+
else
126+
fail "Volume ${vol} missing"
127+
fi
128+
done
129+
130+
# SMTP / Mailhog env
131+
if docker exec freepbx-a03-app printenv SMTP_HOST 2>/dev/null | grep -q 'freepbx-a03-mail'; then
132+
pass "SMTP_HOST → freepbx-a03-mail"
133+
else
134+
fail "SMTP_HOST not pointing to Mailhog"
135+
fi
136+
137+
# HTTP response code
138+
HTTP_CODE=$(curl -o /dev/null -s -w "%{http_code}" http://localhost:8320/admin/config.php 2>/dev/null || echo 000)
139+
if [[ "${HTTP_CODE}" =~ ^(200|301|302)$ ]]; then
140+
pass "FreePBX HTTP ${HTTP_CODE} on :8320"
141+
else
142+
fail "FreePBX HTTP ${HTTP_CODE}"
143+
fi
61144

62145
# ── Results ───────────────────────────────────────────────────────────────────
63146
echo ""
64-
echo -e "${CYAN}======================================${NC}"
65-
echo -e " Lab ${LAB_ID} Complete"
147+
echo -e "${CYAN}========================================${NC}"
148+
echo " Lab ${LAB_ID} Results"
66149
echo -e " ${GREEN}PASS: ${PASS}${NC} | ${RED}FAIL: ${FAIL}${NC}"
67-
echo -e "${CYAN}======================================${NC}"
68-
69-
if [ "${FAIL}" -gt 0 ]; then
70-
exit 1
71-
fi
150+
echo -e "${CYAN}========================================${NC}"
151+
[[ "${FAIL}" -gt 0 ]] && exit 1
152+
exit 0

0 commit comments

Comments
 (0)