93 lines
3.1 KiB
Bash
Executable File
93 lines
3.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# Cloudflare DNS upsert — create or update a DNS record.
|
|
# Usage: CLOUDFLARE_API_TOKEN=xxx ./scripts/cloudflare-dns.sh <zone> <type> <name> <content> [ttl]
|
|
#
|
|
# Examples:
|
|
# cloudflare-dns.sh jimmygan.com A code 161.33.182.109
|
|
# cloudflare-dns.sh jimmygan.com CNAME www jimmygan.com 120
|
|
set -euo pipefail
|
|
|
|
ZONE="${1:?Usage: $0 <zone> <type> <name> <content> [ttl]}"
|
|
TYPE="${2:?}"
|
|
NAME="${3:?}"
|
|
CONTENT="${4:?}"
|
|
TTL="${5:-120}"
|
|
|
|
if [ -z "${CLOUDFLARE_API_TOKEN:-}" ]; then
|
|
echo "❌ CLOUDFLARE_API_TOKEN not set" >&2
|
|
exit 1
|
|
fi
|
|
|
|
API="https://api.cloudflare.com/client/v4"
|
|
AUTH_HEADER="Authorization: Bearer $CLOUDFLARE_API_TOKEN"
|
|
CONTENT_TYPE="Content-Type: application/json"
|
|
|
|
echo "🔍 Looking up zone: $ZONE"
|
|
ZONE_RESP=$(curl -s -H "$AUTH_HEADER" -H "$CONTENT_TYPE" \
|
|
"$API/zones?name=$ZONE&status=active")
|
|
ZONE_ID=$(echo "$ZONE_RESP" | python3 -c "
|
|
import sys, json
|
|
d = json.load(sys.stdin)
|
|
if not d.get('success'):
|
|
print('API error:', d.get('errors'), file=sys.stderr)
|
|
sys.exit(1)
|
|
result = d.get('result', [])
|
|
if not result:
|
|
print('Zone not found:', '$ZONE', file=sys.stderr)
|
|
sys.exit(1)
|
|
print(result[0]['id'])
|
|
")
|
|
|
|
echo "✅ Zone ID: $ZONE_ID"
|
|
|
|
echo "🔍 Checking existing record: $NAME.$ZONE ($TYPE)"
|
|
RECORD_RESP=$(curl -s -H "$AUTH_HEADER" -H "$CONTENT_TYPE" \
|
|
"$API/zones/$ZONE_ID/dns_records?type=$TYPE&name=$NAME.$ZONE")
|
|
RECORD_ID=$(echo "$RECORD_RESP" | python3 -c "
|
|
import sys, json
|
|
d = json.load(sys.stdin)
|
|
if not d.get('success'):
|
|
sys.exit(0) # skip, will create
|
|
result = d.get('result', [])
|
|
if result:
|
|
# Prefer exact content match
|
|
for r in result:
|
|
if r['content'] == '$CONTENT':
|
|
print(r['id'])
|
|
sys.exit(0)
|
|
# Fall back to first match
|
|
print(result[0]['id'])
|
|
")
|
|
|
|
FULL_NAME="$NAME.$ZONE"
|
|
|
|
if [ -n "$RECORD_ID" ]; then
|
|
echo "🔄 Updating existing record ($RECORD_ID): $FULL_NAME → $CONTENT"
|
|
RESP=$(curl -s -X PUT \
|
|
-H "$AUTH_HEADER" -H "$CONTENT_TYPE" \
|
|
-d "{\"type\":\"$TYPE\",\"name\":\"$FULL_NAME\",\"content\":\"$CONTENT\",\"ttl\":$TTL,\"proxied\":false}" \
|
|
"$API/zones/$ZONE_ID/dns_records/$RECORD_ID")
|
|
SUCCESS=$(echo "$RESP" | python3 -c "import sys,json; d=json.load(sys.stdin); print('true' if d.get('success') else 'false')")
|
|
if [ "$SUCCESS" = "true" ]; then
|
|
echo "✅ Updated: $FULL_NAME → $CONTENT"
|
|
else
|
|
echo "❌ Failed to update:" >&2
|
|
echo "$RESP" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('errors'))" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "🆕 Creating new record: $FULL_NAME → $CONTENT"
|
|
RESP=$(curl -s -X POST \
|
|
-H "$AUTH_HEADER" -H "$CONTENT_TYPE" \
|
|
-d "{\"type\":\"$TYPE\",\"name\":\"$FULL_NAME\",\"content\":\"$CONTENT\",\"ttl\":$TTL,\"proxied\":false}" \
|
|
"$API/zones/$ZONE_ID/dns_records")
|
|
SUCCESS=$(echo "$RESP" | python3 -c "import sys,json; d=json.load(sys.stdin); print('true' if d.get('success') else 'false')")
|
|
if [ "$SUCCESS" = "true" ]; then
|
|
echo "✅ Created: $FULL_NAME → $CONTENT"
|
|
else
|
|
echo "❌ Failed to create:" >&2
|
|
echo "$RESP" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('errors'))" >&2
|
|
exit 1
|
|
fi
|
|
fi
|