feat(lab-03): complete Phase 4 - Compute & EC2 lab
Phase Plans (5 files): - 04-RESEARCH.md: Domain research on Docker limits, healthchecks, EC2 parallels - 04-VALIDATION.md: Success criteria and validation strategy - 04-01-PLAN.md: Test infrastructure (RED phase) - 04-02-PLAN.md: Diátxis documentation - 04-03-PLAN.md: Infrastructure implementation (GREEN phase) Test Scripts (6 files, 1300+ lines): - 01-resource-limits-test.sh: Validate INF-03 compliance - 02-healthcheck-test.sh: Validate healthcheck configuration - 03-enforcement-test.sh: Verify resource limits with docker stats - 04-verify-infrastructure.sh: Infrastructure verification - 99-final-verification.sh: End-to-end student verification - run-all-tests.sh: Test orchestration with fail-fast - quick-test.sh: Fast validation (<30s) Documentation (11 files, 2500+ lines): Tutorials (3): - 01-set-resource-limits.md: EC2 instance types, Docker limits syntax - 02-implement-healthchecks.md: ELB health check parallels - 03-dependencies-with-health.md: depends_on with service_healthy How-to Guides (4): - check-resource-usage.md: docker stats monitoring - test-limits-enforcement.md: Stress testing CPU/memory - custom-healthcheck.md: HTTP, TCP, database healthchecks - instance-type-mapping.md: Docker limits → EC2 mapping Reference (3): - compose-resources-syntax.md: Complete deploy.resources reference - healthcheck-syntax.md: All healthcheck parameters - ec2-instance-mapping.md: Instance type mapping table Explanation (1): - compute-ec2-parallels.md: Container=EC2, Limits=Instance Type, Healthcheck=ELB Infrastructure: - docker-compose.yml: 5 services (web, app, worker, db, stress-test) All services: INF-03 compliant (cpus + memory limits) All services: healthcheck configured EC2 parallels: t2.nano, t2.micro, t2.small, t2.medium, m5.large - Dockerfile: Alpine 3.19 + stress tools + non-root user Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
84
labs/lab-03-compute/tests/04-verify-infrastructure.sh
Executable file
84
labs/lab-03-compute/tests/04-verify-infrastructure.sh
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
# Infrastructure Verification for Lab 03
|
||||
# Verifies docker-compose.yml is correctly deployed with resource limits and healthchecks
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; BLUE='\033[0;34m'; YELLOW='\033[1;33m'; BOLD='\033[1m'; NC='\033[0m'
|
||||
pass_count=0; fail_count=0
|
||||
|
||||
inc_pass() { ((pass_count++)) || true; }
|
||||
inc_fail() { ((fail_count++)) || true; }
|
||||
|
||||
print_header() {
|
||||
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${BLUE}║${NC} ${BOLD}$1${NC}"
|
||||
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
}
|
||||
|
||||
print_test() { echo -e "\n${BLUE}[TEST]${NC} $1"; }
|
||||
print_pass() { echo -e " ${GREEN}[✓]${NC} $1"; inc_pass; }
|
||||
print_fail() { echo -e " ${RED}[✗]${NC} $1"; inc_fail; }
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
print_header "Lab 03 Infrastructure Verification"
|
||||
|
||||
# File and syntax
|
||||
print_test "Verifying docker-compose.yml exists and valid"
|
||||
[[ -f "docker-compose.yml" ]] && print_pass "docker-compose.yml found" || { print_fail "docker-compose.yml not found"; exit 1; }
|
||||
docker compose config &> /dev/null && print_pass "Syntax valid" || { print_fail "Syntax error"; exit 1; }
|
||||
|
||||
# Services and limits
|
||||
print_test "Checking INF-03 compliance (resource limits)"
|
||||
SERVICES=$(docker compose config --services 2>/dev/null)
|
||||
NON_COMPLIANT=0
|
||||
for s in $SERVICES; do
|
||||
has_cpu=$(docker compose config 2>/dev/null | grep -A30 "^$s:" | grep -c "cpus:" || echo "0")
|
||||
has_mem=$(docker compose config 2>/dev/null | grep -A30 "^$s:" | grep -c "memory:" || echo "0")
|
||||
if [[ $has_cpu -eq 0 || $has_mem -eq 0 ]]; then
|
||||
print_fail " $s: missing limits"
|
||||
((NON_COMPLIANT++)) || true
|
||||
else
|
||||
cpu_val=$(docker compose config 2>/dev/null | grep -A30 "^$s:" | grep "cpus:" | sed 's/.*cpus: //' | tr -d ' "')
|
||||
mem_val=$(docker compose config 2>/dev/null | grep -A30 "^$s:" | grep "memory:" | sed 's/.*memory: //' | tr -d " '""")
|
||||
print_pass " $s: cpus=$cpu_val, memory=$mem_val"
|
||||
fi
|
||||
done
|
||||
[[ $NON_COMPLIANT -eq 0 ]] && print_pass "INF-03 COMPLIANT" || print_fail "INF-03 VIOLATION: $NON_COMPLIANT services"
|
||||
|
||||
# Healthchecks
|
||||
print_test "Verifying healthcheck configuration"
|
||||
MISSING_HC=0
|
||||
for s in $SERVICES; do
|
||||
has_hc=$(docker compose config 2>/dev/null | grep -A50 "^$s:" | grep -c "healthcheck:" || echo "0")
|
||||
[[ $has_hc -gt 0 ]] && print_pass " $s: healthcheck configured" || { print_fail " $s: missing healthcheck"; ((MISSING_HC++)); }
|
||||
done
|
||||
[[ $MISSING_HC -eq 0 ]] && print_pass "All services have healthchecks" || print_fail "$MISSING_HC missing healthchecks"
|
||||
|
||||
# Deploy and verify
|
||||
print_test "Starting services"
|
||||
docker compose up -d &> /dev/null && print_pass "Services started" && sleep 8 || { print_fail "Failed to start"; exit 1; }
|
||||
|
||||
print_test "Checking running containers"
|
||||
RUNNING=$(docker compose ps --services --filter "status=running" | wc -l)
|
||||
[[ $RUNNING -ge 4 ]] && print_pass "$RUNNING containers running" || print_fail "Only $RUNNING containers"
|
||||
|
||||
# Enforcement
|
||||
print_test "Verifying resource limits enforced"
|
||||
ENFORCED=0
|
||||
for s in $SERVICES; do
|
||||
c="lab03-$s"
|
||||
if docker ps --format '{{.Names}}' | grep -q "$c"; then
|
||||
nano_cpus=$(docker inspect "$c" --format '{{.HostConfig.NanoCpus}}' 2>/dev/null || echo "0")
|
||||
mem_bytes=$(docker inspect "$c" --format '{{.HostConfig.Memory}}' 2>/dev/null || echo "0")
|
||||
[[ $nano_cpus -gt 0 && $mem_bytes -gt 0 ]] && print_pass " $c: limits enforced" || print_fail " $c: limits not applied"
|
||||
[[ $nano_cpus -gt 0 && $mem_bytes -gt 0 ]] && ((ENFORCED++)) || true
|
||||
fi
|
||||
done
|
||||
[[ $ENFORCED -gt 0 ]] && print_pass "Limits enforced for $ENFORCED containers"
|
||||
|
||||
# Summary
|
||||
print_header "Summary"
|
||||
echo "Tests: $((pass_count + fail_count)) | ${GREEN}Passed: $pass_count${NC} ${RED}Failed: $fail_count${NC}"
|
||||
[[ $fail_count -eq 0 ]] && { echo -e "\n${GREEN}${BOLD}✓ ALL CHECKS PASSED${NC}\n"; exit 0; } || { echo -e "\n${RED}Some checks failed${NC}\n"; exit 1; }
|
||||
Reference in New Issue
Block a user