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:
@@ -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 [{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user