1
0
mirror of https://github.com/github/octodns.git synced 2024-05-11 05:55:00 +00:00

Implement Dync populate dynamic, flesh out testing for all but dyn

This commit is contained in:
Ross McFarland
2018-12-10 15:30:15 -08:00
parent a169d50fcf
commit 60911917b4
5 changed files with 275 additions and 61 deletions

View File

@@ -466,7 +466,7 @@ class DynProvider(BaseProvider):
values = [] values = []
data = { data = {
'dynamic': { 'dynamic': {
'pool': pools, 'pools': pools,
'rules': rules, 'rules': rules,
}, },
'type': _type, 'type': _type,
@@ -523,11 +523,13 @@ class DynProvider(BaseProvider):
# Geo # Geo
geo = ruleset.criteria['geoip'] geo = ruleset.criteria['geoip']
geos = [] geos = []
# TODO: we need to reconstitude geos here :-/ # Dyn uses the same 2-letter codes as octoDNS (except for
# continents) but it doesn't have the hierary, e.g. US is
# just US, not NA-US. We'll have to map these things back
for code in geo['country']: for code in geo['country']:
geos.append(code) geos.append(GeoCodes.country_to_code(code))
for code in geo['province']: for code in geo['province']:
geos.append(code) geos.append(GeoCodes.province_to_code(code.upper()))
for code in geo['region']: for code in geo['region']:
geos.append(self.REGION_CODES_LOOKUP[int(code)]) geos.append(self.REGION_CODES_LOOKUP[int(code)])
rule['geos'] = geos rule['geos'] = geos
@@ -543,8 +545,6 @@ class DynProvider(BaseProvider):
pprint(data) pprint(data)
raise Exception('boom')
name = zone.hostname_from_fqdn(fqdn) name = zone.hostname_from_fqdn(fqdn)
record = Record.new(zone, name, data, source=self, lenient=lenient) record = Record.new(zone, name, data, source=self, lenient=lenient)
zone.add_record(record, lenient=lenient) zone.add_record(record, lenient=lenient)
@@ -1012,6 +1012,10 @@ class DynProvider(BaseProvider):
def _mod_dynamic_rulesets(self, td, change): def _mod_dynamic_rulesets(self, td, change):
new = change.new new = change.new
# TODO: make sure we can update TTLs
if td.ttl != new.ttl:
td.ttl = new.ttl
# Get existing pools. This should be simple, but it's not b/c the dyn # Get existing pools. This should be simple, but it's not b/c the dyn
# api is a POS. We need all response pools so we can GC and check to # api is a POS. We need all response pools so we can GC and check to
# make sure that what we're after doesn't already exist. # make sure that what we're after doesn't already exist.

View File

@@ -12,6 +12,9 @@ import re
from .geo import GeoCodes from .geo import GeoCodes
from pprint import pprint
class Change(object): class Change(object):
def __init__(self, existing, new): def __init__(self, existing, new):
@@ -384,7 +387,24 @@ class _DynamicPool(object):
def __init__(self, _id, data): def __init__(self, _id, data):
self._id = _id self._id = _id
self.data = data
pprint(['before', data])
values = [
{
'value': d['value'],
'weight': d.get('weight', 1),
} for d in data['values']
]
values.sort(key=lambda d: d['value'])
fallback = data.get('fallback', None)
self.data = {
'fallback': fallback if fallback != 'default' else None,
'values': values,
}
pprint(['after', self.data])
def _data(self): def _data(self):
return self.data return self.data
@@ -403,12 +423,30 @@ class _DynamicRule(object):
def __init__(self, i, data): def __init__(self, i, data):
self.i = i self.i = i
self.data = data
pprint(['before', data])
self.data = {}
try:
self.data['pool'] = data['pool']
except KeyError:
pass
try:
self.data['geos'] = sorted(data['geos'])
except KeyError:
pass
pprint(['after', self.data])
def _data(self): def _data(self):
return self.data return self.data
def __eq__(self, other): def __eq__(self, other):
pprint([
self.data,
other.data,
self.data == other.data,
])
return self.data == other.data return self.data == other.data
def __ne__(self, other): def __ne__(self, other):

View File

@@ -2,11 +2,13 @@
# #
# #
from logging import getLogger
from .geo_data import geo_data from .geo_data import geo_data
class GeoCodes(object): class GeoCodes(object):
__COUNTRIES = None log = getLogger('GeoCodes')
@classmethod @classmethod
def validate(cls, code, prefix): def validate(cls, code, prefix):
@@ -50,3 +52,20 @@ class GeoCodes(object):
'country_code': country_code, 'country_code': country_code,
'province_code': province_code, 'province_code': province_code,
} }
@classmethod
def country_to_code(cls, country):
for continent, countries in geo_data.items():
if country in countries:
return '{}-{}'.format(continent, country)
cls.log.warn('country_to_code: unrecognized country "%s"', country)
return
@classmethod
def province_to_code(cls, province):
# We get to cheat on this one since we only support provinces in NA-US
if province not in geo_data['NA']['US']['provinces']:
cls.log.warn('country_to_code: unrecognized province "%s"',
province)
return
return 'NA-US-{}'.format(province)

View File

@@ -1906,10 +1906,11 @@ class TestDynamicRecords(TestCase):
}], }],
}, },
'two': { 'two': {
# Testing out of order value sorting here
'values': [{ 'values': [{
'value': '4.4.4.4',
}, {
'value': '5.5.5.5', 'value': '5.5.5.5',
}, {
'value': '4.4.4.4',
}], }],
}, },
'three': { 'three': {
@@ -1948,10 +1949,24 @@ class TestDynamicRecords(TestCase):
pools = dynamic.pools pools = dynamic.pools
self.assertTrue(pools) self.assertTrue(pools)
self.assertEquals(a_data['dynamic']['pools']['one'], pools['one'].data) self.assertEquals({
self.assertEquals(a_data['dynamic']['pools']['two'], pools['two'].data) 'value': '3.3.3.3',
self.assertEquals(a_data['dynamic']['pools']['three'], 'weight': 1,
pools['three'].data) }, pools['one'].data['values'][0])
self.assertEquals([{
'value': '4.4.4.4',
'weight': 1,
}, {
'value': '5.5.5.5',
'weight': 1,
}], pools['two'].data['values'])
self.assertEquals([{
'weight': 10,
'value': '4.4.4.4',
}, {
'weight': 12,
'value': '5.5.5.5',
}], pools['three'].data['values'])
rules = dynamic.rules rules = dynamic.rules
self.assertTrue(rules) self.assertTrue(rules)
@@ -1994,10 +2009,11 @@ class TestDynamicRecords(TestCase):
}], }],
}, },
'two': { 'two': {
# Testing out of order value sorting here
'values': [{ 'values': [{
'value': '2601:642:500:e210:62f8:1dff:feb8:9474',
}, {
'value': '2601:642:500:e210:62f8:1dff:feb8:9475', 'value': '2601:642:500:e210:62f8:1dff:feb8:9475',
}, {
'value': '2601:642:500:e210:62f8:1dff:feb8:9474',
}], }],
}, },
'three': { 'three': {
@@ -2036,12 +2052,24 @@ class TestDynamicRecords(TestCase):
pools = dynamic.pools pools = dynamic.pools
self.assertTrue(pools) self.assertTrue(pools)
self.assertEquals(aaaa_data['dynamic']['pools']['one'], self.assertEquals({
pools['one'].data) 'value': '2601:642:500:e210:62f8:1dff:feb8:9473',
self.assertEquals(aaaa_data['dynamic']['pools']['two'], 'weight': 1,
pools['two'].data) }, pools['one'].data['values'][0])
self.assertEquals(aaaa_data['dynamic']['pools']['three'], self.assertEquals([{
pools['three'].data) 'value': '2601:642:500:e210:62f8:1dff:feb8:9474',
'weight': 1,
}, {
'value': '2601:642:500:e210:62f8:1dff:feb8:9475',
'weight': 1,
}], pools['two'].data['values'])
self.assertEquals([{
'weight': 10,
'value': '2601:642:500:e210:62f8:1dff:feb8:9476',
}, {
'weight': 12,
'value': '2601:642:500:e210:62f8:1dff:feb8:9477',
}], pools['three'].data['values'])
rules = dynamic.rules rules = dynamic.rules
self.assertTrue(rules) self.assertTrue(rules)
@@ -2094,12 +2122,21 @@ class TestDynamicRecords(TestCase):
pools = dynamic.pools pools = dynamic.pools
self.assertTrue(pools) self.assertTrue(pools)
self.assertEquals(cname_data['dynamic']['pools']['one'], self.assertEquals({
pools['one'].data) 'value': 'one.cname.target.',
self.assertEquals(cname_data['dynamic']['pools']['two'], 'weight': 1,
pools['two'].data) }, pools['one'].data['values'][0])
self.assertEquals(cname_data['dynamic']['pools']['three'], self.assertEquals({
pools['three'].data) 'value': 'two.cname.target.',
'weight': 1,
}, pools['two'].data['values'][0])
self.assertEquals([{
'value': 'three-1.cname.target.',
'weight': 12,
}, {
'value': 'three-2.cname.target.',
'weight': 32,
}], pools['three'].data['values'])
rules = dynamic.rules rules = dynamic.rules
self.assertTrue(rules) self.assertTrue(rules)
@@ -2906,9 +2943,10 @@ class TestDynamicRecords(TestCase):
a_data = { a_data = {
'dynamic': { 'dynamic': {
'rules': [{ 'rules': [{
'pools': { 'geos': ['EU'],
1: 'one', 'pool': 'two',
} }, {
'pool': 'one',
}], }],
}, },
'ttl': 60, 'ttl': 60,
@@ -2928,7 +2966,19 @@ class TestDynamicRecords(TestCase):
a_data = { a_data = {
'dynamic': { 'dynamic': {
'pools': { 'pools': {
'one': '1.1.1.1', 'one': {
'values': [{
'value': '3.3.3.3',
}]
},
'two': {
'values': [{
'value': '4.4.4.4',
}, {
'value': '5.5.5.5',
'weight': 2,
}]
},
}, },
}, },
'ttl': 60, 'ttl': 60,
@@ -2941,11 +2991,82 @@ class TestDynamicRecords(TestCase):
a = Record.new(self.zone, 'bad', a_data, lenient=True) a = Record.new(self.zone, 'bad', a_data, lenient=True)
self.assertEquals({ self.assertEquals({
'pools': { 'pools': {
'one': '1.1.1.1', 'one': {
'fallback': None,
'values': [{
'value': '3.3.3.3',
'weight': 1,
}]
},
'two': {
'fallback': None,
'values': [{
'value': '4.4.4.4',
'weight': 1,
}, {
'value': '5.5.5.5',
'weight': 2,
}]
},
}, },
'rules': [], 'rules': [],
}, a._data()['dynamic']) }, a._data()['dynamic'])
# rule without pool
a_data = {
'dynamic': {
'pools': {
'one': {
'values': [{
'value': '3.3.3.3',
}]
},
'two': {
'values': [{
'value': '4.4.4.4',
}, {
'value': '5.5.5.5',
'weight': 2,
}]
},
},
'rules': [{
'geos': ['EU'],
'pool': 'two',
}, {
}],
},
'ttl': 60,
'type': 'A',
'values': [
'1.1.1.1',
'2.2.2.2',
],
}
a = Record.new(self.zone, 'bad', a_data, lenient=True)
self.assertEquals({
'pools': {
'one': {
'fallback': None,
'values': [{
'value': '3.3.3.3',
'weight': 1,
}]
},
'two': {
'fallback': None,
'values': [{
'value': '4.4.4.4',
'weight': 1,
}, {
'value': '5.5.5.5',
'weight': 2,
}]
},
},
'rules': a_data['dynamic']['rules'],
}, a._data()['dynamic'])
def test_dynamic_changes(self): def test_dynamic_changes(self):
simple = SimpleProvider() simple = SimpleProvider()
dynamic = DynamicProvider() dynamic = DynamicProvider()
@@ -2953,17 +3074,24 @@ class TestDynamicRecords(TestCase):
a_data = { a_data = {
'dynamic': { 'dynamic': {
'pools': { 'pools': {
'one': '3.3.3.3', 'one': {
'two': [ 'values': [{
'4.4.4.4', 'value': '3.3.3.3',
'5.5.5.5', }]
], },
'two': {
'values': [{
'value': '4.4.4.4',
}, {
'value': '5.5.5.5',
}]
},
}, },
'rules': [{ 'rules': [{
'pools': { 'geos': ['EU'],
100: 'one', 'pool': 'two',
200: 'two', }, {
} 'pool': 'one',
}], }],
}, },
'ttl': 60, 'ttl': 60,
@@ -2978,17 +3106,25 @@ class TestDynamicRecords(TestCase):
b_data = { b_data = {
'dynamic': { 'dynamic': {
'pools': { 'pools': {
'one': '3.3.3.5', 'one': {
'two': [ 'values': [{
'4.4.4.4', 'value': '3.3.3.3',
'5.5.5.5', }]
], },
'two': {
'values': [{
'value': '4.4.4.4',
'weight': 2,
}, {
'value': '5.5.5.5',
}]
},
}, },
'rules': [{ 'rules': [{
'pools': { 'geos': ['EU'],
100: 'one', 'pool': 'two',
200: 'two', }, {
} 'pool': 'one',
}], }],
}, },
'ttl': 60, 'ttl': 60,
@@ -3002,17 +3138,24 @@ class TestDynamicRecords(TestCase):
c_data = { c_data = {
'dynamic': { 'dynamic': {
'pools': { 'pools': {
'one': '3.3.3.3', 'one': {
'two': [ 'values': [{
'4.4.4.4', 'value': '3.3.3.3',
'5.5.5.5', }]
], },
'two': {
'values': [{
'value': '4.4.4.4',
}, {
'value': '5.5.5.5',
}]
},
}, },
'rules': [{ 'rules': [{
'pools': { 'geos': ['NA'],
100: 'one', 'pool': 'two',
300: 'two', }, {
} 'pool': 'one',
}], }],
}, },
'ttl': 60, 'ttl': 60,

View File

@@ -68,3 +68,13 @@ class TestRecordGeoCodes(TestCase):
'country_code': 'US', 'country_code': 'US',
'province_code': 'CA', 'province_code': 'CA',
}, GeoCodes.parse('NA-US-CA')) }, GeoCodes.parse('NA-US-CA'))
def test_country_to_code(self):
self.assertEquals('NA-US', GeoCodes.country_to_code('US'))
self.assertEquals('EU-GB', GeoCodes.country_to_code('GB'))
self.assertFalse(GeoCodes.country_to_code('XX'))
def test_province_to_code(self):
self.assertEquals('NA-US-OR', GeoCodes.province_to_code('OR'))
self.assertEquals('NA-US-KY', GeoCodes.province_to_code('KY'))
self.assertFalse(GeoCodes.province_to_code('XX'))