#!/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