def test_aggregate_target(self): simple = SimpleProvider() geo = GeoProvider() dynamic = DynamicProvider() nosshfp = NoSshFpProvider() self.assertFalse(_AggregateTarget([simple, simple]).SUPPORTS_GEO) self.assertFalse(_AggregateTarget([simple, geo]).SUPPORTS_GEO) self.assertFalse(_AggregateTarget([geo, simple]).SUPPORTS_GEO) self.assertTrue(_AggregateTarget([geo, geo]).SUPPORTS_GEO) self.assertFalse(_AggregateTarget([simple, simple]).SUPPORTS_DYNAMIC) self.assertFalse(_AggregateTarget([simple, dynamic]).SUPPORTS_DYNAMIC) self.assertFalse(_AggregateTarget([dynamic, simple]).SUPPORTS_DYNAMIC) self.assertTrue(_AggregateTarget([dynamic, dynamic]).SUPPORTS_DYNAMIC) zone = Zone('unit.tests.', []) record = Record.new( zone, 'sshfp', { 'ttl': 60, 'type': 'SSHFP', 'value': { 'algorithm': 1, 'fingerprint_type': 1, 'fingerprint': 'abcdefg', }, }) self.assertTrue(simple.supports(record)) self.assertFalse(nosshfp.supports(record)) self.assertTrue(_AggregateTarget([simple, simple]).supports(record)) self.assertFalse(_AggregateTarget([simple, nosshfp]).supports(record))
def test_aggregate_target(self): simple = SimpleProvider() geo = GeoProvider() dynamic = DynamicProvider() nosshfp = NoSshFpProvider() targets = [simple, geo] at = _AggregateTarget(targets) # expected targets self.assertEqual(targets, at.targets) # union of their SUPPORTS self.assertEqual(set(('A')), at.SUPPORTS) # unknown property will go up into super and throw the normal # exception with self.assertRaises(AttributeError) as ctx: at.FOO self.assertEqual('_AggregateTarget object has no attribute FOO', str(ctx.exception)) self.assertFalse(_AggregateTarget([simple, simple]).SUPPORTS_GEO) self.assertFalse(_AggregateTarget([simple, geo]).SUPPORTS_GEO) self.assertFalse(_AggregateTarget([geo, simple]).SUPPORTS_GEO) self.assertTrue(_AggregateTarget([geo, geo]).SUPPORTS_GEO) self.assertFalse(_AggregateTarget([simple, simple]).SUPPORTS_DYNAMIC) self.assertFalse(_AggregateTarget([simple, dynamic]).SUPPORTS_DYNAMIC) self.assertFalse(_AggregateTarget([dynamic, simple]).SUPPORTS_DYNAMIC) self.assertTrue(_AggregateTarget([dynamic, dynamic]).SUPPORTS_DYNAMIC) zone = Zone('unit.tests.', []) record = Record.new( zone, 'sshfp', { 'ttl': 60, 'type': 'SSHFP', 'value': { 'algorithm': 1, 'fingerprint_type': 1, 'fingerprint': 'abcdefg', }, }, ) self.assertTrue(simple.supports(record)) self.assertFalse(nosshfp.supports(record)) self.assertTrue(_AggregateTarget([simple, simple]).supports(record)) self.assertFalse(_AggregateTarget([simple, nosshfp]).supports(record))
def assertSingleValue(self, _type, a_value, b_value): a_data = {'ttl': 30, 'value': a_value} a = _type(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_value, a.value) self.assertEquals(a_data, a.data) b_data = {'ttl': 30, 'value': b_value} b = _type(self.zone, 'b', b_data) self.assertEquals(b_value, b.value) self.assertEquals(b_data, b.data) target = SimpleProvider() # No changes with self self.assertFalse(a.changes(a, target)) # Diff in value causes change other = _type(self.zone, 'a', {'ttl': 30, 'value': b_value}) change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # __repr__ doesn't blow up a.__repr__()
def test_populate_in_addr_arpa(self): got = Zone('3.2.10.in-addr.arpa.', []) self.source.populate(got) expected = Zone('3.2.10.in-addr.arpa.', []) for name, data in ( ('10', { 'type': 'PTR', 'ttl': 3600, 'value': 'a-ptr.example.com.' }), ('11', { 'type': 'PTR', 'ttl': 30, 'value': 'a-ptr-2.example.com.' }), ('8', { 'type': 'PTR', 'ttl': 3600, 'value': 'has-dup-def123.example.com.' }), ('7', { 'type': 'PTR', 'ttl': 1800, 'value': 'some-host-abc123.example.com.' }), ): record = Record.new(expected, name, data) expected.add_record(record) changes = expected.changes(got, SimpleProvider()) self.assertEqual([], changes)
def test_not_included_records(self): zone_normal = Zone('unit.tests.', []) zone_included = Zone('unit.tests.', []) zone_missing = Zone('unit.tests.', []) normal = Record.new(zone_normal, 'www', { 'ttl': 60, 'type': 'A', 'value': '9.9.9.9', }) zone_normal.add_record(normal) included = Record.new(zone_included, 'www', { 'octodns': { 'included': ['not-here'] }, 'ttl': 60, 'type': 'A', 'value': '9.9.9.9', }) zone_included.add_record(included) provider = SimpleProvider() self.assertFalse(zone_normal.changes(zone_included, provider)) self.assertTrue(zone_normal.changes(zone_missing, provider)) self.assertFalse(zone_included.changes(zone_normal, provider)) self.assertFalse(zone_included.changes(zone_missing, provider)) self.assertTrue(zone_missing.changes(zone_normal, provider)) self.assertFalse(zone_missing.changes(zone_included, provider))
def test_sshfp(self): a_values = [{ 'algorithm': 10, 'fingerprint_type': 11, 'fingerprint': 'abc123', }, { 'algorithm': 20, 'fingerprint_type': 21, 'fingerprint': 'def456', }] a_data = {'ttl': 30, 'values': a_values} a = SshfpRecord(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[0]['algorithm'], a.values[0].algorithm) self.assertEquals(a_values[0]['fingerprint_type'], a.values[0].fingerprint_type) self.assertEquals(a_values[0]['fingerprint'], a.values[0].fingerprint) self.assertEquals(a_data, a.data) b_value = { 'algorithm': 30, 'fingerprint_type': 31, 'fingerprint': 'ghi789', } b_data = {'ttl': 30, 'value': b_value} b = SshfpRecord(self.zone, 'b', b_data) self.assertEquals(b_value['algorithm'], b.values[0].algorithm) self.assertEquals(b_value['fingerprint_type'], b.values[0].fingerprint_type) self.assertEquals(b_value['fingerprint'], b.values[0].fingerprint) self.assertEquals(b_data, b.data) target = SimpleProvider() # No changes with self self.assertFalse(a.changes(a, target)) # Diff in algorithm causes change other = SshfpRecord(self.zone, 'a', {'ttl': 30, 'values': a_values}) other.values[0].algorithm = 22 change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # Diff in fingerprint_type causes change other = SshfpRecord(self.zone, 'a', {'ttl': 30, 'values': a_values}) other.values[0].algorithm = a.values[0].algorithm other.values[0].fingerprint_type = 22 change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # Diff in fingerprint causes change other = SshfpRecord(self.zone, 'a', {'ttl': 30, 'values': a_values}) other.values[0].fingerprint_type = a.values[0].fingerprint_type other.values[0].fingerprint = 22 change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # __repr__ doesn't blow up a.__repr__()
def test_caa(self): a_values = [{ 'flags': 0, 'tag': 'issue', 'value': 'ca.example.net', }, { 'flags': 128, 'tag': 'iodef', 'value': 'mailto:[email protected]', }] a_data = {'ttl': 30, 'values': a_values} a = CaaRecord(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[0]['flags'], a.values[0].flags) self.assertEquals(a_values[0]['tag'], a.values[0].tag) self.assertEquals(a_values[0]['value'], a.values[0].value) self.assertEquals(a_values[1]['flags'], a.values[1].flags) self.assertEquals(a_values[1]['tag'], a.values[1].tag) self.assertEquals(a_values[1]['value'], a.values[1].value) self.assertEquals(a_data, a.data) b_value = { 'tag': 'iodef', 'value': 'http://iodef.example.com/', } b_data = {'ttl': 30, 'value': b_value} b = CaaRecord(self.zone, 'b', b_data) self.assertEquals(0, b.values[0].flags) self.assertEquals(b_value['tag'], b.values[0].tag) self.assertEquals(b_value['value'], b.values[0].value) b_data['value']['flags'] = 0 self.assertEquals(b_data, b.data) target = SimpleProvider() # No changes with self self.assertFalse(a.changes(a, target)) # Diff in flags causes change other = CaaRecord(self.zone, 'a', {'ttl': 30, 'values': a_values}) other.values[0].flags = 128 change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # Diff in tag causes change other.values[0].flags = a.values[0].flags other.values[0].tag = 'foo' change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # Diff in value causes change other.values[0].tag = a.values[0].tag other.values[0].value = 'bar' change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # __repr__ doesn't blow up a.__repr__()
def test_mx(self): a_values = [{ 'priority': 10, 'value': 'smtp1' }, { 'priority': 20, 'value': 'smtp2' }] a_data = {'ttl': 30, 'values': a_values} a = MxRecord(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[0]['priority'], a.values[0].priority) self.assertEquals(a_values[0]['value'], a.values[0].value) self.assertEquals(a_values[1]['priority'], a.values[1].priority) self.assertEquals(a_values[1]['value'], a.values[1].value) self.assertEquals(a_data, a.data) b_value = { 'priority': 12, 'value': 'smtp3', } b_data = {'ttl': 30, 'value': b_value} b = MxRecord(self.zone, 'b', b_data) self.assertEquals(b_value['priority'], b.values[0].priority) self.assertEquals(b_value['value'], b.values[0].value) self.assertEquals(b_data, b.data) # missing value with self.assertRaises(Exception) as ctx: MxRecord(self.zone, None, {'ttl': 42}) self.assertTrue('missing value(s)' in ctx.exception.message) # invalid value with self.assertRaises(Exception) as ctx: MxRecord(self.zone, None, {'ttl': 42, 'value': {}}) self.assertTrue('Invalid value' in ctx.exception.message) target = SimpleProvider() # No changes with self self.assertFalse(a.changes(a, target)) # Diff in priority causes change other = MxRecord(self.zone, 'a', {'ttl': 30, 'values': a_values}) other.values[0].priority = 22 change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # Diff in value causes change other.values[0].priority = a.values[0].priority other.values[0].value = 'smtpX' change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # __repr__ doesn't blow up a.__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__()
def test_mx(self): a_values = [{ 'preference': 10, 'exchange': 'smtp1.' }, { 'priority': 20, 'value': 'smtp2.' }] a_data = {'ttl': 30, 'values': a_values} a = MxRecord(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[0]['preference'], a.values[0].preference) self.assertEquals(a_values[0]['exchange'], a.values[0].exchange) self.assertEquals(a_values[1]['priority'], a.values[1].preference) self.assertEquals(a_values[1]['value'], a.values[1].exchange) a_data['values'][1] = { 'preference': 20, 'exchange': 'smtp2.', } self.assertEquals(a_data, a.data) b_value = { 'preference': 12, 'exchange': 'smtp3.', } b_data = {'ttl': 30, 'value': b_value} b = MxRecord(self.zone, 'b', b_data) self.assertEquals(b_value['preference'], b.values[0].preference) self.assertEquals(b_value['exchange'], b.values[0].exchange) self.assertEquals(b_data, b.data) target = SimpleProvider() # No changes with self self.assertFalse(a.changes(a, target)) # Diff in preference causes change other = MxRecord(self.zone, 'a', {'ttl': 30, 'values': a_values}) other.values[0].preference = 22 change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # Diff in value causes change other.values[0].preference = a.values[0].preference other.values[0].exchange = 'smtpX' change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # __repr__ doesn't blow up a.__repr__()
def test_populate_normal_sub1(self): got = Zone('asdf.subtest.com.', []) self.source.populate(got) self.assertEquals(1, len(got.records)) expected = Zone('asdf.subtest.com.', []) for name, data in (('a3', { 'type': 'A', 'ttl': 3600, 'values': ['10.2.3.7'], }), ): record = Record.new(expected, name, data) expected.add_record(record) changes = expected.changes(got, SimpleProvider()) self.assertEquals([], changes)
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_populate(self, execute_mock): provider = DynProvider('test', 'cust', 'user', 'pass') # Test Zone create execute_mock.side_effect = [ # get Zone { 'data': {} }, # get_all_records { 'data': { 'a_records': [{ 'fqdn': 'www.unit.tests', 'rdata': { 'address': '1.2.3.4' }, 'record_id': 1, 'record_type': 'A', 'ttl': 300, 'zone': 'unit.tests', }], 'alias_records': [{ 'fqdn': 'unit.tests', 'rdata': { 'alias': 'www.unit.tests.' }, 'record_id': 2, 'record_type': 'ALIAS', 'ttl': 300, 'zone': 'unit.tests', }], } } ] got = Zone('unit.tests.', []) provider.populate(got) execute_mock.assert_has_calls([ call('/Zone/unit.tests/', 'GET', {}), call('/AllRecord/unit.tests/unit.tests./', 'GET', {'detail': 'Y'}) ]) changes = self.expected.changes(got, SimpleProvider()) self.assertEquals([], changes)
def test_alias(self): a_data = {'ttl': 0, 'value': 'www.unit.tests.'} a = AliasRecord(self.zone, '', a_data) self.assertEquals('', a.name) self.assertEquals('unit.tests.', a.fqdn) self.assertEquals(0, a.ttl) self.assertEquals(a_data['value'], a.value) self.assertEquals(a_data, a.data) target = SimpleProvider() # No changes with self self.assertFalse(a.changes(a, target)) # Diff in value causes change other = AliasRecord(self.zone, 'a', a_data) other.value = 'foo.unit.tests.' change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # __repr__ doesn't blow up a.__repr__()
def test_populate_normal(self): got = Zone('example.com.', []) self.source.populate(got) self.assertEquals(11, len(got.records)) expected = Zone('example.com.', []) for name, data in ( ('', { 'type': 'A', 'ttl': 30, 'values': ['10.2.3.4', '10.2.3.5'], }), ('sub', { 'type': 'NS', 'ttl': 30, 'values': ['ns1.ns.com.', 'ns2.ns.com.'], }), ('www', { 'type': 'A', 'ttl': 3600, 'value': '10.2.3.6', }), ('cname', { 'type': 'CNAME', 'ttl': 3600, 'value': 'www.example.com.', }), ('some-host-abc123', { 'type': 'A', 'ttl': 1800, 'value': '10.2.3.7', }), ('has-dup-def123', { 'type': 'A', 'ttl': 3600, 'value': '10.2.3.8', }), ('www.sub', { 'type': 'A', 'ttl': 3600, 'value': '1.2.3.4', }), ('has-dup-def456', { 'type': 'A', 'ttl': 3600, 'value': '10.2.3.8', }), ('', { 'type': 'MX', 'ttl': 3600, 'values': [{ 'priority': 10, 'value': 'smtp-1-host.example.com.', }, { 'priority': 20, 'value': 'smtp-2-host.example.com.', }] }), ('smtp', { 'type': 'MX', 'ttl': 1800, 'values': [{ 'priority': 30, 'value': 'smtp-1-host.example.com.', }, { 'priority': 40, 'value': 'smtp-2-host.example.com.', }] }), ): record = Record.new(expected, name, data) expected.add_record(record) changes = expected.changes(got, SimpleProvider()) self.assertEquals([], changes)
def test_populate_normal(self): got = Zone('example.com.', []) self.source.populate(got) self.assertEqual(17, len(got.records)) expected = Zone('example.com.', []) for name, data in ( ('', { 'type': 'A', 'ttl': 30, 'values': ['10.2.3.4', '10.2.3.5'], }), ('sub', { 'type': 'NS', 'ttl': 30, 'values': ['ns1.ns.com.', 'ns2.ns.com.'], }), ('www', { 'type': 'A', 'ttl': 3600, 'value': '10.2.3.6', }), ('cname', { 'type': 'CNAME', 'ttl': 3600, 'value': 'www.example.com.', }), ('some-host-abc123', { 'type': 'A', 'ttl': 1800, 'value': '10.2.3.7', }), ('has-dup-def123', { 'type': 'A', 'ttl': 3600, 'value': '10.2.3.8', }), ('www.sub', { 'type': 'A', 'ttl': 3600, 'value': '1.2.3.4', }), ('has-dup-def456', { 'type': 'A', 'ttl': 3600, 'value': '10.2.3.8', }), ('', { 'type': 'MX', 'ttl': 3600, 'values': [{ 'preference': 10, 'exchange': 'smtp-1-host.example.com.', }, { 'preference': 20, 'exchange': 'smtp-2-host.example.com.', }] }), ('smtp', { 'type': 'MX', 'ttl': 1800, 'values': [{ 'preference': 30, 'exchange': 'smtp-1-host.example.com.', }, { 'preference': 40, 'exchange': 'smtp-2-host.example.com.', }] }), ('', { 'type': 'TXT', 'ttl': 300, 'value': 'test TXT', }), ('colon', { 'type': 'TXT', 'ttl': 300, 'value': 'test : TXT', }), ('nottl', { 'type': 'TXT', 'ttl': 3600, 'value': 'nottl test TXT', }), ('ipv6-3', { 'type': 'AAAA', 'ttl': 300, 'value': '2a02:1348:017c:d5d0:0024:19ff:fef3:5742', }), ('ipv6-6', { 'type': 'AAAA', 'ttl': 3600, 'value': '2a02:1348:017c:d5d0:0024:19ff:fef3:5743', }), ('semicolon', { 'type': 'TXT', 'ttl': 300, 'value': 'v=DKIM1\\; k=rsa\\; p=blah', }), ): record = Record.new(expected, name, data) expected.add_record(record) changes = expected.changes(got, SimpleProvider()) self.assertEqual([], changes)
def test_populate(self, execute_mock): provider = DynProvider('test', 'cust', 'user', 'pass') # Test Zone create execute_mock.side_effect = [ # get Zone { 'data': {} }, # get_all_records { 'data': { 'a_records': [{ 'fqdn': 'unit.tests', 'rdata': { 'address': '1.2.3.4' }, 'record_id': 1, 'record_type': 'A', 'ttl': 300, 'zone': 'unit.tests', }], 'cname_records': [{ 'fqdn': 'cname.unit.tests', 'rdata': { 'cname': 'unit.tests.' }, 'record_id': 2, 'record_type': 'CNAME', 'ttl': 301, 'zone': 'unit.tests', }], 'ns_records': [{ 'fqdn': 'unit.tests', 'rdata': { 'nsdname': 'ns1.p10.dynect.net.' }, 'record_id': 254597562, 'record_type': 'NS', 'service_class': '', 'ttl': 3600, 'zone': 'unit.tests' }, { 'fqdn': 'unit.tests', 'rdata': { 'nsdname': 'ns2.p10.dynect.net.' }, 'record_id': 254597563, 'record_type': 'NS', 'service_class': '', 'ttl': 3600, 'zone': 'unit.tests' }, { 'fqdn': 'unit.tests', 'rdata': { 'nsdname': 'ns3.p10.dynect.net.' }, 'record_id': 254597564, 'record_type': 'NS', 'service_class': '', 'ttl': 3600, 'zone': 'unit.tests' }, { 'fqdn': 'unit.tests', 'rdata': { 'nsdname': 'ns4.p10.dynect.net.' }, 'record_id': 254597565, 'record_type': 'NS', 'service_class': '', 'ttl': 3600, 'zone': 'unit.tests' }, { 'fqdn': 'sub.unit.tests', 'rdata': { 'nsdname': 'ns3.p10.dynect.net.' }, 'record_id': 254597564, 'record_type': 'NS', 'service_class': '', 'ttl': 3600, 'zone': 'unit.tests' }, { 'fqdn': 'sub.unit.tests', 'rdata': { 'nsdname': 'ns3.p10.dynect.net.' }, 'record_id': 254597564, 'record_type': 'NS', 'service_class': '', 'ttl': 3600, 'zone': 'unit.tests' }], 'mx_records': [{ 'fqdn': 'unit.tests', 'rdata': { 'exchange': 'smtp-1.unit.tests.', 'preference': 10 }, 'record_id': 3, 'record_type': 'MX', 'ttl': 302, 'zone': 'unit.tests', }, { 'fqdn': 'unit.tests', 'rdata': { 'exchange': 'smtp-2.unit.tests.', 'preference': 20 }, 'record_id': 4, 'record_type': 'MX', 'ttl': 302, 'zone': 'unit.tests', }], 'naptr_records': [{ 'fqdn': 'naptr.unit.tests', 'rdata': { 'flags': 'U', 'order': 100, 'preference': 101, 'regexp': '!^.*$!sip:[email protected]!', 'replacement': '.', 'services': 'SIP+D2U' }, 'record_id': 5, 'record_type': 'MX', 'ttl': 303, 'zone': 'unit.tests', }, { 'fqdn': 'naptr.unit.tests', 'rdata': { 'flags': 'U', 'order': 200, 'preference': 201, 'regexp': '!^.*$!sip:[email protected]!', 'replacement': '.', 'services': 'SIP+D2U' }, 'record_id': 6, 'record_type': 'MX', 'ttl': 303, 'zone': 'unit.tests', }], 'ptr_records': [{ 'fqdn': 'ptr.unit.tests', 'rdata': { 'ptrdname': 'xx.unit.tests.' }, 'record_id': 7, 'record_type': 'PTR', 'ttl': 304, 'zone': 'unit.tests', }], 'soa_records': [{ 'fqdn': 'unit.tests', 'rdata': { 'txtdata': 'ns1.p16.dynect.net. ' 'hostmaster.unit.tests. 4 3600 600 604800 1800' }, 'record_id': 99, 'record_type': 'SOA', 'ttl': 299, 'zone': 'unit.tests', }], 'spf_records': [{ 'fqdn': 'spf.unit.tests', 'rdata': { 'txtdata': 'v=spf1 ip4:192.168.0.1/16-all' }, 'record_id': 8, 'record_type': 'SPF', 'ttl': 305, 'zone': 'unit.tests', }, { 'fqdn': 'spf.unit.tests', 'rdata': { 'txtdata': 'v=spf1 -all' }, 'record_id': 8, 'record_type': 'SPF', 'ttl': 305, 'zone': 'unit.tests', }], 'sshfp_records': [{ 'fqdn': 'unit.tests', 'rdata': { 'algorithm': 1, 'fingerprint': 'bf6b6825d2977c511a475bbefb88aad54a92ac73', 'fptype': 1 }, 'record_id': 9, 'record_type': 'SSHFP', 'ttl': 306, 'zone': 'unit.tests', }], 'srv_records': [{ 'fqdn': '_srv._tcp.unit.tests', 'rdata': { 'port': 10, 'priority': 11, 'target': 'foo-1.unit.tests.', 'weight': 12 }, 'record_id': 10, 'record_type': 'SRV', 'ttl': 307, 'zone': 'unit.tests', }, { 'fqdn': '_srv._tcp.unit.tests', 'rdata': { 'port': 20, 'priority': 21, 'target': 'foo-2.unit.tests.', 'weight': 22 }, 'record_id': 11, 'record_type': 'SRV', 'ttl': 307, 'zone': 'unit.tests', }], 'caa_records': [{ 'fqdn': 'unit.tests', 'rdata': { 'flags': 0, 'tag': 'issue', 'value': 'ca.unit.tests' }, 'record_id': 12, 'record_type': 'cAA', 'ttl': 308, 'zone': 'unit.tests', }], } } ] got = Zone('unit.tests.', []) provider.populate(got) execute_mock.assert_has_calls([ call('/Zone/unit.tests/', 'GET', {}), call('/AllRecord/unit.tests/unit.tests./', 'GET', {'detail': 'Y'}) ]) changes = self.expected.changes(got, SimpleProvider()) self.assertEquals([], changes)
# from __future__ import absolute_import, division, print_function, \ unicode_literals from io import StringIO from logging import getLogger from unittest import TestCase from octodns.provider.plan import Plan, PlanHtml, PlanLogger, PlanMarkdown from octodns.record import Create, Delete, Record, Update from octodns.zone import Zone from helpers import SimpleProvider simple = SimpleProvider() zone = Zone('unit.tests.', []) existing = Record.new( zone, 'a', { 'ttl': 300, 'type': 'A', # This matches the zone data above, one to swap, one to leave 'values': ['1.1.1.1', '2.2.2.2'], }) new = Record.new( zone, 'a', { 'geo': {
def test_naptr(self): a_values = [{ 'order': 10, 'preference': 11, 'flags': 'X', 'service': 'Y', 'regexp': 'Z', 'replacement': '.', }, { 'order': 20, 'preference': 21, 'flags': 'A', 'service': 'B', 'regexp': 'C', 'replacement': 'foo.com', }] a_data = {'ttl': 30, 'values': a_values} a = NaptrRecord(self.zone, 'a', a_data) self.assertEquals('a', a.name) self.assertEquals('a.unit.tests.', a.fqdn) self.assertEquals(30, a.ttl) for i in (0, 1): for k in a_values[0].keys(): self.assertEquals(a_values[i][k], getattr(a.values[i], k)) self.assertEquals(a_data, a.data) b_value = { 'order': 30, 'preference': 31, 'flags': 'M', 'service': 'N', 'regexp': 'O', 'replacement': 'x', } b_data = {'ttl': 30, 'value': b_value} b = NaptrRecord(self.zone, 'b', b_data) for k in a_values[0].keys(): self.assertEquals(b_value[k], getattr(b.values[0], k)) self.assertEquals(b_data, b.data) target = SimpleProvider() # No changes with self self.assertFalse(a.changes(a, target)) # Diff in priority causes change other = NaptrRecord(self.zone, 'a', {'ttl': 30, 'values': a_values}) other.values[0].order = 22 change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # Diff in replacement causes change other.values[0].order = a.values[0].order other.values[0].replacement = 'smtpX' change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # full sorting # equivilent b_naptr_value = b.values[0] self.assertEquals(0, b_naptr_value.__cmp__(b_naptr_value)) # by order self.assertEquals( 1, b_naptr_value.__cmp__( NaptrValue({ 'order': 10, 'preference': 31, 'flags': 'M', 'service': 'N', 'regexp': 'O', 'replacement': 'x', }))) self.assertEquals( -1, b_naptr_value.__cmp__( NaptrValue({ 'order': 40, 'preference': 31, 'flags': 'M', 'service': 'N', 'regexp': 'O', 'replacement': 'x', }))) # by preference self.assertEquals( 1, b_naptr_value.__cmp__( NaptrValue({ 'order': 30, 'preference': 10, 'flags': 'M', 'service': 'N', 'regexp': 'O', 'replacement': 'x', }))) self.assertEquals( -1, b_naptr_value.__cmp__( NaptrValue({ 'order': 30, 'preference': 40, 'flags': 'M', 'service': 'N', 'regexp': 'O', 'replacement': 'x', }))) # by flags self.assertEquals( 1, b_naptr_value.__cmp__( NaptrValue({ 'order': 30, 'preference': 31, 'flags': 'A', 'service': 'N', 'regexp': 'O', 'replacement': 'x', }))) self.assertEquals( -1, b_naptr_value.__cmp__( NaptrValue({ 'order': 30, 'preference': 31, 'flags': 'Z', 'service': 'N', 'regexp': 'O', 'replacement': 'x', }))) # by service self.assertEquals( 1, b_naptr_value.__cmp__( NaptrValue({ 'order': 30, 'preference': 31, 'flags': 'M', 'service': 'A', 'regexp': 'O', 'replacement': 'x', }))) self.assertEquals( -1, b_naptr_value.__cmp__( NaptrValue({ 'order': 30, 'preference': 31, 'flags': 'M', 'service': 'Z', 'regexp': 'O', 'replacement': 'x', }))) # by regexp self.assertEquals( 1, b_naptr_value.__cmp__( NaptrValue({ 'order': 30, 'preference': 31, 'flags': 'M', 'service': 'N', 'regexp': 'A', 'replacement': 'x', }))) self.assertEquals( -1, b_naptr_value.__cmp__( NaptrValue({ 'order': 30, 'preference': 31, 'flags': 'M', 'service': 'N', 'regexp': 'Z', 'replacement': 'x', }))) # by replacement self.assertEquals( 1, b_naptr_value.__cmp__( NaptrValue({ 'order': 30, 'preference': 31, 'flags': 'M', 'service': 'N', 'regexp': 'O', 'replacement': 'a', }))) self.assertEquals( -1, b_naptr_value.__cmp__( NaptrValue({ 'order': 30, 'preference': 31, 'flags': 'M', 'service': 'N', 'regexp': 'O', 'replacement': 'z', }))) # __repr__ doesn't blow up a.__repr__()
def test_srv(self): a_values = [{ 'priority': 10, 'weight': 11, 'port': 12, 'target': 'server1', }, { 'priority': 20, 'weight': 21, 'port': 22, 'target': 'server2', }] a_data = {'ttl': 30, 'values': a_values} a = SrvRecord(self.zone, '_a._tcp', a_data) self.assertEquals('_a._tcp', a.name) self.assertEquals('_a._tcp.unit.tests.', a.fqdn) self.assertEquals(30, a.ttl) self.assertEquals(a_values[0]['priority'], a.values[0].priority) self.assertEquals(a_values[0]['weight'], a.values[0].weight) self.assertEquals(a_values[0]['port'], a.values[0].port) self.assertEquals(a_values[0]['target'], a.values[0].target) self.assertEquals(a_data, a.data) b_value = { 'priority': 30, 'weight': 31, 'port': 32, 'target': 'server3', } b_data = {'ttl': 30, 'value': b_value} b = SrvRecord(self.zone, '_b._tcp', b_data) self.assertEquals(b_value['priority'], b.values[0].priority) self.assertEquals(b_value['weight'], b.values[0].weight) self.assertEquals(b_value['port'], b.values[0].port) self.assertEquals(b_value['target'], b.values[0].target) self.assertEquals(b_data, b.data) target = SimpleProvider() # No changes with self self.assertFalse(a.changes(a, target)) # Diff in priority causes change other = SrvRecord(self.zone, '_a._icmp', { 'ttl': 30, 'values': a_values }) other.values[0].priority = 22 change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # Diff in weight causes change other.values[0].priority = a.values[0].priority other.values[0].weight = 33 change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # Diff in port causes change other.values[0].weight = a.values[0].weight other.values[0].port = 44 change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # Diff in target causes change other.values[0].port = a.values[0].port other.values[0].target = 'serverX' change = a.changes(other, target) self.assertEqual(change.existing, a) self.assertEqual(change.new, other) # __repr__ doesn't blow up a.__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__()