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

Testing #5

Merged
merged 8 commits into from
Jan 3, 2025
Merged
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
8 changes: 2 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
TODO: Review this README and add or modify as necessary.

## AutoDNS provider for octoDNS

An [octoDNS](https://github.com/octodns/octodns/) provider that targets [AutoDNS](https://de.autodns.com/domain-robot-api/).
Expand Down Expand Up @@ -47,14 +45,12 @@ providers:

#### Records

TODO: All octoDNS record types are supported.
AutoDNSProvider supports A, AAAA, CAA, TXT, CNAME, MX, NS, SRV, ALIAS

#### Dynamic

TODO: AutoDNSProvider does not support dynamic records.
AutoDNSProvider does not support dynamic records.

### Development

See the [/script/](/script/) directory for some tools to help with the development process. They generally follow the [Script to rule them all](https://github.com/github/scripts-to-rule-them-all) pattern. Most useful is `./script/bootstrap` which will create a venv and install both the runtime and development related requirements. It will also hook up a pre-commit hook that covers most of what's run by CI.

TODO: any provider specific setup, a docker compose to run things locally etc?
115 changes: 53 additions & 62 deletions octodns_autodns/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,6 @@ def zone_get(self, name):
"""
return self._do_json('GET', f'/zone/{name}/{self.system_name_server}')

# TODO: implement creating new zones in AutoDNS, haven't done this so far
def zone_create(self, origin, soa, nameservers):
"""
Creates a new zone in AutoDNS API
"""
data = {'origin': origin, 'soa': soa, 'nameservers': nameservers}
return self._do_json('POST', '/zone', data=data)['zone']

def zone_update_records(
self,
zone_name: str,
Expand All @@ -101,23 +93,8 @@ class AutoDNSProvider(BaseProvider):
"""

SUPPORTS_GEO = False
# SUPPORTS_DYNAMIC = False
# SUPPORTS_ROOT_NS = True
SUPPORTS = set(
(
'A',
'AAAA',
'CAA',
'HINFO',
'NAPTR',
'PTR',
'TXT',
'CNAME',
'MX',
'NS',
'SRV',
'ALIAS',
)
('A', 'AAAA', 'CAA', 'TXT', 'CNAME', 'MX', 'NS', 'SRV', 'ALIAS')
)

def __init__(
Expand Down Expand Up @@ -154,7 +131,7 @@ def __init__(

self.client = AutoDNSClient(sess, system_name_servers[0])

def _data_for_mx(self, _type, records, default_ttl):
def _data_for_MX(self, _type, records, default_ttl):
values = []
for record in records:
preference = record.get('pref')
Expand All @@ -166,7 +143,7 @@ def _data_for_mx(self, _type, records, default_ttl):
_ttl = default_ttl
return {'ttl': _ttl, 'type': _type, 'values': values}

def _data_for_multi(self, _type, records, default_ttl):
def _data_for_MULTI(self, _type, records, default_ttl):
values = []
for record in records:
values.append(record.get('value'))
Expand All @@ -176,15 +153,15 @@ def _data_for_multi(self, _type, records, default_ttl):
_ttl = default_ttl
return {'ttl': _ttl, 'type': _type, 'values': values}

def _data_for_cname(self, _type, records, default_ttl):
def _data_for_SINGLE(self, _type, records, default_ttl):
record = records[0]
try:
_ttl = records[0]["ttl"]
except KeyError:
_ttl = default_ttl
return {'ttl': _ttl, 'type': _type, 'value': record.get('value')}

def _data_for_srv(self, _type, records, default_ttl):
def _data_for_SRV(self, _type, records, default_ttl):
values = []
for record in records:
priority = record.get('pref')
Expand All @@ -206,7 +183,21 @@ def _data_for_srv(self, _type, records, default_ttl):

return {'ttl': _ttl, 'type': _type, 'values': values}

def _params_for_multiple(self, record):
def _data_for_CAA(self, _type, records, default_ttl):
values = []
for record in records:
flags = record.get('value').split(' ')[0]
tag = record.get('value').split(' ')[1]
value = record.get('value').split(' ')[2].strip('"')
values.append({'flags': flags, 'tag': tag, 'value': value})
try:
_ttl = records[0]["ttl"]
except KeyError:
_ttl = default_ttl

return {'ttl': _ttl, 'type': _type, 'values': values}

def _params_for_MULTIPLE(self, record):
for value in record.values:
yield {
'value': value,
Expand All @@ -215,10 +206,10 @@ def _params_for_multiple(self, record):
'type': record._type,
}

_params_for_A = _params_for_multiple
_params_for_AAAA = _params_for_multiple
_params_for_A = _params_for_MULTIPLE
_params_for_AAAA = _params_for_MULTIPLE

def _params_for_caa(self, record):
def _params_for_CAA(self, record):
for value in record.values:
data = f'{value.flags} {value.tag} "{value.value}"'
yield {
Expand All @@ -228,17 +219,18 @@ def _params_for_caa(self, record):
'type': record._type,
}

def _params_for_single(self, record):
def _params_for_SINGLE(self, record):
yield {
'value': record.value,
'name': record.name,
'ttl': record.ttl,
'type': record._type,
}

_params_for_CNAME = _params_for_single
_params_for_CNAME = _params_for_SINGLE
_params_for_ALIAS = _params_for_SINGLE

def _params_for_mx(self, record):
def _params_for_MX(self, record):
for value in record.values:
yield {
'value': value.exchange,
Expand All @@ -248,9 +240,9 @@ def _params_for_mx(self, record):
'pref': value.preference,
}

_params_for_NS = _params_for_multiple
_params_for_NS = _params_for_MULTIPLE

def _params_for_srv(self, record):
def _params_for_SRV(self, record):
for value in record.values:
data = f'{value.weight} {value.port} {value.target}'
yield {
Expand All @@ -261,9 +253,9 @@ def _params_for_srv(self, record):
'pref': value.priority,
}

_params_for_TXT = _params_for_multiple
_params_for_TXT = _params_for_MULTIPLE

def _apply_create(self, zone_name, change):
def _apply_Create(self, zone_name, change):
new = change.new
params_for = getattr(self, f'_params_for_{new._type}')

Expand All @@ -272,12 +264,12 @@ def _apply_create(self, zone_name, change):
zone_name, records_remove=[], records_add=[params]
)

def _apply_update(self, zone_name, change):
def _apply_Update(self, zone_name, change):
# It's way simpler to delete-then-recreate than to update
self._apply_delete(zone_name, change)
self._apply_create(zone_name, change)
self._apply_Delete(zone_name, change)
self._apply_Create(zone_name, change)

def _apply_delete(self, zone_name, change):
def _apply_Delete(self, zone_name, change):
existing = change.existing

params_for = getattr(self, f'_params_for_{existing._type}')
Expand Down Expand Up @@ -316,25 +308,24 @@ def populate(self, zone: Zone, target=False, lenient=False):

for name, types in values.items():
for _type, records in types.items():
print(_type, records)

match _type:
case 'MX':
record_data = self._data_for_mx(
_type, records, default_ttl
)
case 'SRV':
record_data = self._data_for_srv(
_type, records, default_ttl
)
case 'CNAME':
record_data = self._data_for_cname(
_type, records, default_ttl
)
case _:
record_data = self._data_for_multi(
_type, records, default_ttl
)
if _type == 'MX':
record_data = self._data_for_MX(_type, records, default_ttl)
elif _type == 'SRV':
record_data = self._data_for_SRV(
_type, records, default_ttl
)
elif _type in ('CNAME', 'ALIAS'):
record_data = self._data_for_SINGLE(
_type, records, default_ttl
)
elif _type == 'CAA':
record_data = self._data_for_CAA(
_type, records, default_ttl
)
else:
record_data = self._data_for_MULTI(
_type, records, default_ttl
)

record = Record.new(
zone, name, record_data, source=self, lenient=lenient
Expand Down
40 changes: 22 additions & 18 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,42 +1,46 @@
# DO NOT EDIT THIS FILE DIRECTLY - use ./script/update-requirements to update
Pygments==2.18.0
SecretStorage==3.3.3
backports.tarfile==1.2.0
black==24.10.0
build==1.2.2.post1
certifi==2024.8.30
cffi==1.17.1
charset-normalizer==3.3.2
click==8.1.7
cmarkgfm==2024.1.14
coverage==7.6.1
docutils==0.20.1
click==8.1.8
cmarkgfm==2024.11.20
coverage==7.6.10
cryptography==44.0.0
docutils==0.21.2
exceptiongroup==1.2.2
importlib_metadata==8.5.0
iniconfig==2.0.0
isort==5.13.2
jaraco.classes==3.4.0
jaraco.context==6.0.1
jaraco.functools==4.1.0
keyring==25.4.1
jeepney==0.8.0
keyring==25.6.0
markdown-it-py==3.0.0
mdurl==0.1.2
more-itertools==10.5.0
mypy-extensions==1.0.0
nh3==0.2.18
packaging==24.1
nh3==0.2.20
packaging==24.2
pathspec==0.12.1
pkginfo==1.10.0
pkginfo==1.12.0
platformdirs==4.3.6
pluggy==1.5.0
pycparser==2.22
pyflakes==3.2.0
pyproject_hooks==1.2.0
pytest-cov==5.0.0
pytest==8.3.3
pytest-cov==6.0.0
pytest==8.3.4
pytest_network==0.0.1
readme_renderer==43.0
readme_renderer==44.0
requests-mock==1.12.1
requests-toolbelt==1.0.0
requests==2.32.3
rfc3986==2.0.0
rich==13.9.2
twine==5.1.1
urllib3==2.2.3
zipp==3.20.2
rich==13.9.4
tomli==2.2.1
twine==6.0.1
typing_extensions==4.12.2
zipp==3.21.0
7 changes: 5 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# TODO: run ./script/update-requirements to fill this and requirements-dev.txt out
# DO NOT EDIT THIS FILE DIRECTLY - use ./script/update-requirements to update
PyYAML==6.0.2
certifi==2024.12.14
charset-normalizer==3.4.1
dnspython==2.7.0
fqdn==1.5.1
idna==3.10
natsort==8.4.0
octodns==1.10.0
python-dateutil==2.9.0.post0
six==1.16.0
requests==2.32.3
six==1.17.0
urllib3==2.3.0
2 changes: 1 addition & 1 deletion script/cibuild-setup-py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ python -m build --sdist --wheel
echo "## validate wheel install ###################################################"
pip install dist/*$VERSION*.whl
echo "## validate tests can run against installed code ###############################"
pip install pytest pytest-network
pip install -r requirements-dev.txt
pytest --disable-network
echo "## complete ####################################################################"
16 changes: 4 additions & 12 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,11 @@ def version():

description, long_description = descriptions()

tests_require = (
'pytest',
'pytest-cov',
'pytest-network',
# TODO: other test-time requirements
)
tests_require = ('pytest', 'pytest-cov', 'pytest-network', 'requests_mock')

setup(
author='Christoph Sieber',
author_email='[email protected]',
author='Christoph Sieber, Martin Neubert, Martin Schurz, Christopher Grau',
author_email='[email protected], [email protected], [email protected], [email protected]',
description=description,
extras_require={
'dev': tests_require
Expand All @@ -47,10 +42,7 @@ def version():
),
'test': tests_require,
},
install_requires=(
'octodns>=1.0.0',
# TODO: other requirements
),
install_requires=('octodns>=1.0.0', 'requests>=2.32.3'),
license='MIT',
long_description=long_description,
long_description_content_type='text/markdown',
Expand Down
Loading
Loading