-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
135 lines (108 loc) · 4.78 KB
/
main.py
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import logging
import logging.handlers as handlers
import os
import sys
import requests
import validators
from dotenv import load_dotenv
# logging configuration
logger = logging.getLogger('netlify_ddns')
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logHandler = handlers.TimedRotatingFileHandler('netlify_ddns.log', when='D', interval=1, backupCount=2)
logHandler.setLevel(logging.INFO)
logHandler.setFormatter(formatter)
logger.addHandler(logHandler)
# load .env and FQDN validation
try:
load_dotenv()
FQDN = os.environ.get('FQDN')
API_TOKEN = os.environ.get('NETLIFY_API_TOKEN')
if len(FQDN.split('.')) > 3 or not validators.domain(FQDN):
logger.error('Provided hostname \' {} \' is not a valid FQDN'.format(FQDN))
sys.exit(1)
except Exception as e:
logger.error('Unexpected error trying to retrieve required variables from .env file. Cause: ' + e.__str__())
sys.exit(1)
# constants
PUBLIC_IP_URI = 'https://api.bigdatacloud.net/data/client-ip'
DNS_ZONES_URI = 'https://api.netlify.com/api/v1/dns_zones/'
DEFAULT_TTL = 600
headers = {
'Content-Type': 'application/json;charset=utf-8',
'Authorization': 'Bearer ' + API_TOKEN
}
# get current public IP address
def get_public_ip_address():
try:
logger.debug('HTTP GET to {}'.format(PUBLIC_IP_URI))
public_ip_address = requests.get(PUBLIC_IP_URI, timeout=15).json()['ipString']
logger.info('System current public IP address is: {}'.format(public_ip_address))
return public_ip_address
except Exception as ex:
logger.error('An error occurred trying to retrieve your public IP address. Cause: {}'.format(ex.__str__()))
sys.exit(1)
# creating new dns record
def create_dns_record(hostname, value):
req_url = DNS_ZONES_URI + FQDN.split('.')[-2] + '_' + FQDN.split('.')[-1] + '/dns_records'
body = {
'type': "A",
'hostname': hostname,
'value': value,
'ttl': DEFAULT_TTL,
'priority': None,
'weight': None,
'port': None,
'flag': None,
'tag': None
}
try:
res = requests.post(req_url, json=body, headers=headers, timeout=15)
if res.status_code != 201:
logger.error('An error occurred trying to create new DNS record. Response status code: {}'.format(res.status_code))
sys.exit(1)
elif res.status_code == 201:
logger.info('New DNS record created successfully for hostname: {}, with value: {}'.format(hostname, value))
return res.json()
except Exception as ex:
logger.error('An error occurred trying to create new DNS record. Cause: {}'.format(ex.__str__()))
sys.exit(1)
def delete_dns_record(dns_record_id):
req_url = DNS_ZONES_URI + FQDN.split('.')[-2] + '_' + FQDN.split('.')[-1] + '/dns_records/' + dns_record_id
try:
res = requests.delete(req_url, headers=headers, timeout=15)
if res.status_code != 204:
logger.error('An error occurred trying to delete the old DNS record. Response status code: {}'.format(res.status_code))
sys.exit(1)
elif res.status_code == 204:
logger.info('Old DNS record with ID {} deleted successfully'.format(dns_record_id))
except Exception as ex:
logger.error('An error occurred trying to delete old DNS record with ID {}. Cause: {}'.format(dns_record_id, ex.__str__()))
sys.exit(1)
def get_dns_records():
req_url = DNS_ZONES_URI + FQDN.split('.')[-2] + '_' + FQDN.split('.')[-1] + '/dns_records'
try:
return requests.get(req_url, headers=headers).json()
except Exception as ex:
logger.error('An error occurred trying to fetch all DNS records. Cause: {}'.format(ex.__str__()))
def extract_target_record_id(records):
for record in records:
if FQDN == record['hostname'] and 'A' == record['type']:
return record['id'], record['value']
return None, None
if __name__ == '__main__':
logger.info('----- Executing netlify_ddns -----')
current_public_ip = get_public_ip_address()
# fetch all dns records
records_list = get_dns_records()
# check if a DNS A record already exists for the provided FQDN
record_id, record_ip = extract_target_record_id(records_list)
if record_id is None: # create a new record
new_dns_record = create_dns_record(FQDN, current_public_ip)
elif (record_id is not None) and (current_public_ip != record_ip): # create new record and delete the old one
new_dns_record = create_dns_record(FQDN, current_public_ip)
delete_dns_record(record_id)
else:
logger.info('DNS record already present with correct IP for the hostname: {}'.format(FQDN))
logger.info('----- Script executed successfully -----')
sys.exit(0)