Skip to content

Instantly share code, notes, and snippets.

@joshspicer
Created November 7, 2018 11:40
Show Gist options
  • Save joshspicer/39fd9aa423aca17ef0703b60416920b0 to your computer and use it in GitHub Desktop.
Save joshspicer/39fd9aa423aca17ef0703b60416920b0 to your computer and use it in GitHub Desktop.
#!/bin/bash
# Written by Josh Spicer (Oct. 7, 2018)
# Creates a new EC2 instance based on a clean image taken previously.
# Prereqs:
# - aws-cli in user path
# - aws creds (aws configure --profile <profile name>) as first argument
# `jq` installed in user path
if [ "$#" -ne 2 ]; then
echo "[-] Usage: ./launch.sh <aws profile name> <key-name>"
exit 1
fi
rm debug.txt &> /dev/null
profile=$1 # The name of local profile that stores your AWS secret key.
keyName=$2 # The name of the SSH key you'd like to add. Must already exist in ec2.
# Creates an instance of whatever you want.
aws ec2 run-instances --profile "$profile" --key-name "$keyName" --image-id <YOUR-IMAGE> --count 1 --instance-type t2.small --security-group-ids <YOUR-S-GROUP> --region us-east-2 --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=WebServer}]' > tmp.txt
# Collect the new instance ID and Availability Zone
instanceID=$(jq -r '.Instances[].InstanceId' < tmp.txt)
availabilityZone=$(jq -r '.Instances[].Placement.AvailabilityZone' < tmp.txt)
echo "[+] Created Instance $instanceID in Availability Zone $availabilityZone "
# Create a new volume. Use the `josh-master` snapshot to init!
# This comes with a webserver already preconfigured and ready to launch.
# This `snapshot-id` can be replaced to change the software on instance.
# Collect the new volume ID
volumeID=$(aws ec2 create-volume --profile "$profile" --snapshot-id <YOUR-SNAPSHOT> --region us-east-2 --availability-zone "$availabilityZone" | jq -r '.VolumeId')
echo "[+] Created New Volume with ID $volumeID "
echo "[+] Waiting for instance to be created...."
keepWaiting=true
# Wait for instance to be created (marked as `running`)
while $keepWaiting; do
status=$(aws ec2 --profile "$profile" describe-instance-status -- --include-all-instances --instance-id "$instanceID" | jq -r '.InstanceStatuses[].InstanceState.Name')
if [[ $status == "running" ]]; then
keepWaiting=false
break
fi
echo "[+] Still working. Status: $status "
sleep 5s
done
# Collect the ID of the original volume.
# We want to unmount this drive and attach one with our master image.
unwantedVolumeID=$(aws ec2 describe-volumes --filters Name=attachment.instance-id,Values="$instanceID" --profile "$profile" | jq -r '.Volumes[].VolumeId')
echo "[+] Will be unmounting volume with ID $unwantedVolumeID "
# Stop our instance to begin the unmount.
aws ec2 stop-instances --profile "$profile" --instance-ids "$instanceID" >> debug.txt
echo "[+] Waiting for instance to be stopped to swap drives..."
echo "[+] Note: This part takes a minute or so..."
keepWaiting=true
# Wait for instance to be stopped.
while $keepWaiting; do
status=$(aws ec2 --profile "$profile" describe-instance-status -- --include-all-instances --instance-id "$instanceID" | jq -r '.InstanceStatuses[].InstanceState.Name')
if [[ $status == "stopped" ]]; then
keepWaiting=false
break
fi
echo "[+] Still working. Status: $status "
sleep 20s
done
# Swap out the default volume with a volume configured with our clean, master image.
aws ec2 detach-volume --profile "$profile" --device /dev/sda1 --instance-id "$instanceID" --volume-id "$unwantedVolumeID" >> debug.txt
aws ec2 attach-volume --profile "$profile" --volume-id "$volumeID" --instance-id "$instanceID" --device /dev/sda1 >> debug.txt
# At this point check for error.
if [ $? -ne 0 ]; then
echo "An Error Occurred. Please try again and check the debug.txt file."
exit 1
fi
aws ec2 start-instances --profile "$profile" --instance-ids "$instanceID" >> debug.txt
echo "[+] Restarting your instance...."
keepWaiting=true
while $keepWaiting; do
status=$(aws ec2 --profile "$profile" describe-instance-status -- --include-all-instances --instance-id "$instanceID" | jq -r '.InstanceStatuses[].InstanceState.Name')
if [[ $status == "running" ]]; then
keepWaiting=false
break
fi
echo "[+] Still working. Status: $status "
sleep 5s
done
# Extract the public IP address of the new instance
identifier=$(aws ec2 --profile "$profile" describe-instances --instance-id "$instanceID" | jq -r '.Reservations[].Instances[].PublicIpAddress')
echo; echo "Your Instance is Almost Ready! Its Public IP will be: "
echo "$identifier"
echo;
echo "Note: This IP will most likely change since it is not elastic."
echo "Saving configuration information in file ./$identifier.txt"
# Save this information to a file so that we have a way to remove this instance later!
echo "$instanceID" >> ./"$identifier".txt
echo "$volumeID" >> ./"$identifier".txt
echo; echo "Run the following command to remove this instance:"
echo "./removeInstance.sh <aws profile name> $identifier.txt"
# Clean up
rm tmp.txt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment