Create a gist now

Instantly share code, notes, and snippets.

@jsianes /ipassign
Last active Mar 29, 2017

What would you like to do?
Script to assign Public IP from Elastic IP pool for instances hosted in AWS. 'ec2-utils' and AWS CLI packages required. Instance role or access keys need to allow at least next EC2 actions: describe-addresses, associate-address and disassociate-address. Shell script is designed to be integrated with instance start-up
#!/bin/bash
# chkconfig: 2345 99 10
# description: Set Public IP from ElasticIP pool during instance startup
# processname: ipassign
# Provides: ipassign
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop:
# Short-Description: Set Public IP from ElasticIP pool during instance startup
#
#
# Developed by: Javier Sianes - jsianes@gmail.com
#
OUTPUT="text"
REGION="eu-west-1"
IPLOGFILE="/var/log/ipassign.log"
export PATH=/usr/share/pear:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin
timestamp() {
TIMESTAMP=`date -u +"%Y-%m-%dT%H:%M:%S.000Z"`
}
usage() {
echo "$0 {start|stop|status}"
exit 255
}
write_log() {
timestamp
echo "${TIMESTAMP} - ${LOG}" >> ${IPLOGFILE}
}
valid_ip() {
RX='([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'
if [[ ${EC2PUBLICIP} =~ ^${RX}\.${RX}\.${RX}\.${RX}$ ]]
then
VALIDIP=1
else
VALIDIP=0
fi
}
check_ec2metadata() {
ec2-metadata >/dev/null 2>&1
if [ $? -eq 0 ]
then
# Amazon Linux ec2-metadata command found
EC2INSTANCE=`ec2-metadata -i | awk '{ print $NF; }'`
EC2PUBLICIP=`ec2-metadata -v | awk '{ print $NF; }'`
else
# Checking ec2metadata command
ec2metadata >/dev/null 2>&1
if [ $? -eq 0 ]
then
# ec2metadata command found
EC2INSTANCE=`ec2metadata --instance-id`
EC2PUBLICIP=`ec2metadata --public-ipv4`
else
# No ec2metadata/ec2-metadata command found. Trying to obtain using curl requests directly
IP_AVAILABLE=`curl --connect-timeout 5 -i http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null | grep "200 OK" | wc -l`
IS_AVAILABLE=`curl --connect-timeout 5 -i http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null | grep "200 OK" | wc -l`
(( INFO=${IP_AVAILABLE}+${IS_AVAILABLE} ))
if [ ${INFO} -eq 2 ]
then
EC2INSTANCE=`curl --connect-timeout 5 http://169.254.169.254/latest/meta-data/instance-id 2>/dev/null`
EC2PUBLICIP=`curl --connect-timeout 5 http://169.254.169.254/latest/meta-data/public-ipv4 2>/dev/null`
else
# ec2metadata/ec2-metadata command not found and unable to obtain metadata info using curl
LOG="ERROR: Unable to obtain metadata information using ec2metadata/ec2-metadata command or curl requests"; write_log
exit 127
fi
fi
fi
}
check_awscli() {
aws ec2 describe-addresses >/dev/null 2>&1
if [ $? -ne 0 ]
then
# Incorrect instance role or invalid AWS CLI configuration
LOG="ERROR: AWS CLI command not available. Check instance role or AWS CLI installation/configuration"; write_log
exit 128
fi
}
start() {
check_ec2metadata
# Check Public IP
valid_ip
if [ ${VALIDIP} -eq 0 ]
then
# No Public IP available. So, AWS CLI unavailable
LOG="ERROR: There is no Public IP address attached to ${EC2INSTANCE} instance. Unable to use AWS CLI."; write_log
exit 3
fi
# Check if AWS CLI is available
check_awscli
# Check if instance has a public IP from Elastic pool assigned
PUBLICIPASSIGNED=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep ${EC2INSTANCE} | wc -l`
if [ ${PUBLICIPASSIGNED} -gt 0 ]
then
# Instance has (at least) one Pulic IP associated from Elastic pool
IP=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep ${EC2INSTANCE} | head -1 | awk '{ print $NF; }'`
LOG="Instance ${EC2INSTANCE} has (at least) one Public IP address from Elastic pool in ${REGION} region (${IP})"; write_log
exit 4
else
# Get IP address from Elastic pool
IP=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep -v 'i-' | head -1 | awk '{ print $NF; }'`
if [ "${IP}" = "" ]
then
# Public IP on Elastic pool unavailable
LOG="ERROR: Free Public IP inside Elastic pool in ${REGION} region unavailable"; write_log
exit 5
else
# Attach Public IP from Elastic pool
BOOL=0
aws ec2 associate-address --output ${OUTPUT} --region ${REGION} --instance-id ${EC2INSTANCE} --public-ip ${IP} >/dev/null 2>&1
EXITCODE=$?
if [ ${EXITCODE} -eq 0 ]
then
LOG="${IP} Public IP from Elastic pool assigned to ${EC2INSTANCE} instance"; write_log
else
LOG="ERROR: (${EXITCODE}) Unable to attach ${IP} Public IP from Elastic pool to ${EC2INSTANCE} instance"; write_log
BOOL=1
fi
if [ ${BOOL} -eq 0 ]
then
# Detaching default Public IP
aws ec2 disassociate-address --output ${OUTPUT} --region ${REGION} --instance-id ${EC2INSTANCE} --public-ip ${EC2PUBLICIP} >/dev/null 2>&1
EXITCODE=$?
if [ ${EXITCODE} -eq 0 ] || [ ${EXITCODE} -eq 255 ]
then
LOG="Default public IP ${EC2PUBLICIP} outside Elastic pool detached from ${EC2INSTANCE} instance"; write_log
else
LOG="ERROR: (${EXITCODE}) Unable to detach default public IP ${EC2PUBLICIP} from ${EC2INSTANCE} instance"; write_log
BOOL=2
fi
fi
exit ${BOOL}
fi
fi
}
stop() {
exit 6
}
status() {
check_ec2metadata
valid_ip
if [ ${VALIDIP} -eq 0 ]
then
echo "No Public IP address attached to ${EC2INSTANCE} instance."
exit 1
fi
check_awscli
IPPRESENTINPOOL=`aws ec2 describe-addresses --output ${OUTPUT} --region ${REGION} | grep "${EC2INSTANCE}" | grep ${EC2PUBLICIP} | wc -l`
if [ ${IPPRESENTINPOOL} -eq 1 ]
then
echo "Public IP ${EC2PUBLICIP} attached to ${EC2INSTANCE} instance in ${REGION} region belongs to ElasticIP pool"
exit 0
else
echo "Public IP ${EC2PUBLICIP} attached to ${EC2INSTANCE} instance in ${REGION} region is a generic public IP NOT present in ElasticIP pool"
exit 2
fi
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
*)
usage
;;
esac
lodotek commented Jan 2, 2017

Thank man, you rock!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment