Skip to content

Commit a3e0e26

Browse files
committed
feat(lab-02): Odoo External Dependencies -- PostgreSQL + Redis + Mailhog SMTP relay, real compose and test script
1 parent 17faca3 commit a3e0e26

3 files changed

Lines changed: 241 additions & 61 deletions

File tree

.github/workflows/ci.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,33 @@ 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 -- Odoo External Dependencies (PostgreSQL + Redis + 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 postgresql-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 PostgreSQL
114+
run: timeout 60 bash -c 'until docker exec odoo-l02-db pg_isready -U odoo -d odoo_lab02; do sleep 5; done'
115+
- name: Wait for Redis
116+
run: timeout 30 bash -c 'until docker exec odoo-l02-redis redis-cli ping | grep -q PONG; do sleep 3; done'
117+
- name: Wait for Mailhog
118+
run: timeout 60 bash -c 'until curl -sf http://localhost:8612/api/v2/messages; do sleep 5; done'
119+
- name: Wait for Odoo
120+
run: timeout 180 bash -c 'until curl -sf http://localhost:8312/web/health | grep -q ok; do sleep 10; done'
121+
- name: Run Lab 13-02 test script
122+
run: bash tests/labs/test-lab-13-02.sh --no-cleanup
123+
- name: Collect logs on failure
124+
if: failure()
125+
run: docker compose -f docker/docker-compose.lan.yml logs
126+
- name: Cleanup
127+
if: always()
128+
run: docker compose -f docker/docker-compose.lan.yml down -v

docker/docker-compose.lan.yml

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,100 @@
1-
# Lab 02 — External Dependencies: odoo with external PostgreSQL and Redis
2-
---
1+
# Lab 02 — External Dependencies
2+
# Module 13: Odoo ERP
3+
# External PostgreSQL + Redis (sessions/cache) + Mailhog SMTP relay
4+
# Web UI: http://localhost:8312
5+
# Mailhog: http://localhost:8612
6+
7+
name: it-stack-odoo-lab02
8+
39
services:
4-
odoo:
5-
image: odoo:17
6-
container_name: it-stack-odoo
10+
# ── External Database (simulates lab-db1) ────────────────────────────────────
11+
odoo-l02-db:
12+
image: postgres:15-alpine
13+
container_name: odoo-l02-db
714
restart: unless-stopped
8-
ports:
9-
- "8069:$firstPort"
1015
environment:
11-
- IT_STACK_ENV=lab-02-lan
12-
- DB_HOST=
13-
- DB_PORT=5432
14-
- REDIS_HOST=
16+
POSTGRES_DB: odoo_lab02
17+
POSTGRES_USER: odoo
18+
POSTGRES_PASSWORD: OdooLab02!
19+
volumes:
20+
- odoo-l02-db-data:/var/lib/postgresql/data
21+
healthcheck:
22+
test: ["CMD-SHELL", "pg_isready -U odoo -d odoo_lab02"]
23+
interval: 10s
24+
timeout: 5s
25+
retries: 10
26+
start_period: 20s
27+
networks:
28+
- odoo-l02-net
29+
30+
# ── Redis (session store / cache) ─────────────────────────────────────────────
31+
odoo-l02-redis:
32+
image: redis:7-alpine
33+
container_name: odoo-l02-redis
34+
restart: unless-stopped
35+
command: redis-server --save 60 1 --loglevel warning
36+
volumes:
37+
- odoo-l02-redis-data:/data
38+
healthcheck:
39+
test: ["CMD", "redis-cli", "ping"]
40+
interval: 10s
41+
timeout: 3s
42+
retries: 5
43+
start_period: 10s
44+
networks:
45+
- odoo-l02-net
46+
47+
# ── External SMTP Relay ───────────────────────────────────────────────────────
48+
odoo-l02-mail:
49+
image: mailhog/mailhog:latest
50+
container_name: odoo-l02-mail
51+
restart: unless-stopped
52+
ports:
53+
- "8612:8025"
1554
networks:
16-
- it-stack-net
55+
- odoo-l02-net
1756

18-
# Lightweight local DB for lab (replace with lab-db1 in real env)
19-
postgres:
20-
image: postgres:16
21-
container_name: it-stack-odoo-db
57+
# ── Odoo Application ──────────────────────────────────────────────────────────
58+
odoo-l02-app:
59+
image: odoo:17
60+
container_name: odoo-l02-app
61+
restart: unless-stopped
62+
depends_on:
63+
odoo-l02-db:
64+
condition: service_healthy
65+
odoo-l02-redis:
66+
condition: service_healthy
67+
odoo-l02-mail:
68+
condition: service_started
69+
ports:
70+
- "8312:8069"
2271
environment:
23-
POSTGRES_DB: odoo_db
24-
POSTGRES_USER: odoo_user
25-
POSTGRES_PASSWORD: odoo_pass
72+
HOST: odoo-l02-db
73+
PORT: "5432"
74+
USER: odoo
75+
PASSWORD: OdooLab02!
76+
command:
77+
- --db-filter=odoo_lab02
78+
- --limit-time-cpu=600
79+
- --limit-time-real=1200
2680
volumes:
27-
- odoo_pg_data:/var/lib/postgresql/data
81+
- odoo-l02-data:/var/lib/odoo
82+
- odoo-l02-addons:/mnt/extra-addons
83+
healthcheck:
84+
test: ["CMD-SHELL", "curl -sf http://localhost:8069/web/health | grep -q 'ok\\|pass'"]
85+
interval: 30s
86+
timeout: 10s
87+
retries: 10
88+
start_period: 60s
2889
networks:
29-
- it-stack-net
90+
- odoo-l02-net
3091

3192
networks:
32-
it-stack-net:
93+
odoo-l02-net:
3394
driver: bridge
3495

3596
volumes:
36-
odoo_pg_data:
97+
odoo-l02-db-data:
98+
odoo-l02-redis-data:
99+
odoo-l02-data:
100+
odoo-l02-addons:

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

Lines changed: 124 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env bash
22
# test-lab-13-02.sh — Lab 13-02: External Dependencies
3-
# Module 13: Odoo ERP and business management
4-
# odoo with external PostgreSQL, Redis, and network integration
3+
# Module 13: Odoo ERP
4+
# Tests: external PostgreSQL + Redis cache/sessions + Mailhog SMTP relay
55
set -euo pipefail
66

77
LAB_ID="13-02"
@@ -11,61 +11,147 @@ 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 PostgreSQL (odoo-l02-db, up to 60s)..."
46+
for i in $(seq 1 12); do
47+
if docker exec odoo-l02-db pg_isready -U odoo -d odoo_lab02 > /dev/null 2>&1; then
48+
pass "External PostgreSQL healthy"; break
49+
fi
50+
[[ $i -eq 12 ]] && fail "External PostgreSQL timed out"
51+
sleep 5
52+
done
53+
54+
info "Waiting for Redis (odoo-l02-redis, up to 30s)..."
55+
for i in $(seq 1 6); do
56+
if docker exec odoo-l02-redis redis-cli ping 2>/dev/null | grep -q PONG; then
57+
pass "Redis healthy (PONG)"; break
58+
fi
59+
[[ $i -eq 6 ]] && fail "Redis not responding"
60+
sleep 5
61+
done
62+
63+
info "Waiting for Mailhog (odoo-l02-mail, up to 60s)..."
64+
for i in $(seq 1 12); do
65+
if curl -sf http://localhost:8612/api/v2/messages > /dev/null 2>&1; then
66+
pass "Mailhog UI reachable on :8612"; break
67+
fi
68+
[[ $i -eq 12 ]] && fail "Mailhog not reachable on :8612"
69+
sleep 5
70+
done
3771

38-
if docker compose -f "${COMPOSE_FILE}" ps | grep -q "running\|Up"; then
39-
pass "Container is running"
72+
info "Waiting for Odoo (up to 2 min)..."
73+
for i in $(seq 1 24); do
74+
if curl -sf http://localhost:8312/web/health 2>/dev/null | grep -q 'ok\|pass'; then
75+
pass "Odoo /web/health returns ok on :8312"; break
76+
fi
77+
[[ $i -eq 24 ]] && fail "Odoo not reachable on :8312"
78+
sleep 5
79+
done
80+
81+
# ── PHASE 3: Functional Tests ─────────────────────────────────────────────────
82+
section "Phase 3: Functional Tests"
83+
84+
# Container states
85+
for cname in odoo-l02-db odoo-l02-redis odoo-l02-mail odoo-l02-app; do
86+
if docker inspect "${cname}" --format '{{.State.Status}}' 2>/dev/null | grep -q running; then
87+
pass "${cname} running"
88+
else
89+
fail "${cname} not running"
90+
fi
91+
done
92+
93+
# External DB connectivity from app
94+
if docker exec odoo-l02-app psql -h odoo-l02-db -U odoo -d odoo_lab02 \
95+
-c "SELECT 1;" > /dev/null 2>&1; then
96+
pass "App connects to external PostgreSQL (odoo_lab02)"
4097
else
41-
fail "Container is not running"
98+
fail "App cannot connect to external PostgreSQL"
4299
fi
43100

44-
# ── PHASE 3: Functional Tests ─────────────────────────────────────────────────
45-
info "Phase 3: Functional Tests (Lab 02 — External Dependencies)"
101+
# Redis connectivity from app
102+
if docker exec odoo-l02-app redis-cli -h odoo-l02-redis ping 2>/dev/null | grep -q PONG; then
103+
pass "App connects to Redis"
104+
else
105+
fail "App cannot reach Redis"
106+
fi
46107

47-
# TODO: Add module-specific functional tests here
48-
# Example:
49-
# if curl -sf http://localhost:8069/health > /dev/null 2>&1; then
50-
# pass "Health endpoint responds"
51-
# else
52-
# fail "Health endpoint not reachable"
53-
# fi
108+
# Odoo web health
109+
if curl -sf http://localhost:8312/web/health | grep -q 'ok\|pass'; then
110+
pass "Odoo /web/health endpoint OK"
111+
else
112+
fail "Odoo /web/health not OK"
113+
fi
54114

55-
warn "Functional tests for Lab 13-02 pending implementation"
115+
# Odoo JSON-RPC database list
116+
DB_LIST=$(curl -sf -X POST http://localhost:8312/web/database/get_list \
117+
-H 'Content-Type: application/json' \
118+
-d '{"jsonrpc":"2.0","method":"call","params":{}}' 2>/dev/null || echo "{}")
119+
if echo "${DB_LIST}" | grep -q 'result\|odoo'; then
120+
pass "Odoo JSON-RPC /web/database/get_list responds"
121+
else
122+
fail "Odoo JSON-RPC not responding"
123+
fi
56124

57-
# ── PHASE 4: Cleanup ──────────────────────────────────────────────────────────
58-
info "Phase 4: Cleanup"
59-
docker compose -f "${COMPOSE_FILE}" down -v --remove-orphans
60-
info "Cleanup complete"
125+
# Mailhog API
126+
if curl -sf http://localhost:8612/api/v2/messages | grep -q 'total\|items'; then
127+
pass "Mailhog API returns valid JSON"
128+
else
129+
fail "Mailhog API not valid"
130+
fi
131+
132+
# Environment variables
133+
for envvar in HOST PORT USER PASSWORD; do
134+
if docker exec odoo-l02-app printenv "${envvar}" > /dev/null 2>&1; then
135+
pass "Env var ${envvar} set"
136+
else
137+
fail "Env var ${envvar} missing"
138+
fi
139+
done
140+
141+
# Volumes
142+
for vol in odoo-l02-db-data odoo-l02-redis-data odoo-l02-data odoo-l02-addons; do
143+
if docker volume ls --format '{{.Name}}' | grep -q "${vol}"; then
144+
pass "Volume ${vol} exists"
145+
else
146+
fail "Volume ${vol} missing"
147+
fi
148+
done
61149

62150
# ── Results ───────────────────────────────────────────────────────────────────
63151
echo ""
64-
echo -e "${CYAN}======================================${NC}"
65-
echo -e " Lab ${LAB_ID} Complete"
152+
echo -e "${CYAN}========================================${NC}"
153+
echo " Lab ${LAB_ID} Results"
66154
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
155+
echo -e "${CYAN}========================================${NC}"
156+
[[ "${FAIL}" -gt 0 ]] && exit 1
157+
exit 0

0 commit comments

Comments
 (0)