Private GIT

Skip to content
Snippets Groups Projects
Unverified Commit fa63bc3b authored by rmarchant's avatar rmarchant Committed by GitHub
Browse files

Merge pull request #13 from DarkGigaByte/master

make ipify api configurable & codestyle
parents f3b2eca3 95bd2663
Branches master
No related tags found
No related merge requests found
......@@ -7,14 +7,15 @@ domain = example.com
# A-record name (@, dev, home, etc) that will be updated
# example is for raspbian.example.com
a_name = raspbian
a_name = raspbian
# TTL (seconds)
ttl = 900
# Production API
api = https://dns.api.gandi.net/api/v5/
gandi_api = https://dns.api.gandi.net/api/v5/
# Number of retries for looking up our own IP address, since
# the service seems to be flaky sometimes.
retries = 3
ipify_api = https://api.ipify.org
......@@ -11,114 +11,121 @@ config_file = "config.txt"
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
DEFAULT_RETRIES = 3
DEFAULT_IPIFY_API = "https://api.ipify.org"
class GandiDdnsError(Exception):
pass
pass
def get_ip_inner():
#Get external IP
def get_ip_inner(ipify_api):
# Get external IP
try:
# Could be any service that just gives us a simple raw ASCII IP address (not HTML etc)
r = requests.get(ipify_api, timeout=3)
except requests.exceptions.RequestException:
raise GandiDdnsError('Failed to retrieve external IP.')
if r.status_code != 200:
raise GandiDdnsError(
'Failed to retrieve external IP.'
' Server responded with status_code: %d' % r.status_code)
ip = r.text.rstrip() # strip \n and any trailing whitespace
if not(ipaddress.IPv4Address(ip)): # check if valid IPv4 address
raise GandiDdnsError('Got invalid IP: ' + ip)
return ip
def get_ip(ipify_api, retries):
# Get external IP with retries
# Start at 5 seconds, double on every retry.
retry_delay_time = 5
for attempt in range(retries):
try:
# Could be any service that just gives us a simple raw ASCII IP address (not HTML etc)
r = requests.get('https://api.ipify.org', timeout=3)
except requests.exceptions.RequestException:
raise GandiDdnsError('Failed to retrieve external IP.')
if r.status_code != 200:
raise GandiDdnsError(
'Failed to retrieve external IP.'
' Server responded with status_code: %d' % r.status_code)
ip = r.text.rstrip() # strip \n and any trailing whitespace
if not(ipaddress.IPv4Address(ip)): # check if valid IPv4 address
raise GandiDdnsError('Got invalid IP: ' + ip)
return ip
def get_ip(retries):
#Get external IP with retries
# Start at 5 seconds, double on every retry.
retry_delay_time = 5
for attempt in range(retries):
try:
return get_ip_inner()
except GandiDdnsError as e:
print('Getting external IP failed: %s' % e)
print('Waiting for %d seconds before trying again' % retry_delay_time)
time.sleep(retry_delay_time)
# Double retry time, cap at 60s.
retry_delay_time = min(60, 2 * retry_delay_time)
return get_ip_inner(ipify_api)
except GandiDdnsError as e:
print('Getting external IP failed: %s' % e)
print('Waiting for %d seconds before trying again' % retry_delay_time)
time.sleep(retry_delay_time)
# Double retry time, cap at 60s.
retry_delay_time = min(60, 2 * retry_delay_time)
print('Exhausted retry attempts')
sys.exit(2)
def read_config(config_path):
#Read configuration file
cfg = configparser.ConfigParser()
cfg.read(config_path)
# Read configuration file
cfg = configparser.ConfigParser()
cfg.read(config_path)
return cfg
return cfg
def get_record(url, headers):
#Get existing record
r = requests.get(url, headers=headers)
# Get existing record
r = requests.get(url, headers=headers)
return r
return r
def update_record(url, headers, payload):
#Add record
r = requests.put(url, headers=headers, json=payload)
if r.status_code != 201:
print(('Record update failed with status code: %d' % r.status_code))
print((r.text))
sys.exit(2)
print ('Zone record updated.')
# Add record
r = requests.put(url, headers=headers, json=payload)
if r.status_code != 201:
print(('Record update failed with status code: %d' % r.status_code))
print((r.text))
sys.exit(2)
print('Zone record updated.')
return r
return r
def main():
path = config_file
if not path.startswith('/'):
path = os.path.join(SCRIPT_DIR, path)
config = read_config(path)
if not config:
sys.exit("Please fill in the 'config.txt' file.")
for section in config.sections():
print('%s - section %s' % (str(datetime.now()), section))
#Retrieve API key
apikey = config.get(section, 'apikey')
#Set headers
headers = { 'Content-Type': 'application/json', 'X-Api-Key': '%s' % config.get(section, 'apikey')}
#Set URL
url = '%sdomains/%s/records/%s/A' % (config.get(section, 'api'), config.get(section, 'domain'), config.get(section, 'a_name'))
print(url)
#Discover External IP
retries = int(config.get(section, 'retries', fallback=DEFAULT_RETRIES))
external_ip = get_ip(retries)
print(('External IP is: %s' % external_ip))
#Prepare record
payload = {'rrset_ttl': config.get(section, 'ttl'), 'rrset_values': [external_ip]}
#Check current record
record = get_record(url, headers)
if record.status_code == 200:
print(('Current record value is: %s' % json.loads(record.text)['rrset_values'][0]))
if(json.loads(record.text)['rrset_values'][0] == external_ip):
print('No change in IP address. Goodbye.')
continue
else:
print('No existing record. Adding...')
update_record(url, headers, payload)
path = config_file
if not path.startswith('/'):
path = os.path.join(SCRIPT_DIR, path)
config = read_config(path)
if not config:
sys.exit("Please fill in the 'config.txt' file.")
for section in config.sections():
print('%s - section %s' % (str(datetime.now()), section))
# Retrieve API key
apikey = config.get(section, 'apikey')
# Set headers
headers = {'Content-Type': 'application/json', 'X-Api-Key': '%s' % apikey}
# Set URL
url = '%sdomains/%s/records/%s/A' % (config.get(section, 'gandi_api'),
config.get(section, 'domain'), config.get(section, 'a_name'))
print(url)
# Discover External IP
ipify_api = config.get(section, 'ipify_api', fallback=DEFAULT_IPIFY_API)
retries = int(config.get(section, 'retries', fallback=DEFAULT_RETRIES))
external_ip = get_ip(ipify_api, retries)
print(('External IP is: %s' % external_ip))
# Prepare record
payload = {'rrset_ttl': config.get(section, 'ttl'), 'rrset_values': [external_ip]}
# Check current record
record = get_record(url, headers)
if record.status_code == 200:
print(('Current record value is: %s' % json.loads(record.text)['rrset_values'][0]))
if(json.loads(record.text)['rrset_values'][0] == external_ip):
print('No change in IP address. Goodbye.')
continue
else:
print('No existing record. Adding...')
update_record(url, headers, payload)
if __name__ == "__main__":
main()
main()
import gandi_ddns as script
import requests
def test_get_ip():
assert script.get_ip() == requests.get("http://ipecho.net/plain?").text
\ No newline at end of file
assert script.get_ip("https://api.ipify.org", 3) == requests.get("http://ipecho.net/plain?").text
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment