|
1 | 1 | #!/usr/bin/env bash |
2 | | -# test-lab-17-03.sh — Lab 17-03: Advanced Features |
3 | | -# Module 17: GLPI IT service management and CMDB |
4 | | -# glpi with TLS, resource limits, and production-grade configuration |
| 2 | +# test-lab-17-03.sh — Lab 17-03: GLPI Advanced Features |
| 3 | +# Tests: dedicated cron container · resource limits · scheduler validation |
| 4 | +# Usage: bash test-lab-17-03.sh [--no-cleanup] |
5 | 5 | set -euo pipefail |
6 | 6 |
|
7 | 7 | LAB_ID="17-03" |
8 | | -LAB_NAME="Advanced Features" |
| 8 | +LAB_NAME="Advanced Features — dedicated cron scheduler container" |
9 | 9 | MODULE="glpi" |
10 | 10 | COMPOSE_FILE="docker/docker-compose.advanced.yml" |
11 | 11 | PASS=0 |
12 | 12 | FAIL=0 |
13 | 13 |
|
| 14 | +CLEANUP=true |
| 15 | +[[ "${1:-}" == "--no-cleanup" ]] && CLEANUP=false |
| 16 | + |
| 17 | +# ── Colors ──────────────────────────────────────────────────────────────────── |
| 18 | +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' |
| 19 | +CYAN='\033[0;36m'; NC='\033[0m' |
| 20 | + |
| 21 | +pass() { echo -e "${GREEN}[PASS]${NC} $1"; ((PASS++)); } |
| 22 | +fail() { echo -e "${RED}[FAIL]${NC} $1"; ((FAIL++)); } |
| 23 | +info() { echo -e "${CYAN}[INFO]${NC} $1"; } |
| 24 | +warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } |
| 25 | +section() { echo -e "\n${CYAN}── $1 ──${NC}"; } |
| 26 | + |
| 27 | +cleanup() { |
| 28 | + if [[ "${CLEANUP}" == "true" ]]; then |
| 29 | + info "Cleaning up Lab ${LAB_ID} containers..." |
| 30 | + docker compose -f "${COMPOSE_FILE}" down -v --remove-orphans 2>/dev/null || true |
| 31 | + else |
| 32 | + info "Skipping cleanup (--no-cleanup)" |
| 33 | + fi |
| 34 | +} |
| 35 | +trap cleanup EXIT |
| 36 | + |
| 37 | +echo -e "${CYAN}======================================${NC}" |
| 38 | +echo -e "${CYAN} Lab ${LAB_ID}: ${LAB_NAME}${NC}" |
| 39 | +echo -e "${CYAN} Module: ${MODULE}${NC}" |
| 40 | +echo -e "${CYAN}======================================${NC}" |
| 41 | +echo "" |
| 42 | + |
| 43 | +# ── PHASE 1: Setup ──────────────────────────────────────────────────────────── |
| 44 | +section "Phase 1: Setup" |
| 45 | +info "Starting GLPI stack (db + mail + app + cron)..." |
| 46 | +docker compose -f "${COMPOSE_FILE}" up -d |
| 47 | + |
| 48 | +# ── PHASE 2: Health Checks ──────────────────────────────────────────────────── |
| 49 | +section "Phase 2: Health Checks" |
| 50 | + |
| 51 | +info "Waiting for MariaDB (glpi-a03-db)..." |
| 52 | +for i in $(seq 1 18); do |
| 53 | + if docker exec glpi-a03-db mysqladmin ping -h localhost -uroot -pRootLab03! --silent 2>/dev/null; then |
| 54 | + info "MariaDB ready after ${i}×5s" |
| 55 | + break |
| 56 | + fi |
| 57 | + [[ $i -eq 18 ]] && { fail "MariaDB did not become ready"; exit 1; } |
| 58 | + sleep 5 |
| 59 | +done |
| 60 | + |
| 61 | +info "Waiting for GLPI app on port 8422..." |
| 62 | +for i in $(seq 1 24); do |
| 63 | + HTTP=$(curl -o /dev/null -sw '%{http_code}' http://localhost:8422/ 2>/dev/null || echo "000") |
| 64 | + if echo "${HTTP}" | grep -qE '^[23]'; then |
| 65 | + info "GLPI ready after ${i}×15s (HTTP ${HTTP})" |
| 66 | + break |
| 67 | + fi |
| 68 | + [[ $i -eq 24 ]] && { warn "GLPI did not fully initialize in time"; } |
| 69 | + sleep 15 |
| 70 | +done |
| 71 | + |
| 72 | +# ── PHASE 3: Functional Tests ───────────────────────────────────────────────── |
| 73 | +section "Phase 3: Functional Tests — Advanced Features" |
| 74 | + |
| 75 | +# 3.1 Container states (all 4) |
| 76 | +for cname in glpi-a03-db glpi-a03-mail glpi-a03-app glpi-a03-cron; do |
| 77 | + STATE=$(docker inspect "${cname}" --format '{{.State.Status}}' 2>/dev/null || echo "missing") |
| 78 | + if [[ "${STATE}" == "running" ]]; then |
| 79 | + pass "Container ${cname} is running" |
| 80 | + else |
| 81 | + fail "Container ${cname} state: ${STATE}" |
| 82 | + fi |
| 83 | +done |
| 84 | + |
| 85 | +# 3.2 Cron container (Lab 03 key feature) |
| 86 | +CRON_STATE=$(docker inspect glpi-a03-cron --format '{{.State.Status}}' 2>/dev/null || echo "missing") |
| 87 | +if [[ "${CRON_STATE}" == "running" ]]; then |
| 88 | + pass "glpi-a03-cron scheduler container is running (Lab 03 new container)" |
| 89 | +else |
| 90 | + fail "glpi-a03-cron scheduler state: ${CRON_STATE}" |
| 91 | +fi |
| 92 | + |
| 93 | +# 3.3 Database accessibility from cron container |
| 94 | +DB_CHECK=$(docker exec glpi-a03-cron mysql -h glpi-a03-db -uglpi -pGlpiLab03! \ |
| 95 | + -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='glpidb';" \ |
| 96 | + --skip-column-names 2>/dev/null | tr -d '[:space:]' || echo "0") |
| 97 | +if [[ "${DB_CHECK}" -gt 0 ]]; then |
| 98 | + pass "Cron container can reach database (${DB_CHECK} tables visible)" |
| 99 | +else |
| 100 | + warn "Cron container database check returned ${DB_CHECK}" |
| 101 | +fi |
| 102 | + |
| 103 | +# 3.4 Database table count |
| 104 | +TABLE_COUNT=$(docker exec glpi-a03-db mysql -uglpi -pGlpiLab03! -e \ |
| 105 | + "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='glpidb';" \ |
| 106 | + --skip-column-names 2>/dev/null | tr -d '[:space:]' || echo "0") |
| 107 | +if [[ "${TABLE_COUNT}" -gt 50 ]]; then |
| 108 | + pass "GLPI database has ${TABLE_COUNT} tables (installation complete)" |
| 109 | +elif [[ "${TABLE_COUNT}" -gt 0 ]]; then |
| 110 | + warn "GLPI database has ${TABLE_COUNT} tables (may still installing)" |
| 111 | +else |
| 112 | + fail "GLPI database appears empty" |
| 113 | +fi |
| 114 | + |
| 115 | +# 3.5 HTTP check |
| 116 | +HTTP_CODE=$(curl -o /dev/null -sw '%{http_code}' http://localhost:8422/ 2>/dev/null || echo "000") |
| 117 | +if echo "${HTTP_CODE}" | grep -qE '^[234]'; then |
| 118 | + pass "GLPI HTTP check: ${HTTP_CODE}" |
| 119 | +else |
| 120 | + fail "GLPI HTTP check failed: ${HTTP_CODE}" |
| 121 | +fi |
| 122 | + |
| 123 | +# 3.6 Memory limits |
| 124 | +for cname in glpi-a03-app glpi-a03-cron glpi-a03-db; do |
| 125 | + MEM_LIMIT=$(docker inspect "${cname}" --format '{{.HostConfig.Memory}}' 2>/dev/null || echo "0") |
| 126 | + if [[ "${MEM_LIMIT}" -gt 0 ]]; then |
| 127 | + pass "${cname} has memory limit (${MEM_LIMIT} bytes)" |
| 128 | + else |
| 129 | + fail "${cname} has no memory limit" |
| 130 | + fi |
| 131 | +done |
| 132 | + |
| 133 | +# 3.7 Mailhog |
| 134 | +MAIL_TOTAL=$(curl -sf http://localhost:8722/api/v2/messages 2>/dev/null | grep -o '"total":[0-9]*' | grep -o '[0-9]*' || echo "0") |
| 135 | +pass "Mailhog API reachable (message count: ${MAIL_TOTAL})" |
| 136 | + |
| 137 | +# 3.8 Volumes |
| 138 | +for vol in glpi-a03-db-data glpi-a03-files glpi-a03-plugins; do |
| 139 | + if docker volume ls --format '{{.Name}}' | grep -q "${vol}"; then |
| 140 | + pass "Volume ${vol} exists" |
| 141 | + else |
| 142 | + fail "Volume ${vol} not found" |
| 143 | + fi |
| 144 | +done |
| 145 | + |
| 146 | +# ── PHASE 4: (cleanup via trap) ──────────────────────────────────────────────── |
| 147 | +section "Phase 4: Results" |
| 148 | + |
| 149 | +echo "" |
| 150 | +echo -e "${CYAN}======================================${NC}" |
| 151 | +echo -e " Lab ${LAB_ID} Complete" |
| 152 | +echo -e " ${GREEN}PASS: ${PASS}${NC} | ${RED}FAIL: ${FAIL}${NC}" |
| 153 | +echo -e "${CYAN}======================================${NC}" |
| 154 | + |
| 155 | +if [[ "${FAIL}" -gt 0 ]]; then |
| 156 | + exit 1 |
| 157 | +fi |
| 158 | + |
14 | 159 | # ── Colors ──────────────────────────────────────────────────────────────────── |
15 | 160 | RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' |
16 | 161 | CYAN='\033[0;36m'; NC='\033[0m' |
|
0 commit comments