Browse Source

Merge remote-tracking branch 'origin/master' into alias-support

pull/47/head
Ross McFarland 9 years ago
parent
commit
b777c159ce
12 changed files with 117 additions and 12 deletions
  1. +7
    -1
      octodns/manager.py
  2. +4
    -1
      octodns/provider/route53.py
  3. +3
    -0
      octodns/record.py
  4. +6
    -0
      octodns/zone.py
  5. +20
    -0
      tests/config/always-dry-run.yaml
  6. +5
    -0
      tests/config/unit.tests.yaml
  7. +8
    -0
      tests/test_octodns_manager.py
  8. +2
    -2
      tests/test_octodns_provider_dnsimple.py
  9. +8
    -7
      tests/test_octodns_provider_powerdns.py
  10. +20
    -0
      tests/test_octodns_provider_route53.py
  11. +1
    -1
      tests/test_octodns_provider_yaml.py
  12. +33
    -0
      tests/test_octodns_zone.py

+ 7
- 1
octodns/manager.py View File

@ -273,12 +273,18 @@ class Manager(object):
for target, plan in plans:
plan.raise_if_unsafe()
if dry_run or config.get('always-dry-run', False):
if dry_run:
return 0
total_changes = 0
self.log.debug('sync: applying')
zones = self.config['zones']
for target, plan in plans:
zone_name = plan.existing.name
if zones[zone_name].get('always-dry-run', False):
self.log.info('sync: zone=%s skipping always-dry-run',
zone_name)
continue
total_changes += target.apply(plan)
self.log.info('sync: %d total changes', total_changes)


+ 4
- 1
octodns/provider/route53.py View File

@ -253,10 +253,13 @@ class Route53Provider(BaseProvider):
_data_for_PTR = _data_for_single
_data_for_CNAME = _data_for_single
_fix_semicolons = re.compile(r'(?<!\\);')
def _data_for_quoted(self, rrset):
return {
'type': rrset['Type'],
'values': [rr['Value'][1:-1] for rr in rrset['ResourceRecords']],
'values': [self._fix_semicolons.sub('\;', rr['Value'][1:-1])
for rr in rrset['ResourceRecords']],
'ttl': int(rrset['TTL'])
}


+ 3
- 0
octodns/record.py View File

@ -112,6 +112,9 @@ class Record(object):
raise Exception('Invalid record {}, missing ttl'.format(self.fqdn))
self.source = source
octodns = data.get('octodns', {})
self.ignored = octodns.get('ignored', False)
def _data(self):
return {'ttl': self.ttl}


+ 6
- 0
octodns/zone.py View File

@ -76,8 +76,12 @@ class Zone(object):
# Find diffs & removes
for record in filter(_is_eligible, self.records):
if record.ignored:
continue
try:
desired_record = desired_records[record]
if desired_record.ignored:
continue
except KeyError:
if not target.supports(record):
self.log.debug('changes: skipping record=%s %s - %s does '
@ -103,6 +107,8 @@ class Zone(object):
# This uses set math and our special __hash__ and __cmp__ functions as
# well
for record in filter(_is_eligible, desired.records - self.records):
if record.ignored:
continue
if not target.supports(record):
self.log.debug('changes: skipping record=%s %s - %s does not '
'support it', record.fqdn, record._type,


+ 20
- 0
tests/config/always-dry-run.yaml View File

@ -0,0 +1,20 @@
providers:
in:
class: octodns.provider.yaml.YamlProvider
directory: tests/config
dump:
class: octodns.provider.yaml.YamlProvider
directory: env/YAML_TMP_DIR
zones:
unit.tests.:
always-dry-run: true
sources:
- in
targets:
- dump
subzone.unit.tests.:
always-dry-run: false
sources:
- in
targets:
- dump

+ 5
- 0
tests/config/unit.tests.yaml View File

@ -51,6 +51,11 @@ cname:
ttl: 300
type: CNAME
value: unit.tests.
ignored:
octodns:
ignored: true
type: A
value: 9.9.9.9
mx:
ttl: 300
type: MX


+ 8
- 0
tests/test_octodns_manager.py View File

@ -88,6 +88,14 @@ class TestManager(TestCase):
.sync(['not.targetable.'])
self.assertTrue('does not support targeting' in ctx.exception.message)
def test_always_dry_run(self):
with TemporaryDirectory() as tmpdir:
environ['YAML_TMP_DIR'] = tmpdir.dirname
tc = Manager(get_config_filename('always-dry-run.yaml')) \
.sync(dry_run=False)
# only the stuff from subzone, unit.tests. is always-dry-run
self.assertEquals(3, tc)
def test_simple(self):
with TemporaryDirectory() as tmpdir:
environ['YAML_TMP_DIR'] = tmpdir.dirname


+ 2
- 2
tests/test_octodns_provider_dnsimple.py View File

@ -129,8 +129,8 @@ class TestDnsimpleProvider(TestCase):
]
plan = provider.plan(self.expected)
# No root NS
n = len(self.expected.records) - 1
# No root NS, no ignored
n = len(self.expected.records) - 2
self.assertEquals(n, len(plan.changes))
self.assertEquals(n, provider.apply(plan))


+ 8
- 7
tests/test_octodns_provider_powerdns.py View File

@ -78,7 +78,8 @@ class TestPowerDnsProvider(TestCase):
expected = Zone('unit.tests.', [])
source = YamlProvider('test', join(dirname(__file__), 'config'))
source.populate(expected)
self.assertEquals(14, len(expected.records))
expected_n = len(expected.records) - 1
self.assertEquals(14, expected_n)
# No diffs == no changes
with requests_mock() as mock:
@ -93,7 +94,7 @@ class TestPowerDnsProvider(TestCase):
# Used in a minute
def assert_rrsets_callback(request, context):
data = loads(request.body)
self.assertEquals(len(expected.records), len(data['rrsets']))
self.assertEquals(expected_n, len(data['rrsets']))
return ''
# No existing records -> creates for every record in expected
@ -103,8 +104,8 @@ class TestPowerDnsProvider(TestCase):
mock.patch(ANY, status_code=201, text=assert_rrsets_callback)
plan = provider.plan(expected)
self.assertEquals(len(expected.records), len(plan.changes))
self.assertEquals(len(expected.records), provider.apply(plan))
self.assertEquals(expected_n, len(plan.changes))
self.assertEquals(expected_n, provider.apply(plan))
# Non-existent zone -> creates for every record in expected
# OMG this is fucking ugly, probably better to ditch requests_mocks and
@ -121,8 +122,8 @@ class TestPowerDnsProvider(TestCase):
mock.post(ANY, status_code=201, text=assert_rrsets_callback)
plan = provider.plan(expected)
self.assertEquals(len(expected.records), len(plan.changes))
self.assertEquals(len(expected.records), provider.apply(plan))
self.assertEquals(expected_n, len(plan.changes))
self.assertEquals(expected_n, provider.apply(plan))
with requests_mock() as mock:
# get 422's, unknown zone
@ -166,7 +167,7 @@ class TestPowerDnsProvider(TestCase):
expected = Zone('unit.tests.', [])
source = YamlProvider('test', join(dirname(__file__), 'config'))
source.populate(expected)
self.assertEquals(14, len(expected.records))
self.assertEquals(15, len(expected.records))
# A small change to a single record
with requests_mock() as mock:


+ 20
- 0
tests/test_octodns_provider_route53.py View File

@ -1217,3 +1217,23 @@ class TestRoute53Provider(TestCase):
with self.assertRaises(Exception) as ctx:
provider.apply(plan)
self.assertTrue('modifications' in ctx.exception.message)
def test_semicolon_fixup(self):
provider = Route53Provider('test', 'abc', '123')
self.assertEquals({
'type': 'TXT',
'ttl': 30,
'values': [
'abcd\\; ef\\;g',
'hij\\; klm\\;n',
],
}, provider._data_for_quoted({
'ResourceRecords': [{
'Value': '"abcd; ef;g"',
}, {
'Value': '"hij\\; klm\\;n"',
}],
'TTL': 30,
'Type': 'TXT',
}))

+ 1
- 1
tests/test_octodns_provider_yaml.py View File

@ -30,7 +30,7 @@ class TestYamlProvider(TestCase):
# without it we see everything
source.populate(zone)
self.assertEquals(14, len(zone.records))
self.assertEquals(15, len(zone.records))
# Assumption here is that a clean round-trip means that everything
# worked as expected, data that went in came back out and could be


+ 33
- 0
tests/test_octodns_zone.py View File

@ -172,3 +172,36 @@ class TestZone(TestCase):
with self.assertRaises(SubzoneRecordException) as ctx:
zone.add_record(record)
self.assertTrue('under a managed sub-zone', ctx.exception.message)
def test_ignored_records(self):
zone_normal = Zone('unit.tests.', [])
zone_ignored = 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)
ignored = Record.new(zone_ignored, 'www', {
'octodns': {
'ignored': True
},
'ttl': 60,
'type': 'A',
'value': '9.9.9.9',
})
zone_ignored.add_record(ignored)
provider = SimpleProvider()
self.assertFalse(zone_normal.changes(zone_ignored, provider))
self.assertTrue(zone_normal.changes(zone_missing, provider))
self.assertFalse(zone_ignored.changes(zone_normal, provider))
self.assertFalse(zone_ignored.changes(zone_missing, provider))
self.assertTrue(zone_missing.changes(zone_normal, provider))
self.assertFalse(zone_missing.changes(zone_ignored, provider))

Loading…
Cancel
Save