Created
February 4, 2026 09:56
-
-
Save adamseoul/8d384747393901e70f115c15e2c6f1d5 to your computer and use it in GitHub Desktop.
Image EC2 and update ASG launch template - SigningOrder (no SO GitHub account, using personal)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Image a production machine and update its ASG launch template | |
| # | |
| # Usage: | |
| # ./image-machine.sh # List all running machines | |
| # ./image-machine.sh i-XXXXX # Image (new version NOT default) | |
| # ./image-machine.sh i-XXXXX --default # Image and SET as default | |
| REGION="us-east-1" | |
| SET_DEFAULT=false | |
| if [ "$2" == "--default" ]; then | |
| SET_DEFAULT=true | |
| fi | |
| list_machines() { | |
| echo "=== Running Production Machines ===" | |
| echo "" | |
| printf "%-22s %-45s %-25s\n" "INSTANCE ID" "NAME" "ASG" | |
| printf "%-22s %-45s %-25s\n" "-----------" "----" "---" | |
| aws ec2 describe-instances \ | |
| --filters "Name=instance-state-name,Values=running" \ | |
| --query "Reservations[].Instances[].[InstanceId, Tags[?Key=='Name'].Value | [0], Tags[?Key=='aws:autoscaling:groupName'].Value | [0]]" \ | |
| --output text \ | |
| --region $REGION | while read -r id name asg; do | |
| printf "%-22s %-45s %-25s\n" "$id" "${name:-No Name}" "${asg:-None}" | |
| done | |
| echo "" | |
| echo "Usage: $0 <instance-id>" | |
| } | |
| image_machine() { | |
| INSTANCE_ID="$1" | |
| echo "=== Getting Instance Info ===" | |
| # Get instance name | |
| INSTANCE_NAME=$(aws ec2 describe-tags \ | |
| --filters "Name=resource-id,Values=$INSTANCE_ID" "Name=key,Values=Name" \ | |
| --query "Tags[0].Value" \ | |
| --output text \ | |
| --region $REGION) | |
| echo "Instance: $INSTANCE_NAME ($INSTANCE_ID)" | |
| # Get ASG | |
| ASG_NAME=$(aws autoscaling describe-auto-scaling-instances \ | |
| --instance-ids "$INSTANCE_ID" \ | |
| --query "AutoScalingInstances[0].AutoScalingGroupName" \ | |
| --output text \ | |
| --region $REGION 2>/dev/null) | |
| if [ -z "$ASG_NAME" ] || [ "$ASG_NAME" == "None" ]; then | |
| echo "WARNING: Instance not in an ASG" | |
| echo "Will create AMI but cannot update launch template" | |
| ASG_NAME="" | |
| else | |
| echo "ASG: $ASG_NAME" | |
| fi | |
| # Determine AMI name based on instance name | |
| TIMESTAMP=$(date +"%Y%m%d %H%M") | |
| if echo "$INSTANCE_NAME" | grep -qi "cron"; then | |
| AMI_NAME="SO PROD CRON $TIMESTAMP" | |
| elif echo "$INSTANCE_NAME" | grep -qi "beta"; then | |
| AMI_NAME="SO BETA Web Node $TIMESTAMP" | |
| elif echo "$INSTANCE_NAME" | grep -qi "canary"; then | |
| AMI_NAME="SO Prod Canary $TIMESTAMP" | |
| else | |
| AMI_NAME="SO PROD ELB Web Node $TIMESTAMP" | |
| fi | |
| echo "AMI Name: $AMI_NAME" | |
| echo "" | |
| # Create AMI | |
| echo "=== Creating AMI (no reboot) ===" | |
| AMI_ID=$(aws ec2 create-image \ | |
| --instance-id "$INSTANCE_ID" \ | |
| --name "$AMI_NAME" \ | |
| --description "Created from $INSTANCE_NAME" \ | |
| --no-reboot \ | |
| --region $REGION \ | |
| --query "ImageId" \ | |
| --output text) | |
| echo "AMI ID: $AMI_ID" | |
| echo "" | |
| echo "Waiting for AMI to be available..." | |
| aws ec2 wait image-available --image-ids "$AMI_ID" --region $REGION | |
| echo "AMI ready!" | |
| echo "" | |
| # If no ASG, we're done | |
| if [ -z "$ASG_NAME" ]; then | |
| echo "=== DONE ===" | |
| echo "AMI: $AMI_ID" | |
| echo "No ASG - manually update launch template if needed" | |
| exit 0 | |
| fi | |
| # Get launch template from ASG | |
| echo "=== Updating Launch Template ===" | |
| LT_INFO=$(aws autoscaling describe-auto-scaling-groups \ | |
| --auto-scaling-group-names "$ASG_NAME" \ | |
| --query "AutoScalingGroups[0].LaunchTemplate" \ | |
| --output json \ | |
| --region $REGION) | |
| LT_ID=$(echo "$LT_INFO" | jq -r '.LaunchTemplateId // empty') | |
| if [ -z "$LT_ID" ]; then | |
| echo "ASG doesn't use a launch template" | |
| echo "" | |
| echo "=== DONE ===" | |
| echo "AMI: $AMI_ID" | |
| exit 0 | |
| fi | |
| LT_NAME=$(aws ec2 describe-launch-templates \ | |
| --launch-template-ids "$LT_ID" \ | |
| --query "LaunchTemplates[0].LaunchTemplateName" \ | |
| --output text \ | |
| --region $REGION) | |
| CURRENT_VERSION=$(aws ec2 describe-launch-templates \ | |
| --launch-template-ids "$LT_ID" \ | |
| --query "LaunchTemplates[0].LatestVersionNumber" \ | |
| --output text \ | |
| --region $REGION) | |
| DEFAULT_VERSION=$(aws ec2 describe-launch-templates \ | |
| --launch-template-ids "$LT_ID" \ | |
| --query "LaunchTemplates[0].DefaultVersionNumber" \ | |
| --output text \ | |
| --region $REGION) | |
| echo "Launch Template: $LT_NAME ($LT_ID)" | |
| echo "Current Latest: v$CURRENT_VERSION" | |
| echo "Current Default: v$DEFAULT_VERSION" | |
| echo "" | |
| # Create new version (NOT setting as default) | |
| echo "Creating new version with AMI $AMI_ID..." | |
| NEW_VERSION=$(aws ec2 create-launch-template-version \ | |
| --launch-template-id "$LT_ID" \ | |
| --source-version "$CURRENT_VERSION" \ | |
| --launch-template-data "{\"ImageId\":\"$AMI_ID\"}" \ | |
| --version-description "CloudWatch agent - $TIMESTAMP" \ | |
| --region $REGION \ | |
| --query "LaunchTemplateVersion.VersionNumber" \ | |
| --output text) | |
| echo "New Version: v$NEW_VERSION" | |
| echo "" | |
| # Set as default if requested | |
| if [ "$SET_DEFAULT" == "true" ]; then | |
| echo "Setting v$NEW_VERSION as default..." | |
| aws ec2 modify-launch-template \ | |
| --launch-template-id "$LT_ID" \ | |
| --default-version "$NEW_VERSION" \ | |
| --region $REGION > /dev/null | |
| echo "" | |
| echo "=========================================" | |
| echo "DONE - SET AS DEFAULT" | |
| echo "=========================================" | |
| echo "" | |
| echo "AMI: $AMI_ID" | |
| echo "Launch Template: $LT_NAME" | |
| echo "New Version: v$NEW_VERSION (NOW DEFAULT)" | |
| echo "Previous Default: v$DEFAULT_VERSION" | |
| echo "ASG: $ASG_NAME" | |
| echo "" | |
| echo "New instances will use this AMI." | |
| echo "" | |
| echo "To rollback:" | |
| echo " aws ec2 modify-launch-template --launch-template-id $LT_ID --default-version $DEFAULT_VERSION --region $REGION" | |
| else | |
| echo "=========================================" | |
| echo "DONE - NOT SET AS DEFAULT" | |
| echo "=========================================" | |
| echo "" | |
| echo "AMI: $AMI_ID" | |
| echo "Launch Template: $LT_NAME" | |
| echo "New Version: v$NEW_VERSION (NOT default)" | |
| echo "Default Version: v$DEFAULT_VERSION (unchanged)" | |
| echo "ASG: $ASG_NAME" | |
| echo "" | |
| echo "To make default:" | |
| echo " aws ec2 modify-launch-template --launch-template-id $LT_ID --default-version $NEW_VERSION --region $REGION" | |
| echo "" | |
| echo "Or re-run with: $0 $INSTANCE_ID --default" | |
| fi | |
| } | |
| # Main | |
| if [ -z "$1" ]; then | |
| list_machines | |
| else | |
| image_machine "$1" | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment