mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
Merge branch 'master' into multi-value-PTR
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
from __future__ import absolute_import, division, print_function, \
|
||||
unicode_literals
|
||||
|
||||
from logging import getLogger
|
||||
|
||||
from .base import BaseProcessor
|
||||
|
||||
|
||||
class AcmeMangingProcessor(BaseProcessor):
|
||||
log = getLogger('AcmeMangingProcessor')
|
||||
|
||||
def __init__(self, name):
|
||||
'''
|
||||
processors:
|
||||
acme:
|
||||
class: octodns.processor.acme.AcmeMangingProcessor
|
||||
|
||||
...
|
||||
|
||||
zones:
|
||||
something.com.:
|
||||
...
|
||||
processors:
|
||||
- acme
|
||||
...
|
||||
'''
|
||||
super(AcmeMangingProcessor, self).__init__(name)
|
||||
|
||||
self._owned = set()
|
||||
|
||||
def process_source_zone(self, zone, *args, **kwargs):
|
||||
ret = self._clone_zone(zone)
|
||||
for record in zone.records:
|
||||
if record._type == 'TXT' and \
|
||||
record.name.startswith('_acme-challenge'):
|
||||
# We have a managed acme challenge record (owned by octoDNS) so
|
||||
# we should mark it as such
|
||||
record = record.copy()
|
||||
record.values.append('*octoDNS*')
|
||||
record.values.sort()
|
||||
# This assumes we'll see things as sources before targets,
|
||||
# which is the case...
|
||||
self._owned.add(record)
|
||||
ret.add_record(record)
|
||||
return ret
|
||||
|
||||
def process_target_zone(self, zone, *args, **kwargs):
|
||||
ret = self._clone_zone(zone)
|
||||
for record in zone.records:
|
||||
# Uses a startswith rather than == to ignore subdomain challenges,
|
||||
# e.g. _acme-challenge.foo.domain.com when managing domain.com
|
||||
if record._type == 'TXT' and \
|
||||
record.name.startswith('_acme-challenge') and \
|
||||
'*octoDNS*' not in record.values and \
|
||||
record not in self._owned:
|
||||
self.log.info('_process: ignoring %s', record.fqdn)
|
||||
continue
|
||||
ret.add_record(record)
|
||||
|
||||
return ret
|
||||
+13
-6
@@ -627,11 +627,14 @@ class Ns1Provider(BaseProvider):
|
||||
for c in countries:
|
||||
geos.add('{}-{}'.format(continent, c))
|
||||
|
||||
# States are easy too, just assume NA-US (CA providences aren't
|
||||
# supported by octoDNS currently)
|
||||
# States and provinces are easy too,
|
||||
# just assume NA-US or NA-CA
|
||||
for state in meta.get('us_state', []):
|
||||
geos.add('NA-US-{}'.format(state))
|
||||
|
||||
for province in meta.get('ca_province', []):
|
||||
geos.add('NA-CA-{}'.format(province))
|
||||
|
||||
if geos:
|
||||
# There are geos, combine them with any existing geos for this
|
||||
# pool and recorded the sorted unique set of them
|
||||
@@ -1150,12 +1153,15 @@ class Ns1Provider(BaseProvider):
|
||||
country = set()
|
||||
georegion = set()
|
||||
us_state = set()
|
||||
ca_province = set()
|
||||
|
||||
for geo in rule.data.get('geos', []):
|
||||
n = len(geo)
|
||||
if n == 8:
|
||||
# US state, e.g. NA-US-KY
|
||||
us_state.add(geo[-2:])
|
||||
# CA province, e.g. NA-CA-NL
|
||||
us_state.add(geo[-2:]) if "NA-US" in geo \
|
||||
else ca_province.add(geo[-2:])
|
||||
# For filtering. State filtering is done by the country
|
||||
# filter
|
||||
has_country = True
|
||||
@@ -1188,7 +1194,7 @@ class Ns1Provider(BaseProvider):
|
||||
'meta': georegion_meta,
|
||||
}
|
||||
|
||||
if country or us_state:
|
||||
if country or us_state or ca_province:
|
||||
# If there's country and/or states its a country pool,
|
||||
# countries and states can coexist as they're handled by the
|
||||
# same step in the filterchain (countries and georegions
|
||||
@@ -1199,11 +1205,12 @@ class Ns1Provider(BaseProvider):
|
||||
country_state_meta['country'] = sorted(country)
|
||||
if us_state:
|
||||
country_state_meta['us_state'] = sorted(us_state)
|
||||
if ca_province:
|
||||
country_state_meta['ca_province'] = sorted(ca_province)
|
||||
regions['{}__country'.format(pool_name)] = {
|
||||
'meta': country_state_meta,
|
||||
}
|
||||
|
||||
if not georegion and not country and not us_state:
|
||||
elif not georegion:
|
||||
# If there's no targeting it's a catchall
|
||||
regions['{}__catchall'.format(pool_name)] = {
|
||||
'meta': meta,
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
from __future__ import absolute_import, division, print_function, \
|
||||
unicode_literals
|
||||
|
||||
from unittest import TestCase
|
||||
|
||||
from octodns.processor.acme import AcmeMangingProcessor
|
||||
from octodns.record import Record
|
||||
from octodns.zone import Zone
|
||||
|
||||
zone = Zone('unit.tests.', [])
|
||||
records = {
|
||||
'root-unowned': Record.new(zone, '_acme-challenge', {
|
||||
'ttl': 30,
|
||||
'type': 'TXT',
|
||||
'value': 'magic bit',
|
||||
}),
|
||||
'sub-unowned': Record.new(zone, '_acme-challenge.sub-unowned', {
|
||||
'ttl': 30,
|
||||
'type': 'TXT',
|
||||
'value': 'magic bit',
|
||||
}),
|
||||
'not-txt': Record.new(zone, '_acme-challenge.not-txt', {
|
||||
'ttl': 30,
|
||||
'type': 'AAAA',
|
||||
'value': '::1',
|
||||
}),
|
||||
'not-acme': Record.new(zone, 'not-acme', {
|
||||
'ttl': 30,
|
||||
'type': 'TXT',
|
||||
'value': 'Hello World!',
|
||||
}),
|
||||
'managed': Record.new(zone, '_acme-challenge.managed', {
|
||||
'ttl': 30,
|
||||
'type': 'TXT',
|
||||
'value': 'magic bit',
|
||||
}),
|
||||
'owned': Record.new(zone, '_acme-challenge.owned', {
|
||||
'ttl': 30,
|
||||
'type': 'TXT',
|
||||
'values': ['*octoDNS*', 'magic bit'],
|
||||
}),
|
||||
'going-away': Record.new(zone, '_acme-challenge.going-away', {
|
||||
'ttl': 30,
|
||||
'type': 'TXT',
|
||||
'values': ['*octoDNS*', 'magic bit'],
|
||||
}),
|
||||
}
|
||||
|
||||
|
||||
class TestAcmeMangingProcessor(TestCase):
|
||||
|
||||
def test_process_zones(self):
|
||||
acme = AcmeMangingProcessor('acme')
|
||||
|
||||
source = Zone(zone.name, [])
|
||||
# Unrelated stuff that should be untouched
|
||||
source.add_record(records['not-txt'])
|
||||
source.add_record(records['not-acme'])
|
||||
# A managed acme that will have ownership value added
|
||||
source.add_record(records['managed'])
|
||||
|
||||
got = acme.process_source_zone(source)
|
||||
self.assertEquals([
|
||||
'_acme-challenge.managed',
|
||||
'_acme-challenge.not-txt',
|
||||
'not-acme',
|
||||
], sorted([r.name for r in got.records]))
|
||||
managed = None
|
||||
for record in got.records:
|
||||
print(record.name)
|
||||
if record.name.endswith('managed'):
|
||||
managed = record
|
||||
break
|
||||
self.assertTrue(managed)
|
||||
# Ownership was marked with an extra value
|
||||
self.assertEquals(['*octoDNS*', 'magic bit'], record.values)
|
||||
|
||||
existing = Zone(zone.name, [])
|
||||
# Unrelated stuff that should be untouched
|
||||
existing.add_record(records['not-txt'])
|
||||
existing.add_record(records['not-acme'])
|
||||
# Stuff that will be ignored
|
||||
existing.add_record(records['root-unowned'])
|
||||
existing.add_record(records['sub-unowned'])
|
||||
# A managed acme that needs ownership value added
|
||||
existing.add_record(records['managed'])
|
||||
# A managed acme that has ownershp managed
|
||||
existing.add_record(records['owned'])
|
||||
# A managed acme that needs to go away
|
||||
existing.add_record(records['going-away'])
|
||||
|
||||
got = acme.process_target_zone(existing)
|
||||
self.assertEquals([
|
||||
'_acme-challenge.going-away',
|
||||
'_acme-challenge.managed',
|
||||
'_acme-challenge.not-txt',
|
||||
'_acme-challenge.owned',
|
||||
'not-acme'
|
||||
], sorted([r.name for r in got.records]))
|
||||
@@ -1260,7 +1260,7 @@ class TestNs1ProviderDynamic(TestCase):
|
||||
rule0 = record.data['dynamic']['rules'][0]
|
||||
rule1 = record.data['dynamic']['rules'][1]
|
||||
rule0['geos'] = ['AF', 'EU']
|
||||
rule1['geos'] = ['NA-US-CA']
|
||||
rule1['geos'] = ['NA-US-CA', 'NA-CA-NL']
|
||||
ret, _ = provider._params_for_A(record)
|
||||
self.assertEquals(10, len(ret['answers']))
|
||||
exp = Ns1Provider._FILTER_CHAIN_WITH_REGION_AND_COUNTRY(provider,
|
||||
@@ -1275,7 +1275,8 @@ class TestNs1ProviderDynamic(TestCase):
|
||||
'iad__country': {
|
||||
'meta': {
|
||||
'note': 'rule-order:1',
|
||||
'us_state': ['CA']
|
||||
'us_state': ['CA'],
|
||||
'ca_province': ['NL']
|
||||
}
|
||||
},
|
||||
'lhr__georegion': {
|
||||
@@ -1637,8 +1638,9 @@ class TestNs1ProviderDynamic(TestCase):
|
||||
'lhr__country': {
|
||||
'meta': {
|
||||
'note': 'rule-order:1 fallback:iad',
|
||||
'country': ['CA'],
|
||||
'country': ['MX'],
|
||||
'us_state': ['OR'],
|
||||
'ca_province': ['NL']
|
||||
},
|
||||
},
|
||||
# iad will use the old style "plain" region naming. We won't
|
||||
@@ -1682,8 +1684,9 @@ class TestNs1ProviderDynamic(TestCase):
|
||||
'_order': '1',
|
||||
'geos': [
|
||||
'AF',
|
||||
'NA-CA',
|
||||
'NA-US-OR',
|
||||
'NA-CA-NL',
|
||||
'NA-MX',
|
||||
'NA-US-OR'
|
||||
],
|
||||
'pool': 'lhr',
|
||||
}, {
|
||||
|
||||
Reference in New Issue
Block a user