summaryrefslogtreecommitdiff
path: root/dyndns.bash
blob: 280e2dc2363fd795a75312e347488e268055d283 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#! /bin/bash  

# Work with DigitalOcean api to update "A" record for a domain.
# Store DigitalOcean API token in file : DIGITALOCEAN_TOKEN 
# Store domain to be updated in file : DIGITALOCEAN_DOMAIN 

SCRIPT="${BASH_SOURCE[0]}"
SCRIPT_DIR=$(builtin cd "${SCRIPT%/*}" && pwd )
SCRIPT_NAME=${SCRIPT##*/}

REPEAT_CHECK_DIR=$HOME/repeat_check
REPEAT_CHECK=$REPEAT_CHECK_DIR/$SCRIPT_NAME # file to save argument in if successful

DIGITALOCEAN_DOMAIN=`cat $SCRIPT_DIR/DIGITALOCEAN_DOMAIN`
DIGITALOCEAN_TOKEN=`cat $SCRIPT_DIR/DIGITALOCEAN_TOKEN`

# Get IP from command line if available.  Otherwise use curl to get public IP.
IP=""
if [ "$#" == "1" ]; then
    IP=$1
else
    IP=`curl -4 icanhazip.com 2> /dev/null` 
fi

# If $IP does not look like a valid address then complain and exit.
# For regular expression, thank you to : https://tecadmin.net/shell-script-validate-ipv4-addresses/
if ! [[ $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
    echo Invalid IP address format: $IP
    exit
fi

get_a_record_ids() {
    curl -X GET \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
      "https://api.digitalocean.com/v2/domains/$DIGITALOCEAN_DOMAIN/records" 2> /dev/null | jq '.domain_records |  map(select(.type == "A" and .name == "@")) | map(.id) | .[]'
}

add_a_record() {
    curl -X POST \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
      -d "{\"type\":\"A\"         \
          ,\"name\":\"@\"         \
          ,\"data\":\"$IP\"       \
          ,\"priority\":null      \
          ,\"port\":null          \
          ,\"ttl\":1800           \
          ,\"weight\":null        \
          ,\"flags\":null         \
          ,\"tag\":null           \
          }"                      \
      "https://api.digitalocean.com/v2/domains/$DIGITALOCEAN_DOMAIN/records" 2> /dev/null | jq '.domain_record.id'
}

delete_record_by_id() {
    echo deleting existing A record for $DIGITALOCEAN_DOMAIN
    curl -X DELETE \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
      "https://api.digitalocean.com/v2/domains/$DIGITALOCEAN_DOMAIN/records/$1" > /dev/null 2>&1
}

replace_a_record() {
    for id in `get_a_record_ids`; do
        delete_record_by_id $id
    done

    new_record_id=`add_a_record`
    if [ "$new_record_id" == "null" ] ; then
        echo unable to add new A record for $DIGITALOCEAN_DOMAIN with value : $1
        return 1
    fi
    echo added new A record for $DIGITALOCEAN_DOMAIN with value : $1
}


# exit if previous successful call was with same argument
if [[ -e $REPEAT_CHECK ]]; then
    PREVIOUS_IP=`cat $REPEAT_CHECK`
    if [[ "$IP" ==  "$PREVIOUS_IP" ]]; then
        echo previous update was also with argument: \"$IP\"  so exiting now to avoid duplicate work.
        exit
    fi
fi

# attempt to replace A record and, if successful, save arguments to check against next time
if replace_a_record $IP; then
    # if successful then save arguments.
    echo update worked so saving arguments \"$IP\" in $REPEAT_CHECK
    mkdir -p $REPEAT_CHECK_DIR
    echo "$IP" > $REPEAT_CHECK
fi