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

Use dns-lexicon's Client instead of deprecated providers #27

Merged
merged 5 commits into from
Jun 20, 2024
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
48 changes: 18 additions & 30 deletions certbot_dns_hetzner/dns_hetzner.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""DNS Authenticator for Hetzner DNS."""
import tldextract
from certbot.plugins import dns_common, dns_common_lexicon
from lexicon.providers import hetzner
from certbot.plugins import dns_common
from lexicon.client import Client
from lexicon.config import ConfigResolver

TTL = 60

Expand Down Expand Up @@ -47,40 +48,27 @@
return '.'.join([zone_name.domain, zone_name.suffix])

def _perform(self, domain, validation_name, validation):
self._get_hetzner_client().add_txt_record(
self._get_zone(domain),
self._fqdn_format(validation_name),
validation
)
with self._get_hetzner_client(domain) as client:
client.create_record("TXT", self._fqdn_format(validation_name), validation)

def _cleanup(self, domain, validation_name, validation):
self._get_hetzner_client().del_txt_record(
self._get_zone(domain),
self._fqdn_format(validation_name),
validation
)
with self._get_hetzner_client(domain) as client:
client.delete_record(None, "TXT", self._fqdn_format(validation_name), validation)

def _get_hetzner_client(self, domain):
config = ConfigResolver().with_env().with_dict({

Check warning on line 59 in certbot_dns_hetzner/dns_hetzner.py

View check run for this annotation

Codecov / codecov/patch

certbot_dns_hetzner/dns_hetzner.py#L59

Added line #L59 was not covered by tests
"provider_name": "hetzner",
"hetzner": {
"auth_token": self.credentials.conf("api_token")
},

def _get_hetzner_client(self):
return _HetznerClient(self.credentials.conf("api_token"))
"ttl": TTL,
"domain": self._get_zone(domain),
})
return Client(config)

Check warning on line 68 in certbot_dns_hetzner/dns_hetzner.py

View check run for this annotation

Codecov / codecov/patch

certbot_dns_hetzner/dns_hetzner.py#L68

Added line #L68 was not covered by tests

@staticmethod
def _fqdn_format(name):
if not name.endswith("."):
return f"{name}."
return name


class _HetznerClient(dns_common_lexicon.LexiconClient):
"""
Encapsulates all communication with the Hetzner via Lexicon.
"""
def __init__(self, auth_token):
super().__init__()

config = dns_common_lexicon.build_lexicon_config('hetzner', {
'ttl': TTL,
}, {
'auth_token': auth_token,
})

self.provider = hetzner.Provider(config)
42 changes: 24 additions & 18 deletions certbot_dns_hetzner/dns_hetzner_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from certbot_dns_hetzner.fakes import FAKE_API_TOKEN, FAKE_RECORD



patch_display_util = test_util.patch_display_util


Expand Down Expand Up @@ -44,52 +43,59 @@ def setUp(self):
self.auth = Authenticator(self.config, "hetzner")

self.mock_client = mock.MagicMock()

mock_client_wrapper = mock.MagicMock()
mock_client_wrapper.__enter__ = mock.MagicMock(
return_value=self.mock_client
)

# _get_ispconfig_client | pylint: disable=protected-access
self.auth._get_hetzner_client = mock.MagicMock(
return_value=self.mock_client)
return_value=mock_client_wrapper
)

@patch_display_util()
def test_perform(self, unused_mock_get_utility):
self.mock_client.add_txt_record.return_value = FAKE_RECORD
def test_perform(self, _unused_mock_get_utility):
self.mock_client.create_record.return_value = FAKE_RECORD
self.auth.perform([self.achall])
self.mock_client.add_txt_record.assert_called_with(
DOMAIN, "_acme-challenge." + DOMAIN + ".", mock.ANY
self.mock_client.create_record.assert_called_with(
"TXT", "_acme-challenge." + DOMAIN + ".", mock.ANY
)

def test_perform_but_raises_plugin_error(self):
self.mock_client.add_txt_record.side_effect = mock.MagicMock(
self.mock_client.create_record.side_effect = mock.MagicMock(
side_effect=PluginError()
)
self.assertRaises(PluginError, self.auth.perform, [self.achall])
self.mock_client.add_txt_record.assert_called_with(
DOMAIN, "_acme-challenge." + DOMAIN + ".", mock.ANY
self.mock_client.create_record.assert_called_with(
"TXT", "_acme-challenge." + DOMAIN + ".", mock.ANY
)

@patch_display_util()
def test_cleanup(self, unused_mock_get_utility):
self.mock_client.add_txt_record.return_value = FAKE_RECORD
def test_cleanup(self, _unused_mock_get_utility):
self.mock_client.create_record.return_value = FAKE_RECORD
# _attempt_cleanup | pylint: disable=protected-access
self.auth.perform([self.achall])
self.auth._attempt_cleanup = True
self.auth.cleanup([self.achall])

self.mock_client.del_txt_record.assert_called_with(
DOMAIN, "_acme-challenge." + DOMAIN + ".", mock.ANY
self.mock_client.delete_record.assert_called_with(
None, "TXT", "_acme-challenge." + DOMAIN + ".", mock.ANY
)

@patch_display_util()
def test_cleanup_but_raises_plugin_error(self, unused_mock_get_utility):
self.mock_client.add_txt_record.return_value = FAKE_RECORD
self.mock_client.del_txt_record.side_effect = mock.MagicMock(
def test_cleanup_but_raises_plugin_error(self, _unused_mock_get_utility):
self.mock_client.create_record.return_value = FAKE_RECORD
self.mock_client.delete_record.side_effect = mock.MagicMock(
side_effect=PluginError()
)
# _attempt_cleanup | pylint: disable=protected-access
self.auth.perform([self.achall])
self.auth._attempt_cleanup = True

self.assertRaises(PluginError, self.auth.cleanup, [self.achall])
self.mock_client.del_txt_record.assert_called_with(
DOMAIN, "_acme-challenge." + DOMAIN + ".", mock.ANY
self.mock_client.delete_record.assert_called_with(
None, "TXT", "_acme-challenge." + DOMAIN + ".", mock.ANY
)


Expand Down
Loading