diff options
author | Zuul <zuul@review.opendev.org> | 2021-10-25 17:11:26 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2021-10-25 17:11:26 +0000 |
commit | 77f239634242315e1533d8c969fd1bcc59cc8a12 (patch) | |
tree | 13e9e5125a2a733d24ae348f80f4fc81931ccad6 /designate | |
parent | 4807c23228fbb23af3087ee072bf73d7fc43aff5 (diff) | |
parent | 03a5d5d74eb5de3f37b2e7ac5f28ae139ae436a5 (diff) | |
download | designate-77f239634242315e1533d8c969fd1bcc59cc8a12.tar.gz |
Merge "Allow TXT record over 255 characters if split"
Diffstat (limited to 'designate')
-rw-r--r-- | designate/objects/rrdata_txt.py | 38 | ||||
-rw-r--r-- | designate/tests/test_api/test_v2/test_recordsets.py | 11 | ||||
-rw-r--r-- | designate/tests/unit/objects/test_rrdata_txt.py | 10 |
3 files changed, 56 insertions, 3 deletions
diff --git a/designate/objects/rrdata_txt.py b/designate/objects/rrdata_txt.py index 44e13fff..9fcec720 100644 --- a/designate/objects/rrdata_txt.py +++ b/designate/objects/rrdata_txt.py @@ -26,14 +26,23 @@ class TXT(Record): Defined in: RFC1035 """ fields = { - 'txt_data': fields.TxtField(maxLength=255) + 'txt_data': fields.TxtField() } def _to_string(self): return self.txt_data - def _from_string(self, value): - if (not value.startswith('"') and not value.endswith('"')): + @staticmethod + def _is_wrapped_in_double_quotes(value): + return value.startswith('"') and value.endswith('"') + + def _validate_record_single_string(self, value): + if len(value) > 255: + err = ("Any TXT record string exceeding " + "255 characters has to be split.") + raise InvalidObject(err) + + if not self._is_wrapped_in_double_quotes(value): # value with spaces should be quoted as per RFC1035 5.1 for element in value: if element.isspace(): @@ -50,6 +59,29 @@ class TXT(Record): "backslash.") raise InvalidObject(err) + def _from_string(self, value): + if len(value) > 255: + # expecting record containing multiple strings as + # per rfc7208 3.3 and rfc1035 3.3.14 + stripped_value = value.strip('"') + if (not self._is_wrapped_in_double_quotes(value) and + '" "' not in stripped_value): + err = ("TXT record strings over 255 characters " + "have to be split into multiple strings " + "wrapped in double quotes.") + raise InvalidObject(err) + + record_strings = stripped_value.split('" "') + for record_string in record_strings: + # add back the delimiting quotes after + # strip and split for each string + record_string = '"{}"'.format(record_string) + # further validate each string individually + self._validate_record_single_string(value=record_string) + else: + # validate single TXT record string + self._validate_record_single_string(value=value) + self.txt_data = value # The record type is defined in the RFC. This will be used when the record diff --git a/designate/tests/test_api/test_v2/test_recordsets.py b/designate/tests/test_api/test_v2/test_recordsets.py index 850ac086..9b96157c 100644 --- a/designate/tests/test_api/test_v2/test_recordsets.py +++ b/designate/tests/test_api/test_v2/test_recordsets.py @@ -567,6 +567,17 @@ class ApiV2RecordSetsTest(ApiV2TestCase): self._assert_exception('invalid_object', 400, self.client.put_json, url, body) + def test_create_txt_record_multiple_strings(self): + # create TXT record with string split in 2 + new_zone = self.create_zone(name='example.net.') + recordset = self.create_recordset(new_zone, 'TXT') + self.create_record(new_zone, recordset) + record = '"{}" "{}"'.format('a' * 250, 'a' * 250) + body = {'description': 'Tester', 'records': [record]} + url = '/zones/%s/recordsets/%s' % (recordset['zone_id'], + recordset['id']) + self.client.put_json(url, body, status=202) + def test_update_recordset_with_record_clear(self): # Create a recordset with one record recordset = self.create_recordset(self.zone, 'A') diff --git a/designate/tests/unit/objects/test_rrdata_txt.py b/designate/tests/unit/objects/test_rrdata_txt.py index f41cd930..22274816 100644 --- a/designate/tests/unit/objects/test_rrdata_txt.py +++ b/designate/tests/unit/objects/test_rrdata_txt.py @@ -34,3 +34,13 @@ class RRDataTXTTest(oslotest.base.BaseTestCase): 'Provided object does not match schema', record.validate ) + + def test_multiple_strings_one_record(self): + # these quotes do not have to be escaped as + # per rfc7208 3.3 and rfc1035 3.3.14 + record = objects.TXT(data='"foo" "bar"') + self.assertRaisesRegex( + exceptions.InvalidObject, + 'Provided object does not match schema', + record.validate + ) |