mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
Impliment Dynamic rule geo validation
This commit is contained in:
@@ -406,6 +406,22 @@ class _DynamicPool(object):
|
||||
return '{}'.format(self.data)
|
||||
|
||||
|
||||
class _DynamicRuleGeo(object):
|
||||
geo_re = re.compile(r'^(?P<continent_code>\w\w)(-(?P<country_code>\w\w)'
|
||||
r'(-(?P<subdivision_code>\w\w))?)?$')
|
||||
|
||||
@classmethod
|
||||
def validate(cls, rule_num, code):
|
||||
reasons = []
|
||||
# TODO: ideally this would validate the actual code...
|
||||
match = cls.geo_re.match(code)
|
||||
if not match:
|
||||
reasons.append('rule {} invalid geo "{}"'.format(rule_num, code))
|
||||
return reasons
|
||||
|
||||
# TODO: flesh this out
|
||||
|
||||
|
||||
class _DynamicRule(object):
|
||||
|
||||
def __init__(self, i, data):
|
||||
@@ -517,6 +533,8 @@ class _DynamicMixin(object):
|
||||
elif not rules:
|
||||
reasons.append('missing rules')
|
||||
else:
|
||||
seen_default = False
|
||||
|
||||
for rule_num, rule in enumerate(rules):
|
||||
rule_num += 1
|
||||
try:
|
||||
@@ -532,7 +550,21 @@ class _DynamicMixin(object):
|
||||
reasons.append('rule {} undefined pool "{}"'
|
||||
.format(rule_num, pool))
|
||||
|
||||
# TODO: validate GEOs if present
|
||||
try:
|
||||
geos = rule['geos']
|
||||
except KeyError:
|
||||
geos = []
|
||||
if seen_default:
|
||||
reasons.append('rule {} duplicate default'
|
||||
.format(rule_num))
|
||||
seen_default = True
|
||||
|
||||
if not isinstance(geos, (list, tuple)):
|
||||
reasons.append('rule {} geos must be a list'
|
||||
.format(rule_num))
|
||||
else:
|
||||
for geo in geos:
|
||||
reasons.extend(_DynamicRuleGeo.validate(rule_num, geo))
|
||||
|
||||
return reasons
|
||||
|
||||
|
@@ -21,9 +21,11 @@ a:
|
||||
- value: 5.5.5.5
|
||||
weight: 25
|
||||
rules:
|
||||
- geo: EU-UK
|
||||
- geos:
|
||||
- EU-UK
|
||||
pool: iad
|
||||
- geo: EU
|
||||
- geos:
|
||||
- EU
|
||||
pool: ams
|
||||
- geos:
|
||||
- NA-US-CA
|
||||
@@ -55,9 +57,11 @@ aaaa:
|
||||
- value: 2601:642:500:e210:62f8:1dff:feb8:9476
|
||||
weight: 2
|
||||
rules:
|
||||
- geo: EU-UK
|
||||
- geos:
|
||||
- EU-UK
|
||||
pool: iad
|
||||
- geo: EU
|
||||
- geos:
|
||||
- EU
|
||||
pool: ams
|
||||
- geos:
|
||||
- NA-US-CA
|
||||
@@ -88,9 +92,11 @@ cname:
|
||||
- value: target-sea-2.unit.tests.
|
||||
weight: 175
|
||||
rules:
|
||||
- geo: EU-UK
|
||||
- geos:
|
||||
- EU-UK
|
||||
pool: iad
|
||||
- geo: EU
|
||||
- geos:
|
||||
- EU
|
||||
pool: ams
|
||||
- geos:
|
||||
- NA-US-CA
|
||||
|
@@ -2688,6 +2688,113 @@ class TestDynamicRecords(TestCase):
|
||||
self.assertEquals(["rule 1 undefined pool \"non-existant\""],
|
||||
ctx.exception.reasons)
|
||||
|
||||
# rule with invalid geos
|
||||
a_data = {
|
||||
'dynamic': {
|
||||
'pools': {
|
||||
'one': {
|
||||
'values': [{
|
||||
'value': '3.3.3.3',
|
||||
}]
|
||||
},
|
||||
'two': {
|
||||
'values': [{
|
||||
'value': '4.4.4.4',
|
||||
}, {
|
||||
'value': '5.5.5.5',
|
||||
}]
|
||||
},
|
||||
},
|
||||
'rules': [{
|
||||
'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(['rule 1 geos must be a list'],
|
||||
ctx.exception.reasons)
|
||||
|
||||
# rule with invalid geo
|
||||
a_data = {
|
||||
'dynamic': {
|
||||
'pools': {
|
||||
'one': {
|
||||
'values': [{
|
||||
'value': '3.3.3.3',
|
||||
}]
|
||||
},
|
||||
'two': {
|
||||
'values': [{
|
||||
'value': '4.4.4.4',
|
||||
}, {
|
||||
'value': '5.5.5.5',
|
||||
}]
|
||||
},
|
||||
},
|
||||
'rules': [{
|
||||
'geos': ['invalid'],
|
||||
'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(['rule 1 invalid geo "invalid"'],
|
||||
ctx.exception.reasons)
|
||||
|
||||
# multiple default rules
|
||||
a_data = {
|
||||
'dynamic': {
|
||||
'pools': {
|
||||
'one': {
|
||||
'values': [{
|
||||
'value': '3.3.3.3',
|
||||
}]
|
||||
},
|
||||
'two': {
|
||||
'values': [{
|
||||
'value': '4.4.4.4',
|
||||
}, {
|
||||
'value': '5.5.5.5',
|
||||
}]
|
||||
},
|
||||
},
|
||||
'rules': [{
|
||||
'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(['rule 2 duplicate default'],
|
||||
ctx.exception.reasons)
|
||||
|
||||
def test_dynamic_lenient(self):
|
||||
# Missing pools
|
||||
a_data = {
|
||||
|
Reference in New Issue
Block a user