Compare commits
9 commits
1f59fcf8db
...
b70621b018
Author | SHA1 | Date | |
---|---|---|---|
b70621b018 | |||
fcb18989b9 | |||
e0b7e598e0 | |||
d504a6a177 | |||
cf926700e4 | |||
0714cbce8a | |||
b55e96d78c | |||
d46419ef3d | |||
c1fd36d383 |
132
.gitignore
vendored
132
.gitignore
vendored
|
@ -1,2 +1,134 @@
|
||||||
|
# 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/
|
||||||
|
pip-wheel-metadata/
|
||||||
|
share/python-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/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# 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/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# Custom
|
||||||
|
|
||||||
src/config.py
|
src/config.py
|
||||||
src/config.pyc
|
src/config.pyc
|
||||||
|
|
17
.project
17
.project
|
@ -1,17 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>gandi_live_dns</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.python.pydev.PyDevBuilder</name>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.python.pydev.pythonNature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<?eclipse-pydev version="1.0"?><pydev_project>
|
|
||||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
|
||||||
<path>/${PROJECT_DIR_NAME}/src</path>
|
|
||||||
</pydev_pathproperty>
|
|
||||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
|
|
||||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
|
||||||
</pydev_project>
|
|
13
Dockerfile
Normal file
13
Dockerfile
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
FROM python:3.7-buster
|
||||||
|
|
||||||
|
LABEL maintainer=david@dme.ninja
|
||||||
|
LABEL version="0.1"
|
||||||
|
|
||||||
|
# Copy scripts and requirements.txt
|
||||||
|
COPY src/ /gandi-live-dns
|
||||||
|
COPY requirements.txt /requirements.txt
|
||||||
|
|
||||||
|
# Install script requirements.txt
|
||||||
|
RUN pip install -r /requirements.txt
|
||||||
|
|
||||||
|
CMD ["python", "/gandi-live-dns/gandi-live-dns.py", "-v", "-r", "3600"]
|
28
README.md
28
README.md
|
@ -4,7 +4,9 @@ gandi-live-dns
|
||||||
This is a simple dynamic DNS updater for the
|
This is a simple dynamic DNS updater for the
|
||||||
[Gandi](https://www.gandi.net) registrar. It uses their [LiveDNS REST API](http://doc.livedns.gandi.net/) to update the zone file for a subdomain of a domain to point at the external IPv4 address of the computer it has been run from.
|
[Gandi](https://www.gandi.net) registrar. It uses their [LiveDNS REST API](http://doc.livedns.gandi.net/) to update the zone file for a subdomain of a domain to point at the external IPv4 address of the computer it has been run from.
|
||||||
|
|
||||||
It has been developed on Debian 8 Jessie and tested on Debian 9 Stretch GNU/Linux using Python 2.7.
|
~~It has been developed on Debian 8 Jessie and tested on Debian 9 Stretch GNU/Linux using Python 2.7.~~
|
||||||
|
|
||||||
|
This has been update to work with Python 3 (Python 3.6 at Ubuntu 18.04). This will not work with Python 2 since it ~~will be deprecated in~~ is deprecated since 2020-01-01.
|
||||||
|
|
||||||
With the new v5 Website, Gandi has also launched a new REST API which makes it easier to communicate via bash/curl or python/requests.
|
With the new v5 Website, Gandi has also launched a new REST API which makes it easier to communicate via bash/curl or python/requests.
|
||||||
|
|
||||||
|
@ -22,7 +24,10 @@ https://account.gandi.net/en/ and apply for (at least) the production API
|
||||||
key by following their directions.
|
key by following their directions.
|
||||||
|
|
||||||
#### A DNS Record
|
#### A DNS Record
|
||||||
Create the DNS A Records in the GANDI Webinterface which you want to update if your IP changes.
|
Create the DNS A Records in the GANDI Webinterface which you want to update if your IPv4 changes.
|
||||||
|
|
||||||
|
#### AAAA DNS Record (only needed if ipv6 is in use)
|
||||||
|
Create the DNS AAAA Records for ipv6 in the GANDI Webinterface which you want to update if your IPv6 changes.
|
||||||
|
|
||||||
#### Git Clone or Download the Script
|
#### Git Clone or Download the Script
|
||||||
Download the Script from here as [zip](https://github.com/cavebeat/gandi-live-dns/archive/master.zip)/[tar.gz](https://github.com/cavebeat/gandi-live-dns/archive/master.tar.gz) and extract it.
|
Download the Script from here as [zip](https://github.com/cavebeat/gandi-live-dns/archive/master.zip)/[tar.gz](https://github.com/cavebeat/gandi-live-dns/archive/master.tar.gz) and extract it.
|
||||||
|
@ -56,10 +61,16 @@ Your domain for the subdomains to be updated
|
||||||
##### subdomains
|
##### subdomains
|
||||||
All subdomains which should be updated. They get created if they do not yet exist.
|
All subdomains which should be updated. They get created if they do not yet exist.
|
||||||
|
|
||||||
|
* `subdomains` for ipv4
|
||||||
|
* `subdomains6` for ipv6
|
||||||
|
|
||||||
```
|
```
|
||||||
subdomains = ["subdomain1", "subdomain2", "subdomain3"]
|
subdomains = ["subdomain1", "subdomain2", "subdomain3"]
|
||||||
|
subdomains6 = ["subdomain1v6", "subdomain2v6", "subdomain3v6"]
|
||||||
```
|
```
|
||||||
|
|
||||||
The first subdomain is used to find out the actual IP in the Zone Records.
|
The first subdomain is used to find out the actual IP in the Zone Records.
|
||||||
|
If the returnded ip from is ipv6, it will use the first from subdomains6.
|
||||||
|
|
||||||
#### Run the script
|
#### Run the script
|
||||||
And run the script:
|
And run the script:
|
||||||
|
@ -88,12 +99,14 @@ Status Code: 201 , DNS Record Created , IP updated for subdomain3
|
||||||
|
|
||||||
```
|
```
|
||||||
root@dyndns:~/gandi-live-dns-master/src# ./gandi-live-dns.py -h
|
root@dyndns:~/gandi-live-dns-master/src# ./gandi-live-dns.py -h
|
||||||
usage: gandi-live-dns.py [-h] [-f]
|
usage: gandi-live-dns.py [-h] [-f] [-v] [-r]
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
|
-v, --verbose increase output verbosity
|
||||||
-f, --force force an update/create
|
-f, --force force an update/create
|
||||||
|
-r REPEAT, --repeat REPEAT
|
||||||
|
keep running and repeat every N seconds
|
||||||
```
|
```
|
||||||
|
|
||||||
The force option runs the script, even when no IP change has been detected.
|
The force option runs the script, even when no IP change has been detected.
|
||||||
|
@ -124,12 +137,17 @@ Run the script every five minutes.
|
||||||
```
|
```
|
||||||
*/5 * * * * /root/gandi-live-dns-master/src/gandi-live-dns.py >/dev/null 2>&1
|
*/5 * * * * /root/gandi-live-dns-master/src/gandi-live-dns.py >/dev/null 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Run with Docker
|
||||||
|
|
||||||
|
Use the docker file to build the image. With docker, the script will run every 3600 seconds. (This value can be changed in the Dockerfile.
|
||||||
|
|
||||||
### Limitations
|
### Limitations
|
||||||
The XML-RPC API has a limit of 30 requests per 2 seconds, so i guess it's safe to update 25 subdomains at once with the REST API.
|
The XML-RPC API has a limit of 30 requests per 2 seconds, so i guess it's safe to update 25 subdomains at once with the REST API.
|
||||||
|
|
||||||
|
|
||||||
### Upcoming Features
|
### Upcoming Features
|
||||||
* command line Argument for verbose mode
|
* ~~command line Argument for verbose mode~~ Aditional verbosity implemented.
|
||||||
|
|
||||||
### Inspiration
|
### Inspiration
|
||||||
|
|
||||||
|
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
requests
|
|
@ -20,12 +20,22 @@ https://dns.api.gandi.net/api/v5/
|
||||||
'''
|
'''
|
||||||
api_endpoint = 'https://dns.api.gandi.net/api/v5'
|
api_endpoint = 'https://dns.api.gandi.net/api/v5'
|
||||||
|
|
||||||
|
#your domain with the subdomains in the zone file/UUID
|
||||||
|
domain = 'mydomain.tld'
|
||||||
|
|
||||||
|
#enter all subdomains to be updated, subdomains must already exist to be updated
|
||||||
#your domain and subdomains to be updated, subdomains must already exist to be updated
|
#your domain and subdomains to be updated, subdomains must already exist to be updated
|
||||||
dnsentries = {
|
dnsentries = {
|
||||||
"mydomain.tld": ["subdomain1", "subdomain2"],
|
"mydomain.tld": {
|
||||||
"myotherdomain.tld": ["subdomain3"],
|
"ipv4": ["subdomain1", "subdomain2"],
|
||||||
|
"ipv6": ["subdomain3v6"],
|
||||||
|
},
|
||||||
|
"myotherdomain.tld": {
|
||||||
|
"ipv4": ["subdomain4"],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#300 seconds = 5 minutes
|
#300 seconds = 5 minutes
|
||||||
ttl = '300'
|
ttl = '300'
|
||||||
|
|
||||||
|
@ -36,10 +46,15 @@ run your own external IP provider:
|
||||||
+ <?php $ip = $_SERVER['REMOTE_ADDR']; ?>
|
+ <?php $ip = $_SERVER['REMOTE_ADDR']; ?>
|
||||||
<?php print $ip; ?>
|
<?php print $ip; ?>
|
||||||
e.g.
|
e.g.
|
||||||
+ https://ifconfig.co
|
+ https://api[4|6].ipify.org
|
||||||
|
+ https://ifconfig.co/ip
|
||||||
+ http://ifconfig.me/ip
|
+ http://ifconfig.me/ip
|
||||||
+ http://whatismyip.akamai.com/
|
+ http://whatismyip.akamai.com/
|
||||||
+ http://ipinfo.io/ip
|
+ http://ipinfo.io/ip
|
||||||
+ many more ...
|
+ many more ...
|
||||||
'''
|
'''
|
||||||
ifconfig = 'choose_from_above_or_run_your_own'
|
ifconfig = 'choose_from_above_or_run_your_own'
|
||||||
|
ifconfig = {
|
||||||
|
"ipv4": 'choose_from_above_or_run_your_own_ipv4_lookup_service',
|
||||||
|
"ipv6": 'choose_from_above_or_run_your_own_ipv6_lookup_service',
|
||||||
|
}
|
||||||
|
|
|
@ -1,48 +1,61 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
'''
|
'''
|
||||||
Gandi v5 LiveDNS - DynDNS Update via REST API and CURL/requests
|
Gandi v5 LiveDNS - DynDNS Update via REST API and CURL/requests
|
||||||
|
|
||||||
@author: cave
|
@author: cave
|
||||||
|
@author: dvdme
|
||||||
License GPLv3
|
License GPLv3
|
||||||
https://www.gnu.org/licenses/gpl-3.0.html
|
https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
Created on 13 Aug 2017
|
Created on 13 Aug 2017
|
||||||
|
Forked on 08 Dec 2019
|
||||||
http://doc.livedns.gandi.net/
|
http://doc.livedns.gandi.net/
|
||||||
http://doc.livedns.gandi.net/#api-endpoint -> https://dns.gandi.net/api/v5/
|
http://doc.livedns.gandi.net/#api-endpoint -> https://dns.gandi.net/api/v5/
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import requests, json
|
import json
|
||||||
|
import requests
|
||||||
|
import ipaddress
|
||||||
import config
|
import config
|
||||||
import argparse
|
import argparse
|
||||||
|
import threading as th
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
def get_dynip(ifconfig_provider):
|
def check_is_ipv6(ip_address, verbose=False):
|
||||||
|
return ipaddress.ip_address(ip_address).version == 6
|
||||||
|
|
||||||
|
|
||||||
|
def get_dynip(ifconfig_provider, verbose=False):
|
||||||
''' find out own IPv4 at home <-- this is the dynamic IP which changes more or less frequently
|
''' 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
|
similar to curl ifconfig.me/ip, see example.config.py for details to ifconfig providers
|
||||||
'''
|
'''
|
||||||
|
if verbose:
|
||||||
|
print(f'Using {ifconfig_provider}')
|
||||||
r = requests.get(ifconfig_provider)
|
r = requests.get(ifconfig_provider)
|
||||||
print('Checking dynamic IP: ' , r.text.strip('\n'))
|
print (f'Checking dynamic IP: {r.text.strip()}')
|
||||||
return r.text.strip('\n')
|
return r.text.strip()
|
||||||
|
|
||||||
def get_uuid():
|
def get_uuid(verbose=False):
|
||||||
'''
|
'''
|
||||||
find out ZONE UUID from domain
|
find out ZONE UUID from domain
|
||||||
Info on domain "DOMAIN"
|
Info on domain "DOMAIN"
|
||||||
GET /domains/<DOMAIN>:
|
GET /domains/<DOMAIN>:
|
||||||
|
|
||||||
'''
|
'''
|
||||||
url = config.api_endpoint + '/domains/' + config.domain
|
url = config.api_endpoint + '/domains/' + config.domain
|
||||||
u = requests.get(url, headers={"X-Api-Key":config.api_secret})
|
u = requests.get(url, headers={"X-Api-Key":config.api_secret})
|
||||||
json_object = json.loads(u._content)
|
json_object = u.json()
|
||||||
|
if verbose:
|
||||||
|
pprint(json_object)
|
||||||
if u.status_code == 200:
|
if u.status_code == 200:
|
||||||
return json_object['zone_uuid']
|
return json_object['zone_uuid']
|
||||||
else:
|
else:
|
||||||
print('Error: HTTP Status Code ', u.status_code, 'when trying to get Zone UUID')
|
print(f'Error: HTTP Status Code {u.status_code} when trying to get Zone UUID')
|
||||||
print(json_object['message'])
|
pprint(u.json())
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
def get_dnsip(uuid):
|
def get_dnsip(uuid, is_ipv6=False, verbose=False):
|
||||||
''' find out IP from first Subdomain DNS-Record
|
''' find out IP from first Subdomain DNS-Record
|
||||||
List all records with name "NAME" and type "TYPE" in the zone UUID
|
List all records with name "NAME" and type "TYPE" in the zone UUID
|
||||||
GET /zones/<UUID>/records/<NAME>/<TYPE>:
|
GET /zones/<UUID>/records/<NAME>/<TYPE>:
|
||||||
|
@ -50,20 +63,28 @@ def get_dnsip(uuid):
|
||||||
The first subdomain from config.subdomain will be used to get
|
The first subdomain from config.subdomain will be used to get
|
||||||
the actual DNS Record IP
|
the actual DNS Record IP
|
||||||
'''
|
'''
|
||||||
|
if is_ipv6:
|
||||||
|
record_type = '/AAAA'
|
||||||
|
else:
|
||||||
|
record_type = '/A'
|
||||||
|
|
||||||
url = config.api_endpoint+ '/zones/' + uuid + '/records/' + config.subdomains[0] + '/A'
|
subdomain = config.subdomains[0]
|
||||||
headers = {"X-Api-Key":config.api_secret}
|
url = config.api_endpoint+ '/zones/' + uuid + '/records/' + subdomain + record_type
|
||||||
|
headers = {'X-Api-Key':config.api_secret}
|
||||||
u = requests.get(url, headers=headers)
|
u = requests.get(url, headers=headers)
|
||||||
if u.status_code == 200:
|
if u.status_code == 200:
|
||||||
json_object = json.loads(u._content)
|
json_object = u.json()
|
||||||
print('Checking IP from DNS Record' , config.subdomains[0], ':', json_object['rrset_values'][0].encode('ascii','ignore').decode().strip('\n'))
|
if verbose:
|
||||||
return json_object['rrset_values'][0].encode('ascii','ignore').decode().strip('\n')
|
pprint(json_object)
|
||||||
|
dnsip = json_object['rrset_values'][0].strip()
|
||||||
|
print (f'Checking IP from DNS Record {subdomain}: {dnsip}')
|
||||||
|
return dnsip
|
||||||
else:
|
else:
|
||||||
print('Error: HTTP Status Code ', u.status_code, 'when trying to get IP from subdomain', config.subdomains[0])
|
print('Error: HTTP Status Code ', u.status_code, 'when trying to get IP from subdomain', subdomain)
|
||||||
print (json_object['message'])
|
pprint(u.json())
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
def update_records(uuid, dynIP, subdomain):
|
def update_records(uuid, dynIP, subdomain, is_ipv6=False, verbose=False):
|
||||||
''' update DNS Records for Subdomains
|
''' update DNS Records for Subdomains
|
||||||
Change the "NAME"/"TYPE" record from the zone UUID
|
Change the "NAME"/"TYPE" record from the zone UUID
|
||||||
PUT /zones/<UUID>/records/<NAME>/<TYPE>:
|
PUT /zones/<UUID>/records/<NAME>/<TYPE>:
|
||||||
|
@ -73,54 +94,83 @@ def update_records(uuid, dynIP, subdomain):
|
||||||
"rrset_values": ["<VALUE>"]}' \
|
"rrset_values": ["<VALUE>"]}' \
|
||||||
https://dns.gandi.net/api/v5/zones/<UUID>/records/<NAME>/<TYPE>
|
https://dns.gandi.net/api/v5/zones/<UUID>/records/<NAME>/<TYPE>
|
||||||
'''
|
'''
|
||||||
url = config.api_endpoint+ '/zones/' + uuid + '/records/' + subdomain + '/A'
|
if is_ipv6:
|
||||||
payload = {"rrset_ttl": config.ttl, "rrset_values": [dynIP]}
|
record_type = '/AAAA'
|
||||||
headers = {"Content-Type": "application/json", "X-Api-Key":config.api_secret}
|
else:
|
||||||
|
record_type = '/A'
|
||||||
|
url = config.api_endpoint+ '/zones/' + uuid + '/records/' + subdomain + record_type
|
||||||
|
payload = {'rrset_ttl': config.ttl, "rrset_values": [dynIP]}
|
||||||
|
headers = {'Content-Type': 'application/json', 'X-Api-Key':config.api_secret}
|
||||||
u = requests.put(url, data=json.dumps(payload), headers=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:
|
if u.status_code == 201:
|
||||||
print('Status Code:', u.status_code, ',', json_object['message'], ', IP updated for', subdomain)
|
print (f'Status Code: {u.status_code}, {json_object["message"]}, IP updated for {subdomain}')
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print('Error: HTTP Status Code ', u.status_code, 'when trying to update IP from subdomain', subdomain)
|
print (f'Error: HTTP Status Code {u.status_code} when trying to update IP from subdomain {subdomain}')
|
||||||
print(json_object['message'])
|
print (json_object['message'])
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main(force_update, verbosity):
|
def main(force_update, verbosity, repeat):
|
||||||
|
|
||||||
if verbosity:
|
if verbosity:
|
||||||
print("verbosity turned on - not implemented by now")
|
print('verbosity turned on')
|
||||||
|
verbose = True
|
||||||
|
else:
|
||||||
|
verbose =False
|
||||||
|
|
||||||
for key, value in config.dnsentries.items():
|
if repeat and verbose:
|
||||||
config.domain = key
|
print(f'repeat turned on, will repeat every {repeat} seconds')
|
||||||
|
|
||||||
|
for domain, content in config.dnsentries.items():
|
||||||
|
config.domain = domain
|
||||||
|
for key, value in content.items():
|
||||||
|
afi = key
|
||||||
config.subdomains = value
|
config.subdomains = value
|
||||||
|
|
||||||
#get zone ID from Account
|
#get zone ID from Account
|
||||||
uuid = get_uuid()
|
uuid = get_uuid()
|
||||||
|
|
||||||
#compare dynIP and DNS IP
|
#compare dynIP and DNS IP
|
||||||
dynIP = get_dynip(config.ifconfig)
|
dynIP = get_dynip(config.ifconfig[afi], verbose)
|
||||||
dnsIP = get_dnsip(uuid)
|
|
||||||
|
if check_is_ipv6(dynIP, verbose):
|
||||||
|
is_ipv6 = True
|
||||||
|
print('Detected ipv6')
|
||||||
|
else:
|
||||||
|
print('Detected ipv4')
|
||||||
|
is_ipv6 = False
|
||||||
|
|
||||||
|
dnsIP = get_dnsip(uuid, is_ipv6, verbose)
|
||||||
|
|
||||||
|
subdomains = config.subdomains
|
||||||
|
|
||||||
if force_update:
|
if force_update:
|
||||||
print("Going to update/create the DNS Records for the subdomains")
|
print ('Going to update/create the DNS Records for the subdomains')
|
||||||
for sub in config.subdomains:
|
for sub in subdomains:
|
||||||
update_records(uuid, dynIP, sub)
|
update_records(uuid, dynIP, sub, is_ipv6, verbose)
|
||||||
else:
|
else:
|
||||||
|
if verbose:
|
||||||
|
print(f'dynIP: {dynIP}')
|
||||||
|
print(f'dnsIP: {dnsIP}')
|
||||||
if dynIP == dnsIP:
|
if dynIP == dnsIP:
|
||||||
print("IP Address Match - no further action")
|
print ('IP Address Match - no further action')
|
||||||
else:
|
else:
|
||||||
print("IP Address Mismatch - going to update the DNS Records for the subdomains with new IP", dynIP)
|
print (f'IP Address Mismatch - going to update the DNS Records for the subdomains with new IP {dynIP}')
|
||||||
for sub in config.subdomains:
|
for sub in subdomains:
|
||||||
update_records(uuid, dynIP, sub)
|
update_records(uuid, dynIP, sub, is_ipv6, verbose)
|
||||||
|
if repeat:
|
||||||
|
if verbosity:
|
||||||
|
print(f'Repeating in {repeat} seconds')
|
||||||
|
th.Timer(repeat, main, [force_update, verbosity, repeat]).start()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('-v', '--verbose', help="increase output verbosity", action="store_true")
|
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")
|
parser.add_argument('-f', '--force', help='force an update/create', action='store_true')
|
||||||
|
parser.add_argument('-r', '--repeat', type=int, help='keep running and repeat every N seconds')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
main(args.force, args.verbose, args.repeat)
|
||||||
main(args.force, args.verbose)
|
|
||||||
|
|
Loading…
Reference in a new issue