Skip to content

Commit d17e6d5

Browse files
committed
feat(labs): implement Lab 17-02 external dependencies (MariaDB + Mailhog)
1 parent ab15486 commit d17e6d5

3 files changed

Lines changed: 211 additions & 44 deletions

File tree

.github/workflows/ci.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,39 @@ run: bash tests/labs/test-lab-17-01.sh
111111
- name: Cleanup
112112
if: always()
113113
run: docker compose -f docker/docker-compose.standalone.yml down -v
114+
lab-02-smoke:
115+
name: Lab 02 -- GLPI External Dependencies (MariaDB + Mailhog)
116+
runs-on: ubuntu-latest
117+
needs: validate
118+
continue-on-error: true
119+
steps:
120+
- uses: actions/checkout@v4
121+
122+
- name: Install tools
123+
run: sudo apt-get install -y curl default-mysql-client -qq
124+
125+
- name: Validate LAN compose
126+
run: docker compose -f docker/docker-compose.lan.yml config -q && echo "LAN compose valid"
127+
128+
- name: Start LAN stack
129+
run: docker compose -f docker/docker-compose.lan.yml up -d
130+
131+
- name: Wait for MariaDB
132+
run: timeout 120 bash -c 'until docker exec glpi-l02-db mysqladmin ping -uroot -pRootLab02! --silent; do sleep 5; done'
133+
134+
- name: Wait for Mailhog
135+
run: timeout 60 bash -c 'until curl -sf http://localhost:8712/api/v2/messages; do sleep 5; done'
136+
137+
- name: Wait for GLPI web
138+
run: timeout 300 bash -c 'until curl -sf http://localhost:8412/ | grep -qi "glpi\|login\|html"; do sleep 10; done'
139+
140+
- name: Run Lab 17-02 test script
141+
run: bash tests/labs/test-lab-17-02.sh --no-cleanup
142+
143+
- name: Collect logs on failure
144+
if: failure()
145+
run: docker compose -f docker/docker-compose.lan.yml logs
146+
147+
- name: Cleanup
148+
if: always()
149+
run: docker compose -f docker/docker-compose.lan.yml down -v

docker/docker-compose.lan.yml

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,85 @@
1-
# Lab 02 — External Dependencies: glpi with external PostgreSQL and Redis
1+
# Lab 02 — External Dependencies: GLPI with external MariaDB and Mailhog
2+
# Models the LAN tier: MariaDB on data-net (simulates lab-db1), app on app-net.
3+
# GLPI: http://localhost:8412
4+
# Mailhog: http://localhost:8712
25
---
6+
name: it-stack-glpi-lab02
7+
38
services:
4-
glpi:
5-
image: diouxx/glpi:latest
6-
container_name: it-stack-glpi
9+
10+
# ── External Database (simulates lab-db1) ─────────────────────────────────
11+
glpi-l02-db:
12+
image: mariadb:10.11
13+
container_name: glpi-l02-db
714
restart: unless-stopped
8-
ports:
9-
- "80:$firstPort"
1015
environment:
11-
- IT_STACK_ENV=lab-02-lan
12-
- DB_HOST=
13-
- DB_PORT=5432
14-
- REDIS_HOST=
16+
MARIADB_ROOT_PASSWORD: RootLab02!
17+
MARIADB_DATABASE: glpidb
18+
MARIADB_USER: glpi
19+
MARIADB_PASSWORD: GlpiLab02!
20+
volumes:
21+
- glpi-l02-db-data:/var/lib/mysql
22+
healthcheck:
23+
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
24+
interval: 10s
25+
timeout: 5s
26+
retries: 10
27+
start_period: 30s
1528
networks:
16-
- it-stack-net
29+
- glpi-l02-data-net
1730

18-
# Lightweight local DB for lab (replace with lab-db1 in real env)
19-
postgres:
20-
image: postgres:16
21-
container_name: it-stack-glpi-db
31+
# ── External SMTP relay (Mailhog) ─────────────────────────────────────────
32+
glpi-l02-mail:
33+
image: mailhog/mailhog:latest
34+
container_name: glpi-l02-mail
35+
restart: unless-stopped
36+
ports:
37+
- "8712:8025"
38+
networks:
39+
- glpi-l02-app-net
40+
41+
# ── GLPI application ──────────────────────────────────────────────────────
42+
glpi-l02-app:
43+
image: diouxx/glpi:latest
44+
container_name: glpi-l02-app
45+
restart: unless-stopped
46+
depends_on:
47+
glpi-l02-db:
48+
condition: service_healthy
49+
glpi-l02-mail:
50+
condition: service_started
2251
environment:
23-
POSTGRES_DB: glpi_db
24-
POSTGRES_USER: glpi_user
25-
POSTGRES_PASSWORD: glpi_pass
52+
MARIADB_HOST: glpi-l02-db
53+
MARIADB_PORT: "3306"
54+
MARIADB_DATABASE: glpidb
55+
MARIADB_USER: glpi
56+
MARIADB_PASSWORD: GlpiLab02!
57+
MARIADB_ROOT_PASSWORD: RootLab02!
58+
GLPI_LANG: en_GB
59+
TIMEZONE: UTC
60+
VERSION: "10.0.14"
61+
ports:
62+
- "8412:80"
2663
volumes:
27-
- glpi_pg_data:/var/lib/postgresql/data
64+
- glpi-l02-files:/var/www/html/files
65+
- glpi-l02-plugins:/var/www/html/plugins
66+
healthcheck:
67+
test: ["CMD-SHELL", "curl -sf http://localhost/ | grep -qi 'glpi\\|login\\|doctype' || exit 1"]
68+
interval: 30s
69+
timeout: 15s
70+
retries: 8
71+
start_period: 120s
2872
networks:
29-
- it-stack-net
73+
- glpi-l02-data-net
74+
- glpi-l02-app-net
3075

3176
networks:
32-
it-stack-net:
77+
glpi-l02-data-net:
78+
driver: bridge
79+
glpi-l02-app-net:
3380
driver: bridge
3481

3582
volumes:
36-
glpi_pg_data:
83+
glpi-l02-db-data:
84+
glpi-l02-files:
85+
glpi-l02-plugins:

tests/labs/test-lab-17-02.sh

Lines changed: 104 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,38 +26,120 @@ echo -e "${CYAN} Module: ${MODULE}${NC}"
2626
echo -e "${CYAN}======================================${NC}"
2727
echo ""
2828

29+
# ── Cleanup control ───────────────────────────────────────────────────────────
30+
CLEANUP=true
31+
[[ "${1:-}" == "--no-cleanup" ]] && CLEANUP=false
32+
33+
cleanup() {
34+
if [[ "${CLEANUP}" == "true" ]]; then
35+
info "Phase 4: Cleanup"
36+
docker compose -f "${COMPOSE_FILE}" down -v --remove-orphans 2>/dev/null || true
37+
info "Cleanup complete"
38+
else
39+
info "Skipping cleanup (--no-cleanup)"
40+
fi
41+
}
42+
trap cleanup EXIT
43+
2944
# ── PHASE 1: Setup ────────────────────────────────────────────────────────────
3045
info "Phase 1: Setup"
3146
docker compose -f "${COMPOSE_FILE}" up -d
32-
info "Waiting 30s for ${MODULE} to initialize..."
33-
sleep 30
3447

3548
# ── PHASE 2: Health Checks ────────────────────────────────────────────────────
3649
info "Phase 2: Health Checks"
3750

38-
if docker compose -f "${COMPOSE_FILE}" ps | grep -q "running\|Up"; then
39-
pass "Container is running"
51+
info "Waiting for external MariaDB (glpi-l02-db, up to 90s)..."
52+
for i in $(seq 1 18); do
53+
if docker exec glpi-l02-db mysqladmin ping -uroot -pRootLab02! --silent 2>/dev/null; then
54+
pass "External MariaDB healthy"
55+
break
56+
fi
57+
[[ $i -eq 18 ]] && fail "External MariaDB timed out after 90s"
58+
sleep 5
59+
done
60+
61+
info "Waiting for Mailhog (glpi-l02-mail, up to 60s)..."
62+
for i in $(seq 1 12); do
63+
if curl -sf http://localhost:8712/api/v2/messages >/dev/null 2>&1; then
64+
pass "Mailhog API reachable"
65+
break
66+
fi
67+
[[ $i -eq 12 ]] && fail "Mailhog timed out after 60s"
68+
sleep 5
69+
done
70+
71+
info "Waiting for GLPI web (glpi-l02-app, up to 300s)..."
72+
for i in $(seq 1 30); do
73+
if curl -sf http://localhost:8412/ 2>/dev/null | grep -qi 'glpi\|login\|doctype\|html'; then
74+
pass "GLPI web serving HTML"
75+
break
76+
fi
77+
[[ $i -eq 30 ]] && fail "GLPI web timed out after 300s"
78+
sleep 10
79+
done
80+
81+
# ── PHASE 3: Functional Tests ─────────────────────────────────────────────────
82+
info "Phase 3: Functional Tests (Lab 17-02 — External Dependencies)"
83+
84+
# Container states
85+
for svc in glpi-l02-db glpi-l02-mail glpi-l02-app; do
86+
state=$(docker inspect --format='{{.State.Status}}' "${svc}" 2>/dev/null || echo "missing")
87+
if [[ "${state}" == "running" ]]; then
88+
pass "Container ${svc} is running"
89+
else
90+
fail "Container ${svc} state: ${state}"
91+
fi
92+
done
93+
94+
# DB connectivity from app container
95+
table_count=$(docker exec glpi-l02-db \
96+
mysql -uglpi -pGlpiLab02! glpidb -e 'SHOW TABLES;' 2>/dev/null | wc -l | tr -d ' ')
97+
if [[ "${table_count}" -gt 10 ]]; then
98+
pass "GLPI database has ${table_count} tables (setup ran)"
4099
else
41-
fail "Container is not running"
100+
warn "GLPI database tables: ${table_count} (setup may still be running)"
42101
fi
43102

44-
# ── PHASE 3: Functional Tests ─────────────────────────────────────────────────
45-
info "Phase 3: Functional Tests (Lab 02 — External Dependencies)"
46-
47-
# TODO: Add module-specific functional tests here
48-
# Example:
49-
# if curl -sf http://localhost:80/health > /dev/null 2>&1; then
50-
# pass "Health endpoint responds"
51-
# else
52-
# fail "Health endpoint not reachable"
53-
# fi
54-
55-
warn "Functional tests for Lab 17-02 pending implementation"
56-
57-
# ── PHASE 4: Cleanup ──────────────────────────────────────────────────────────
58-
info "Phase 4: Cleanup"
59-
docker compose -f "${COMPOSE_FILE}" down -v --remove-orphans
60-
info "Cleanup complete"
103+
# Mailhog API format check
104+
mailhog_resp=$(curl -sf http://localhost:8712/api/v2/messages 2>/dev/null || echo "{}")
105+
if echo "${mailhog_resp}" | grep -q 'total\|items\|count'; then
106+
pass "Mailhog API returns valid JSON message list"
107+
else
108+
fail "Mailhog API response unexpected: ${mailhog_resp}"
109+
fi
110+
111+
# HTTP status check
112+
http_code=$(curl -o /dev/null -sw '%{http_code}' -L http://localhost:8412/ 2>/dev/null || echo "000")
113+
if [[ "${http_code}" =~ ^[234] ]]; then
114+
pass "GLPI HTTP GET / -> ${http_code}"
115+
else
116+
fail "GLPI HTTP GET / -> ${http_code}"
117+
fi
118+
119+
# Login page present
120+
if curl -sf -L http://localhost:8412/ 2>/dev/null | grep -qi 'glpi\|login\|glpikey\|password'; then
121+
pass "GLPI login page rendered"
122+
else
123+
warn "GLPI login page check inconclusive"
124+
fi
125+
126+
# Key env vars present in app container
127+
for var in MARIADB_HOST MARIADB_DATABASE MARIADB_USER; do
128+
if docker exec glpi-l02-app printenv "${var}" 2>/dev/null | grep -q '.'; then
129+
pass "Env var ${var} set in glpi-l02-app"
130+
else
131+
fail "Env var ${var} missing in glpi-l02-app"
132+
fi
133+
done
134+
135+
# Volume existence
136+
for vol in glpi-l02-db-data glpi-l02-files glpi-l02-plugins; do
137+
if docker volume ls --format '{{.Name}}' | grep -q "${vol}"; then
138+
pass "Volume ${vol} exists"
139+
else
140+
fail "Volume ${vol} missing"
141+
fi
142+
done
61143

62144
# ── Results ───────────────────────────────────────────────────────────────────
63145
echo ""

0 commit comments

Comments
 (0)