Browse Source

NS1 rate_limit_delay param, unit tests for rate limit handling

pull/81/head
Ross McFarland 9 years ago
parent
commit
a44b82c2c7
No known key found for this signature in database GPG Key ID: 61C10C4FC8FE4A89
2 changed files with 36 additions and 12 deletions
  1. +7
    -6
      octodns/provider/ns1.py
  2. +29
    -6
      tests/test_octodns_provider_ns1.py

+ 7
- 6
octodns/provider/ns1.py View File

@ -26,14 +26,15 @@ class Ns1Provider(BaseProvider):
SUPPORTS = set(('A', 'AAAA', 'ALIAS', 'CNAME', 'MX', 'NAPTR', 'NS', 'PTR',
'SPF', 'SRV', 'TXT'))
RATE_LIMIT_DELAY = 1
ZONE_NOT_FOUND_MESSAGE = 'server error: zone not found'
def __init__(self, id, api_key, *args, **kwargs):
def __init__(self, id, api_key, rate_limit_delay=1, *args, **kwargs):
self.log = getLogger('Ns1Provider[{}]'.format(id))
self.log.debug('__init__: id=%s, api_key=***', id)
self.log.debug('__init__: id=%s, api_key=***, rate_limit_delay=%d', id,
rate_limit_delay)
super(Ns1Provider, self).__init__(id, *args, **kwargs)
self._client = NSONE(apiKey=api_key)
self.rate_limit_delay = rate_limit_delay
def _data_for_A(self, _type, record):
return {
@ -179,7 +180,7 @@ class Ns1Provider(BaseProvider):
except RateLimitException:
self.log.warn('_apply_Create: rate limit encountered, pausing '
'and trying again')
sleep(self.RATE_LIMIT_DELAY)
sleep(self.rate_limit_delay)
meth(name, **params)
def _apply_Update(self, nsone_zone, change):
@ -194,7 +195,7 @@ class Ns1Provider(BaseProvider):
except RateLimitException:
self.log.warn('_apply_Update: rate limit encountered, pausing '
'and trying again')
sleep(self.RATE_LIMIT_DELAY)
sleep(self.rate_limit_delay)
record.update(**params)
def _apply_Delete(self, nsone_zone, change):
@ -207,7 +208,7 @@ class Ns1Provider(BaseProvider):
except RateLimitException:
self.log.warn('_apply_Delete: rate limit encountered, pausing '
'and trying again')
sleep(self.RATE_LIMIT_DELAY)
sleep(self.rate_limit_delay)
record.delete()
def _apply(self, plan):


+ 29
- 6
tests/test_octodns_provider_ns1.py View File

@ -6,7 +6,8 @@ from __future__ import absolute_import, division, print_function, \
unicode_literals
from mock import Mock, call, patch
from nsone.rest.errors import AuthException, ResourceException
from nsone.rest.errors import AuthException, RateLimitException, \
ResourceException
from unittest import TestCase
from octodns.record import Delete, Record, Update
@ -192,7 +193,7 @@ class TestNs1Provider(TestCase):
@patch('nsone.NSONE.createZone')
@patch('nsone.NSONE.loadZone')
def test_sync(self, load_mock, create_mock):
provider = Ns1Provider('test', 'api-key')
provider = Ns1Provider('test', 'api-key', rate_limit_delay=0)
desired = Zone('unit.tests.', [])
desired.records.update(self.expected)
@ -225,7 +226,15 @@ class TestNs1Provider(TestCase):
create_mock.reset_mock()
load_mock.side_effect = \
ResourceException('server error: zone not found')
create_mock.side_effect = None
# ugh, need a mock zone with a mock prop since we're using getattr, we
# can actually control side effects on `meth` with that.
mock_zone = Mock()
mock_zone.add_SRV = Mock()
mock_zone.add_SRV.side_effect = [
RateLimitException('boo'),
None,
]
create_mock.side_effect = [mock_zone]
got_n = provider.apply(plan)
self.assertEquals(expected_n, got_n)
@ -245,12 +254,26 @@ class TestNs1Provider(TestCase):
self.assertEquals(2, len(plan.changes))
self.assertIsInstance(plan.changes[0], Update)
self.assertIsInstance(plan.changes[1], Delete)
# ugh, we need a mock record that can be returned from loadRecord for
# the update and delete targets, we can add our side effects to that to
# trigger rate limit handling
mock_record = Mock()
mock_record.update.side_effect = [
RateLimitException('one'),
None,
]
mock_record.delete.side_effect = [
RateLimitException('two'),
None,
]
nsone_zone.loadRecord.side_effect = [mock_record, mock_record]
got_n = provider.apply(plan)
self.assertEquals(2, got_n)
nsone_zone.loadRecord.assert_has_calls([
call('unit.tests', u'A'),
call().update(answers=[u'1.2.3.4'], ttl=32),
call('delete-me', u'A'),
call().delete()
])
mock_record.assert_has_calls([
call.update(answers=[u'1.2.3.4'], ttl=32),
call.delete()
])

Loading…
Cancel
Save