Skip to main content
Glama
cleanup.sh10.2 kB
#!/usr/bin/env bash # # Resource Cleanup Utility # # Safely terminates EC2 instances, removes Docker containers, and cleans up # resources based on deployment tags. Use this to tear down a deployment. # # Usage: # ./cleanup.sh [--instance-id <id>] [--all] [--dry-run] [--force] # # Options: # --instance-id <id> Clean up specific EC2 instance # --all Clean up all resources with deployment tags # --dry-run Show what would be cleaned up without doing it # --force Skip confirmation prompts # # Examples: # ./cleanup.sh --instance-id i-1234567890abcdef0 # ./cleanup.sh --all --dry-run # ./cleanup.sh --all --force # # Safety Features: # - Requires confirmation before destructive operations # - Supports dry-run mode # - Tags-based filtering to avoid accidental deletion # - Graceful container shutdown before removal set -euo pipefail # Colors readonly RED='\033[0;31m' readonly GREEN='\033[0;32m' readonly YELLOW='\033[1;33m' readonly BLUE='\033[0;34m' readonly NC='\033[0m' # Configuration readonly PROJECT_TAG="Project=FHIR-AI-Hackathon" readonly MANAGED_BY_TAG="ManagedBy=deployment-automation" # Flags INSTANCE_ID="" CLEANUP_ALL=false DRY_RUN=false FORCE=false # Parse arguments while [[ $# -gt 0 ]]; then case "$1" in --instance-id) INSTANCE_ID="$2" shift 2 ;; --all) CLEANUP_ALL=true shift ;; --dry-run) DRY_RUN=true shift ;; --force) FORCE=true shift ;; *) echo "Unknown option: $1" >&2 echo "Usage: $0 [--instance-id <id>] [--all] [--dry-run] [--force]" >&2 exit 1 ;; esac done # Validate arguments if [[ -z "$INSTANCE_ID" ]] && [[ "$CLEANUP_ALL" == "false" ]]; then echo "Error: Must specify either --instance-id or --all" >&2 echo "Usage: $0 [--instance-id <id>] [--all] [--dry-run] [--force]" >&2 exit 1 fi # Logging functions log_info() { echo -e "${BLUE}→${NC} $1" } log_success() { echo -e "${GREEN}✓${NC} $1" } log_warn() { echo -e "${YELLOW}!${NC} $1" } log_error() { echo -e "${RED}✗${NC} $1" >&2 } log_dry_run() { echo -e "${YELLOW}[DRY RUN]${NC} $1" } # Function to confirm action confirm() { local message="$1" if [[ "$FORCE" == "true" ]]; then return 0 fi echo -en "${YELLOW}?${NC} ${message} (yes/no): " read -r response if [[ "$response" != "yes" ]]; then log_warn "Operation cancelled" return 1 fi return 0 } # Function to get instances get_instances() { if [[ -n "$INSTANCE_ID" ]]; then echo "$INSTANCE_ID" else # Get all instances with our tags aws ec2 describe-instances \ --filters \ "Name=tag:${PROJECT_TAG%%=*},Values=${PROJECT_TAG##*=}" \ "Name=tag:${MANAGED_BY_TAG%%=*},Values=${MANAGED_BY_TAG##*=}" \ "Name=instance-state-name,Values=running,stopped,stopping" \ --query 'Reservations[*].Instances[*].InstanceId' \ --output text || true fi } # Function to cleanup Docker containers on remote instance cleanup_docker_containers() { local instance_ip="$1" local ssh_key="${SSH_KEY_PATH:-./fhir-ai-key.pem}" log_info "Cleaning up Docker containers on ${instance_ip}" if [[ "$DRY_RUN" == "true" ]]; then log_dry_run "Would stop and remove Docker containers: iris-fhir, nim-llm, nim-embeddings, nim-vision" return 0 fi # SSH into instance and cleanup containers ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 -i "$ssh_key" "ubuntu@${instance_ip}" << 'EOF' || true echo "Stopping Docker containers..." # Stop containers gracefully (30 second timeout) for container in iris-fhir nim-llm nim-embeddings nim-vision; do if docker ps -a --format '{{.Names}}' | grep -q "^${container}$"; then echo " Stopping ${container}..." docker stop -t 30 "$container" 2>/dev/null || true fi done # Remove containers echo "Removing Docker containers..." for container in iris-fhir nim-llm nim-embeddings nim-vision; do if docker ps -a --format '{{.Names}}' | grep -q "^${container}$"; then echo " Removing ${container}..." docker rm "$container" 2>/dev/null || true fi done echo "Docker cleanup complete" EOF if [[ $? -eq 0 ]]; then log_success "Docker containers cleaned up" else log_warn "Could not connect to instance or cleanup failed (instance may already be terminated)" fi } # Function to terminate EC2 instance terminate_instance() { local instance_id="$1" log_info "Terminating EC2 instance: ${instance_id}" # Get instance details instance_details=$(aws ec2 describe-instances \ --instance-ids "$instance_id" \ --query 'Reservations[0].Instances[0].[PublicIpAddress,InstanceType,State.Name]' \ --output text 2>/dev/null || echo "unknown unknown unknown") read -r public_ip instance_type state <<< "$instance_details" echo " IP Address: ${public_ip:-N/A}" echo " Instance Type: ${instance_type}" echo " Current State: ${state}" if [[ "$DRY_RUN" == "true" ]]; then log_dry_run "Would terminate instance ${instance_id}" return 0 fi # Cleanup Docker containers if instance is accessible if [[ "$state" == "running" ]] && [[ -n "$public_ip" ]] && [[ "$public_ip" != "None" ]]; then cleanup_docker_containers "$public_ip" fi # Terminate instance if aws ec2 terminate-instances --instance-ids "$instance_id" &>/dev/null; then log_success "Instance ${instance_id} terminated" else log_error "Failed to terminate instance ${instance_id}" return 1 fi } # Function to cleanup security groups cleanup_security_groups() { log_info "Looking for security groups to cleanup" # Find security groups with our tags sg_ids=$(aws ec2 describe-security-groups \ --filters \ "Name=tag:${PROJECT_TAG%%=*},Values=${PROJECT_TAG##*=}" \ "Name=tag:${MANAGED_BY_TAG%%=*},Values=${MANAGED_BY_TAG##*=}" \ --query 'SecurityGroups[*].GroupId' \ --output text || true) if [[ -z "$sg_ids" ]]; then log_info "No security groups found" return 0 fi for sg_id in $sg_ids; do sg_name=$(aws ec2 describe-security-groups \ --group-ids "$sg_id" \ --query 'SecurityGroups[0].GroupName' \ --output text) if [[ "$DRY_RUN" == "true" ]]; then log_dry_run "Would delete security group: ${sg_id} (${sg_name})" else log_info "Deleting security group: ${sg_id} (${sg_name})" # Wait a bit for instances to fully terminate sleep 5 if aws ec2 delete-security-group --group-id "$sg_id" 2>/dev/null; then log_success "Security group ${sg_id} deleted" else log_warn "Could not delete security group ${sg_id} (may still be in use)" fi fi done } # Function to cleanup EBS volumes cleanup_ebs_volumes() { log_info "Looking for unattached EBS volumes to cleanup" # Find available (unattached) volumes with our tags volume_ids=$(aws ec2 describe-volumes \ --filters \ "Name=tag:${PROJECT_TAG%%=*},Values=${PROJECT_TAG##*=}" \ "Name=tag:${MANAGED_BY_TAG%%=*},Values=${MANAGED_BY_TAG##*=}" \ "Name=status,Values=available" \ --query 'Volumes[*].VolumeId' \ --output text || true) if [[ -z "$volume_ids" ]]; then log_info "No unattached volumes found" return 0 fi for volume_id in $volume_ids; do volume_size=$(aws ec2 describe-volumes \ --volume-ids "$volume_id" \ --query 'Volumes[0].Size' \ --output text) if [[ "$DRY_RUN" == "true" ]]; then log_dry_run "Would delete volume: ${volume_id} (${volume_size}GB)" else log_info "Deleting volume: ${volume_id} (${volume_size}GB)" if aws ec2 delete-volume --volume-id "$volume_id" 2>/dev/null; then log_success "Volume ${volume_id} deleted" else log_warn "Could not delete volume ${volume_id}" fi fi done } # Main cleanup logic main() { log_info "FHIR AI Hackathon Deployment Cleanup" echo "" if [[ "$DRY_RUN" == "true" ]]; then log_warn "DRY RUN MODE - No resources will be modified" echo "" fi # Get instances to cleanup instances=$(get_instances) if [[ -z "$instances" ]]; then log_warn "No instances found to cleanup" return 0 fi # Count instances instance_count=$(echo "$instances" | wc -w) # Show summary echo "Found ${instance_count} instance(s) to cleanup:" for id in $instances; do echo " - $id" done echo "" # Confirm if not in force mode if ! confirm "Proceed with cleanup of ${instance_count} instance(s)?"; then return 1 fi echo "" # Terminate instances for instance_id in $instances; do terminate_instance "$instance_id" echo "" done # Wait for instances to terminate if [[ "$DRY_RUN" == "false" ]] && [[ -n "$instances" ]]; then log_info "Waiting for instances to terminate..." aws ec2 wait instance-terminated --instance-ids $instances || true log_success "All instances terminated" echo "" fi # Cleanup security groups cleanup_security_groups echo "" # Cleanup EBS volumes cleanup_ebs_volumes echo "" if [[ "$DRY_RUN" == "true" ]]; then log_info "Dry run complete - no resources were modified" else log_success "Cleanup complete!" fi } # Run main function main

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/isc-tdyar/medical-graphrag-assistant'

If you have feedback or need assistance with the MCP directory API, please join our Discord server