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

Merge pull request #115 from github/long-txt-records

Implement "chunked" TXT/SPF value support for long values
This commit is contained in:
Ross McFarland
2017-10-09 09:45:15 -07:00
committed by GitHub
4 changed files with 85 additions and 15 deletions

View File

@@ -455,7 +455,7 @@ class DynProvider(BaseProvider):
return [{
'txtdata': v,
'ttl': record.ttl,
} for v in record.values]
} for v in record.chunked_values]
def _kwargs_for_SRV(self, record):
return [{

View File

@@ -114,8 +114,7 @@ class _Route53Record(object):
for v in record.values]
def _values_for_quoted(self, record):
return ['"{}"'.format(v.replace('"', '\\"'))
for v in record.values]
return record.chunked_values
_values_for_SPF = _values_for_quoted
_values_for_TXT = _values_for_quoted

View File

@@ -704,8 +704,8 @@ class SshfpRecord(_ValuesMixin, Record):
_unescaped_semicolon_re = re.compile(r'\w;')
class SpfRecord(_ValuesMixin, Record):
_type = 'SPF'
class _ChunkedValuesMixin(_ValuesMixin):
CHUNK_SIZE = 255
@classmethod
def _validate_value(cls, value):
@@ -714,9 +714,29 @@ class SpfRecord(_ValuesMixin, Record):
return []
def _process_values(self, values):
ret = []
for v in values:
if v and v[0] == '"':
v = v[1:-1]
ret.append(v.replace('" "', ''))
return ret
@property
def chunked_values(self):
values = []
for v in self.values:
v = v.replace('"', '\\"')
vs = [v[i:i + self.CHUNK_SIZE]
for i in range(0, len(v), self.CHUNK_SIZE)]
vs = '" "'.join(vs)
values.append('"{}"'.format(vs))
return values
class SpfRecord(_ChunkedValuesMixin, Record):
_type = 'SPF'
class SrvValue(object):
@classmethod
@@ -797,14 +817,5 @@ class SrvRecord(_ValuesMixin, Record):
return [SrvValue(v) for v in values]
class TxtRecord(_ValuesMixin, Record):
class TxtRecord(_ChunkedValuesMixin, Record):
_type = 'TXT'
@classmethod
def _validate_value(cls, value):
if _unescaped_semicolon_re.search(value):
return ['unescaped ;']
return []
def _process_values(self, values):
return values

View File

@@ -1490,3 +1490,63 @@ class TestRecordValidation(TestCase):
'value': 'this has some; semi-colons\; in it',
})
self.assertEquals(['unescaped ;'], ctx.exception.reasons)
def test_TXT_long_value_chunking(self):
expected = '"Lorem ipsum dolor sit amet, consectetur adipiscing ' \
'elit, sed do eiusmod tempor incididunt ut labore et dolore ' \
'magna aliqua. Ut enim ad minim veniam, quis nostrud ' \
'exercitation ullamco laboris nisi ut aliquip ex ea commodo ' \
'consequat. Duis aute irure dolor i" "n reprehenderit in ' \
'voluptate velit esse cillum dolore eu fugiat nulla pariatur. ' \
'Excepteur sint occaecat cupidatat non proident, sunt in culpa ' \
'qui officia deserunt mollit anim id est laborum."'
long_value = 'Lorem ipsum dolor sit amet, consectetur adipiscing ' \
'elit, sed do eiusmod tempor incididunt ut labore et dolore ' \
'magna aliqua. Ut enim ad minim veniam, quis nostrud ' \
'exercitation ullamco laboris nisi ut aliquip ex ea commodo ' \
'consequat. Duis aute irure dolor in reprehenderit in ' \
'voluptate velit esse cillum dolore eu fugiat nulla ' \
'pariatur. Excepteur sint occaecat cupidatat non proident, ' \
'sunt in culpa qui officia deserunt mollit anim id est ' \
'laborum.'
# Single string
single = Record.new(self.zone, '', {
'type': 'TXT',
'ttl': 600,
'values': [
'hello world',
long_value,
'this has some\; semi-colons\; in it',
]
})
self.assertEquals(3, len(single.values))
self.assertEquals(3, len(single.chunked_values))
# Note we are checking that this normalizes the chunking, not that we
# get out what we put in.
self.assertEquals(expected, single.chunked_values[0])
long_split_value = '"Lorem ipsum dolor sit amet, consectetur ' \
'adipiscing elit, sed do eiusmod tempor incididunt ut ' \
'labore et dolore magna aliqua. Ut enim ad minim veniam, ' \
'quis nostrud exercitation ullamco laboris nisi ut aliquip ' \
'ex" " ea commodo consequat. Duis aute irure dolor in ' \
'reprehenderit in voluptate velit esse cillum dolore eu ' \
'fugiat nulla pariatur. Excepteur sint occaecat cupidatat ' \
'non proident, sunt in culpa qui officia deserunt mollit ' \
'anim id est laborum."'
# Chunked
chunked = Record.new(self.zone, '', {
'type': 'TXT',
'ttl': 600,
'values': [
'"hello world"',
long_split_value,
'"this has some\; semi-colons\; in it"',
]
})
self.assertEquals(expected, chunked.chunked_values[0])
# should be single values, no quoting
self.assertEquals(single.values, chunked.values)
# should be chunked values, with quoting
self.assertEquals(single.chunked_values, chunked.chunked_values)