Inspired by a shell script I saw on Github, I put together a Python version to update the dynamic IP address for a subdomain I have that uses DigitalOcean's nameservers. I added a check to see if the IP address actually needs to be updated, and not do the update if the IP address hasn't changed. All of the user-configurable variables - API token, domain, subdomain - are stored in a separate .env
file alongside the script.
#!/usr/bin/env python3
# Import required modules
import dotenv
import json
import os
import requests
# Load user-configured variables from .env file
dotenv.load_dotenv()
token = os.environ.get('DO_API_TOKEN')
domain = os.environ.get('DO_DOMAIN')
subdomain = os.environ.get('DO_SUBDOMAIN')
# Other variables
check_ip_url = 'https://api.ipify.org'
do_api_url = 'https://api.digitalocean.com/v2/domains/'
# Get the current external IP
def get_current_ip():
curr_ip = requests.get(check_ip_url).text.rstrip()
return curr_ip
# Get the current subdomain IP
def get_sub_info():
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
}
response = requests.get(do_api_url + domain + '/records', headers=headers).text
records = json.loads(response)
for record in records['domain_records']:
if record['name'] == subdomain:
subdomain_info = {
'ip': record['data'],
'record_id': record['id']
}
return subdomain_info
# Update DNS records if required
def update_dns():
current_ip_address = get_current_ip()
subdomain_ip_address = get_sub_info()['ip']
subdomain_record_id = get_sub_info()['record_id']
if current_ip_address == subdomain_ip_address:
print('Subdomain DNS record does not need updating.')
return
else:
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
}
data = '{"data":"' + current_ip_address + '"}'
response = requests.put(do_api_url + domain + '/records/' + subdomain_record_id, headers=headers, data=data)
if '200' in response:
print('Subdomain IP address updated to ' + current_ip_address)
else:
print('IP address update failed with message: ' + response.text)
return
if __name__ == '__main__':
update_dns()
It works, but isn't the prettiest Python code out there, and I'm sure if could be made a bit more efficient. Are there any stylistic changes I should make to better adhere to best practices? I have run it through a PEP8 checker, and the only thing it brought up was about the line length in a few places, which I'm not super concerned about.