-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Nicolai Buchwitz
committed
Aug 10, 2018
1 parent
59e1f32
commit df5e663
Showing
4 changed files
with
204 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
venv | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,37 @@ | ||
# nc_dnsapi | ||
API wrapper for the netcup DNS API | ||
A simple API wrapper for the netcup DNS API | ||
|
||
```python | ||
import nc_dnsapi | ||
|
||
customer = 123456 | ||
api_key = "your-personal-api-key" | ||
api_password = "your-private-api-password" | ||
|
||
with nc_dnsapi.Client(customer, api_key, api_password) as api: | ||
# fetch records | ||
records = api.dns_records("example.com") | ||
print(records) | ||
|
||
# fetch zone details | ||
zone = api.dns_zone("example.com") | ||
print(zone) | ||
|
||
# update single record | ||
api.update_dns_record("example.com", DNSRecord("my-hostname", "A", "127.0.0.2", id=108125)) | ||
|
||
# update list of records | ||
api.update_dns_record("example.com", [ DNSRecord("my-hostname", "A", "127.0.0.2", id=108125), | ||
DNSRecord("my-hostname2", "A", "127.0.0.2", id=108126)]) | ||
|
||
# delete record | ||
api.delete_dns_record("example.com", DNSRecord("my-hostname", "A", "127.0.0.2", id=108125)) | ||
|
||
# add record | ||
api.add_dns_record("example.com", DNSRecord("another-host", "AAAA", "::1")) | ||
|
||
# update zone | ||
zone = api.dns_zone("example.com") | ||
zone.refresh = 3600 | ||
api.update_dns_zone("example.com", zone) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
import requests | ||
import json | ||
|
||
|
||
class DNSZone(object): | ||
def __init__(self, name, ttl, serial, refresh, retry, expire, dnssecstatus): | ||
self.name = name | ||
self.ttl = ttl | ||
self.serial = serial | ||
self.refresh = refresh | ||
self.retry = retry | ||
self.expire = expire | ||
self.dnssecstatus = dnssecstatus | ||
|
||
def __str__(self): | ||
return str(self.__dict__) | ||
|
||
|
||
class DNSRecord(object): | ||
__valid_types = ['A', 'AAAA', 'MX', 'CNAME', 'CAA', 'SRV', 'TXT', 'TLSA', 'NS', 'DS'] | ||
|
||
def __init__(self, hostname, record_type, destination, **kwargs): | ||
self.hostname = hostname | ||
self.type = record_type.upper() | ||
self.destination = destination | ||
self.priority = kwargs.get("priority", 0) | ||
self.id = kwargs.get("id", "") | ||
self.deleterecord = kwargs.get("deleterecord", False) | ||
self.state = True | ||
|
||
if self.type not in self.__valid_types: | ||
raise TypeError("Invalid record type: {}".format(self.type)) | ||
|
||
def __str__(self): | ||
return str(self.__dict__) | ||
|
||
|
||
class Client(object): | ||
__endpoint = "https://ccp.netcup.net/run/webservice/servers/endpoint.php?JSON" | ||
__api_session_id = None | ||
|
||
def request(self, action, **kwargs): | ||
params = kwargs.get("params", {}) | ||
params.update({ | ||
"apikey": self.__api_key, | ||
"customernumber": self.__customer, | ||
}) | ||
|
||
if "apipassword" in kwargs: | ||
params.update({kwargs.get("apipassword")}) | ||
|
||
if self.__api_session_id: | ||
params.update({"apisessionid": self.__api_session_id}) | ||
|
||
response = requests.post( | ||
self.__endpoint, | ||
data=json.dumps({ | ||
"action": action, | ||
"param": params | ||
}), | ||
timeout=self.__api_timeout | ||
) | ||
|
||
if response.ok: | ||
data = response.json() | ||
|
||
if data['status'] == 'success': | ||
return data | ||
else: | ||
raise Exception("{} ({})".format(data['longmessage'], data['statuscode'])) | ||
else: | ||
raise Exception("{} ({})".format(response.reason, response.status_code)) | ||
|
||
def logout(self): | ||
self.request("logout") | ||
|
||
def login(self): | ||
data = self.request("login", params={"apipassword": self.__api_password}) | ||
self.__api_session_id = data['responsedata']['apisessionid'] | ||
|
||
def add_dns_record(self, domain, record: DNSRecord): | ||
self.update_dns_records(domain, [record]) | ||
|
||
def update_dns_record(self, domain, record: DNSRecord): | ||
if not record.id: | ||
raise ValueError("Missing id of record to update") | ||
|
||
self.update_dns_records(domain, [record]) | ||
|
||
def update_dns_records(self, domain, records): | ||
if not all(isinstance(r, DNSRecord) for r in records): | ||
raise TypeError("Record has to be instance of DNSRecord") | ||
|
||
self.request("updateDnsRecords", params={ | ||
"domainname": domain, | ||
"dnsrecordset": {"dnsrecords": [record.__dict__ for record in records]} | ||
}) | ||
|
||
def delete_dns_record(self, domain, record: DNSRecord, ignore_unknown=True): | ||
if not record.id: | ||
raise ValueError("Missing id of record to update") | ||
|
||
record.deleterecord = True | ||
|
||
try: | ||
self.update_dns_records(domain, [record]) | ||
except Exception as ex: | ||
if not ignore_unknown: | ||
raise ex | ||
|
||
def dns_records(self, domain): | ||
data = self.request("infoDnsRecords", params={"domainname": domain}) | ||
return [DNSRecord(**r) for r in data['responsedata']['dnsrecords']] | ||
|
||
def update_dns_zone(self, domain, zone: DNSZone): | ||
if not isinstance(zone, DNSZone): | ||
raise TypeError("Zone has to be instance of DNSZone") | ||
|
||
self.request("updateDnsZone", params={ | ||
"domainname": domain, | ||
"dnszone": zone.__dict__ | ||
}) | ||
|
||
def dns_zone(self, domain): | ||
data = self.request("infoDnsZone", params={"domainname": domain}) | ||
return DNSZone(**data['responsedata']) | ||
|
||
def __init__(self, customer, api_key, api_password, timeout=5): | ||
self.__customer = customer | ||
self.__api_key = api_key | ||
self.__api_password = api_password | ||
self.__api_timeout = timeout | ||
|
||
def __enter__(self): | ||
self.login() | ||
return self | ||
|
||
def __exit__(self, exc_type, exc_value, traceback): | ||
self.logout() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#!/usr/bin/env python | ||
|
||
from setuptools import setup | ||
|
||
setup( | ||
name='nc_dnsapi', | ||
version='0.1.0', | ||
description='API wrapper for the netcup DNS api', | ||
author='Nicolai Buchwitz', | ||
author_email='[email protected]', | ||
zip_safe=False, | ||
include_package_data=True, | ||
classifiers=[ | ||
'Development Status :: 4 - Beta', | ||
'Intended Audience :: Developers', | ||
'License :: OSI Approved :: BSD License', | ||
'Natural Language :: English', | ||
'Operating System :: POSIX :: Linux', | ||
'Programming Language :: Python', | ||
], | ||
install_requires=[ | ||
'requests', | ||
], | ||
packages=[ | ||
'nc_dnsapi', | ||
], | ||
) |