Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python3 support #9

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 112 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,112 @@
src/config.py
src/config.pyc
## From https://raw.githubusercontent.com/github/gitignore/master/Python.gitignore

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
.static_storage/
.media/
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/

# Custom

config.py
test.py
.vscode/
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"python.linting.pylintEnabled": false
}
2 changes: 0 additions & 2 deletions src/.gitignore

This file was deleted.

41 changes: 40 additions & 1 deletion src/example.config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,49 @@
+ <?php $ip = $_SERVER['REMOTE_ADDR']; ?>
<?php print $ip; ?>
e.g.
+ https://ifconfig.co
+ https://ifconfig.co/ip
+ http://ifconfig.me/ip
+ http://whatismyip.akamai.com/
+ http://ipinfo.io/ip
+ many more ...
'''
ifconfig = 'choose_from_above_or_run_your_own'


'''
Sample logging config
This is optmized for *nix
Permission are needed to write the log file
'''
log_config = {
'version': 1,
'formatters': {
'detailed': {
'class': 'logging.Formatter',
'format': '%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s'
},
'simple': {
'class': 'logging.Formatter',
'format': '%(message)s'
}
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'simple',
},
'file': {
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': '/var/log/gandi-live-dns.log',
'when': 'W6',
'backupCount': '3',
'formatter': 'detailed',
},
},
'loggers': {
'gandi-live-dns': {
'level': 'DEBUG',
'handlers': ['console', 'file']
},
},
}
63 changes: 36 additions & 27 deletions src/gandi-live-dns.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,24 @@
http://doc.livedns.gandi.net/#api-endpoint -> https://dns.beta.gandi.net/api/v5/
'''

import requests, json
import json
import logging
import logging.config
import requests
import config
import argparse

logging.config.dictConfig(config.log_config)
log = logging.getLogger('gandi-live-dns')

def get_dynip(ifconfig_provider):
''' find out own IPv4 at home <-- this is the dynamic IP which changes more or less frequently
similar to curl ifconfig.me/ip, see example.config.py for details to ifconfig providers
'''
log.debug('Using ifconfig_provider {}'.format(ifconfig_provider))
r = requests.get(ifconfig_provider)
print 'Checking dynamic IP: ' , r._content.strip('\n')
return r.content.strip('\n')
log.info('Checking dynamic IP: {}'.format(r.text.strip('\n')))
return r.text.strip('\n')

def get_uuid():
'''
Expand All @@ -33,13 +39,14 @@ def get_uuid():

'''
url = config.api_endpoint + '/domains/' + config.domain
log.debug('Using url {}'.format(url))
u = requests.get(url, headers={"X-Api-Key":config.api_secret})
json_object = json.loads(u._content)
json_object = u.json()
if u.status_code == 200:
return json_object['zone_uuid']
else:
print 'Error: HTTP Status Code ', u.status_code, 'when trying to get Zone UUID'
print json_object['message']
log.error('Error: HTTP Status Code {} when trying to get Zone UUID'.format(u.status_code))
log.error('{}'.format(json_object['message']))
exit()

def get_dnsip(uuid):
Expand All @@ -52,15 +59,17 @@ def get_dnsip(uuid):
'''

url = config.api_endpoint+ '/zones/' + uuid + '/records/' + config.subdomains[0] + '/A'
log.debug('Using url {}'.format(url))
headers = {"X-Api-Key":config.api_secret}
log.debug('Using headers {}'.format(headers))
u = requests.get(url, headers=headers)
if u.status_code == 200:
json_object = json.loads(u._content)
print 'Checking IP from DNS Record' , config.subdomains[0], ':', json_object['rrset_values'][0].encode('ascii','ignore').strip('\n')
return json_object['rrset_values'][0].encode('ascii','ignore').strip('\n')
json_object = u.json()
log.info('Checking IP from DNS Record {} : {}'.format(config.subdomains[0], json_object['rrset_values'][0].strip('\n')))
return json_object['rrset_values'][0].strip('\n')
else:
print 'Error: HTTP Status Code ', u.status_code, 'when trying to get IP from subdomain', config.subdomains[0]
print json_object['message']
log.error('Error: HTTP Status Code {} when trying to get IP from subdomain {}'.format(u.status_code, config.subdomains[0]))
log.error('{}'.format(json_object['message']))
exit()

def update_records(uuid, dynIP, subdomain):
Expand All @@ -74,57 +83,57 @@ def update_records(uuid, dynIP, subdomain):
https://dns.beta.gandi.net/api/v5/zones/<UUID>/records/<NAME>/<TYPE>
'''
url = config.api_endpoint+ '/zones/' + uuid + '/records/' + subdomain + '/A'
log.debug('Using url {}'.format(url))
payload = {"rrset_ttl": config.ttl, "rrset_values": [dynIP]}
log.debug('Using payload {}'.format(payload))
headers = {"Content-Type": "application/json", "X-Api-Key":config.api_secret}
log.debug('Using headers {}'.format(headers))
u = requests.put(url, data=json.dumps(payload), headers=headers)
json_object = json.loads(u._content)
json_object = u.json()

if u.status_code == 201:
print 'Status Code:', u.status_code, ',', json_object['message'], ', IP updated for', subdomain
log.info('Status Code: {}, {}, IP updated for {}'.format(u.status_code, json_object['message'], subdomain))
return True
else:
print 'Error: HTTP Status Code ', u.status_code, 'when trying to update IP from subdomain', subdomain
print json_object['message']
log.error('Error: HTTP Status Code {} when trying to update IP from subdomain {}'.format(u.status_code, subdomain))
log.error('{}'.format(json_object['message']))
exit()



def main(force_update, verbosity):

if verbosity:
print "verbosity turned on - not implemented by now"
log.setLevel(logging.DEBUG)
log.debug('Verbosity On')


#get zone ID from Account
uuid = get_uuid()
log.debug('uuid: {}'.format(uuid))

#compare dynIP and DNS IP
dynIP = get_dynip(config.ifconfig)
dnsIP = get_dnsip(uuid)
log.debug('dynIP: {}, dnsIP: {}'.format(dynIP, dnsIP))

if force_update:
print "Going to update/create the DNS Records for the subdomains"
log.info("Going to update/create the DNS Records for the subdomains")
for sub in config.subdomains:
log.debug('Forcing update on {}'.format(sub))
update_records(uuid, dynIP, sub)
else:
if dynIP == dnsIP:
print "IP Address Match - no further action"
log.info("IP Address Match - no further action")
else:
print "IP Address Mismatch - going to update the DNS Records for the subdomains with new IP", dynIP
log.info("IP Address Mismatch - going to update the DNS Records for the subdomains with new IP", dynIP)
for sub in config.subdomains:
log.debug('Updating on {}'.format(sub))
update_records(uuid, dynIP, sub)

if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose', help="increase output verbosity", action="store_true")
parser.add_argument('-f', '--force', help="force an update/create", action="store_true")
args = parser.parse_args()


main(args.force, args.verbose)