Merge "Add test coverage for update: SOA and NS managed records"
diff --git a/designate_tempest_plugin/common/constants.py b/designate_tempest_plugin/common/constants.py
index 4f6c72b..96ed58b 100644
--- a/designate_tempest_plugin/common/constants.py
+++ b/designate_tempest_plugin/common/constants.py
@@ -18,6 +18,7 @@
ERROR = 'ERROR'
DELETED = 'DELETED'
ACTIVE = 'ACTIVE'
+INACTIVE = 'INACTIVE'
UP = 'UP'
CREATE = 'CREATE'
diff --git a/designate_tempest_plugin/common/exceptions.py b/designate_tempest_plugin/common/exceptions.py
index d3f343d..27bf848 100644
--- a/designate_tempest_plugin/common/exceptions.py
+++ b/designate_tempest_plugin/common/exceptions.py
@@ -15,7 +15,7 @@
class InvalidStatusError(Exception):
"""
- Exception raise when an entity changes to an unexpected status.
+ Exception raised when an entity changes to an unexpected status.
"""
def __init__(self, entity, entity_id, status, expected_status=None):
diff --git a/designate_tempest_plugin/common/waiters.py b/designate_tempest_plugin/common/waiters.py
index 6bc5dfa..a606fda 100644
--- a/designate_tempest_plugin/common/waiters.py
+++ b/designate_tempest_plugin/common/waiters.py
@@ -73,6 +73,10 @@
LOG.info('Zone %s reached %s', zone_id, status)
return
+ if zone['status'] == const.ERROR:
+ raise exceptions.InvalidStatusError('Zone', zone_id,
+ zone['status'])
+
if int(time.time()) - start >= client.build_timeout:
message = ('Zone %(zone_id)s failed to reach status=%(status)s '
'within the required time (%(timeout)s s). Current '
@@ -105,6 +109,10 @@
LOG.info('Zone import %s reached %s', zone_import_id, status)
return
+ if zone_import['status'] == const.ERROR:
+ raise exceptions.InvalidStatusError('Zone Import', zone_import_id,
+ zone_import['status'])
+
if int(time.time()) - start >= client.build_timeout:
message = ('Zone import %(zone_import_id)s failed to reach '
'status=%(status)s within the required time '
@@ -138,6 +146,10 @@
LOG.info('Zone export %s reached %s', zone_export_id, status)
return
+ if zone_export['status'] == const.ERROR:
+ raise exceptions.InvalidStatusError('Zone Export', zone_export_id,
+ zone_export['status'])
+
if int(time.time()) - start >= client.build_timeout:
message = ('Zone export %(zone_export_id)s failed to reach '
'status=%(status)s within the required time '
@@ -172,6 +184,10 @@
LOG.info('Recordset %s reached %s', recordset_id, status)
return
+ if recordset['status'] == const.ERROR:
+ raise exceptions.InvalidStatusError('Recordset', recordset_id,
+ recordset['status'])
+
if int(time.time()) - start >= client.build_timeout:
message = ('Recordset %(recordset_id)s failed to reach '
'status=%(status)s within the required time '
@@ -250,6 +266,10 @@
LOG.info('PTR %s reached %s', fip_id, status)
return
+ if ptr['status'] == const.ERROR:
+ raise exceptions.InvalidStatusError('PTR', fip_id,
+ ptr['status'])
+
if int(time.time()) - start >= client.build_timeout:
message = ('PTR for FIP: %(fip_id)s failed to reach '
'status=%(status)s within the required time '
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 4fd47f9..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)
@@ -238,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
"""
@@ -268,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...)
"""
@@ -279,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
"""
@@ -288,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/v2/json/zone_exports_client.py b/designate_tempest_plugin/services/dns/v2/json/zone_exports_client.py
index 8915ceb..4057b7e 100644
--- a/designate_tempest_plugin/services/dns/v2/json/zone_exports_client.py
+++ b/designate_tempest_plugin/services/dns/v2/json/zone_exports_client.py
@@ -23,7 +23,7 @@
"""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 @@
"""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 @@
'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 @@
"""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.
"""
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_recordset.py b/designate_tempest_plugin/tests/api/v2/test_recordset.py
index ac337b9..c9e17ed 100644
--- a/designate_tempest_plugin/tests/api/v2/test_recordset.py
+++ b/designate_tempest_plugin/tests/api/v2/test_recordset.py
@@ -38,7 +38,7 @@
# All the recordset tests need a zone, create one to share
LOG.info('Create a zone')
- _, cls.zone = cls.zone_client.create_zone()
+ cls.zone = cls.zone_client.create_zone()[1]
@classmethod
def resource_cleanup(cls):
@@ -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):
@@ -201,7 +203,7 @@
self.zone['id'], body['id'])
LOG.info('List zone recordsets')
- _, body = self.client.list_recordset(self.zone['id'])
+ body = self.client.list_recordset(self.zone['id'])[1]
self.assertGreater(len(body), 0)
@@ -218,7 +220,7 @@
self.zone['id'], body['id'])
LOG.info('Re-Fetch the Recordset')
- _, record = self.client.show_recordset(self.zone['id'], body['id'])
+ record = self.client.show_recordset(self.zone['id'], body['id'])[1]
LOG.info('Ensure the fetched response matches the expected one')
self.assertExpected(body, record, self.excluded_keys)
@@ -229,14 +231,14 @@
record_type='A', zone_name=self.zone['name'])
LOG.info('Create a Recordset')
- _, record = self.client.create_recordset(
- self.zone['id'], recordset_data)
+ record = self.client.create_recordset(
+ self.zone['id'], recordset_data)[1]
self.addCleanup(
self.wait_recordset_delete, self.client,
self.zone['id'], record['id'])
LOG.info('Delete a Recordset')
- _, body = self.client.delete_recordset(self.zone['id'], record['id'])
+ self.client.delete_recordset(self.zone['id'], record['id'])
LOG.info('Ensure successful deletion of Recordset')
self.assertRaises(lib_exc.NotFound,
@@ -248,8 +250,8 @@
record_type='A', zone_name=self.zone['name'])
LOG.info('Create a recordset')
- _, record = self.client.create_recordset(
- self.zone['id'], recordset_data)
+ record = self.client.create_recordset(
+ self.zone['id'], recordset_data)[1]
self.addCleanup(
self.wait_recordset_delete, self.client,
self.zone['id'], record['id'])
@@ -258,8 +260,8 @@
record_type='A', zone_name=self.zone['name'], name=record['name'])
LOG.info('Update the recordset')
- _, update = self.client.update_recordset(self.zone['id'],
- record['id'], recordset_data)
+ update = self.client.update_recordset(self.zone['id'],
+ record['id'], recordset_data)[1]
self.assertEqual(record['name'], update['name'])
self.assertNotEqual(record['records'], update['records'])
@@ -270,8 +272,8 @@
record_type='A', zone_name=self.zone['name'])
LOG.info('Create a recordset')
- _, record = self.client.create_recordset(
- self.zone['id'], recordset_data)
+ record = self.client.create_recordset(
+ self.zone['id'], recordset_data)[1]
self.addCleanup(
self.wait_recordset_delete, self.client,
self.zone['id'], record['id'])
@@ -281,8 +283,8 @@
}
LOG.info('Update the recordset')
- _, update = self.client.update_recordset(self.zone['id'],
- record['id'], recordset_data)
+ update = self.client.update_recordset(self.zone['id'],
+ record['id'], recordset_data)[1]
self.assertEqual(record['name'], update['name'])
self.assertEqual(record['records'], update['records'])
@@ -442,7 +444,7 @@
@decorators.idempotent_id('b6dad57e-5ce9-4fa5-8d66-aebbcd23b4ad')
def test_get_nonexistent_recordset(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('Attempt to get an invalid Recordset')
@@ -453,7 +455,7 @@
@decorators.idempotent_id('93d744a8-0dfd-4650-bcef-1e6ad632ad72')
def test_get_nonexistent_recordset_invalid_id(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('Attempt to get an invalid Recordset')
@@ -463,7 +465,7 @@
@decorators.idempotent_id('da08f19a-7f10-47cc-8b41-994507190812')
def test_update_nonexistent_recordset(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'])
recordset_data = data_utils.rand_recordset_data('A', zone['name'])
@@ -477,7 +479,7 @@
@decorators.idempotent_id('158340a1-3f69-4aaa-9968-956190563768')
def test_update_nonexistent_recordset_invalid_id(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'])
recordset_data = data_utils.rand_recordset_data('A', zone['name'])
@@ -490,7 +492,7 @@
@decorators.idempotent_id('64bd94d4-54bd-4bee-b6fd-92ede063234e')
def test_delete_nonexistent_recordset(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('Attempt to delete an invalid Recordset')
@@ -502,7 +504,7 @@
@decorators.idempotent_id('5948b599-a332-4dcb-840b-afc825075ba3')
def test_delete_nonexistent_recordset_invalid_id(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('Attempt to get an invalid Recordset')
@@ -578,7 +580,7 @@
@decorators.idempotent_id('48a081b9-4474-4da0-9b1a-6359a80456ce')
def test_list_zones_recordsets(self):
LOG.info('List recordsets')
- _, body = self.client.list_zones_recordsets()
+ body = self.client.list_zones_recordsets()[1]
self.assertGreater(len(body['recordsets']), 0)
@@ -609,7 +611,7 @@
self.zone['id'], zone_recordset['id'])
LOG.info('Create another zone')
- _, zone2 = self.zone_client.create_zone()
+ zone2 = self.zone_client.create_zone()[1]
self.addCleanup(self.wait_zone_delete, self.zone_client, zone2['id'])
LOG.info('Create another Recordset')
@@ -623,7 +625,7 @@
self.zone['id'], zone_recordset2['id'])
LOG.info('List recordsets')
- _, body = self.client.list_zones_recordsets(params={"data": "10.0.*"})
+ body = self.client.list_zones_recordsets(params={"data": "10.0.*"})[1]
recordsets = body['recordsets']
@@ -641,11 +643,11 @@
@decorators.idempotent_id('7f4970bf-9aeb-4a3c-9afd-02f5a7178d35')
def test_list_zones_recordsets_zone_names(self):
LOG.info('Create another zone')
- _, zone2 = self.zone_client.create_zone()
+ zone2 = self.zone_client.create_zone()[1]
self.addCleanup(self.wait_zone_delete, self.zone_client, zone2['id'])
LOG.info('List recordsets')
- _, body = self.client.list_zones_recordsets()
+ body = self.client.list_zones_recordsets()[1]
recordsets = body['recordsets']
zone_names = set()
@@ -763,7 +765,7 @@
zone_name = data_utils.rand_zone_name()
LOG.info('Create a zone as a default user')
- _, zone = self.zone_client.create_zone(name='a.b.' + zone_name)
+ zone = self.zone_client.create_zone(name='a.b.' + zone_name)[1]
self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
rrset_data = data_utils.rand_recordset_data(
@@ -777,8 +779,8 @@
@decorators.idempotent_id('3dbe244d-fa85-4afc-869b-0306388d8746')
def test_no_create_recordset_via_alt_domain(self):
- _, zone = self.zone_client.create_zone()
- _, alt_zone = self.alt_zone_client.create_zone()
+ zone = self.zone_client.create_zone()[1]
+ alt_zone = self.alt_zone_client.create_zone()[1]
self.addCleanup(self.wait_zone_delete,
self.zone_client,
zone['id'])
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_exports.py b/designate_tempest_plugin/tests/api/v2/test_zones_exports.py
index 4841d18..31da506 100644
--- a/designate_tempest_plugin/tests/api/v2/test_zones_exports.py
+++ b/designate_tempest_plugin/tests/api/v2/test_zones_exports.py
@@ -16,8 +16,11 @@
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 @@
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 @@
_, 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 @@
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 @@
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 @@
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 @@
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))
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 916e634..5d0de56 100644
--- a/designate_tempest_plugin/tests/scenario/v2/test_zones_export.py
+++ b/designate_tempest_plugin/tests/scenario/v2/test_zones_export.py
@@ -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 @@
_, 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)
diff --git a/tox.ini b/tox.ini
index 3b481d0..a413aeb 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-minversion = 3.1.1
+minversion = 3.18.0
envlist = pep8
skipsdist = True
ignore_basepython_conflict = True
@@ -9,7 +9,7 @@
usedevelop = True
install_command = pip install {opts} {packages}
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
+ -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
setenv =