Merge "Add "cleanup" for created recordsets + NEW delete zone test"
diff --git a/designate_tempest_plugin/common/constants.py b/designate_tempest_plugin/common/constants.py
index 5ae7c3f..1111c72 100644
--- a/designate_tempest_plugin/common/constants.py
+++ b/designate_tempest_plugin/common/constants.py
@@ -12,15 +12,17 @@
# License for the specific language governing permissions and limitations
# under the License.
-# Designate statuses strings
+# Designate statuses/actions strings
PENDING = 'PENDING'
COMPLETE = 'COMPLETE'
ERROR = 'ERROR'
DELETED = 'DELETED'
DELETE = 'DELETE'
ACTIVE = 'ACTIVE'
+INACTIVE = 'INACTIVE'
UP = 'UP'
CREATE = 'CREATE'
+UPDATE = 'UPDATE'
# Zone types
PRIMARY_ZONE_TYPE = 'PRIMARY'
diff --git a/designate_tempest_plugin/config.py b/designate_tempest_plugin/config.py
index 99c9a04..989acb8 100644
--- a/designate_tempest_plugin/config.py
+++ b/designate_tempest_plugin/config.py
@@ -51,8 +51,10 @@
help="The timeout on a single dns query to a nameserver"),
cfg.StrOpt('zone_id',
help="The target zone to test the dns recordsets "
- "If it is not specified, a new zone will be created ")
-
+ "If it is not specified, a new zone will be created "),
+ cfg.StrOpt('tld_suffix',
+ default='com',
+ help="TLD suffix that used in all tests (if not overridden)")
]
dns_feature_group = cfg.OptGroup(name='dns_feature_enabled',
@@ -79,6 +81,10 @@
default=True,
help="Is https://bugs.launchpad.net/designate/+bug/1573141 "
"fixed"),
+ cfg.BoolOpt('bug_1932026_fixed',
+ default=False,
+ help="Is https://bugs.launchpad.net/designate/+bug/1932026 "
+ "fixed"),
# Note: Also see the enforce_scope section (from tempest) for Designate API
# scope checking setting.
cfg.BoolOpt('enforce_new_defaults',
diff --git a/designate_tempest_plugin/data_utils.py b/designate_tempest_plugin/data_utils.py
index 4b5d24d..61c6da0 100644
--- a/designate_tempest_plugin/data_utils.py
+++ b/designate_tempest_plugin/data_utils.py
@@ -35,7 +35,7 @@
return an.format(netaddr.ipv6_compact)
-def rand_zone_name(name='', prefix='rand', suffix='.com.'):
+def rand_zone_name(name='', prefix='rand', suffix=None):
"""Generate a random zone name
:param str name: The name that you want to include
:param prefix: the exact text to start the string. Defaults to "rand"
@@ -43,6 +43,8 @@
:return: a random zone name e.g. example.org.
:rtype: string
"""
+ if suffix is None:
+ suffix = '.{}.'.format(CONF.dns.tld_suffix)
name = data_utils.rand_name(name=name, prefix=prefix)
return name + suffix
@@ -67,7 +69,6 @@
def rand_zonefile_data(name=None, ttl=None):
"""Generate random zone data, with optional overrides
-
:return: A ZoneModel
"""
zone_base = ('$ORIGIN &\n& # IN SOA ns.& nsadmin.& # # # # #\n'
@@ -105,11 +106,11 @@
def rand_zone_data(name=None, email=None, ttl=None, description=None):
"""Generate random zone data, with optional overrides
-
:return: A ZoneModel
"""
if name is None:
- name = rand_zone_name(prefix='testdomain', suffix='.com.')
+ name = rand_zone_name(
+ prefix='testdomain', suffix='.{}.'.format(CONF.dns.tld_suffix))
if email is None:
email = ("admin@" + name).strip('.')
if description is None:
@@ -126,7 +127,6 @@
def rand_recordset_data(record_type, zone_name, name=None, records=None,
ttl=None):
"""Generate random recordset data, with optional overrides
-
:return: A RecordsetModel
"""
if name is None:
@@ -202,7 +202,7 @@
def wildcard_ns_recordset(zone_name):
name = "*.{0}".format(zone_name)
- records = ["ns.example.com."]
+ records = ["ns.example.{}.".format(CONF.dns.tld_suffix)]
return rand_recordset_data('NS', zone_name, name, records)
@@ -216,6 +216,19 @@
return ns_records
+def rand_soa_records(number_of_records=2):
+ return ['{} {} {} {} {} {}.'.format(
+ '{}.{}.{}'.format(rand_string(3), rand_string(7), rand_string(3)),
+ random.randint(1000000000, 2020080302), random.randint(3000, 7200),
+ random.randint(1000, 3600), random.randint(1000000, 1209600),
+ random.randint(1000, 3600)) for i in range(0, number_of_records)]
+
+
+def rand_soa_recordset(zone_name, **kwargs):
+ return rand_recordset_data(
+ 'SOA', zone_name, records=rand_soa_records(), **kwargs)
+
+
def rand_tld():
data = {
"name": rand_zone_name(prefix='tld', suffix='')
@@ -225,7 +238,6 @@
def rand_transfer_request_data(description=None, target_project_id=None):
"""Generate random transfer request data, with optional overrides
-
:return: A TransferRequest data
"""
@@ -255,7 +267,6 @@
"""Create a rand recordset by type
This essentially just dispatches to the relevant random recordset
creation functions.
-
:param str zone_name: The zone name the recordset applies to
:param str record_type: The type of recordset (ie A, MX, NS, etc...)
"""
@@ -266,7 +277,6 @@
def rand_string(size):
"""Create random string of ASCII chars by size
-
:param int size - length os the string to be create
:return - random creates string of ASCII lover characters
"""
@@ -275,7 +285,6 @@
def rand_domain_name(tld=None):
"""Create random valid domain name
-
:param tld (optional) - TLD that will be used to random domain name
:return - valid domain name, for example: paka.zbabun.iuh
"""
diff --git a/designate_tempest_plugin/services/dns/json/base.py b/designate_tempest_plugin/services/dns/json/base.py
index d484ac9..e1107ab 100644
--- a/designate_tempest_plugin/services/dns/json/base.py
+++ b/designate_tempest_plugin/services/dns/json/base.py
@@ -191,7 +191,8 @@
return resp, self.deserialize(resp, body)
- def _put_request(self, resource, uuid, data, params=None):
+ def _put_request(self, resource, uuid, data, params=None,
+ headers=None, extra_headers=False):
"""Updates the specified object using PUT request.
:param resource: The name of the REST resource, e.g., 'zones'.
:param uuid: Unique identifier of the object in UUID format.
@@ -200,11 +201,18 @@
is sent as-is.
:param params: A Python dict that represents the query paramaters to
include in the request URI.
+ :param headers (dict): The headers to use for the request.
+ :param extra_headers (bool): Boolean value than indicates if the
+ headers returned by the get_headers()
+ method are to be used but additional
+ headers are needed in the request
+ pass them in as a dict.
:returns: Serialized object as a dictionary.
"""
body = self.serialize(data)
uri = self.get_uri(resource, uuid=uuid, params=params)
- resp, body = self.put(uri, body=body)
+ resp, body = self.put(
+ uri, body=body, headers=headers, extra_headers=extra_headers)
self.expected_success(self.PUT_STATUS_CODES, resp.status)
diff --git a/designate_tempest_plugin/services/dns/v2/json/quotas_client.py b/designate_tempest_plugin/services/dns/v2/json/quotas_client.py
index 97398c0..1b1d005 100644
--- a/designate_tempest_plugin/services/dns/v2/json/quotas_client.py
+++ b/designate_tempest_plugin/services/dns/v2/json/quotas_client.py
@@ -58,17 +58,29 @@
return resp, body
@base.handle_errors
- def show_quotas(self, project_id, params=None, headers=None):
+ def show_quotas(self, project_id=None, params=None, headers=None):
"""Gets a specific quota.
- :param project_id: Show the quotas of this project id
+ :param project_id: if provided - show the quotas of this project id.
+ https://docs.openstack.org/api-ref/dns/?expanded=
+ get-the-name-servers-for-a-zone-detail#view-quotas
+ If not - show the quotas for a current
+ project.
+ https://docs.openstack.org/api-ref/dns/?expanded=ge
+ t-the-name-servers-for-a-zone-detail#view-current-p
+ roject-s-quotas
+
:param params: A Python dict that represents the query paramaters to
include in the request URI.
:param headers (dict): The headers to use for the request.
:return: Serialized quota as a dictionary.
"""
- return self._show_request('quotas', project_id, params=params,
- headers=headers, extra_headers=True)
+ if project_id is None:
+ return self._show_request(
+ 'quotas', uuid=None, params=params, headers=headers)
+ else:
+ return self._show_request(
+ 'quotas', project_id, params=params, headers=headers)
@base.handle_errors
def delete_quotas(self, project_id, params=None, headers=None):
@@ -100,13 +112,10 @@
:param headers (dict): The headers to use for the request.
:return: Serialized quota as a dictionary.
"""
- if headers is None:
- headers = {'content-type': 'application/json'}
- if 'content-type' not in [header.lower() for header in headers]:
- headers['content-type'] = 'application/json'
resp, body = self._update_request(
"quotas", project_id,
- data=quotas, params=params, headers=headers)
+ data=quotas, params=params, headers=headers,
+ extra_headers=True)
self.expected_success(200, resp.status)
return resp, body
diff --git a/designate_tempest_plugin/services/dns/v2/json/recordset_client.py b/designate_tempest_plugin/services/dns/v2/json/recordset_client.py
index 6dea20d..20b6fcf 100644
--- a/designate_tempest_plugin/services/dns/v2/json/recordset_client.py
+++ b/designate_tempest_plugin/services/dns/v2/json/recordset_client.py
@@ -60,7 +60,8 @@
@base.handle_errors
def update_recordset(self, zone_uuid, recordset_uuid,
- recordet_data, params=None):
+ recordet_data, params=None,
+ headers=None, extra_headers=None):
"""Update the recordset related to the specified zone.
:param zone_uuid: Unique identifier of the zone in UUID format.
:param recordset_uuid: Unique identifier of the recordset in UUID
@@ -69,11 +70,18 @@
data.
:param params: A Python dict that represents the query paramaters to
include in the request URI.
+ :param headers (dict): The headers to use for the request.
+ :param extra_headers (bool): Boolean value than indicates if the
+ headers returned by the get_headers()
+ method are to be used but additional
+ headers are needed in the request
+ pass them in as a dict.
:return: A tuple with the server response and the created zone.
"""
resp, body = self._put_request(
'zones/{0}/recordsets'.format(zone_uuid), recordset_uuid,
- data=recordet_data, params=params)
+ data=recordet_data, params=params,
+ headers=headers, extra_headers=extra_headers)
# Update Recordset should Return a HTTP 202, or a 200 if the recordset
# is already active
diff --git a/designate_tempest_plugin/services/dns/v2/json/service_client.py b/designate_tempest_plugin/services/dns/v2/json/service_client.py
index 267e7a5..87da51a 100644
--- a/designate_tempest_plugin/services/dns/v2/json/service_client.py
+++ b/designate_tempest_plugin/services/dns/v2/json/service_client.py
@@ -25,3 +25,14 @@
"""
return self._list_request(
'service_statuses', headers=headers)[1]['service_statuses']
+
+ @base.handle_errors
+ def show_statuses(self, uuid, headers=None):
+ """Show Service status
+
+ :param headers: (dict): The headers to use for the request.
+ :param uuid: service ID
+ :return: Service status dictionary
+ """
+ return self._show_request(
+ 'service_statuses', uuid, headers=headers)[1]
diff --git a/designate_tempest_plugin/tests/api/v2/test_ptrs.py b/designate_tempest_plugin/tests/api/v2/test_ptrs.py
index b094a5d..0b0cddf 100644
--- a/designate_tempest_plugin/tests/api/v2/test_ptrs.py
+++ b/designate_tempest_plugin/tests/api/v2/test_ptrs.py
@@ -16,6 +16,7 @@
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
+import testtools
from designate_tempest_plugin.tests import base
from designate_tempest_plugin.common import constants as const
@@ -67,7 +68,8 @@
ptr = self.primary_ptr_client.set_ptr_record(
fip_id, ptr_name=ptr_name, ttl=ttl, description=description,
headers=headers, tld=tld)
- self.addCleanup(self.primary_ptr_client.unset_ptr_record, fip_id)
+ self.addCleanup(self.unset_ptr, self.primary_ptr_client, fip_id)
+
self.assertEqual('CREATE', ptr['action'])
self.assertEqual('PENDING', ptr['status'])
waiters.wait_for_ptr_status(
@@ -77,7 +79,7 @@
def _unset_ptr(self, fip_id):
self.primary_ptr_client.unset_ptr_record(fip_id)
waiters.wait_for_ptr_status(
- self.primary_ptr_client, fip_id=fip_id, status=const.DELETED)
+ self.primary_ptr_client, fip_id=fip_id, status=const.INACTIVE)
@decorators.idempotent_id('2fb9d6ea-871d-11eb-9f9a-74e5f9e2a801')
def test_set_floatingip_ptr(self):
@@ -137,7 +139,8 @@
'Failed, expected ID was not found in "received_ptr_ids" list.')
@decorators.idempotent_id('499b5a7e-87e1-11eb-b412-74e5f9e2a801')
- @decorators.skip_because(bug="1932026")
+ @testtools.skipUnless(config.CONF.dns_feature_enabled.bug_1932026_fixed,
+ 'Skip unless bug 1932026 has been fixed.')
def test_unset_floatingip_ptr(self):
fip_id, ptr = self._set_ptr()
self._unset_ptr(fip_id)
@@ -172,7 +175,7 @@
ptr = self.primary_ptr_client.set_ptr_record(
fip_id, ptr_name=ptr_name, ttl=ttl, description=description,
headers=headers, tld=tld)
- self.addCleanup(self.primary_ptr_client.unset_ptr_record, fip_id)
+ self.addCleanup(self.unset_ptr, self.primary_ptr_client, fip_id)
self.assertEqual('CREATE', ptr['action'])
self.assertEqual('PENDING', ptr['status'])
waiters.wait_for_ptr_status(
diff --git a/designate_tempest_plugin/tests/api/v2/test_quotas.py b/designate_tempest_plugin/tests/api/v2/test_quotas.py
index db870af..0366843 100644
--- a/designate_tempest_plugin/tests/api/v2/test_quotas.py
+++ b/designate_tempest_plugin/tests/api/v2/test_quotas.py
@@ -23,6 +23,9 @@
CONF = config.CONF
LOG = logging.getLogger(__name__)
+quotas_types = ["api_export_size", "recordset_records",
+ "zone_records", "zone_recordsets", "zones"]
+
class QuotasV2Test(base.BaseDnsV2Test):
@@ -53,7 +56,6 @@
cls.admin_client = cls.os_admin.dns_v2.QuotasClient()
cls.quotas_client = cls.os_primary.dns_v2.QuotasClient()
cls.alt_client = cls.os_alt.dns_v2.QuotasClient()
- cls.alt_zone_client = cls.os_alt.dns_v2.ZonesClient()
def _store_quotas(self, project_id, cleanup=True):
"""Remember current quotas and reset them after the test"""
@@ -68,29 +70,33 @@
@decorators.idempotent_id('1dac991a-9e2e-452c-a47a-26ac37381ec5')
def test_show_quotas(self):
- self._store_quotas(project_id=self.quotas_client.project_id)
- LOG.info("Updating quotas")
- quotas = dns_data_utils.rand_quotas()
- _, body = self.admin_client.update_quotas(
- project_id=self.quotas_client.project_id,
- headers=self.all_projects_header,
- **quotas)
-
- LOG.info("Fetching quotas")
- _, body = self.admin_client.show_quotas(
- project_id=self.quotas_client.project_id,
- headers=self.all_projects_header)
-
- LOG.info("Ensuring the response has all quota types")
- self.assertExpected(quotas, body, [])
+ LOG.info("Show default quotas, validate all quota types exists and "
+ "their values are integers.")
+ for user in ['primary', 'admin']:
+ if user == 'primary':
+ body = self.quotas_client.show_quotas()[1]
+ if user == 'admin':
+ body = self.admin_client.show_quotas(
+ project_id=self.quotas_client.project_id,
+ headers=self.all_projects_header)[1]
+ for quota_type in quotas_types:
+ self.assertIn(
+ quota_type, body.keys(),
+ 'Failed, expected quota type:{} was not found '
+ 'in received quota body'.format(quota_type))
+ for quota_type, quota_value in body.items():
+ self.assertTrue(
+ isinstance(quota_value, int),
+ 'Failed, the value of:{} is:{}, expected integer'.format(
+ quota_type, quota_value))
@decorators.idempotent_id('0448b089-5803-4ce3-8a6c-5c15ff75a2cc')
- def test_delete_quotas(self):
+ def test_reset_quotas(self):
self._store_quotas(project_id=self.quotas_client.project_id)
- LOG.info("Deleting quotas")
- _, body = self.admin_client.delete_quotas(
+ LOG.info("Deleting (reset) quotas")
+ body = self.admin_client.delete_quotas(
project_id=self.quotas_client.project_id,
- headers=self.all_projects_header)
+ headers=self.all_projects_header)[1]
LOG.info("Ensuring an empty response body")
self.assertEqual(body.strip(), b"")
@@ -104,9 +110,9 @@
self._store_quotas(project_id=self.admin_client.project_id)
LOG.info("Updating quotas")
quotas = dns_data_utils.rand_quotas()
- _, body = self.admin_client.update_quotas(
+ body = self.admin_client.update_quotas(
project_id=self.admin_client.project_id,
- **quotas)
+ **quotas)[1]
LOG.info("Ensuring the response has all quota types")
self.assertExpected(quotas, body, [])
@@ -121,15 +127,15 @@
quotas = dns_data_utils.rand_quotas()
request = quotas.copy()
- _, body = self.admin_client.update_quotas(
+ body = self.admin_client.update_quotas(
project_id=project_id,
headers=self.all_projects_header,
- **request)
+ **request)[1]
LOG.info("Ensuring the response has all quota types")
self.assertExpected(quotas, body, [])
- _, client_body = self.quotas_client.show_quotas(project_id=project_id)
+ client_body = self.quotas_client.show_quotas(project_id=project_id)[1]
self.assertExpected(quotas, client_body, [])
@@ -145,15 +151,15 @@
project_id=project_id,
headers=self.all_projects_header)
- _, default_quotas = self.admin_client.show_quotas(
+ default_quotas = self.admin_client.show_quotas(
project_id=project_id,
- headers=self.all_projects_header)
+ headers=self.all_projects_header)[1]
LOG.info("Updating quotas for %s ", project_id)
quotas = dns_data_utils.rand_quotas()
request = quotas.copy()
- _, body = self.admin_client.update_quotas(
+ self.admin_client.update_quotas(
project_id=project_id,
headers=self.all_projects_header,
**request)
@@ -162,9 +168,9 @@
project_id=project_id,
headers=self.all_projects_header)
- _, final_quotas = self.admin_client.show_quotas(
+ final_quotas = self.admin_client.show_quotas(
project_id=project_id,
- headers=self.all_projects_header)
+ headers=self.all_projects_header)[1]
self.assertExpected(default_quotas, final_quotas, [])
@@ -188,16 +194,45 @@
**request)
LOG.info("Make sure that the quotas weren't changed")
- _, client_body = self.quotas_client.show_quotas(
- project_id=self.quotas_client.project_id)
+ client_body = self.quotas_client.show_quotas(
+ project_id=self.quotas_client.project_id)[1]
self.assertExpected(original_quotas, client_body, [])
+
+class QuotasV2TestNegative(base.BaseDnsV2Test):
+
+ credentials = ["primary", "admin", "system_admin"]
+
+ @classmethod
+ def setup_credentials(cls):
+ # Do not create network resources for these test.
+ cls.set_network_resources()
+ super(QuotasV2TestNegative, cls).setup_credentials()
+
+ @classmethod
+ def skip_checks(cls):
+ super(QuotasV2TestNegative, cls).skip_checks()
+
+ if not CONF.dns_feature_enabled.api_v2_quotas:
+ skip_msg = ("%s skipped as designate V2 Quotas API is not "
+ "available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+
+ @classmethod
+ def setup_clients(cls):
+ super(QuotasV2TestNegative, cls).setup_clients()
+
+ if CONF.enforce_scope.designate:
+ cls.admin_client = cls.os_system_admin.dns_v2.QuotasClient()
+ else:
+ cls.admin_client = cls.os_admin.dns_v2.QuotasClient()
+ cls.quotas_client = cls.os_primary.dns_v2.QuotasClient()
+
@decorators.idempotent_id('ae82a0ba-da60-11eb-bf12-74e5f9e2a801')
def test_admin_sets_quota_for_a_project(self):
primary_project_id = self.quotas_client.project_id
- http_headers_to_use = [
- {'X-Auth-All-Projects': True},
+ http_headers_to_use = [self.all_projects_header,
{'x-auth-sudo-project-id': primary_project_id}]
for http_header in http_headers_to_use:
@@ -240,21 +275,33 @@
lib_exc.Forbidden, self.quotas_client.set_quotas,
project_id=self.quotas_client.project_id,
quotas=dns_data_utils.rand_quotas(),
- headers={'x-auth-all-projects': True})
+ headers=self.all_projects_header)
@decorators.idempotent_id('a6ce5b46-dcce-11eb-903e-74e5f9e2a801')
@decorators.skip_because(bug="1934596")
def test_admin_sets_invalid_quota_values(self):
primary_project_id = self.quotas_client.project_id
- http_header = {'X-Auth-All-Projects': True}
- for item in ['zones', 'zone_records',
- 'zone_recordsets', 'recordset_records']:
+ for item in quotas_types:
quota = dns_data_utils.rand_quotas()
quota[item] = tempest_data_utils.rand_name()
self.assertRaises(
lib_exc.BadRequest, self.admin_client.set_quotas,
project_id=primary_project_id,
quotas=quota,
- headers=http_header)
+ headers=self.all_projects_header)
+
+ @decorators.idempotent_id('ac212fd8-c602-11ec-b042-201e8823901f')
+ def test_admin_sets_not_existing_quota_type(self):
+
+ LOG.info('Try to set quota using not existing quota type in its body')
+ primary_project_id = self.quotas_client.project_id
+ quota = dns_data_utils.rand_quotas()
+ quota[tempest_data_utils.rand_name()] = 777
+
+ with self.assertRaisesDns(
+ lib_exc.ServerFault, 'quota_resource_unknown', 500):
+ self.admin_client.set_quotas(
+ project_id=primary_project_id,
+ quotas=quota, headers=self.all_projects_header)
diff --git a/designate_tempest_plugin/tests/api/v2/test_recordset.py b/designate_tempest_plugin/tests/api/v2/test_recordset.py
index 71bf455..f6e9a4a 100644
--- a/designate_tempest_plugin/tests/api/v2/test_recordset.py
+++ b/designate_tempest_plugin/tests/api/v2/test_recordset.py
@@ -127,16 +127,18 @@
@decorators.idempotent_id('6c22a3f9-3f4d-4b32-bdf2-5237851ed25e')
def test_create_recordset_type_SRV_TCP(self):
self._test_create_recordset_type(
- "_sip._tcp", "SRV", ["10 60 5060 server1.example.com.",
- "20 60 5060 server2.example.com.",
- "20 30 5060 server3.example.com."])
+ "_sip._tcp", "SRV", [
+ "10 60 5060 server1.example.{}.".format(self.tld_suffix),
+ "20 60 5060 server2.example.{}.".format(self.tld_suffix),
+ "20 30 5060 server3.example.{}.".format(self.tld_suffix)])
@decorators.idempotent_id('59c1aa42-278e-4f7b-a6a1-4320d5daf1fd')
def test_create_recordset_type_SRV_UDP(self):
self._test_create_recordset_type(
- "_sip._udp", "SRV", ["10 60 5060 server1.example.com.",
- "10 60 5060 server2.example.com.",
- "20 30 5060 server3.example.com."])
+ "_sip._udp", "SRV", [
+ "10 60 5060 server1.example.{}.".format(self.tld_suffix),
+ "10 60 5060 server2.example.{}.".format(self.tld_suffix),
+ "20 30 5060 server3.example.{}.".format(self.tld_suffix)])
@decorators.idempotent_id('1ac46f94-f03a-4f85-b84f-826a2660b927')
def test_create_recordset_type_CNAME(self):
@@ -891,3 +893,59 @@
{primary_project_id}, project_ids_api,
'Failed, unique project_ids {} are not as expected {}'.format(
project_ids_api, primary_project_id))
+
+
+class AdminManagedRecordsetTest(BaseRecordsetsTest):
+
+ credentials = ["primary", "admin", "system_admin"]
+
+ @classmethod
+ def setup_credentials(cls):
+ # Do not create network resources for these test.
+ cls.set_network_resources()
+ super(AdminManagedRecordsetTest, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(AdminManagedRecordsetTest, cls).setup_clients()
+ if CONF.enforce_scope.designate:
+ cls.admin_client = cls.os_system_admin.dns_v2.RecordsetClient()
+ else:
+ cls.admin_client = cls.os_admin.dns_v2.RecordsetClient()
+ cls.client = cls.os_primary.dns_v2.RecordsetClient()
+ cls.zone_client = cls.os_primary.dns_v2.ZonesClient()
+
+ @decorators.idempotent_id('84164ff4-8e68-11ec-983f-201e8823901f')
+ def test_admin_updates_soa_and_ns_recordsets(self):
+ # HTTP headers to be used in the test
+ sudo_header = {'X-Auth-All-Projects': True}
+ managed_records_header = {'X-Designate-Edit-Managed-Records': True}
+ sudo_managed_headers = sudo_header.copy()
+ sudo_managed_headers.update(managed_records_header)
+
+ LOG.info('Primary user creates a Zone')
+ zone = self.zone_client.create_zone(
+ description='Zone for "managed recordsets update" test',
+ wait_until=const.ACTIVE)[1]
+ self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
+ recordsets = self.admin_client.list_recordset(
+ zone['id'], headers=sudo_header)[1]['recordsets']
+
+ LOG.info('As Admin try to update SOA and NS recordsets,'
+ ' Expected not allowed')
+ for recordset in recordsets:
+ if recordset['type'] == 'NS':
+ self.assertRaisesDns(
+ lib_exc.BadRequest, 'bad_request', 400,
+ self.admin_client.update_recordset,
+ zone['id'], recordset['id'],
+ recordet_data=data_utils.rand_ns_records(),
+ headers=sudo_managed_headers, extra_headers=True)
+
+ if recordset['type'] == 'SOA':
+ self.assertRaisesDns(
+ lib_exc.BadRequest, 'bad_request', 400,
+ self.admin_client.update_recordset,
+ zone['id'], recordset['id'],
+ recordet_data=data_utils.rand_soa_recordset(zone['name']),
+ headers=sudo_managed_headers, extra_headers=True)
diff --git a/designate_tempest_plugin/tests/api/v2/test_service_statuses.py b/designate_tempest_plugin/tests/api/v2/test_service_statuses.py
index 0deeb74..bee364e 100644
--- a/designate_tempest_plugin/tests/api/v2/test_service_statuses.py
+++ b/designate_tempest_plugin/tests/api/v2/test_service_statuses.py
@@ -24,27 +24,28 @@
LOG = logging.getLogger(__name__)
-class ServiceStatus(base.BaseDnsV2Test):
+class ServiceStatusAdmin(base.BaseDnsV2Test):
- credentials = ["primary", "admin", "system_admin", "alt"]
+ credentials = ["admin", "system_admin"]
+
+ mandatory_services = ['central', 'mdns', 'worker', 'producer']
+ service_status_fields = [
+ 'id', 'hostname', 'service_name', 'status', 'stats', 'capabilities',
+ 'heartbeated_at', 'created_at', 'updated_at', 'links']
@classmethod
def setup_credentials(cls):
# Do not create network resources for these test.
cls.set_network_resources()
- super(ServiceStatus, cls).setup_credentials()
+ super(ServiceStatusAdmin, cls).setup_credentials()
@classmethod
def setup_clients(cls):
- super(ServiceStatus, cls).setup_clients()
+ super(ServiceStatusAdmin, cls).setup_clients()
if CONF.enforce_scope.designate:
cls.admin_client = cls.os_system_admin.dns_v2.ServiceClient()
else:
cls.admin_client = cls.os_admin.dns_v2.ServiceClient()
- cls.client = cls.os_primary.dns_v2.ServiceClient()
-
- cls.primary_client = cls.os_primary.dns_v2.ServiceClient()
- cls.alt_client = cls.os_alt.dns_v2.ServiceClient()
@decorators.idempotent_id('bf277a76-8583-11eb-a557-74e5f9e2a801')
def test_admin_list_service_statuses(self):
@@ -57,8 +58,8 @@
LOG.info('Make sure that all expected/mandatory services are '
'listed in API response.')
- expected_services = ['central', 'mdns', 'worker', 'producer']
- for service in expected_services:
+
+ for service in self.mandatory_services:
self.assertIn(
service, [item[0] for item in services_statuses_tup],
"Failed, expected service: {} wasn't detected in API "
@@ -70,6 +71,37 @@
"Failed, not all listed services are in UP status, "
"services: {}".format(services_statuses_tup))
+ @decorators.idempotent_id('fce0f704-c0ae-11ec-8213-201e8823901f')
+ def test_admin_show_service_status(self):
+
+ LOG.info('List services and get the IDs of mandatory services only')
+ services_ids = [
+ service['id'] for service in self.admin_client.list_statuses()
+ if service['service_name'] in self.mandatory_services]
+
+ LOG.info('Ensure all service status fields presents in response')
+ for id in services_ids:
+ service_show = self.admin_client.show_statuses(id)
+ self.assertEqual(
+ sorted(self.service_status_fields), sorted(service_show))
+
+
+class ServiceStatusNegative(base.BaseDnsV2Test):
+
+ credentials = ["primary", "alt"]
+
+ @classmethod
+ def setup_credentials(cls):
+ # Do not create network resources for these test.
+ cls.set_network_resources()
+ super(ServiceStatusNegative, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(ServiceStatusNegative, cls).setup_clients()
+ cls.primary_client = cls.os_primary.dns_v2.ServiceClient()
+ cls.alt_client = cls.os_alt.dns_v2.ServiceClient()
+
@decorators.idempotent_id('d4753f76-de43-11eb-91d1-74e5f9e2a801')
def test_primary_is_forbidden_to_list_service_statuses(self):
diff --git a/designate_tempest_plugin/tests/api/v2/test_tld.py b/designate_tempest_plugin/tests/api/v2/test_tld.py
index 831c13c..11882a3 100644
--- a/designate_tempest_plugin/tests/api/v2/test_tld.py
+++ b/designate_tempest_plugin/tests/api/v2/test_tld.py
@@ -51,7 +51,7 @@
def resource_setup(cls):
super(TldAdminTest, cls).resource_setup()
cls.tld = cls.admin_client.create_tld(
- tld_name='com', ignore_errors=lib_exc.Conflict
+ tld_name=cls.tld_suffix, ignore_errors=lib_exc.Conflict
)
@classmethod
@@ -66,8 +66,8 @@
"description": "sample tld"}
LOG.info('Create a tld')
- _, tld = self.admin_client.create_tld(tld_data['name'],
- tld_data['description'])
+ tld = self.admin_client.create_tld(tld_data['name'],
+ tld_data['description'])[1]
self.addCleanup(self.admin_client.delete_tld, tld['id'])
self.assertEqual(tld_data["name"], tld['name'])
@@ -116,21 +116,6 @@
lib_exc.BadRequest, self.admin_client.create_tld,
tld_name='org', description='test_create_invalid_tld' * 1000)
- @decorators.idempotent_id('06deced8-d4de-11eb-b8ee-74e5f9e2a801')
- def test_create_zone_for_not_existing_tld(self):
- LOG.info('Create an "org" TLD')
- tld_data = {"name": "org",
- "description": "test_create_zone_for_not_existing_tld"}
- tld = self.admin_client.create_tld(
- tld_data['name'], tld_data['description'])[1]
- self.addCleanup(self.admin_client.delete_tld, tld['id'])
- self.assertEqual(tld_data["name"], tld['name'])
-
- LOG.info('Try to create a Primary zone with "zzz" (not existing) TLD.')
- self.assertRaises(
- lib_exc.BadRequest, self.primary_zone_client.create_zone,
- name='example.zzz.')
-
@decorators.idempotent_id('757019c0-d4e2-11eb-b8ee-74e5f9e2a801')
def test_create_tld_as_primary_user(self):
tld_data = {
@@ -147,12 +132,12 @@
"description": "sample tld"}
LOG.info('Create a tld')
- _, tld = self.admin_client.create_tld(tld_data['name'],
- tld_data['description'])
+ tld = self.admin_client.create_tld(tld_data['name'],
+ tld_data['description'])[1]
self.addCleanup(self.admin_client.delete_tld, tld['id'])
LOG.info('Fetch the tld')
- _, body = self.admin_client.show_tld(tld['id'])
+ body = self.admin_client.show_tld(tld['id'])[1]
LOG.info('Ensure the fetched response matches the created tld')
self.assertExpected(tld, body, self.excluded_keys)
@@ -160,12 +145,12 @@
@decorators.idempotent_id('26708cb8-7126-48a7-9424-1c225e56e609')
def test_delete_tld(self):
LOG.info('Create a tld')
- _, tld = self.admin_client.create_tld()
+ tld = self.admin_client.create_tld()[1]
self.addCleanup(self.admin_client.delete_tld, tld['id'],
ignore_errors=lib_exc.NotFound)
LOG.info('Delete the tld')
- _, body = self.admin_client.delete_tld(tld['id'])
+ self.admin_client.delete_tld(tld['id'])
self.assertRaises(lib_exc.NotFound,
lambda: self.admin_client.show_tld(tld['id']))
@@ -173,13 +158,13 @@
@decorators.idempotent_id('95b13759-c85c-4791-829b-9591ca15779d')
def test_list_tlds(self):
LOG.info('List tlds')
- _, body = self.admin_client.list_tlds()
+ body = self.admin_client.list_tlds()[1]
self.assertGreater(len(body['tlds']), 0)
@decorators.idempotent_id('1a233812-48d9-4d15-af5e-9961744286ff')
def test_update_tld(self):
- _, tld = self.admin_client.create_tld()
+ tld = self.admin_client.create_tld()[1]
self.addCleanup(self.admin_client.delete_tld, tld['id'])
tld_data = {
@@ -188,8 +173,8 @@
}
LOG.info('Update the tld')
- _, patch_tld = self.admin_client.update_tld(tld['id'],
- tld_data['name'], tld_data['description'])
+ patch_tld = self.admin_client.update_tld(tld['id'],
+ tld_data['name'], tld_data['description'])[1]
self.assertEqual(tld_data["name"], patch_tld["name"])
self.assertEqual(tld_data["description"], patch_tld["description"])
diff --git a/designate_tempest_plugin/tests/api/v2/test_zones.py b/designate_tempest_plugin/tests/api/v2/test_zones.py
index dec5028..f2faa88 100644
--- a/designate_tempest_plugin/tests/api/v2/test_zones.py
+++ b/designate_tempest_plugin/tests/api/v2/test_zones.py
@@ -24,8 +24,6 @@
from designate_tempest_plugin import data_utils as dns_data_utils
from designate_tempest_plugin.tests import base
-from designate_tempest_plugin.common import waiters
-
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -62,8 +60,8 @@
self.addCleanup(self.wait_zone_delete, self.client, zone['id'])
LOG.info('Ensure we respond with CREATE+PENDING')
- self.assertEqual('CREATE', zone['action'])
- self.assertEqual('PENDING', zone['status'])
+ self.assertEqual(const.CREATE, zone['action'])
+ self.assertEqual(const.PENDING, zone['status'])
# Get the Name Servers (hosts) created in PRIMARY zone
nameservers = self.client.show_zone_nameservers(zone['id'])[1]
@@ -76,22 +74,19 @@
self.addCleanup(self.wait_zone_delete, self.client, zone['id'])
LOG.info('Ensure we respond with CREATE+PENDING')
- self.assertEqual('CREATE', zone['action'])
- self.assertEqual('PENDING', zone['status'])
+ self.assertEqual(const.CREATE, zone['action'])
+ self.assertEqual(const.PENDING, zone['status'])
@decorators.idempotent_id('ec150c22-f52e-11eb-b09b-74e5f9e2a801')
def test_create_zone_validate_recordsets_created(self):
# Create a PRIMARY zone and wait till it's Active
LOG.info('Create a PRIMARY zone')
- zone = self.client.create_zone()[1]
+ zone = self.client.create_zone(wait_until=const.ACTIVE)[1]
self.addCleanup(self.wait_zone_delete, self.client, zone['id'])
LOG.info('Ensure we respond with CREATE+PENDING')
- self.assertEqual('CREATE', zone['action'])
- self.assertEqual('PENDING', zone['status'])
-
- LOG.info('Wait till the zone is Active')
- waiters.wait_for_zone_status(self.client, zone['id'], 'ACTIVE')
+ self.assertEqual(const.CREATE, zone['action'])
+ self.assertEqual(const.PENDING, zone['status'])
LOG.info('Ensure that SOA and NS recordsets types has been created.')
recordsets = self.recordset_client.list_recordset(
@@ -140,8 +135,8 @@
_, body = self.client.delete_zone(zone['id'])
LOG.info('Ensure we respond with DELETE+PENDING')
- self.assertEqual('DELETE', body['action'])
- self.assertEqual('PENDING', body['status'])
+ self.assertEqual(const.DELETE, body['action'])
+ self.assertEqual(const.PENDING, body['status'])
@decorators.idempotent_id('79921370-92e1-11eb-9d02-74e5f9e2a801')
def test_delete_non_existing_zone(self):
@@ -176,12 +171,53 @@
zone['id'], description=description)
LOG.info('Ensure we respond with UPDATE+PENDING')
- self.assertEqual('UPDATE', zone['action'])
- self.assertEqual('PENDING', zone['status'])
+ self.assertEqual(const.UPDATE, zone['action'])
+ self.assertEqual(const.PENDING, zone['status'])
LOG.info('Ensure we respond with updated values')
self.assertEqual(description, zone['description'])
+ @decorators.idempotent_id('3acddc86-62cc-4bfa-8589-b99e5d239bf2')
+ @decorators.skip_because(bug="1960487")
+ def test_serial_changes_on_update(self):
+ LOG.info('Create a zone')
+ zone = self.client.create_zone(wait_until=const.ACTIVE)[1]
+ self.addCleanup(self.wait_zone_delete, self.client, zone['id'])
+
+ LOG.info("Update Zone's email")
+ update_email = self.client.update_zone(
+ zone['id'], email=dns_data_utils.rand_email())[1]
+ self.assertNotEqual(
+ zone['serial'], update_email['serial'],
+ "Failed, expected: 'Serial' is supposed to be changed "
+ "on Email update.")
+
+ LOG.info("Update Zone's TTL")
+ update_ttl = self.client.update_zone(
+ zone['id'], ttl=dns_data_utils.rand_ttl())[1]
+ self.assertNotEqual(
+ update_email['serial'], update_ttl['serial'],
+ "Failed, expected: 'Serial' is supposed to be changed "
+ "on TTL update.")
+
+ LOG.info("Update Zone's email and description")
+ update_email_description = self.client.update_zone(
+ zone['id'],
+ email=dns_data_utils.rand_email(),
+ description=data_utils.rand_name())[1]
+ self.assertNotEqual(
+ update_ttl['serial'], update_email_description['serial'],
+ "Failed, expect the Serial to change "
+ "when the Email and Description are updated")
+
+ LOG.info("Update Zone's description")
+ update_description = self.client.update_zone(
+ zone['id'], description=data_utils.rand_name())[1]
+ self.assertEqual(
+ update_email_description['serial'], update_description['serial'],
+ "Failed, expect the Serial to not change "
+ "when the Description is updated")
+
@decorators.idempotent_id('e391e30a-92e0-11eb-9d02-74e5f9e2a801')
def test_update_non_existing_zone(self):
LOG.info('Update non existing zone')
@@ -280,31 +316,21 @@
def test_list_all_projects_zones(self):
LOG.info('Create zone "A" using Primary client')
- primary_zone = self.client.create_zone()[1]
+ primary_zone = self.client.create_zone(wait_until=const.ACTIVE)[1]
self.addCleanup(
self.wait_zone_delete, self.client, primary_zone['id'])
- LOG.info('Wait till the zone is ACTIVE')
- waiters.wait_for_zone_status(
- self.client, primary_zone['id'], 'ACTIVE')
LOG.info('Create zone "B" using Alt client')
- alt_zone = self.alt_client.create_zone()[1]
+ alt_zone = self.alt_client.create_zone(wait_until=const.ACTIVE)[1]
self.addCleanup(
self.wait_zone_delete, self.alt_client, alt_zone['id'])
- LOG.info('Wait till the zone is ACTIVE')
- waiters.wait_for_zone_status(
- self.alt_client, alt_zone['id'], 'ACTIVE')
LOG.info('Create zone "C" using Admin client')
admin_zone = self.admin_client.create_zone(
- project_id="FakeProjectID")[1]
+ project_id="FakeProjectID", wait_until=const.ACTIVE)[1]
self.addCleanup(
self.wait_zone_delete, self.admin_client, admin_zone['id'],
headers=self.all_projects_header)
- LOG.info('Wait till the zone is ACTIVE')
- waiters.wait_for_zone_status(
- self.admin_client, admin_zone['id'], 'ACTIVE',
- headers=self.all_projects_header)
LOG.info('As admin user list all projects zones')
# Note: This is an all-projects list call, so other tests running
diff --git a/designate_tempest_plugin/tests/base.py b/designate_tempest_plugin/tests/base.py
index 2e02a8c..28b43cb 100644
--- a/designate_tempest_plugin/tests/base.py
+++ b/designate_tempest_plugin/tests/base.py
@@ -135,6 +135,10 @@
zone_id,
recordset_id)
+ def unset_ptr(self, ptr_client, fip_id, **kwargs):
+ return utils.call_and_ignore_notfound_exc(
+ ptr_client.unset_ptr_record, fip_id, **kwargs)
+
def _delete_zone(self, zone_client, zone_id, **kwargs):
return utils.call_and_ignore_notfound_exc(zone_client.delete_zone,
zone_id, **kwargs)
@@ -159,6 +163,7 @@
"""Base class for DNS V2 API tests."""
all_projects_header = {'X-Auth-All-Projects': True}
+ tld_suffix = CONF.dns.tld_suffix
@classmethod
def skip_checks(cls):
diff --git a/designate_tempest_plugin/tests/scenario/v2/test_tld.py b/designate_tempest_plugin/tests/scenario/v2/test_tld.py
new file mode 100644
index 0000000..9c048a1
--- /dev/null
+++ b/designate_tempest_plugin/tests/scenario/v2/test_tld.py
@@ -0,0 +1,80 @@
+# Copyright 2021 Red Hat.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslo_log import log as logging
+from tempest import config
+from tempest.lib import decorators
+from tempest.lib import exceptions as lib_exc
+
+from designate_tempest_plugin.common import constants as const
+from designate_tempest_plugin.tests import base
+from designate_tempest_plugin import data_utils as dns_data_utils
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+class TldZoneTest(base.BaseDnsV2Test):
+ credentials = ["admin", "system_admin", "primary"]
+
+ @classmethod
+ def setup_credentials(cls):
+ # Do not create network resources for these test.
+ cls.set_network_resources()
+ super(TldZoneTest, cls).setup_credentials()
+
+ @classmethod
+ def setup_clients(cls):
+ super(TldZoneTest, cls).setup_clients()
+ if CONF.enforce_scope.designate:
+ cls.admin_tld_client = cls.os_system_admin.dns_v2.TldClient()
+ else:
+ cls.admin_tld_client = cls.os_admin.dns_v2.TldClient()
+ cls.primary_tld_client = cls.os_primary.dns_v2.TldClient()
+ cls.primary_zone_client = cls.os_primary.dns_v2.ZonesClient()
+
+ @classmethod
+ def resource_setup(cls):
+ super(TldZoneTest, cls).resource_setup()
+ cls.tld = cls.admin_tld_client.create_tld(
+ tld_name=cls.tld_suffix, ignore_errors=lib_exc.Conflict
+ )
+
+ @classmethod
+ def resource_cleanup(cls):
+ cls.admin_tld_client.delete_tld(cls.tld[1]['id'])
+ super(TldZoneTest, cls).resource_cleanup()
+
+ @decorators.idempotent_id('68b3e7cc-bf0e-11ec-b803-201e8823901f')
+ def test_create_zone_using_existing_tld(self):
+ LOG.info('Creates a zone using existing TLD:"{}"'.format(
+ self.tld_suffix))
+ zone_name = dns_data_utils.rand_zone_name(
+ name='existing_tld_zone', prefix='rand',
+ suffix='.{}.'.format(self.tld_suffix))
+ zone = self.primary_zone_client.create_zone(
+ name=zone_name, wait_until=const.ACTIVE)[1]
+ self.addCleanup(
+ self.wait_zone_delete, self.primary_zone_client, zone['id'])
+
+ @decorators.idempotent_id('06deced8-d4de-11eb-b8ee-74e5f9e2a801')
+ def test_create_zone_using_not_existing_tld(self):
+ LOG.info('Try to create a Zone using not existing TLD:"{}"'.format(
+ self.tld_suffix[::-1]))
+ zone_name = dns_data_utils.rand_zone_name(
+ name='not_existing_tld_zone', prefix='rand',
+ suffix='.{}.'.format(self.tld_suffix)[::-1])
+ self.assertRaises(
+ lib_exc.BadRequest, self.primary_zone_client.create_zone,
+ name=zone_name)
diff --git a/designate_tempest_plugin/tests/scenario/v2/test_zones_export.py b/designate_tempest_plugin/tests/scenario/v2/test_zones_export.py
index 5d0de56..f094498 100644
--- a/designate_tempest_plugin/tests/scenario/v2/test_zones_export.py
+++ b/designate_tempest_plugin/tests/scenario/v2/test_zones_export.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import json
+import os
from oslo_log import log as logging
from tempest import config
from tempest.lib import decorators
@@ -42,6 +44,7 @@
cls.admin_client = cls.os_admin.dns_v2.ZoneExportsClient()
cls.client = cls.os_primary.dns_v2.ZoneExportsClient()
cls.zones_client = cls.os_primary.dns_v2.ZonesClient()
+ cls.recordset_client = cls.os_primary.dns_v2.RecordsetClient()
def _create_zone_export(self):
LOG.info('Create a zone')
@@ -49,10 +52,10 @@
self.addCleanup(self.wait_zone_delete, self.zones_client, zone['id'])
LOG.info('Create a zone export')
- zone_export = self.client.create_zone_export(zone['id'])[1]
+ zone_export = self.client.create_zone_export(
+ zone['id'], wait_until=const.COMPLETE)[1]
self.addCleanup(self.client.delete_zone_export, zone_export['id'])
- waiters.wait_for_zone_export_status(
- self.client, zone_export['id'], const.COMPLETE)
+
return zone, zone_export
@decorators.idempotent_id('0484c3c4-df57-458e-a6e5-6eb63e0475e0')
@@ -127,3 +130,58 @@
LOG.info('Ensure exported data ia as expected')
self.assertEqual(zone['name'], resp_data.origin)
self.assertEqual(zone['ttl'], resp_data.ttl)
+
+ @decorators.attr(type='slow')
+ @decorators.idempotent_id('d8f444aa-a645-4a03-b366-46836f57dc69')
+ def test_all_recordset_types_exist_in_show_zonefile(self):
+ recorsets_data_file = os.path.join(
+ os.path.dirname(__file__), 'recordset_data.json')
+
+ if not os.path.exists(recorsets_data_file):
+ raise self.skipException(
+ f"Could not find {recorsets_data_file}")
+
+ file = open(recorsets_data_file, "r")
+ load_file = json.loads(file.read())
+ file.close()
+
+ LOG.info('Create a zone')
+ zone = self.zones_client.create_zone(wait_until=const.ACTIVE)[1]
+ self.addCleanup(self.wait_zone_delete, self.zones_client, zone['id'])
+
+ created_records = []
+ for record_data in load_file.values():
+ recordset_data = {
+ 'name': f"{record_data['name']}.{zone['name']}",
+ 'type': record_data['type'],
+ 'records': record_data['records'],
+ }
+ try:
+ LOG.info('Create a Recordset')
+ recordset = self.recordset_client.create_recordset(
+ zone['id'], recordset_data)[1]
+ self.addCleanup(self.wait_recordset_delete,
+ self.recordset_client, zone['id'],
+ recordset['id'])
+ created_records.append(recordset['records'])
+ waiters.wait_for_recordset_status(self.recordset_client,
+ zone['id'], recordset['id'],
+ const.ACTIVE)
+ except Exception as err:
+ LOG.warning(f"Record of type {recordset['type']} could not be"
+ f" created and failed with error: {err}")
+
+ LOG.info('Create a zone export')
+ zone_export = self.client.create_zone_export(
+ zone['id'], wait_until=const.COMPLETE)[1]
+ self.addCleanup(self.client.delete_zone_export, zone_export['id'])
+
+ LOG.info('Show exported zonefile')
+ created_zonefile = self.client.show_exported_zonefile(
+ zone_export['id'])[1]
+
+ file_records = [item.data for item in created_zonefile.records]
+ for record in created_records:
+ for r in record:
+ self.assertIn(r, file_records,
+ f"Failed, missing record: {r} in zone file")