Skip to content

Instantly share code, notes, and snippets.

@tomgidden
Created November 30, 2022 13:18
Show Gist options
  • Save tomgidden/d0f3c75a2dd82c9f6f9701fbcf173c71 to your computer and use it in GitHub Desktop.
Save tomgidden/d0f3c75a2dd82c9f6f9701fbcf173c71 to your computer and use it in GitHub Desktop.
Low-dependency bash script to upsert/delete current Droplet public and private IPs in DigitalOcean DNS
#!/bin/bash
STATE=$1
TOKEN=$2
TOKEN=${TOKEN:-$DIGITALOCEAN_TOKEN}
HOSTNAME=$(hostname)
PRIVATE_IP_BASE=10.123.
PRIVATE_DOMAIN=internal.example.com
PUBLIC_DOMAIN=external.example.com
CURL=/usr/bin/curl
function exec_api ()
{
$CURL -sS \
-X $1 -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/domains/$2/records$3"
}
function delete_all_records ()
{
echo "Deleting $1.$2"
HOST=$1
DOMAIN=$2
TO_DELETE=$(exec_api GET $DOMAIN "?name=$HOST.$DOMAIN" | jq -r '.domain_records[]|.id')
if [ ! -z $TO_DELETE ]; then
for ID in $TO_DELETE; do
$CURL -sS \
-X DELETE -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/domains/$DOMAIN/records/$ID"
done
fi
}
function add_a_record ()
{
HOST=$1
DOMAIN=$2
IP=$3
TTL=$4
echo "Adding $1.$2 - $3"
TEMP=$(mktemp)
cat > $TEMP <<-EOF
{
"type": "A",
"name": "$HOST",
"data": "$IP",
"ttl": $TTL
}
EOF
$CURL -sS \
-X POST -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
"https://api.digitalocean.com/v2/domains/$DOMAIN/records" \
-d @$TEMP > /dev/null
rm $TEMP
}
function check () {
echo "Checking $1.$2 -> '$3'"
RESULT=$(exec_api GET $2 "?name=$1.$2" | jq -r '.domain_records[]|.data')
RC=$?
if [ $RC != 0 ]; then
return 1
elif [ "$3" != "$RESULT" ]; then
return 1
else
return 0
fi
}
function check_wc () {
check "$1" $2 $3
C0=$?
check "*.$1" $2 $3
C1=$?
let C=$C0+$C1
return $C
}
function verify_loop () {
echo "Checking $1.$2 -> '$3'"
for C in {1..5}; do
RESULT=$(exec_api GET $2 "?name=$1.$2" | jq -r '.domain_records[]|.data')
RC=$?
if [ $RC != 0 ]; then
>&2 echo "$C: Check failed $1 $2: rc=$RC"
elif [ "$3" != "$RESULT" ]; then
>&2 echo "$C: Check failed $1 $2: '$3' != '$RESULT'"
else
return
fi
sleep $C
done
>&2 echo "Check failed: $1 $2 '$3' != '$RESULT' (rc=$RC)"
exit 1
}
function add_records ()
{
add_a_record "$1" $2 $3 300
add_a_record "*.$1" $2 $3 300
verify_loop "$1" $2 $3
verify_loop "*.$1" $2 $3
}
function delete_records ()
{
delete_all_records $1 $2
delete_all_records "*.$1" $2
verify_loop "$1" $2 ""
verify_loop "*.$1" $2 ""
}
function get_private_ip () {
PRIVATE_IP=$(jq -r '.private_ipv4' /etc/ansible/facts.d/droplet.fact)
if [[ $? != 0 || "$PRIVATE_IP" == "" ]]; then
PRIVATE_IP=$(
ip -j -4 -o addr show dev eth1 |
jq -r "[.[0].addr_info[] | select(.local | startswith(\"$PRIVATE_IP_BASE\")) | .local][0]"
)
fi
}
function get_public_ip () {
PUBLIC_IP=$(jq -r '.public_ipv4' /etc/ansible/facts.d/droplet.fact)
if [[ $? != 0 || "$PUBLIC_IP" == "" ]]; then
PUBLIC_IP=$(
ip -j -4 -o addr show dev eth0 |
jq -r '[.[0].addr_info[] | select(.local | startswith("10.") | not) | .local][0]'
)
fi
}
if [ "present" == "$STATE" ]; then
get_public_ip
if ! check_wc $HOSTNAME $PUBLIC_DOMAIN $PUBLIC_IP; then
delete_records $HOSTNAME $PUBLIC_DOMAIN
add_records $HOSTNAME $PUBLIC_DOMAIN $PUBLIC_IP
fi
get_private_ip
if ! check_wc $HOSTNAME $PRIVATE_DOMAIN $PRIVATE_IP; then
delete_records $HOSTNAME $PRIVATE_DOMAIN
add_records $HOSTNAME $PRIVATE_DOMAIN $PRIVATE_IP
fi
elif [ "absent" == "$STATE" ]; then
delete_records $HOSTNAME $PUBLIC_DOMAIN
delete_records $HOSTNAME $PRIVATE_DOMAIN
else
>&2 cat <<-EOF
Syntax: $0 <present|absent> <digitalocean_token>
EOF
exit 1
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment