Files
laboratori-cloud/labs/lab-03-compute/tests/01-resource-limits-test.sh
Luca Sacchi Ricciardi 23a9ffe443 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>
2026-04-03 15:16:58 +02:00

216 lines
6.8 KiB
Bash
Executable File

#!/bin/bash
# Test 01: Resource Limits Configuration
# Verifies that docker-compose.yml services have mandatory resource limits
# Usage: bash labs/lab-03-compute/tests/01-resource-limits-test.sh
set -euo pipefail
# Color definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
BOLD='\033[1m'
NC='\033[0m'
# Get script directory
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LAB_DIR="$(cd "$TEST_DIR/.." && pwd)"
# Counter helpers
pass_count=0
fail_count=0
inc_pass() { ((pass_count++)) || true; }
inc_fail() { ((fail_count++)) || true; }
# Helper functions
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
}
print_info() {
echo -e " ${BLUE}[i]${NC} $1"
}
# Main verification
print_header "Lab 03 Resource Limits Verification"
cd "$LAB_DIR"
# Test 1: docker-compose.yml exists
print_test "Verifying docker-compose.yml exists"
if [[ -f "docker-compose.yml" ]]; then
print_pass "docker-compose.yml found"
else
print_fail "docker-compose.yml not found"
exit 1
fi
# Test 2: docker-compose.yml is valid
print_test "Validating docker-compose.yml syntax"
if docker compose config &> /dev/null; then
print_pass "docker-compose.yml has valid syntax"
else
print_fail "docker-compose.yml has syntax errors"
exit 1
fi
# Test 3: Services are defined
print_test "Verifying services are defined"
SERVICES=$(docker compose config --services 2>/dev/null)
SERVICE_COUNT=$(echo "$SERVICES" | wc -l)
if [[ $SERVICE_COUNT -gt 0 ]]; then
print_pass "Found $SERVICE_COUNT services"
echo "$SERVICES" | while read -r service; do
print_info " - $service"
done
else
print_fail "No services defined"
exit 1
fi
# Test 4: INF-03 compliance check - all services must have resource limits
print_test "Checking INF-03 compliance (resource limits)"
NON_COMPLIANT=0
for service in $SERVICES; do
# Check for deploy.resources section
has_deploy=$(docker compose config 2>/dev/null | grep -A 20 "^$service:" | grep -c "deploy:" || echo "0")
has_resources=$(docker compose config 2>/dev/null | grep -A 25 "^$service:" | grep -c "resources:" || echo "0")
if [[ $has_deploy -eq 0 || $has_resources -eq 0 ]]; then
print_fail " $service: Missing deploy.resources section"
((NON_COMPLIANT++)) || true
else
# Check for CPU limit
has_cpu=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep -c "cpus:" || echo "0")
# Check for memory limit
has_memory=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep -c "memory:" || echo "0")
if [[ $has_cpu -eq 0 ]]; then
print_fail " $service: Missing cpus limit"
((NON_COMPLIANT++)) || true
fi
if [[ $has_memory -eq 0 ]]; then
print_fail " $service: Missing memory limit"
((NON_COMPLIANT++)) || true
fi
if [[ $has_cpu -gt 0 && $has_memory -gt 0 ]]; then
# Extract limits for reporting
cpu_limit=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep "cpus:" | sed 's/.*cpus: //' | tr -d ' "')
mem_limit=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep "memory:" | sed 's/.*memory: //' | tr -d " '")
print_pass " $service: cpus: $cpu_limit, memory: $mem_limit"
fi
fi
done
if [[ $NON_COMPLIANT -eq 0 ]]; then
print_pass "INF-03 compliance: All services have resource limits"
else
print_fail "INF-03 compliance: $NON_COMPLIANT services missing limits"
fi
# Test 5: Verify specific EC2 instance type parallels
print_test "Verifying EC2 instance type parallels"
INSTANCE_TYPES=0
for service in $SERVICES; do
cpu_limit=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep "cpus:" | sed 's/.*cpus: //' | tr -d ' "' || echo "")
mem_limit=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep "memory:" | sed 's/.*memory: //' | tr -d " '"" || echo "")
# Map to EC2 instance types
if [[ -n "$cpu_limit" && -n "$mem_limit" ]]; then
case "$cpu_limit:$mem_limit" in
"0.5:512M"|"0.5:512")
instance_type="t2.nano"
;;
"1:1G"|"1:1024M"|"1:1024")
instance_type="t2.micro"
;;
"1:2G"|"1:2048M"|"1:2048")
instance_type="t2.small"
;;
"2:4G"|"2:4096M"|"2:4096")
instance_type="t2.medium"
;;
"2:8G"|"2:8192M"|"2:8192")
instance_type="m5.large"
;;
*)
instance_type="custom"
;;
esac
print_info " $service$instance_type (cpus: $cpu_limit, memory: $mem_limit)"
((INSTANCE_TYPES++)) || true
fi
done
if [[ $INSTANCE_TYPES -gt 0 ]]; then
print_pass "EC2 instance type mapping complete for $INSTANCE_TYPES services"
else
print_fail "No services with valid resource limits found"
fi
# Test 6: Verify resource limit formats
print_test "Verifying resource limit formats"
FORMAT_OK=0
for service in $SERVICES; do
cpu_limit=$(docker compose config 2>/dev/null | grep -A 30 "^$service:" | grep "cpus:" | sed 's/.*cpus: //' | tr -d ' "' || echo "")
# CPU limit should be a number or decimal
if [[ -n "$cpu_limit" ]]; then
if [[ "$cpu_limit" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
((FORMAT_OK++)) || true
else
print_fail " $service: Invalid CPU format: $cpu_limit"
fi
fi
done
if [[ $FORMAT_OK -eq $SERVICE_COUNT ]]; then
print_pass "All resource limits use valid format"
else
print_fail "Some resource limits have invalid format"
fi
# Summary
print_header "Resource Limits Verification Summary"
echo -e "Tests run: $((pass_count + fail_count))"
echo -e "${GREEN}Passed: $pass_count${NC}"
if [[ $fail_count -gt 0 ]]; then
echo -e "${RED}Failed: $fail_count${NC}"
fi
if [[ $fail_count -eq 0 ]]; then
echo -e "\n${GREEN}${BOLD}✓ ALL RESOURCE LIMITS CHECKS PASSED${NC}"
echo -e "\nINF-03 compliance verified!"
exit 0
else
echo -e "\n${RED}Some resource limits checks failed${NC}"
echo -e "Please ensure all services have cpus and memory limits."
exit 1
fi