Skip to content

Instantly share code, notes, and snippets.

@Luit
Created July 23, 2018 19:58
Show Gist options
  • Save Luit/5c7e2c31718f84ec709c7a21838adbe8 to your computer and use it in GitHub Desktop.
Save Luit/5c7e2c31718f84ec709c7a21838adbe8 to your computer and use it in GitHub Desktop.
Run with EXEC_PATH=/path/to/netlify-dns.sh and a file in the same directory called netlify-dns.sh.token containing a personal access token from https://app.netlify.com/account/applications/personal
#!/bin/bash
set -e
set -o pipefail
# Sanity checks to fail early.
command -V jq >/dev/null
command -V curl >/dev/null
if [ $# -ne 4 ]; then
>&2 printf "expected 4 arguments, got %d\\n" "$#"
exit 2
fi
TOKEN=$(cat "$0.token")
ACTION=$1
FQDN=${2%.} # Stripping the trailing dot.
VALUE=$3
TTL=$4
BASE_URL="https://api.netlify.com/api/v1/dns_zones"
CURL_OPTS=(--header "Accept: application/json")
CURL_OPTS+=(--header "Content-Type: application/json")
CURL_OPTS+=(--header "Authorization: Bearer $TOKEN")
ZONEFILTER=".[] | . as \$r | select(\$fqdn|endswith(\$r.name)).id"
if ! zone=$(curl -fs "${CURL_OPTS[@]}" $BASE_URL | jq --arg fqdn "$FQDN" -r "$ZONEFILTER"); then
>&2 echo "Failed to lookup zone."
exit 1
fi
if [ -z "$zone" ]; then
>&2 printf "No zone found for %s\\n" "$FQDN"
exit 1
fi
if ! records=$(curl -fs "${CURL_OPTS[@]}" "$BASE_URL/$zone/dns_records" | jq -c .); then
>&2 printf "Failed to fetch records for zone %s.\\n" "$zone"
exit 1
fi
if ! fqdn_records=$(echo "$records" | jq -c --arg fqdn "$FQDN" '.[] | select(.hostname == $fqdn)'); then
>&2 echo "Failed to filter \$fqdn_records."
>&2 printf "Input was %s\\n" "$records"
exit 1
fi
if ! txt_records=$(echo "$fqdn_records" | jq -c 'select(.type == "TXT")'); then
>&2 echo "Failed to filter for \$txt_records."
>&2 printf "Input was %s\\n" "$fqdn_records"
exit 1
fi
if ! record=$(echo "$txt_records" | jq -r --arg value "$VALUE" 'select(.value == $value).id'); then
>&2 echo "Failed to filter for \$record"
>&2 printf "Input was %s\\n" "$txt_records"
exit 1
fi
function notempty {
if [ -z "$1" ]; then
>&2 echo "$2"
exit 1
fi
}
case "$ACTION" in
"present")
if [ ! -z "$record" ]; then
printf "The TXT record for %s with value %s already exists. Doing nothing.\\n" "$FQDN" "$VALUE"
exit 0
fi
printf "Creating record for %s with value %s.\\n" "$FQDN" "$VALUE"
DATA=$(printf '{"hostname": "%s", "ttl": %d, "type": "TXT", "value": "%s"}' "$FQDN" "$TTL" "$VALUE")
if ! curl -fs "${CURL_OPTS[@]}" "$BASE_URL/$zone/dns_records" -X POST --data "$DATA" | jq -c .; then
>&2 printf "Failed to create TXT record for %s with value %s.\\n" "$FQDN" "$VALUE"
exit 1
fi
;;
"cleanup")
notempty "$fqdn_records" "$(printf "No records found for fqdn %s\\n" "$FQDN")"
notempty "$txt_records" "$(printf "No TXT records found for fqdn %s\\n" "$FQDN")"
notempty "$record" "$(printf "The TXT records for %s did not contain value %s\\n" "$FQDN" "$VALUE")"
printf "Removing record for %s with value %s.\\n" "$FQDN" "$VALUE"
if ! curl -fs "${CURL_OPTS[@]}" "$BASE_URL/$zone/dns_records/$record" -X DELETE | jq -c .; then
>&2 printf "Failed to delete the TXT record for %s with value %s.\\n" "$FQDN" "$VALUE"
exit 1
fi
printf "Sleeping for %d seconds to wait for caches to clear.\\n" "$TTL"
sleep "$TTL"
sleep 5 # for good measure
;;
*)
>&2 printf "Invalid action %s.\\n" "$ACTION"
exit 2
esac
@Luit
Copy link
Author

Luit commented Jul 23, 2018

This bash script comes with NO WARRANTY, don't use this against Netlify accounts you care about.

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