Skip to content

Commit 7991d83

Browse files
committed
feat(lab-02): OpenKM External Dependencies -- MySQL + Mailhog SMTP relay, real compose and test script
1 parent 6e8edb3 commit 7991d83

3 files changed

Lines changed: 228 additions & 61 deletions

File tree

.github/workflows/ci.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,31 @@ jobs:
9696
- name: Cleanup
9797
if: always()
9898
run: docker compose -f docker/docker-compose.standalone.yml down -v
99+
100+
lab-02-smoke:
101+
name: Lab 02 -- OpenKM External Dependencies (MySQL + Mailhog)
102+
runs-on: ubuntu-latest
103+
needs: validate
104+
continue-on-error: true
105+
steps:
106+
- uses: actions/checkout@v4
107+
- name: Install tools
108+
run: sudo apt-get install -y curl default-mysql-client
109+
- name: Validate LAN compose
110+
run: docker compose -f docker/docker-compose.lan.yml config -q && echo "LAN compose valid"
111+
- name: Start LAN stack
112+
run: docker compose -f docker/docker-compose.lan.yml up -d
113+
- name: Wait for MySQL
114+
run: timeout 120 bash -c 'until docker exec openkm-l02-db mysqladmin ping -uroot -pRootLab02! --silent; do sleep 5; done'
115+
- name: Wait for Mailhog
116+
run: timeout 60 bash -c 'until curl -sf http://localhost:8613/api/v2/messages; do sleep 5; done'
117+
- name: Wait for OpenKM
118+
run: timeout 300 bash -c 'until curl -sf http://localhost:8313/openkm/; do sleep 10; done'
119+
- name: Run Lab 14-02 test script
120+
run: bash tests/labs/test-lab-14-02.sh --no-cleanup
121+
- name: Collect logs on failure
122+
if: failure()
123+
run: docker compose -f docker/docker-compose.lan.yml logs
124+
- name: Cleanup
125+
if: always()
126+
run: docker compose -f docker/docker-compose.lan.yml down -v

docker/docker-compose.lan.yml

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,85 @@
1-
# Lab 02 — External Dependencies: openkm with external PostgreSQL and Redis
2-
---
1+
# Lab 02 — External Dependencies
2+
# Module 14: OpenKM Document Management
3+
# External MySQL + Mailhog SMTP relay
4+
# Web UI: http://localhost:8313/openkm
5+
# Mailhog: http://localhost:8613
6+
7+
name: it-stack-openkm-lab02
8+
39
services:
4-
openkm:
5-
image: openkm/openkm-ce:latest
6-
container_name: it-stack-openkm
10+
# ── External Database (simulates lab-db1) ────────────────────────────────────
11+
openkm-l02-db:
12+
image: mysql:8.0
13+
container_name: openkm-l02-db
714
restart: unless-stopped
8-
ports:
9-
- "8080:$firstPort"
1015
environment:
11-
- IT_STACK_ENV=lab-02-lan
12-
- DB_HOST=
13-
- DB_PORT=5432
14-
- REDIS_HOST=
16+
MYSQL_ROOT_PASSWORD: RootLab02!
17+
MYSQL_DATABASE: openkm
18+
MYSQL_USER: openkm
19+
MYSQL_PASSWORD: OpenKMLab02!
20+
command: >
21+
--character-set-server=utf8mb4
22+
--collation-server=utf8mb4_unicode_ci
23+
--default-authentication-plugin=mysql_native_password
24+
volumes:
25+
- openkm-l02-db-data:/var/lib/mysql
26+
healthcheck:
27+
test: ["CMD", "mysqladmin", "ping", "-uroot", "-pRootLab02!", "--silent"]
28+
interval: 10s
29+
timeout: 5s
30+
retries: 10
31+
start_period: 30s
32+
networks:
33+
- openkm-l02-net
34+
35+
# ── External SMTP Relay ───────────────────────────────────────────────────────
36+
openkm-l02-mail:
37+
image: mailhog/mailhog:latest
38+
container_name: openkm-l02-mail
39+
restart: unless-stopped
40+
ports:
41+
- "8613:8025"
1542
networks:
16-
- it-stack-net
43+
- openkm-l02-net
1744

18-
# Lightweight local DB for lab (replace with lab-db1 in real env)
19-
postgres:
20-
image: postgres:16
21-
container_name: it-stack-openkm-db
45+
# ── OpenKM Application ────────────────────────────────────────────────────────
46+
openkm-l02-app:
47+
image: openkm/openkmdce:7.2.0
48+
container_name: openkm-l02-app
49+
restart: unless-stopped
50+
depends_on:
51+
openkm-l02-db:
52+
condition: service_healthy
53+
openkm-l02-mail:
54+
condition: service_started
55+
ports:
56+
- "8313:8080"
2257
environment:
23-
POSTGRES_DB: openkm_db
24-
POSTGRES_USER: openkm_user
25-
POSTGRES_PASSWORD: openkm_pass
58+
OPENKM_DB_HOST: openkm-l02-db
59+
OPENKM_DB_PORT: "3306"
60+
OPENKM_DB_NAME: openkm
61+
OPENKM_DB_USER: openkm
62+
OPENKM_DB_PASS: OpenKMLab02!
63+
OPENKM_SMTP_HOST: openkm-l02-mail
64+
OPENKM_SMTP_PORT: "1025"
65+
JAVA_OPTS: "-Xms256m -Xmx768m -XX:+UseG1GC"
2666
volumes:
27-
- openkm_pg_data:/var/lib/postgresql/data
67+
- openkm-l02-data:/opt/tomcat/repository
68+
- openkm-l02-logs:/opt/tomcat/logs
69+
healthcheck:
70+
test: ["CMD-SHELL", "curl -sf http://localhost:8080/openkm/"]
71+
interval: 30s
72+
timeout: 15s
73+
retries: 10
74+
start_period: 120s
2875
networks:
29-
- it-stack-net
76+
- openkm-l02-net
3077

3178
networks:
32-
it-stack-net:
79+
openkm-l02-net:
3380
driver: bridge
3481

3582
volumes:
36-
openkm_pg_data:
83+
openkm-l02-db-data:
84+
openkm-l02-data:
85+
openkm-l02-logs:

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

Lines changed: 128 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bash
22
# test-lab-14-02.sh — Lab 14-02: External Dependencies
3-
# Module 14: OpenKM document management system
4-
# openkm with external PostgreSQL, Redis, and network integration
3+
# Module 14: OpenKM Document Management
4+
# Tests: external MySQL + Mailhog SMTP relay + REST API
55
set -euo pipefail
66

77
LAB_ID="14-02"
@@ -11,61 +11,151 @@ COMPOSE_FILE="docker/docker-compose.lan.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 external MySQL (openkm-l02-db, up to 90s)..."
46+
for i in $(seq 1 18); do
47+
if docker exec openkm-l02-db mysqladmin ping -uroot -pRootLab02! --silent 2>/dev/null; then
48+
pass "External MySQL healthy"; break
49+
fi
50+
[[ $i -eq 18 ]] && fail "External MySQL timed out"
51+
sleep 5
52+
done
3753

38-
if docker compose -f "${COMPOSE_FILE}" ps | grep -q "running\|Up"; then
39-
pass "Container is running"
54+
info "Waiting for Mailhog (openkm-l02-mail, up to 60s)..."
55+
for i in $(seq 1 12); do
56+
if curl -sf http://localhost:8613/api/v2/messages > /dev/null 2>&1; then
57+
pass "Mailhog UI reachable on :8613"; break
58+
fi
59+
[[ $i -eq 12 ]] && fail "Mailhog not reachable on :8613"
60+
sleep 5
61+
done
62+
63+
info "Waiting for OpenKM (up to 2 min)..."
64+
for i in $(seq 1 24); do
65+
if curl -sf http://localhost:8313/openkm/ > /dev/null 2>&1; then
66+
pass "OpenKM reachable on :8313/openkm/"; break
67+
fi
68+
[[ $i -eq 24 ]] && fail "OpenKM not reachable on :8313/openkm/"
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 openkm-l02-db openkm-l02-mail openkm-l02-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
83+
84+
# External DB connectivity from app
85+
if docker exec openkm-l02-app mysql -hopenkm-l02-db -uopenkm -pOpenKMLab02! openkm \
86+
-e "SELECT 1;" > /dev/null 2>&1; then
87+
pass "App connects to external MySQL (openkm DB)"
4088
else
41-
fail "Container is not running"
89+
fail "App cannot connect to external MySQL"
4290
fi
4391

44-
# ── PHASE 3: Functional Tests ─────────────────────────────────────────────────
45-
info "Phase 3: Functional Tests (Lab 02 — External Dependencies)"
92+
# DB has OpenKM tables
93+
TABLE_COUNT=$(docker exec openkm-l02-db mysql -uroot -pRootLab02! openkm \
94+
-e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='openkm';" \
95+
--skip-column-names 2>/dev/null || echo 0)
96+
if [[ "${TABLE_COUNT:-0}" -gt 20 ]]; then
97+
pass "External DB has ${TABLE_COUNT} OpenKM tables"
98+
else
99+
fail "External DB has only ${TABLE_COUNT:-0} tables (expected >20)"
100+
fi
46101

47-
# TODO: Add module-specific functional tests here
48-
# Example:
49-
# if curl -sf http://localhost:8080/health > /dev/null 2>&1; then
50-
# pass "Health endpoint responds"
51-
# else
52-
# fail "Health endpoint not reachable"
53-
# fi
102+
# Mailhog API
103+
if curl -sf http://localhost:8613/api/v2/messages | grep -q 'total\|items'; then
104+
pass "Mailhog API returns valid JSON"
105+
else
106+
fail "Mailhog API not valid"
107+
fi
108+
109+
# OpenKM REST API
110+
HTTP_CODE=$(curl -o /dev/null -s -w "%{http_code}" \
111+
-u okmAdmin:admin \
112+
http://localhost:8313/openkm/services/rest/repository/info 2>/dev/null || echo 000)
113+
if [[ "${HTTP_CODE}" =~ ^(200|201)$ ]]; then
114+
pass "OpenKM REST /repository/info HTTP ${HTTP_CODE}"
115+
else
116+
fail "OpenKM REST HTTP ${HTTP_CODE} (expected 200)"
117+
fi
118+
119+
# SMTP config points to Mailhog
120+
if docker exec openkm-l02-app printenv OPENKM_SMTP_HOST 2>/dev/null | grep -q 'openkm-l02-mail'; then
121+
pass "SMTP_HOST configured to openkm-l02-mail"
122+
else
123+
fail "SMTP_HOST not pointing to Mailhog container"
124+
fi
125+
126+
# DB charset is utf8mb4
127+
CHARSET=$(docker exec openkm-l02-db mysql -uroot -pRootLab02! \
128+
-e "SELECT DEFAULT_CHARACTER_SET_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME='openkm';" \
129+
--skip-column-names 2>/dev/null || echo "unknown")
130+
if [[ "${CHARSET}" == "utf8mb4" ]]; then
131+
pass "DB charset is utf8mb4"
132+
else
133+
fail "DB charset is ${CHARSET} (expected utf8mb4)"
134+
fi
54135

55-
warn "Functional tests for Lab 14-02 pending implementation"
136+
# Environment variables
137+
for envvar in OPENKM_DB_HOST OPENKM_DB_NAME OPENKM_DB_USER OPENKM_DB_PASS OPENKM_SMTP_HOST; do
138+
if docker exec openkm-l02-app printenv "${envvar}" > /dev/null 2>&1; then
139+
pass "Env var ${envvar} set"
140+
else
141+
fail "Env var ${envvar} missing"
142+
fi
143+
done
56144

57-
# ── PHASE 4: Cleanup ──────────────────────────────────────────────────────────
58-
info "Phase 4: Cleanup"
59-
docker compose -f "${COMPOSE_FILE}" down -v --remove-orphans
60-
info "Cleanup complete"
145+
# Volumes
146+
for vol in openkm-l02-db-data openkm-l02-data openkm-l02-logs; do
147+
if docker volume ls --format '{{.Name}}' | grep -q "${vol}"; then
148+
pass "Volume ${vol} exists"
149+
else
150+
fail "Volume ${vol} missing"
151+
fi
152+
done
61153

62154
# ── Results ───────────────────────────────────────────────────────────────────
63155
echo ""
64-
echo -e "${CYAN}======================================${NC}"
65-
echo -e " Lab ${LAB_ID} Complete"
156+
echo -e "${CYAN}========================================${NC}"
157+
echo " Lab ${LAB_ID} Results"
66158
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
159+
echo -e "${CYAN}========================================${NC}"
160+
[[ "${FAIL}" -gt 0 ]] && exit 1
161+
exit 0

0 commit comments

Comments
 (0)