mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
Handle domains not registred at Gandi or not using Gandi's DNS
This commit is contained in:
@@ -41,6 +41,12 @@ class GandiClientNotFound(GandiClientException):
|
||||
super(GandiClientNotFound, self).__init__(r.text)
|
||||
|
||||
|
||||
class GandiClientUnknownDomainName(GandiClientException):
|
||||
|
||||
def __init__(self, msg):
|
||||
super(GandiClientUnknownDomainName, self).__init__(msg)
|
||||
|
||||
|
||||
class GandiClient(object):
|
||||
|
||||
def __init__(self, token):
|
||||
@@ -63,6 +69,16 @@ class GandiClient(object):
|
||||
r.raise_for_status()
|
||||
return r
|
||||
|
||||
def zone(self, zone_name):
|
||||
return self._request('GET', '/livedns/domains/{}'
|
||||
.format(zone_name)).json()
|
||||
|
||||
def zone_create(self, zone_name):
|
||||
return self._request('POST', '/livedns/domains', data={
|
||||
'fqdn': zone_name,
|
||||
'zone': {}
|
||||
}).json()
|
||||
|
||||
def zone_records(self, zone_name):
|
||||
records = self._request('GET', '/livedns/domains/{}/records'
|
||||
.format(zone_name)).json()
|
||||
@@ -318,9 +334,25 @@ class GandiProvider(BaseProvider):
|
||||
def _apply(self, plan):
|
||||
desired = plan.desired
|
||||
changes = plan.changes
|
||||
zone = desired.name[:-1]
|
||||
self.log.debug('_apply: zone=%s, len(changes)=%d', desired.name,
|
||||
len(changes))
|
||||
|
||||
try:
|
||||
self._client.zone(zone)
|
||||
except GandiClientNotFound:
|
||||
self.log.info('_apply: no existing zone, trying to create it')
|
||||
try:
|
||||
self._client.zone_create(zone)
|
||||
self.log.info('_apply: zone has been successfully created')
|
||||
except GandiClientNotFound:
|
||||
raise GandiClientUnknownDomainName('This domain is not '
|
||||
'registred at Gandi. '
|
||||
'Please register or '
|
||||
'transfer it here '
|
||||
'to be able to manage its '
|
||||
'DNS zone.')
|
||||
|
||||
# Force records deletion to be done before creation in order to avoid
|
||||
# "CNAME record must be the only record" error when an existing CNAME
|
||||
# record is replaced by an A/AAAA record.
|
||||
|
||||
7
tests/fixtures/gandi-zone.json
vendored
Normal file
7
tests/fixtures/gandi-zone.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"domain_keys_href": "https://api.gandi.net/v5/livedns/domains/unit.tests/keys",
|
||||
"fqdn": "unit.tests",
|
||||
"automatic_snapshots": true,
|
||||
"domain_records_href": "https://api.gandi.net/v5/livedns/domains/unit.tests/records",
|
||||
"domain_href": "https://api.gandi.net/v5/livedns/domains/unit.tests"
|
||||
}
|
||||
@@ -86,6 +86,18 @@ class TestGandiProvider(TestCase):
|
||||
provider.populate(zone)
|
||||
self.assertIn('"cause":"Forbidden"', text_type(ctx.exception))
|
||||
|
||||
# 404 - Not Found.
|
||||
with requests_mock() as mock:
|
||||
mock.get(ANY, status_code=404,
|
||||
text='{"code": 404, "message": "The resource could not '
|
||||
'be found.", "object": "HTTPNotFound", "cause": '
|
||||
'"Not Found"}')
|
||||
|
||||
with self.assertRaises(GandiClientNotFound) as ctx:
|
||||
zone = Zone('unit.tests.', [])
|
||||
provider._client.zone(zone)
|
||||
self.assertIn('"cause": "Not Found"', text_type(ctx.exception))
|
||||
|
||||
# General error
|
||||
with requests_mock() as mock:
|
||||
mock.get(ANY, status_code=502, text='Things caught fire')
|
||||
@@ -95,15 +107,6 @@ class TestGandiProvider(TestCase):
|
||||
provider.populate(zone)
|
||||
self.assertEquals(502, ctx.exception.response.status_code)
|
||||
|
||||
# Non-existent zone doesn't populate anything
|
||||
with requests_mock() as mock:
|
||||
mock.get(ANY, status_code=404,
|
||||
text='{"message": "Domain `foo.bar` not found"}')
|
||||
|
||||
zone = Zone('unit.tests.', [])
|
||||
provider.populate(zone)
|
||||
self.assertEquals(set(), zone.records)
|
||||
|
||||
# No diffs == no changes
|
||||
with requests_mock() as mock:
|
||||
base = 'https://api.gandi.net/v5/livedns/domains/unit.tests' \
|
||||
@@ -147,10 +150,14 @@ class TestGandiProvider(TestCase):
|
||||
resp.json = Mock()
|
||||
provider._client._request = Mock(return_value=resp)
|
||||
|
||||
with open('tests/fixtures/gandi-zone.json') as fh:
|
||||
zone = fh.read()
|
||||
|
||||
# non-existent domain
|
||||
resp.json.side_effect = [
|
||||
GandiClientNotFound(resp), # no zone in populate
|
||||
GandiClientNotFound(resp), # no domain during apply
|
||||
zone
|
||||
]
|
||||
plan = provider.plan(self.expected)
|
||||
|
||||
@@ -162,6 +169,11 @@ class TestGandiProvider(TestCase):
|
||||
|
||||
provider._client._request.assert_has_calls([
|
||||
call('GET', '/livedns/domains/unit.tests/records'),
|
||||
call('GET', '/livedns/domains/unit.tests'),
|
||||
call('POST', '/livedns/domains', data={
|
||||
'fqdn': 'unit.tests',
|
||||
'zone': {}
|
||||
}),
|
||||
call('POST', '/livedns/domains/unit.tests/records', data={
|
||||
'rrset_name': 'www.sub',
|
||||
'rrset_ttl': 300,
|
||||
@@ -258,7 +270,7 @@ class TestGandiProvider(TestCase):
|
||||
})
|
||||
])
|
||||
# expected number of total calls
|
||||
self.assertEquals(14, provider._client._request.call_count)
|
||||
self.assertEquals(16, provider._client._request.call_count)
|
||||
|
||||
provider._client._request.reset_mock()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user