-
Notifications
You must be signed in to change notification settings - Fork 2
/
digitalocean-dyndns
executable file
·118 lines (95 loc) · 3.39 KB
/
digitalocean-dyndns
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
Digital Ocean DynDNS
Dynamic DNS updater for Digital Ocean API v2
Copyright (c) 2014 Frédéric Massart - FMCorz.net
Licensed under The MIT License
Redistributions of files must retain the above copyright notice.
http://github.com/FMCorz/digitalocean-dyndns
"""
import sys
import requests
import argparse
import logging
import json
TOKEN = 'X'
API = 'https://api.digitalocean.com/v2'
# Error codes
DOMAIN_NOT_FOUND = 1
RECORD_NOT_FOUND = 2
REQUEST_ERROR = 4
IP_FETCH_FAILED = 8
def getIp():
"""Return the external IPv4"""
r = requests.get('https://api.ipify.org')
if r.status_code != 200:
logging.error('Could not obtain IP from external resource')
sys.exit(IP_FETCH_FAILED)
return r.text
def request(uri, params={}, method='GET'):
"""Perform a request on Digital Ocean API"""
url = API + '/' + uri.strip('/')
headers = {
'Authorization': 'Bearer {0}'.format(TOKEN)
}
logging.debug('Requesting: %s (%s)' % (url, method))
if method == 'POST':
r = requests.post(url, headers=headers, data=params)
elif method == 'PUT':
r = requests.put(url, headers=headers, data=params)
else:
r = requests.get(url, params=params, headers=headers)
if r.status_code < 200 or r.status_code >= 300:
logging.error(u'Host replied with a non-OK status. Error: %s' % r.status_code)
sys.exit(REQUEST_ERROR)
return r.json()
# Define arguments
parser = argparse.ArgumentParser(description='Dynamic DNS updater for Digital Ocean')
parser.add_argument('--domain', '-d', help='Domain name', required=True)
parser.add_argument('--record', '-r', help='Record for domain', required=True)
parser.add_argument('--allownew', '-c', help='Allow creation of a new record', action='store_true')
parser.add_argument('--verbose', '-v', help='Increase verbosity', action='count', default=0)
args = parser.parse_args()
# Verbosity level
if args.verbose >= 2:
debug = logging.DEBUG
elif args.verbose == 1:
debug = logging.INFO
else:
debug = logging.WARNING
logging.basicConfig(format='%(message)s', level=debug)
# Looking up the records
recordId = None
records = request('/domains/{0}/records'.format(args.domain))
for record in records.get('domain_records'):
if record.get('type') == 'A' and record.get('name') == args.record:
recordId = record.get('id')
logging.info('Found record %s, ID: %s' % (args.record, recordId))
break
# Create the record if it does not exist
if not recordId:
if not args.allownew:
logging.warning('Could not find the A record %s for domain %s' % (args.record, args.domain))
sys.exit(RECORD_NOT_FOUND)
ip = getIp()
params = {
'type': 'A',
'name': args.record,
'data': ip
}
result = request('/domains/{0}/records'.format(args.domain), params=params, method='POST')
logging.info('Record created with ID %s using IP %s' % (result.get('domain_record', {}).get('id', '<?>'), ip))
# Update the existing record
else:
ip = getIp()
if record.get('data') == ip:
logging.info('No update required')
else:
params = {
'type': 'A',
'name': args.record,
'data': ip
}
result = request('/domains/{0}/records/{1}'.format(args.domain, recordId), params=params, method="PUT")
logging.info('Updated record with IP %s' % (ip))