Created
November 30, 2022 13:18
-
-
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
This file contains 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 | |
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