Merge "Adding new test cases for zone export showfile API"

This commit is contained in:
Zuul 2022-03-09 18:03:36 +00:00 committed by Gerrit Code Review
commit 71273444a1
3 changed files with 160 additions and 49 deletions

View File

@ -23,7 +23,7 @@ class ZoneExportsClient(base.DnsClientV2Base):
"""Create a zone export.
:param uuid: Unique identifier of the zone in UUID format.
:param params: A Python dict that represents the query paramaters to
:param params: A Python dict that represents the query parameters to
include in the request URI.
:param wait_until: Block until the exported zone reaches the
desired status
@ -47,7 +47,7 @@ class ZoneExportsClient(base.DnsClientV2Base):
"""Get the zone export task
:param uuid: Unique identifier of the zone export task in UUID format.
:param params: A Python dict that represents the query paramaters to
:param params: A Python dict that represents the query parameters to
include in the request URI.
:param headers (dict): The headers to use for the request.
:return: Serialized exported zone as a dictionary.
@ -56,25 +56,42 @@ class ZoneExportsClient(base.DnsClientV2Base):
'zones/tasks/exports', uuid, params=params, headers=headers)
@base.handle_errors
def show_exported_zonefile(self, uuid, params=None):
def show_exported_zonefile(self, uuid, params=None, headers=None):
"""Get the exported zone file
:param uuid: Unique identifier of the zone exprot task in UUID format.
:param params: A Python dict that represents the query paramaters to
:param uuid: Unique identifier of the zone export task in UUID format.
:param params: A Python dict that represents the query parameters to
include in the request URI.
:param headers: 3 options to send headers:
1) If headers dict provided is missing "Accept" key -
"{Accept:text/dns}" will be added.
2) If header is None -
"{Accept:text/dns}" will be sent.
3) If function is called with no headers,
means empty dict {} -
no headers will be sent (empty dictionary)
:return: Serialized exported zone as a dictionary.
"""
headers = {'Accept': 'text/dns'}
if headers:
if 'accept' not in [key.lower() for key in headers.keys()]:
headers['Accept'] = 'text/dns'
elif headers is None:
headers = {'Accept': 'text/dns'}
else:
headers = {}
return self._show_request(
'zones/tasks/exports/{0}/export'.format(uuid), uuid='',
headers=headers, params=params)
'zones/tasks/exports/{0}/export'.format(uuid),
uuid='', headers=headers, params=params)
@base.handle_errors
def list_zone_exports(self, params=None, headers=None):
"""List zone export tasks
:param params: A Python dict that represents the query paramaters to
:param params: A Python dict that represents the query parameters to
include in the request URI.
:param headers (dict): The headers to use for the request.
:return: Serialized exported zone as a list.
@ -87,7 +104,7 @@ class ZoneExportsClient(base.DnsClientV2Base):
"""Deletes the zone export task with the specified UUID.
:param uuid: The unique identifier of the exported zone.
:param params: A Python dict that represents the query paramaters to
:param params: A Python dict that represents the query parameters to
include in the request URI.
:return: A tuple with the server response and the response body.
"""

View File

@ -16,8 +16,11 @@ 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 tempest.lib.common.utils import data_utils
from designate_tempest_plugin.tests import base
from designate_tempest_plugin.common import waiters
from designate_tempest_plugin.common import constants as const
CONF = config.CONF
LOG = logging.getLogger(__name__)
@ -49,32 +52,32 @@ class ZonesExportTest(BaseZoneExportsTest):
cls.client = cls.os_primary.dns_v2.ZoneExportsClient()
cls.alt_client = cls.os_alt.dns_v2.ZoneExportsClient()
@decorators.idempotent_id('2dd8a9a0-98a2-4bf6-bb51-286583b30f40')
def test_create_zone_export(self):
def _create_zone_export(self):
LOG.info('Create a zone')
_, zone = self.zone_client.create_zone()
zone = self.zone_client.create_zone()[1]
self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
LOG.info('Create a zone export')
_, zone_export = self.client.create_zone_export(zone['id'])
zone_export = self.client.create_zone_export(zone['id'])[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('2dd8a9a0-98a2-4bf6-bb51-286583b30f40')
def test_create_zone_export(self):
zone_export = self._create_zone_export()[1]
LOG.info('Ensure we respond with PENDING')
self.assertEqual('PENDING', zone_export['status'])
self.assertEqual(const.PENDING, zone_export['status'])
@decorators.attr(type='smoke')
@decorators.idempotent_id('2d29a2a9-1941-4b7e-9d8a-ad6c2140ea68')
def test_show_zone_export(self):
LOG.info('Create a zone')
_, zone = self.zone_client.create_zone()
self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
LOG.info('Create a zone export')
resp, zone_export = self.client.create_zone_export(zone['id'])
self.addCleanup(self.client.delete_zone_export, zone_export['id'])
zone_export = self._create_zone_export()[1]
LOG.info('Re-Fetch the zone export')
_, body = self.client.show_zone_export(zone_export['id'])
body = self.client.show_zone_export(zone_export['id'])[1]
LOG.info('Ensure the fetched response matches the zone export')
self.assertExpected(zone_export, body, self.excluded_keys)
@ -116,20 +119,16 @@ class ZonesExportTest(BaseZoneExportsTest):
_, body = self.client.delete_zone_export(zone_export['id'])
LOG.info('Ensure the zone export has been successfully deleted')
self.assertRaises(lib_exc.NotFound,
lambda: self.client.show_zone_export(zone_export['id']))
self.assertRaises(
lib_exc.NotFound,
self.client.show_zone_export, zone_export['id'])
@decorators.idempotent_id('476bfdfe-58c8-46e2-b376-8403c0fff440')
def test_list_zone_exports(self):
LOG.info('Create a zone')
_, zone = self.zone_client.create_zone()
self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
_, export = self.client.create_zone_export(zone['id'])
self.addCleanup(self.client.delete_zone_export, export['id'])
self._create_zone_export()[1]
LOG.info('List zone exports')
_, body = self.client.list_zone_exports()
body = self.client.list_zone_exports()[1]
self.assertGreater(len(body['exports']), 0)
@ -183,8 +182,10 @@ class ZonesExportTest(BaseZoneExportsTest):
alt_export = self.alt_client.create_zone_export(alt_zone['id'])[1]
self.alt_client.delete_zone_export(alt_export['id'])
LOG.info('Ensure the zone export has been successfully deleted')
self.assertRaises(lib_exc.NotFound,
lambda: self.alt_client.show_zone_export(alt_export['id']))
self.assertRaises(
lib_exc.NotFound,
self.alt_client.show_zone_export,
alt_export['id'])
LOG.info('Filter out "export zones" in status:ZAHLABUT,'
' expected: empty list')
@ -236,6 +237,18 @@ class ZonesExportTestNegative(BaseZoneExportsTest):
cls.client = cls.os_primary.dns_v2.ZoneExportsClient()
cls.alt_client = cls.os_alt.dns_v2.ZoneExportsClient()
def _create_zone_export(self):
LOG.info('Create a zone')
zone = self.zone_client.create_zone()[1]
self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
LOG.info('Create a zone export')
zone_export = self.client.create_zone_export(zone['id'])[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('76ab8ec4-95fd-11eb-b1cd-74e5f9e2a801')
def test_create_zone_export_using_invalid_zone_id(self):
self.assertRaises(
@ -260,7 +273,6 @@ class ZonesExportTestNegative(BaseZoneExportsTest):
zone = self.zone_client.create_zone()[1]
self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'],
ignore_errors=lib_exc.NotFound)
LOG.info("Delete the zone and wait till it's done.")
self.zone_client.delete_zone(zone['id'])[1]
self.wait_zone_delete(self.zone_client, zone['id'])
@ -268,3 +280,21 @@ class ZonesExportTestNegative(BaseZoneExportsTest):
LOG.info('Ensure we respond with NotFound exception')
self.assertRaises(
lib_exc.NotFound, self.client.create_zone_export, zone['id'])
@decorators.idempotent_id('9a878646-f66b-4fa4-ae95-f3ac3f8e3d31')
def test_show_zonefile_using_not_existing_zone_export_id(self):
LOG.info('Expected: 404 Not Found zone export')
self.assertRaises(lib_exc.NotFound,
self.client.show_exported_zonefile,
data_utils.rand_uuid())
@decorators.idempotent_id('52a1fee0-c338-4ed9-b9f9-41ee7fd73375')
def test_show_zonefile_not_supported_accept_value(self):
zone, zone_export = self._create_zone_export()
# Tempest-lib _error_checker will raise UnexpectedResponseCode
e = self.assertRaises(
lib_exc.UnexpectedResponseCode, self.client.show_exported_zonefile,
zone_export['id'], headers={'Accept': 'image/jpeg'})
self.assertEqual(406, e.resp.status,
"Failed, actual response code is:{0}"
"but expected is: 406".format(e.resp.status))

View File

@ -13,48 +13,61 @@
# under the License.
from oslo_log import log as logging
from tempest import config
from tempest.lib import decorators
from designate_tempest_plugin.common import waiters
from designate_tempest_plugin.tests.api.v2.test_zones_exports import \
BaseZoneExportsTest
from designate_tempest_plugin.common import constants as const
CONF = config.CONF
LOG = logging.getLogger(__name__)
class ZonesExportTest(BaseZoneExportsTest):
credentials = ["primary", "admin", "system_admin"]
@classmethod
def setup_credentials(cls):
# Do not create network resources for these test.
cls.set_network_resources()
super(ZonesExportTest, cls).setup_credentials()
@classmethod
def setup_clients(cls):
super(ZonesExportTest, cls).setup_clients()
if CONF.enforce_scope.designate:
cls.admin_client = cls.os_system_admin.dns_v2.ZoneExportsClient()
else:
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()
@decorators.attr(type='slow')
@decorators.idempotent_id('0484c3c4-df57-458e-a6e5-6eb63e0475e0')
def test_create_zone_export_and_show_exported_zonefile(self):
LOG.info('Create a zone to be exported')
_, zone = self.zones_client.create_zone()
def _create_zone_export(self):
LOG.info('Create a zone')
zone = self.zones_client.create_zone()[1]
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'])
zone_export = self.client.create_zone_export(zone['id'])[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
self.assertEqual('PENDING', zone_export['status'])
@decorators.idempotent_id('0484c3c4-df57-458e-a6e5-6eb63e0475e0')
def test_create_zone_export_and_show_exported_zonefile(self):
zone, zone_export = self._create_zone_export()
self.assertEqual(const.PENDING, zone_export['status'])
self.assertEqual(zone['id'], zone_export['zone_id'])
self.assertIsNone(zone_export['links'].get('export'))
self.assertIsNone(zone_export['location'])
LOG.info('Wait for the zone export to COMPLETE')
waiters.wait_for_zone_export_status(
self.client, zone_export['id'], 'COMPLETE')
LOG.info('Check the zone export looks good')
_, zone_export = self.client.show_zone_export(zone_export['id'])
self.assertEqual('COMPLETE', zone_export['status'])
self.assertEqual(const.COMPLETE, zone_export['status'])
self.assertEqual(zone['id'], zone_export['zone_id'])
self.assertIsNotNone(zone_export['links'].get('export'))
self.assertIsNotNone(zone_export['location'])
@ -63,3 +76,54 @@ class ZonesExportTest(BaseZoneExportsTest):
_, zonefile = self.client.show_exported_zonefile(zone_export['id'])
self.assertEqual(zone['name'], zonefile.origin)
self.assertEqual(zone['ttl'], zonefile.ttl)
@decorators.idempotent_id('56b8f30e-cd45-4c7a-bc0c-bbf92d7dc697')
def test_show_exported_zonefile_impersonate_another_project(self):
zone, zone_export = self._create_zone_export()
LOG.info('As Admin impersonate "primary" client,'
' to show exported zone file')
response = self.admin_client.show_exported_zonefile(
zone_export['id'], headers={
'x-auth-sudo-project-id': zone['project_id']})[1]
self.assertEqual(zone['name'], response.origin)
self.assertEqual(zone['ttl'], response.ttl)
@decorators.idempotent_id('c2e55514-ff2e-41d9-a3cc-9e78873254c9')
def test_show_exported_zonefile_all_projects(self):
zone, zone_export = self._create_zone_export()
resp_headers, resp_data = self.admin_client.show_exported_zonefile(
zone_export['id'], headers={
'x-auth-all-projects': True
})
self.assertEqual(zone['name'], resp_data.origin)
self.assertEqual(zone['ttl'], resp_data.ttl)
@decorators.idempotent_id('9746b7f2-2df4-448c-8a85-5ab6bf74f1fe')
def test_show_exported_zonefile_any_mime_type(self):
zone, zone_export = self._create_zone_export()
resp_headers, resp_data = self.client.show_exported_zonefile(
zone_export['id'], headers={'Accept': '*/*'})
LOG.info('Ensure Content-Type: text/dns')
self.assertIn(
'text/dns', resp_headers['content-type'],
"Failed, the expected 'Content-type:text/dns wasn't received.")
LOG.info('Ensure exported data ia as expected')
self.assertEqual(zone['name'], resp_data.origin)
self.assertEqual(zone['ttl'], resp_data.ttl)
@decorators.idempotent_id('dc7a9dde-d287-4e22-9788-26578f0d3bf0')
def test_missing_accept_headers(self):
zone, zone_export = self._create_zone_export()
resp_headers, resp_data = self.client.show_exported_zonefile(
zone_export['id'], headers={})
LOG.info('Ensure Content-Type: text/dns')
self.assertIn(
'text/dns', resp_headers['content-type'],
"Failed, the expected 'Content-type:text/dns wasn't received.")
LOG.info('Ensure exported data ia as expected')
self.assertEqual(zone['name'], resp_data.origin)
self.assertEqual(zone['ttl'], resp_data.ttl)