def test_invalid_a(self): with self.assertRaises(Exception) as ctx: ARecord(self.zone, 'a', { 'ttl': 30, 'value': 'foo', }) self.assertTrue('Invalid record' in ctx.exception.message) with self.assertRaises(Exception) as ctx: ARecord(self.zone, 'a', { 'ttl': 30, 'values': ['1.2.3.4', 'bar'], }) self.assertTrue('Invalid record' in ctx.exception.message)
def test_copy(self): zone = Zone('unit.tests.', []) a = ARecord(zone, 'a', {'ttl': 42, 'value': '1.1.1.1'}) zone.add_record(a) b = ARecord(zone, 'b', {'ttl': 42, 'value': '1.1.1.2'}) zone.add_record(b) # Sanity check self.assertEqualsNameAndValues(set((a, b)), zone.records) copy = zone.copy() # We have an origin set and it is the source/original zone self.assertEquals(zone, copy._origin) # Our records are zone's records to start (references) self.assertEqualsNameAndValues(zone.records, copy.records) # If we try and change something that's already there we realize and # then get an error about a duplicate b_prime = ARecord(zone, 'b', {'ttl': 42, 'value': '1.1.1.3'}) with self.assertRaises(DuplicateRecordException): copy.add_record(b_prime) self.assertIsNone(copy._origin) # Unchanged, straight copies self.assertEqualsNameAndValues(zone.records, copy.records) # If we add with replace things will be realized and the record will # have changed copy = zone.copy() copy.add_record(b_prime, replace=True) self.assertIsNone(copy._origin) self.assertEqualsNameAndValues(set((a, b_prime)), copy.records) # If we add another record, things are reliazed and it has been added copy = zone.copy() c = ARecord(zone, 'c', {'ttl': 42, 'value': '1.1.1.3'}) copy.add_record(c) self.assertEqualsNameAndValues(set((a, b, c)), copy.records) # If we remove a record, things are reliazed and it has been removed copy = zone.copy() copy.remove_record(a) self.assertEqualsNameAndValues(set((b, )), copy.records) # Re-realizing is a noop copy = zone.copy() # Happens the first time self.assertTrue(copy.hydrate()) # Doesn't the second self.assertFalse(copy.hydrate())
def test_unsupporting(self): class NoAaaaProvider(object): id = 'no-aaaa' SUPPORTS_GEO = False def supports(self, record): return record._type != 'AAAA' current = Zone('unit.tests.', []) desired = Zone('unit.tests.', []) a = ARecord(desired, 'a', {'ttl': 42, 'value': '1.1.1.1'}) desired.add_record(a) aaaa = AaaaRecord(desired, 'b', {'ttl': 42, 'value': '1:1:1::1'}) desired.add_record(aaaa) # Only create the supported A, not the AAAA changes = current.changes(desired, NoAaaaProvider()) self.assertEquals(1, len(changes)) self.assertIsInstance(changes[0], Create) # Only delete the supported A, not the AAAA changes = desired.changes(current, NoAaaaProvider()) self.assertEquals(1, len(changes)) self.assertIsInstance(changes[0], Delete)
def test_lowering(self): record = ARecord(self.zone, 'MiXeDcAsE', { 'ttl': 30, 'type': 'A', 'value': '1.2.3.4', }) self.assertEquals('mixedcase', record.name)
def test_add_record(self): zone = Zone('unit.tests.', []) a = ARecord(zone, 'a', {'ttl': 42, 'value': '1.1.1.1'}) b = ARecord(zone, 'b', {'ttl': 42, 'value': '1.1.1.1'}) zone.add_record(a) self.assertEquals(zone.records, set([a])) # Can't add record with same name & type with self.assertRaises(DuplicateRecordException) as ctx: zone.add_record(a) self.assertEquals('Duplicate record a.unit.tests., type A', ctx.exception.message) self.assertEquals(zone.records, set([a])) # Can add dup name, with different type zone.add_record(b) self.assertEquals(zone.records, set([a, b]))
def test_root_ns(self): zone = Zone('unit.tests.', []) a = ARecord(zone, 'a', {'ttl': 42, 'value': '1.1.1.1'}) zone.add_record(a) # No root NS yet self.assertFalse(zone.root_ns) non_root_ns = NsRecord( zone, 'sub', { 'ttl': 42, 'values': ('ns1.unit.tests.', 'ns2.unit.tests.') }, ) zone.add_record(non_root_ns) # No root NS yet b/c this was a sub self.assertFalse(zone.root_ns) root_ns = NsRecord( zone, '', { 'ttl': 42, 'values': ('ns3.unit.tests.', 'ns4.unit.tests.') }, ) zone.add_record(root_ns) # Now we have a root NS self.assertEqual(root_ns, zone.root_ns) # make a copy, it has a root_ns copy = zone.copy() self.assertEqual(root_ns, copy.root_ns) # remove the root NS from it and we don't copy.remove_record(root_ns) self.assertFalse(copy.root_ns) # original still does though self.assertEqual(root_ns, zone.root_ns) # remove the A, still has root NS zone.remove_record(a) self.assertEqual(root_ns, zone.root_ns) # remove the sub NS, still has root NS zone.remove_record(non_root_ns) self.assertEqual(root_ns, zone.root_ns) # finally remove the root NS, no more zone.remove_record(root_ns) self.assertFalse(zone.root_ns)
def test_add_record(self): zone = Zone('unit.tests.', []) a = ARecord(zone, 'a', {'ttl': 42, 'value': '1.1.1.1'}) b = ARecord(zone, 'b', {'ttl': 42, 'value': '1.1.1.1'}) c = ARecord(zone, 'a', {'ttl': 43, 'value': '2.2.2.2'}) zone.add_record(a) self.assertEquals(zone.records, set([a])) # Can't add record with same name & type with self.assertRaises(DuplicateRecordException) as ctx: zone.add_record(a) self.assertEquals('Duplicate record a.unit.tests., type A', text_type(ctx.exception)) self.assertEquals(zone.records, set([a])) # can add duplicate with replace=True zone.add_record(c, replace=True) self.assertEquals('2.2.2.2', list(zone.records)[0].values[0]) # Can add dup name, with different type zone.add_record(b) self.assertEquals(zone.records, set([a, b]))
def test_changes(self): before = Zone('unit.tests.', []) a = ARecord(before, 'a', {'ttl': 42, 'value': '1.1.1.1'}) before.add_record(a) b = AaaaRecord(before, 'b', {'ttl': 42, 'value': '1:1:1::1'}) before.add_record(b) after = Zone('unit.tests.', []) after.add_record(a) after.add_record(b) target = SimpleProvider() # before == after -> no changes self.assertFalse(before.changes(after, target)) # add a record, delete a record -> [Delete, Create] c = ARecord(before, 'c', {'ttl': 42, 'value': '1.1.1.1'}) after.add_record(c) after._remove_record(b) self.assertEquals(after.records, set([a, c])) changes = before.changes(after, target) self.assertEquals(2, len(changes)) for change in changes: if isinstance(change, Create): create = change elif isinstance(change, Delete): delete = change self.assertEquals(b, delete.existing) self.assertFalse(delete.new) self.assertEquals(c, create.new) self.assertFalse(create.existing) delete.__repr__() create.__repr__() after = Zone('unit.tests.', []) changed = ARecord(before, 'a', {'ttl': 42, 'value': '2.2.2.2'}) after.add_record(changed) after.add_record(b) changes = before.changes(after, target) self.assertEquals(1, len(changes)) update = changes[0] self.assertIsInstance(update, Update) # Using changes here to get a full equality self.assertFalse(a.changes(update.existing, target)) self.assertFalse(changed.changes(update.new, target)) update.__repr__()
def test_a_and_record(self): a_values = ['1.2.3.4', '2.2.3.4'] a_data = {'ttl': 30, 'values': a_values} a = ARecord(self.zone, 'a', a_data) self.assertEquals('a', a.name) self.assertEquals('a.unit.tests.', a.fqdn) self.assertEquals(30, a.ttl) self.assertEquals(a_values, a.values) self.assertEquals(a_data, a.data) b_value = '3.2.3.4' b_data = {'ttl': 30, 'value': b_value} b = ARecord(self.zone, 'b', b_data) self.assertEquals([b_value], b.values) self.assertEquals(b_data, b.data) # top-level data = {'ttl': 30, 'value': '4.2.3.4'} self.assertEquals(self.zone.name, ARecord(self.zone, '', data).fqdn) self.assertEquals(self.zone.name, ARecord(self.zone, None, data).fqdn) # ARecord equate with itself self.assertTrue(a == a) # Records with differing names and same type don't equate self.assertFalse(a == b) # Records with same name & type equate even if ttl is different self.assertTrue(a == ARecord(self.zone, 'a', { 'ttl': 31, 'values': a_values })) # Records with same name & type equate even if values are different self.assertTrue(a == ARecord(self.zone, 'a', { 'ttl': 30, 'value': b_value })) target = SimpleProvider() # no changes if self self.assertFalse(a.changes(a, target)) # no changes if clone other = ARecord(self.zone, 'a', {'ttl': 30, 'values': a_values}) self.assertFalse(a.changes(other, target)) # changes if ttl modified other.ttl = 31 update = a.changes(other, target) self.assertEquals(a, update.existing) self.assertEquals(other, update.new) # changes if values modified other.ttl = a.ttl other.values = ['4.4.4.4'] update = a.changes(other, target) self.assertEquals(a, update.existing) self.assertEquals(other, update.new) # Hashing records = set() records.add(a) self.assertTrue(a in records) self.assertFalse(b in records) records.add(b) self.assertTrue(b in records) # __repr__ doesn't blow up a.__repr__() # Record.__repr__ does with self.assertRaises(NotImplementedError): class DummyRecord(Record): def __init__(self): pass DummyRecord().__repr__()
def test_geo(self): geo_data = { 'ttl': 42, 'values': ['5.2.3.4', '6.2.3.4'], 'geo': { 'AF': ['1.1.1.1'], 'AS-JP': ['2.2.2.2', '3.3.3.3'], 'NA-US': ['4.4.4.4', '5.5.5.5'], 'NA-US-CA': ['6.6.6.6', '7.7.7.7'] } } geo = ARecord(self.zone, 'geo', geo_data) self.assertEquals(geo_data, geo.data) other_data = { 'ttl': 42, 'values': ['5.2.3.4', '6.2.3.4'], 'geo': { 'AF': ['1.1.1.1'], 'AS-JP': ['2.2.2.2', '3.3.3.3'], 'NA-US': ['4.4.4.4', '5.5.5.5'], 'NA-US-CA': ['6.6.6.6', '7.7.7.7'] } } other = ARecord(self.zone, 'geo', other_data) self.assertEquals(other_data, other.data) simple_target = SimpleProvider() geo_target = GeoProvider() # Geo provider doesn't consider identical geo to be changes self.assertFalse(geo.changes(geo, geo_target)) # geo values don't impact equality other.geo['AF'].values = ['9.9.9.9'] self.assertTrue(geo == other) # Non-geo supporting provider doesn't consider geo diffs to be changes self.assertFalse(geo.changes(other, simple_target)) # Geo provider does consider geo diffs to be changes self.assertTrue(geo.changes(other, geo_target)) # Object without geo doesn't impact equality other.geo = {} self.assertTrue(geo == other) # Non-geo supporting provider doesn't consider lack of geo a diff self.assertFalse(geo.changes(other, simple_target)) # Geo provider does consider lack of geo diffs to be changes self.assertTrue(geo.changes(other, geo_target)) # __repr__ doesn't blow up geo.__repr__()