|
|
@ -197,7 +197,13 @@ class TestNs1Provider(TestCase): |
|
|
def test_populate(self, zone_retrieve_mock, record_retrieve_mock): |
|
|
def test_populate(self, zone_retrieve_mock, record_retrieve_mock): |
|
|
provider = Ns1Provider('test', 'api-key') |
|
|
provider = Ns1Provider('test', 'api-key') |
|
|
|
|
|
|
|
|
|
|
|
def reset(): |
|
|
|
|
|
provider._client.reset_caches() |
|
|
|
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
record_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
# Bad auth |
|
|
# Bad auth |
|
|
|
|
|
reset() |
|
|
zone_retrieve_mock.side_effect = AuthException('unauthorized') |
|
|
zone_retrieve_mock.side_effect = AuthException('unauthorized') |
|
|
zone = Zone('unit.tests.', []) |
|
|
zone = Zone('unit.tests.', []) |
|
|
with self.assertRaises(AuthException) as ctx: |
|
|
with self.assertRaises(AuthException) as ctx: |
|
|
@ -205,7 +211,7 @@ class TestNs1Provider(TestCase): |
|
|
self.assertEquals(zone_retrieve_mock.side_effect, ctx.exception) |
|
|
self.assertEquals(zone_retrieve_mock.side_effect, ctx.exception) |
|
|
|
|
|
|
|
|
# General error |
|
|
# General error |
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
zone_retrieve_mock.side_effect = ResourceException('boom') |
|
|
zone_retrieve_mock.side_effect = ResourceException('boom') |
|
|
zone = Zone('unit.tests.', []) |
|
|
zone = Zone('unit.tests.', []) |
|
|
with self.assertRaises(ResourceException) as ctx: |
|
|
with self.assertRaises(ResourceException) as ctx: |
|
|
@ -214,7 +220,7 @@ class TestNs1Provider(TestCase): |
|
|
self.assertEquals(('unit.tests',), zone_retrieve_mock.call_args[0]) |
|
|
self.assertEquals(('unit.tests',), zone_retrieve_mock.call_args[0]) |
|
|
|
|
|
|
|
|
# Non-existent zone doesn't populate anything |
|
|
# Non-existent zone doesn't populate anything |
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
zone_retrieve_mock.side_effect = \ |
|
|
zone_retrieve_mock.side_effect = \ |
|
|
ResourceException('server error: zone not found') |
|
|
ResourceException('server error: zone not found') |
|
|
zone = Zone('unit.tests.', []) |
|
|
zone = Zone('unit.tests.', []) |
|
|
@ -224,8 +230,7 @@ class TestNs1Provider(TestCase): |
|
|
self.assertFalse(exists) |
|
|
self.assertFalse(exists) |
|
|
|
|
|
|
|
|
# Existing zone w/o records |
|
|
# Existing zone w/o records |
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
record_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
ns1_zone = { |
|
|
ns1_zone = { |
|
|
'records': [{ |
|
|
'records': [{ |
|
|
"domain": "geo.unit.tests", |
|
|
"domain": "geo.unit.tests", |
|
|
@ -255,8 +260,7 @@ class TestNs1Provider(TestCase): |
|
|
'geo.unit.tests', 'A')]) |
|
|
'geo.unit.tests', 'A')]) |
|
|
|
|
|
|
|
|
# Existing zone w/records |
|
|
# Existing zone w/records |
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
record_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
ns1_zone = { |
|
|
ns1_zone = { |
|
|
'records': self.ns1_records + [{ |
|
|
'records': self.ns1_records + [{ |
|
|
"domain": "geo.unit.tests", |
|
|
"domain": "geo.unit.tests", |
|
|
@ -286,8 +290,7 @@ class TestNs1Provider(TestCase): |
|
|
'geo.unit.tests', 'A')]) |
|
|
'geo.unit.tests', 'A')]) |
|
|
|
|
|
|
|
|
# Test skipping unsupported record type |
|
|
# Test skipping unsupported record type |
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
record_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
ns1_zone = { |
|
|
ns1_zone = { |
|
|
'records': self.ns1_records + [{ |
|
|
'records': self.ns1_records + [{ |
|
|
'type': 'UNSUPPORTED', |
|
|
'type': 'UNSUPPORTED', |
|
|
@ -340,19 +343,21 @@ class TestNs1Provider(TestCase): |
|
|
self.assertEquals(expected_n, len(plan.changes)) |
|
|
self.assertEquals(expected_n, len(plan.changes)) |
|
|
self.assertTrue(plan.exists) |
|
|
self.assertTrue(plan.exists) |
|
|
|
|
|
|
|
|
|
|
|
def reset(): |
|
|
|
|
|
provider._client.reset_caches() |
|
|
|
|
|
record_retrieve_mock.reset_mock() |
|
|
|
|
|
zone_create_mock.reset_mock() |
|
|
|
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
# Fails, general error |
|
|
# Fails, general error |
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
record_retrieve_mock.reset_mock() |
|
|
|
|
|
zone_create_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
zone_retrieve_mock.side_effect = ResourceException('boom') |
|
|
zone_retrieve_mock.side_effect = ResourceException('boom') |
|
|
with self.assertRaises(ResourceException) as ctx: |
|
|
with self.assertRaises(ResourceException) as ctx: |
|
|
provider.apply(plan) |
|
|
provider.apply(plan) |
|
|
self.assertEquals(zone_retrieve_mock.side_effect, ctx.exception) |
|
|
self.assertEquals(zone_retrieve_mock.side_effect, ctx.exception) |
|
|
|
|
|
|
|
|
# Fails, bad auth |
|
|
# Fails, bad auth |
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
record_retrieve_mock.reset_mock() |
|
|
|
|
|
zone_create_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
zone_retrieve_mock.side_effect = \ |
|
|
zone_retrieve_mock.side_effect = \ |
|
|
ResourceException('server error: zone not found') |
|
|
ResourceException('server error: zone not found') |
|
|
zone_create_mock.side_effect = AuthException('unauthorized') |
|
|
zone_create_mock.side_effect = AuthException('unauthorized') |
|
|
@ -361,9 +366,7 @@ class TestNs1Provider(TestCase): |
|
|
self.assertEquals(zone_create_mock.side_effect, ctx.exception) |
|
|
self.assertEquals(zone_create_mock.side_effect, ctx.exception) |
|
|
|
|
|
|
|
|
# non-existent zone, create |
|
|
# non-existent zone, create |
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
record_retrieve_mock.reset_mock() |
|
|
|
|
|
zone_create_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
zone_retrieve_mock.side_effect = \ |
|
|
zone_retrieve_mock.side_effect = \ |
|
|
ResourceException('server error: zone not found') |
|
|
ResourceException('server error: zone not found') |
|
|
|
|
|
|
|
|
@ -395,9 +398,7 @@ class TestNs1Provider(TestCase): |
|
|
]) |
|
|
]) |
|
|
|
|
|
|
|
|
# Update & delete |
|
|
# Update & delete |
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
record_retrieve_mock.reset_mock() |
|
|
|
|
|
zone_create_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
|
|
|
|
|
|
ns1_zone = { |
|
|
ns1_zone = { |
|
|
'records': self.ns1_records + [{ |
|
|
'records': self.ns1_records + [{ |
|
|
@ -937,11 +938,14 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
'mon-id': 'feed-id', |
|
|
'mon-id': 'feed-id', |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
def reset(): |
|
|
|
|
|
feed_create_mock.reset_mock() |
|
|
|
|
|
monitor_create_mock.reset_mock() |
|
|
|
|
|
monitor_gen_mock.reset_mock() |
|
|
|
|
|
monitors_update_mock.reset_mock() |
|
|
|
|
|
|
|
|
# No existing monitor |
|
|
# No existing monitor |
|
|
monitor_gen_mock.reset_mock() |
|
|
|
|
|
monitor_create_mock.reset_mock() |
|
|
|
|
|
monitors_update_mock.reset_mock() |
|
|
|
|
|
feed_create_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
monitor_gen_mock.side_effect = [{'key': 'value'}] |
|
|
monitor_gen_mock.side_effect = [{'key': 'value'}] |
|
|
monitor_create_mock.side_effect = [('mon-id', 'feed-id')] |
|
|
monitor_create_mock.side_effect = [('mon-id', 'feed-id')] |
|
|
value = '1.2.3.4' |
|
|
value = '1.2.3.4' |
|
|
@ -955,10 +959,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
feed_create_mock.assert_not_called() |
|
|
feed_create_mock.assert_not_called() |
|
|
|
|
|
|
|
|
# Existing monitor that doesn't need updates |
|
|
# Existing monitor that doesn't need updates |
|
|
monitor_gen_mock.reset_mock() |
|
|
|
|
|
monitor_create_mock.reset_mock() |
|
|
|
|
|
monitors_update_mock.reset_mock() |
|
|
|
|
|
feed_create_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
monitor = { |
|
|
monitor = { |
|
|
'id': 'mon-id', |
|
|
'id': 'mon-id', |
|
|
'key': 'value', |
|
|
'key': 'value', |
|
|
@ -975,10 +976,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
feed_create_mock.assert_not_called() |
|
|
feed_create_mock.assert_not_called() |
|
|
|
|
|
|
|
|
# Existing monitor that doesn't need updates, but is missing its feed |
|
|
# Existing monitor that doesn't need updates, but is missing its feed |
|
|
monitor_gen_mock.reset_mock() |
|
|
|
|
|
monitor_create_mock.reset_mock() |
|
|
|
|
|
monitors_update_mock.reset_mock() |
|
|
|
|
|
feed_create_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
monitor = { |
|
|
monitor = { |
|
|
'id': 'mon-id2', |
|
|
'id': 'mon-id2', |
|
|
'key': 'value', |
|
|
'key': 'value', |
|
|
@ -996,10 +994,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
feed_create_mock.assert_has_calls([call(monitor)]) |
|
|
feed_create_mock.assert_has_calls([call(monitor)]) |
|
|
|
|
|
|
|
|
# Existing monitor that needs updates |
|
|
# Existing monitor that needs updates |
|
|
monitor_gen_mock.reset_mock() |
|
|
|
|
|
monitor_create_mock.reset_mock() |
|
|
|
|
|
monitors_update_mock.reset_mock() |
|
|
|
|
|
feed_create_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
monitor = { |
|
|
monitor = { |
|
|
'id': 'mon-id', |
|
|
'id': 'mon-id', |
|
|
'key': 'value', |
|
|
'key': 'value', |
|
|
@ -1033,11 +1028,14 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
'mon-id': 'feed-id', |
|
|
'mon-id': 'feed-id', |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
def reset(): |
|
|
|
|
|
datafeed_delete_mock.reset_mock() |
|
|
|
|
|
monitors_delete_mock.reset_mock() |
|
|
|
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
|
|
|
# No active monitors and no existing, nothing will happen |
|
|
# No active monitors and no existing, nothing will happen |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
datafeed_delete_mock.reset_mock() |
|
|
|
|
|
monitors_delete_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
monitors_for_mock.side_effect = [{}] |
|
|
monitors_for_mock.side_effect = [{}] |
|
|
record = self.record() |
|
|
record = self.record() |
|
|
provider._monitors_gc(record) |
|
|
provider._monitors_gc(record) |
|
|
@ -1047,10 +1045,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
notifylists_delete_mock.assert_not_called() |
|
|
notifylists_delete_mock.assert_not_called() |
|
|
|
|
|
|
|
|
# No active monitors and one existing, delete all the things |
|
|
# No active monitors and one existing, delete all the things |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
datafeed_delete_mock.reset_mock() |
|
|
|
|
|
monitors_delete_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
monitors_for_mock.side_effect = [{ |
|
|
monitors_for_mock.side_effect = [{ |
|
|
'x': { |
|
|
'x': { |
|
|
'id': 'mon-id', |
|
|
'id': 'mon-id', |
|
|
@ -1070,10 +1065,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
notifylists_delete_mock.assert_has_calls([call('nl-id')]) |
|
|
notifylists_delete_mock.assert_has_calls([call('nl-id')]) |
|
|
|
|
|
|
|
|
# Same existing, this time in active list, should be noop |
|
|
# Same existing, this time in active list, should be noop |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
datafeed_delete_mock.reset_mock() |
|
|
|
|
|
monitors_delete_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
monitors_for_mock.side_effect = [{ |
|
|
monitors_for_mock.side_effect = [{ |
|
|
'x': { |
|
|
'x': { |
|
|
'id': 'mon-id', |
|
|
'id': 'mon-id', |
|
|
@ -1088,10 +1080,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
|
|
|
|
|
|
# Non-active monitor w/o a feed, and another monitor that's left alone |
|
|
# Non-active monitor w/o a feed, and another monitor that's left alone |
|
|
# b/c it's active |
|
|
# b/c it's active |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
datafeed_delete_mock.reset_mock() |
|
|
|
|
|
monitors_delete_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
monitors_for_mock.side_effect = [{ |
|
|
monitors_for_mock.side_effect = [{ |
|
|
'x': { |
|
|
'x': { |
|
|
'id': 'mon-id', |
|
|
'id': 'mon-id', |
|
|
@ -1120,10 +1109,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
|
|
|
|
|
|
# Non-active monitor w/o a notifylist, generally shouldn't happen, but |
|
|
# Non-active monitor w/o a notifylist, generally shouldn't happen, but |
|
|
# code should handle it just in case someone gets clicky in the UI |
|
|
# code should handle it just in case someone gets clicky in the UI |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
datafeed_delete_mock.reset_mock() |
|
|
|
|
|
monitors_delete_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
monitors_for_mock.side_effect = [{ |
|
|
monitors_for_mock.side_effect = [{ |
|
|
'y': { |
|
|
'y': { |
|
|
'id': 'mon-id2', |
|
|
'id': 'mon-id2', |
|
|
@ -1148,11 +1134,8 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
|
|
|
|
|
|
# Non-active monitor with a shared notifylist, monitor deleted, but |
|
|
# Non-active monitor with a shared notifylist, monitor deleted, but |
|
|
# notifylist is left alone |
|
|
# notifylist is left alone |
|
|
|
|
|
reset() |
|
|
provider.shared_notifylist = True |
|
|
provider.shared_notifylist = True |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
datafeed_delete_mock.reset_mock() |
|
|
|
|
|
monitors_delete_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
monitors_for_mock.side_effect = [{ |
|
|
monitors_for_mock.side_effect = [{ |
|
|
'y': { |
|
|
'y': { |
|
|
'id': 'mon-id2', |
|
|
'id': 'mon-id2', |
|
|
@ -1304,6 +1287,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
# provider._params_for_A() calls provider._monitors_for() and |
|
|
# provider._params_for_A() calls provider._monitors_for() and |
|
|
# provider._monitor_sync(). Mock their return values so that we don't |
|
|
# provider._monitor_sync(). Mock their return values so that we don't |
|
|
# make NS1 API calls during tests |
|
|
# make NS1 API calls during tests |
|
|
|
|
|
provider._client.reset_caches() |
|
|
monitors_for_mock.reset_mock() |
|
|
monitors_for_mock.reset_mock() |
|
|
monitor_sync_mock.reset_mock() |
|
|
monitor_sync_mock.reset_mock() |
|
|
monitors_for_mock.side_effect = [{ |
|
|
monitors_for_mock.side_effect = [{ |
|
|
@ -1934,34 +1918,35 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
|
|
|
|
|
|
desired = Zone('unit.tests.', []) |
|
|
desired = Zone('unit.tests.', []) |
|
|
|
|
|
|
|
|
|
|
|
def reset(): |
|
|
|
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
provider._client.reset_caches() |
|
|
|
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
# Empty zone and no changes |
|
|
# Empty zone and no changes |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
|
|
|
|
|
|
extra = provider._extra_changes(desired, []) |
|
|
extra = provider._extra_changes(desired, []) |
|
|
self.assertFalse(extra) |
|
|
self.assertFalse(extra) |
|
|
monitors_for_mock.assert_not_called() |
|
|
monitors_for_mock.assert_not_called() |
|
|
|
|
|
|
|
|
# Non-existent zone. No changes |
|
|
# Non-existent zone. No changes |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
zones_retrieve_mock.side_effect = \ |
|
|
zones_retrieve_mock.side_effect = \ |
|
|
ResourceException('server error: zone not found') |
|
|
ResourceException('server error: zone not found') |
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
extra = provider._extra_changes(desired, []) |
|
|
extra = provider._extra_changes(desired, []) |
|
|
self.assertFalse(extra) |
|
|
self.assertFalse(extra) |
|
|
|
|
|
|
|
|
# Unexpected exception message |
|
|
# Unexpected exception message |
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
zones_retrieve_mock.side_effect = ResourceException('boom') |
|
|
zones_retrieve_mock.side_effect = ResourceException('boom') |
|
|
with self.assertRaises(ResourceException) as ctx: |
|
|
with self.assertRaises(ResourceException) as ctx: |
|
|
extra = provider._extra_changes(desired, []) |
|
|
extra = provider._extra_changes(desired, []) |
|
|
self.assertEquals(zones_retrieve_mock.side_effect, ctx.exception) |
|
|
self.assertEquals(zones_retrieve_mock.side_effect, ctx.exception) |
|
|
|
|
|
|
|
|
# Simple record, ignored, filter update lookups ignored |
|
|
# Simple record, ignored, filter update lookups ignored |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
zones_retrieve_mock.side_effect = \ |
|
|
zones_retrieve_mock.side_effect = \ |
|
|
ResourceException('server error: zone not found') |
|
|
ResourceException('server error: zone not found') |
|
|
|
|
|
|
|
|
@ -2006,9 +1991,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
desired.add_record(dynamic) |
|
|
desired.add_record(dynamic) |
|
|
|
|
|
|
|
|
# untouched, but everything in sync so no change needed |
|
|
# untouched, but everything in sync so no change needed |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
# Generate what we expect to have |
|
|
# Generate what we expect to have |
|
|
gend = provider._monitor_gen(dynamic, '1.2.3.4') |
|
|
gend = provider._monitor_gen(dynamic, '1.2.3.4') |
|
|
gend.update({ |
|
|
gend.update({ |
|
|
@ -2026,9 +2009,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
|
|
|
|
|
|
# If we don't have a notify list we're broken and we'll expect to see |
|
|
# If we don't have a notify list we're broken and we'll expect to see |
|
|
# an Update |
|
|
# an Update |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
del gend['notify_list'] |
|
|
del gend['notify_list'] |
|
|
monitors_for_mock.side_effect = [{ |
|
|
monitors_for_mock.side_effect = [{ |
|
|
'1.2.3.4': gend, |
|
|
'1.2.3.4': gend, |
|
|
@ -2042,9 +2023,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
|
|
|
|
|
|
# Add notify_list back and change the healthcheck protocol, we'll still |
|
|
# Add notify_list back and change the healthcheck protocol, we'll still |
|
|
# expect to see an update |
|
|
# expect to see an update |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
gend['notify_list'] = 'xyz' |
|
|
gend['notify_list'] = 'xyz' |
|
|
dynamic._octodns['healthcheck']['protocol'] = 'HTTPS' |
|
|
dynamic._octodns['healthcheck']['protocol'] = 'HTTPS' |
|
|
del gend['notify_list'] |
|
|
del gend['notify_list'] |
|
|
@ -2059,9 +2038,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
monitors_for_mock.assert_has_calls([call(dynamic)]) |
|
|
monitors_for_mock.assert_has_calls([call(dynamic)]) |
|
|
|
|
|
|
|
|
# If it's in the changed list, it'll be ignored |
|
|
# If it's in the changed list, it'll be ignored |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
extra = provider._extra_changes(desired, [update]) |
|
|
extra = provider._extra_changes(desired, [update]) |
|
|
self.assertFalse(extra) |
|
|
self.assertFalse(extra) |
|
|
monitors_for_mock.assert_not_called() |
|
|
monitors_for_mock.assert_not_called() |
|
|
@ -2069,9 +2046,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
# Test changes in filters |
|
|
# Test changes in filters |
|
|
|
|
|
|
|
|
# No change in filters |
|
|
# No change in filters |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
ns1_zone = { |
|
|
ns1_zone = { |
|
|
'records': [{ |
|
|
'records': [{ |
|
|
"domain": "dyn.unit.tests", |
|
|
"domain": "dyn.unit.tests", |
|
|
@ -2088,9 +2063,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
self.assertFalse(extra) |
|
|
self.assertFalse(extra) |
|
|
|
|
|
|
|
|
# filters need an update |
|
|
# filters need an update |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
ns1_zone = { |
|
|
ns1_zone = { |
|
|
'records': [{ |
|
|
'records': [{ |
|
|
"domain": "dyn.unit.tests", |
|
|
"domain": "dyn.unit.tests", |
|
|
@ -2107,9 +2080,7 @@ class TestNs1ProviderDynamic(TestCase): |
|
|
self.assertTrue(extra) |
|
|
self.assertTrue(extra) |
|
|
|
|
|
|
|
|
# Mixed disabled in filters. Raise Ns1Exception |
|
|
# Mixed disabled in filters. Raise Ns1Exception |
|
|
monitors_for_mock.reset_mock() |
|
|
|
|
|
zones_retrieve_mock.reset_mock() |
|
|
|
|
|
records_retrieve_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
ns1_zone = { |
|
|
ns1_zone = { |
|
|
'records': [{ |
|
|
'records': [{ |
|
|
"domain": "dyn.unit.tests", |
|
|
"domain": "dyn.unit.tests", |
|
|
@ -2234,12 +2205,14 @@ class TestNs1Client(TestCase): |
|
|
client = Ns1Client('dummy-key') |
|
|
client = Ns1Client('dummy-key') |
|
|
|
|
|
|
|
|
# No retry required, just calls and is returned |
|
|
# No retry required, just calls and is returned |
|
|
|
|
|
client.reset_caches() |
|
|
zone_retrieve_mock.reset_mock() |
|
|
zone_retrieve_mock.reset_mock() |
|
|
zone_retrieve_mock.side_effect = ['foo'] |
|
|
zone_retrieve_mock.side_effect = ['foo'] |
|
|
self.assertEquals('foo', client.zones_retrieve('unit.tests')) |
|
|
self.assertEquals('foo', client.zones_retrieve('unit.tests')) |
|
|
zone_retrieve_mock.assert_has_calls([call('unit.tests')]) |
|
|
zone_retrieve_mock.assert_has_calls([call('unit.tests')]) |
|
|
|
|
|
|
|
|
# One retry required |
|
|
# One retry required |
|
|
|
|
|
client.reset_caches() |
|
|
zone_retrieve_mock.reset_mock() |
|
|
zone_retrieve_mock.reset_mock() |
|
|
zone_retrieve_mock.side_effect = [ |
|
|
zone_retrieve_mock.side_effect = [ |
|
|
RateLimitException('boo', period=0), |
|
|
RateLimitException('boo', period=0), |
|
|
@ -2249,6 +2222,7 @@ class TestNs1Client(TestCase): |
|
|
zone_retrieve_mock.assert_has_calls([call('unit.tests')]) |
|
|
zone_retrieve_mock.assert_has_calls([call('unit.tests')]) |
|
|
|
|
|
|
|
|
# Two retries required |
|
|
# Two retries required |
|
|
|
|
|
client.reset_caches() |
|
|
zone_retrieve_mock.reset_mock() |
|
|
zone_retrieve_mock.reset_mock() |
|
|
zone_retrieve_mock.side_effect = [ |
|
|
zone_retrieve_mock.side_effect = [ |
|
|
RateLimitException('boo', period=0), |
|
|
RateLimitException('boo', period=0), |
|
|
@ -2258,6 +2232,7 @@ class TestNs1Client(TestCase): |
|
|
zone_retrieve_mock.assert_has_calls([call('unit.tests')]) |
|
|
zone_retrieve_mock.assert_has_calls([call('unit.tests')]) |
|
|
|
|
|
|
|
|
# Exhaust our retries |
|
|
# Exhaust our retries |
|
|
|
|
|
client.reset_caches() |
|
|
zone_retrieve_mock.reset_mock() |
|
|
zone_retrieve_mock.reset_mock() |
|
|
zone_retrieve_mock.side_effect = [ |
|
|
zone_retrieve_mock.side_effect = [ |
|
|
RateLimitException('first', period=0), |
|
|
RateLimitException('first', period=0), |
|
|
@ -2469,9 +2444,12 @@ class TestNs1Client(TestCase): |
|
|
notifylists_delete_mock): |
|
|
notifylists_delete_mock): |
|
|
client = Ns1Client('dummy-key') |
|
|
client = Ns1Client('dummy-key') |
|
|
|
|
|
|
|
|
notifylists_list_mock.reset_mock() |
|
|
|
|
|
notifylists_create_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
|
|
|
def reset(): |
|
|
|
|
|
notifylists_create_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
notifylists_list_mock.reset_mock() |
|
|
|
|
|
|
|
|
|
|
|
reset() |
|
|
notifylists_list_mock.side_effect = [{}] |
|
|
notifylists_list_mock.side_effect = [{}] |
|
|
expected = { |
|
|
expected = { |
|
|
'id': 'nl-id', |
|
|
'id': 'nl-id', |
|
|
@ -2493,9 +2471,7 @@ class TestNs1Client(TestCase): |
|
|
]) |
|
|
]) |
|
|
notifylists_delete_mock.assert_not_called() |
|
|
notifylists_delete_mock.assert_not_called() |
|
|
|
|
|
|
|
|
notifylists_list_mock.reset_mock() |
|
|
|
|
|
notifylists_create_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
client.notifylists_delete('nlid') |
|
|
client.notifylists_delete('nlid') |
|
|
notifylists_list_mock.assert_not_called() |
|
|
notifylists_list_mock.assert_not_called() |
|
|
notifylists_create_mock.assert_not_called() |
|
|
notifylists_create_mock.assert_not_called() |
|
|
@ -2503,9 +2479,7 @@ class TestNs1Client(TestCase): |
|
|
|
|
|
|
|
|
# Delete again, this time with a cache item that needs cleaned out and |
|
|
# Delete again, this time with a cache item that needs cleaned out and |
|
|
# another that needs to be ignored |
|
|
# another that needs to be ignored |
|
|
notifylists_list_mock.reset_mock() |
|
|
|
|
|
notifylists_create_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
client._notifylists_cache = { |
|
|
client._notifylists_cache = { |
|
|
'another': { |
|
|
'another': { |
|
|
'id': 'notid', |
|
|
'id': 'notid', |
|
|
@ -2524,9 +2498,7 @@ class TestNs1Client(TestCase): |
|
|
# Only another left |
|
|
# Only another left |
|
|
self.assertEquals(['another'], list(client._notifylists_cache.keys())) |
|
|
self.assertEquals(['another'], list(client._notifylists_cache.keys())) |
|
|
|
|
|
|
|
|
notifylists_list_mock.reset_mock() |
|
|
|
|
|
notifylists_create_mock.reset_mock() |
|
|
|
|
|
notifylists_delete_mock.reset_mock() |
|
|
|
|
|
|
|
|
reset() |
|
|
expected = ['one', 'two', 'three'] |
|
|
expected = ['one', 'two', 'three'] |
|
|
notifylists_list_mock.side_effect = [expected] |
|
|
notifylists_list_mock.side_effect = [expected] |
|
|
nls = client.notifylists_list() |
|
|
nls = client.notifylists_list() |
|
|
@ -2534,3 +2506,150 @@ class TestNs1Client(TestCase): |
|
|
notifylists_list_mock.assert_has_calls([call()]) |
|
|
notifylists_list_mock.assert_has_calls([call()]) |
|
|
notifylists_create_mock.assert_not_called() |
|
|
notifylists_create_mock.assert_not_called() |
|
|
notifylists_delete_mock.assert_not_called() |
|
|
notifylists_delete_mock.assert_not_called() |
|
|
|
|
|
|
|
|
|
|
|
@patch('ns1.rest.records.Records.delete') |
|
|
|
|
|
@patch('ns1.rest.records.Records.update') |
|
|
|
|
|
@patch('ns1.rest.records.Records.create') |
|
|
|
|
|
@patch('ns1.rest.records.Records.retrieve') |
|
|
|
|
|
@patch('ns1.rest.zones.Zones.create') |
|
|
|
|
|
@patch('ns1.rest.zones.Zones.delete') |
|
|
|
|
|
@patch('ns1.rest.zones.Zones.retrieve') |
|
|
|
|
|
def test_client_caching(self, zone_retrieve_mock, zone_delete_mock, |
|
|
|
|
|
zone_create_mock, record_retrieve_mock, |
|
|
|
|
|
record_create_mock, record_update_mock, |
|
|
|
|
|
record_delete_mock): |
|
|
|
|
|
client = Ns1Client('dummy-key') |
|
|
|
|
|
|
|
|
|
|
|
def reset(): |
|
|
|
|
|
zone_retrieve_mock.reset_mock() |
|
|
|
|
|
zone_delete_mock.reset_mock() |
|
|
|
|
|
zone_create_mock.reset_mock() |
|
|
|
|
|
record_retrieve_mock.reset_mock() |
|
|
|
|
|
record_create_mock.reset_mock() |
|
|
|
|
|
record_update_mock.reset_mock() |
|
|
|
|
|
record_delete_mock.reset_mock() |
|
|
|
|
|
# Testing caches so we don't reset those |
|
|
|
|
|
|
|
|
|
|
|
# Initial zone get fetches and caches |
|
|
|
|
|
reset() |
|
|
|
|
|
zone_retrieve_mock.side_effect = ['foo'] |
|
|
|
|
|
self.assertEquals('foo', client.zones_retrieve('unit.tests')) |
|
|
|
|
|
zone_retrieve_mock.assert_has_calls([call('unit.tests')]) |
|
|
|
|
|
self.assertEquals({ |
|
|
|
|
|
'unit.tests': 'foo', |
|
|
|
|
|
}, client._zones_cache) |
|
|
|
|
|
|
|
|
|
|
|
# Subsequent zone get does not fetch and returns from cache |
|
|
|
|
|
reset() |
|
|
|
|
|
self.assertEquals('foo', client.zones_retrieve('unit.tests')) |
|
|
|
|
|
zone_retrieve_mock.assert_not_called() |
|
|
|
|
|
|
|
|
|
|
|
# Zone create stores in cache |
|
|
|
|
|
reset() |
|
|
|
|
|
zone_create_mock.side_effect = ['bar'] |
|
|
|
|
|
self.assertEquals('bar', client.zones_create('sub.unit.tests')) |
|
|
|
|
|
zone_create_mock.assert_has_calls([call('sub.unit.tests')]) |
|
|
|
|
|
self.assertEquals({ |
|
|
|
|
|
'sub.unit.tests': 'bar', |
|
|
|
|
|
'unit.tests': 'foo', |
|
|
|
|
|
}, client._zones_cache) |
|
|
|
|
|
|
|
|
|
|
|
# Initial record get fetches and caches |
|
|
|
|
|
reset() |
|
|
|
|
|
record_retrieve_mock.side_effect = ['baz'] |
|
|
|
|
|
self.assertEquals('baz', client.records_retrieve('unit.tests', |
|
|
|
|
|
'a.unit.tests', 'A')) |
|
|
|
|
|
record_retrieve_mock.assert_has_calls([call('unit.tests', |
|
|
|
|
|
'a.unit.tests', 'A')]) |
|
|
|
|
|
self.assertEquals({ |
|
|
|
|
|
'unit.tests': { |
|
|
|
|
|
'a.unit.tests': { |
|
|
|
|
|
'A': 'baz' |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}, client._records_cache) |
|
|
|
|
|
|
|
|
|
|
|
# Subsequent record get does not fetch and returns from cache |
|
|
|
|
|
reset() |
|
|
|
|
|
self.assertEquals('baz', client.records_retrieve('unit.tests', |
|
|
|
|
|
'a.unit.tests', 'A')) |
|
|
|
|
|
record_retrieve_mock.assert_not_called() |
|
|
|
|
|
|
|
|
|
|
|
# Record create stores in cache |
|
|
|
|
|
reset() |
|
|
|
|
|
record_create_mock.side_effect = ['boo'] |
|
|
|
|
|
self.assertEquals('boo', client.records_create('unit.tests', |
|
|
|
|
|
'aaaa.unit.tests', |
|
|
|
|
|
'AAAA', key='val')) |
|
|
|
|
|
record_create_mock.assert_has_calls([call('unit.tests', |
|
|
|
|
|
'aaaa.unit.tests', 'AAAA', |
|
|
|
|
|
key='val')]) |
|
|
|
|
|
self.assertEquals({ |
|
|
|
|
|
'unit.tests': { |
|
|
|
|
|
'a.unit.tests': { |
|
|
|
|
|
'A': 'baz' |
|
|
|
|
|
}, |
|
|
|
|
|
'aaaa.unit.tests': { |
|
|
|
|
|
'AAAA': 'boo' |
|
|
|
|
|
}, |
|
|
|
|
|
} |
|
|
|
|
|
}, client._records_cache) |
|
|
|
|
|
|
|
|
|
|
|
# Record delete removes from cache and removes zone |
|
|
|
|
|
reset() |
|
|
|
|
|
record_delete_mock.side_effect = [{}] |
|
|
|
|
|
self.assertEquals({}, client.records_delete('unit.tests', |
|
|
|
|
|
'aaaa.unit.tests', |
|
|
|
|
|
'AAAA')) |
|
|
|
|
|
record_delete_mock.assert_has_calls([call('unit.tests', |
|
|
|
|
|
'aaaa.unit.tests', 'AAAA')]) |
|
|
|
|
|
self.assertEquals({ |
|
|
|
|
|
'unit.tests': { |
|
|
|
|
|
'a.unit.tests': { |
|
|
|
|
|
'A': 'baz' |
|
|
|
|
|
}, |
|
|
|
|
|
'aaaa.unit.tests': {}, |
|
|
|
|
|
} |
|
|
|
|
|
}, client._records_cache) |
|
|
|
|
|
self.assertEquals({ |
|
|
|
|
|
'sub.unit.tests': 'bar', |
|
|
|
|
|
}, client._zones_cache) |
|
|
|
|
|
|
|
|
|
|
|
# Delete the other record, no zone this time, record should still go |
|
|
|
|
|
# away |
|
|
|
|
|
reset() |
|
|
|
|
|
record_delete_mock.side_effect = [{}] |
|
|
|
|
|
self.assertEquals({}, client.records_delete('unit.tests', |
|
|
|
|
|
'a.unit.tests', 'A')) |
|
|
|
|
|
record_delete_mock.assert_has_calls([call('unit.tests', 'a.unit.tests', |
|
|
|
|
|
'A')]) |
|
|
|
|
|
self.assertEquals({ |
|
|
|
|
|
'unit.tests': { |
|
|
|
|
|
'a.unit.tests': {}, |
|
|
|
|
|
'aaaa.unit.tests': {}, |
|
|
|
|
|
} |
|
|
|
|
|
}, client._records_cache) |
|
|
|
|
|
self.assertEquals({ |
|
|
|
|
|
'sub.unit.tests': 'bar', |
|
|
|
|
|
}, client._zones_cache) |
|
|
|
|
|
|
|
|
|
|
|
# Record update removes zone and caches result |
|
|
|
|
|
record_update_mock.side_effect = ['done'] |
|
|
|
|
|
self.assertEquals('done', client.records_update('sub.unit.tests', |
|
|
|
|
|
'aaaa.sub.unit.tests', |
|
|
|
|
|
'AAAA', key='val')) |
|
|
|
|
|
record_update_mock.assert_has_calls([call('sub.unit.tests', |
|
|
|
|
|
'aaaa.sub.unit.tests', |
|
|
|
|
|
'AAAA', key='val')]) |
|
|
|
|
|
self.assertEquals({ |
|
|
|
|
|
'unit.tests': { |
|
|
|
|
|
'a.unit.tests': {}, |
|
|
|
|
|
'aaaa.unit.tests': {}, |
|
|
|
|
|
}, |
|
|
|
|
|
'sub.unit.tests': { |
|
|
|
|
|
'aaaa.sub.unit.tests': { |
|
|
|
|
|
'AAAA': 'done', |
|
|
|
|
|
}, |
|
|
|
|
|
} |
|
|
|
|
|
}, client._records_cache) |
|
|
|
|
|
self.assertEquals({}, client._zones_cache) |