Browse Source

Implement pool-level fallbacks and validations

pull/307/head
Ross McFarland 7 years ago
parent
commit
a767a5cb25
No known key found for this signature in database GPG Key ID: 61C10C4FC8FE4A89
2 changed files with 125 additions and 0 deletions
  1. +19
    -0
      octodns/record.py
  2. +106
    -0
      tests/test_octodns_record.py

+ 19
- 0
octodns/record.py View File

@ -509,6 +509,25 @@ class _DynamicMixin(object):
reasons.append('missing value in pool "{}" ' reasons.append('missing value in pool "{}" '
'value {}'.format(_id, value_num)) 'value {}'.format(_id, value_num))
fallback = pool.get('fallback', None)
if fallback is not None and fallback not in pools:
reasons.append('undefined fallback "{}" for pool "{}"'
.format(fallback, _id))
# Check for loops
fallback = pools[_id].get('fallback', None)
seen = [_id, fallback]
while fallback is not None:
# See if there's a next fallback
fallback = pools.get(fallback, {}).get('fallback', None)
if fallback in seen:
seen = ' -> '.join(seen)
reasons.append('loop in pool fallbacks: {}'
.format(seen))
# exit the loop
break
seen.append(fallback)
try: try:
rules = data['dynamic']['rules'] rules = data['dynamic']['rules']
except KeyError: except KeyError:


+ 106
- 0
tests/test_octodns_record.py View File

@ -2177,6 +2177,7 @@ class TestDynamicRecords(TestCase):
}], }],
}, },
'two': { 'two': {
'fallback': 'one',
'values': [{ 'values': [{
'value': '4.4.4.4', 'value': '4.4.4.4',
}, { }, {
@ -2184,6 +2185,7 @@ class TestDynamicRecords(TestCase):
}] }]
}, },
'three': { 'three': {
'fallback': 'two',
'values': [{ 'values': [{
'weight': 1, 'weight': 1,
'value': '5.5.5.5', 'value': '5.5.5.5',
@ -2446,6 +2448,110 @@ class TestDynamicRecords(TestCase):
self.assertEquals(['invalid weight "foo" in pool "three" value 2'], self.assertEquals(['invalid weight "foo" in pool "three" value 2'],
ctx.exception.reasons) ctx.exception.reasons)
# invalid fallback
a_data = {
'dynamic': {
'pools': {
'one': {
'values': [{
'value': '3.3.3.3',
}],
},
'two': {
'fallback': 'invalid',
'values': [{
'value': '4.4.4.4',
}, {
'value': '5.5.5.5',
}]
},
'three': {
'fallback': 'two',
'values': [{
'weight': 1,
'value': '6.6.6.6',
}, {
'weight': 5,
'value': '7.7.7.7',
}],
},
},
'rules': [{
'geos': ['AF', 'EU'],
'pool': 'three',
}, {
'geos': ['NA-US-CA'],
'pool': 'two',
}, {
'pool': 'one',
}],
},
'ttl': 60,
'type': 'A',
'values': [
'1.1.1.1',
'2.2.2.2',
],
}
with self.assertRaises(ValidationError) as ctx:
Record.new(self.zone, 'bad', a_data)
self.assertEquals(['undefined fallback "invalid" for pool "two"'],
ctx.exception.reasons)
# fallback loop
a_data = {
'dynamic': {
'pools': {
'one': {
'fallback': 'three',
'values': [{
'value': '3.3.3.3',
}],
},
'two': {
'fallback': 'one',
'values': [{
'value': '4.4.4.4',
}, {
'value': '5.5.5.5',
}]
},
'three': {
'fallback': 'two',
'values': [{
'weight': 1,
'value': '6.6.6.6',
}, {
'weight': 5,
'value': '7.7.7.7',
}],
},
},
'rules': [{
'geos': ['AF', 'EU'],
'pool': 'three',
}, {
'geos': ['NA-US-CA'],
'pool': 'two',
}, {
'pool': 'one',
}],
},
'ttl': 60,
'type': 'A',
'values': [
'1.1.1.1',
'2.2.2.2',
],
}
with self.assertRaises(ValidationError) as ctx:
Record.new(self.zone, 'bad', a_data)
self.assertEquals([
'loop in pool fallbacks: one -> three -> two',
'loop in pool fallbacks: three -> two -> one',
'loop in pool fallbacks: two -> one -> three'
], ctx.exception.reasons)
# multiple pool problems # multiple pool problems
a_data = { a_data = {
'dynamic': { 'dynamic': {


Loading…
Cancel
Save