Merge "Add tests for wildcard RRSets"
diff --git a/designate_tempest_plugin/clients.py b/designate_tempest_plugin/clients.py
index d85d343..5a8136c 100644
--- a/designate_tempest_plugin/clients.py
+++ b/designate_tempest_plugin/clients.py
@@ -13,9 +13,7 @@
# under the License.
from tempest import clients
from tempest import config
-from tempest.lib.auth import KeystoneAuthProvider
-from tempest.lib.auth import KeystoneV2AuthProvider
-from tempest.lib.auth import KeystoneV3AuthProvider
+from tempest.lib import auth
from designate_tempest_plugin.services.dns.v1.json.domains_client import \
DomainsClient
@@ -158,7 +156,7 @@
return KeystoneV2UnauthedProvider
-class BaseUnauthedProvider(KeystoneAuthProvider):
+class BaseUnauthedProvider(auth.KeystoneAuthProvider):
def _decorate_request(self, filters, method, url, headers=None, body=None,
auth_data=None):
@@ -173,13 +171,15 @@
return url, headers, body
-class KeystoneV2UnauthedProvider(KeystoneV2AuthProvider, BaseUnauthedProvider):
+class KeystoneV2UnauthedProvider(auth.KeystoneV2AuthProvider,
+ BaseUnauthedProvider):
def _decorate_request(self, *args, **kwargs):
return BaseUnauthedProvider._decorate_request(self, *args, **kwargs)
-class KeystoneV3UnauthedProvider(KeystoneV3AuthProvider, BaseUnauthedProvider):
+class KeystoneV3UnauthedProvider(auth.KeystoneV3AuthProvider,
+ BaseUnauthedProvider):
def _decorate_request(self, *args, **kwargs):
return BaseUnauthedProvider._decorate_request(self, *args, **kwargs)
diff --git a/designate_tempest_plugin/services/dns/admin/json/quotas_client.py b/designate_tempest_plugin/services/dns/admin/json/quotas_client.py
index 08b1790..fb233d2 100644
--- a/designate_tempest_plugin/services/dns/admin/json/quotas_client.py
+++ b/designate_tempest_plugin/services/dns/admin/json/quotas_client.py
@@ -11,13 +11,10 @@
# 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 designate_tempest_plugin import data_utils as dns_data_utils
from designate_tempest_plugin.services.dns.admin.json import base
-LOG = logging.getLogger(__name__)
-
class QuotasClient(base.DnsClientAdminBase):
diff --git a/designate_tempest_plugin/services/dns/json/base.py b/designate_tempest_plugin/services/dns/json/base.py
index 19dbe45..6c5f1d2 100644
--- a/designate_tempest_plugin/services/dns/json/base.py
+++ b/designate_tempest_plugin/services/dns/json/base.py
@@ -20,7 +20,7 @@
from six.moves.urllib import parse as urllib
import six
-from designate_tempest_plugin.common.models import ZoneFile
+from designate_tempest_plugin.common import models
LOG = logging.getLogger(__name__)
@@ -66,7 +66,7 @@
if 'application/json' in resp['content-type']:
return json.loads(object_str)
elif 'text/dns' in resp['content-type']:
- return ZoneFile.from_text(object_str)
+ return models.ZoneFile.from_text(object_str)
else:
raise lib_exc.InvalidContentType()
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 3522a1d..df2cdee 100644
--- a/designate_tempest_plugin/services/dns/v2/json/quotas_client.py
+++ b/designate_tempest_plugin/services/dns/v2/json/quotas_client.py
@@ -11,13 +11,10 @@
# 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 designate_tempest_plugin import data_utils as dns_data_utils
from designate_tempest_plugin.services.dns.v2.json import base
-LOG = logging.getLogger(__name__)
-
class QuotasClient(base.DnsClientV2Base):
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 3363e0c..28ec56a 100644
--- a/designate_tempest_plugin/services/dns/v2/json/recordset_client.py
+++ b/designate_tempest_plugin/services/dns/v2/json/recordset_client.py
@@ -26,7 +26,7 @@
:param zone_uuid: Unique identifier of the zone in UUID format..
:param recordset_data: A dictionary that represents the recordset
- data.
+ data.
:param params: A Python dict that represents the query paramaters to
include in the request URI.
:return: A tuple with the server response and the created zone.
@@ -44,6 +44,28 @@
return resp, body
@base.handle_errors
+ def update_recordset(self, zone_uuid, recordset_uuid,
+ recordet_data, params=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
+ format.
+ :param recordset_data: A dictionary that represents the recordset
+ data.
+ :param params: A Python dict that represents the query paramaters to
+ include in the request URI.
+ :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)
+
+ # Update Recordset should Return a HTTP 202
+ self.expected_success(202, resp.status)
+
+ return resp, body
+
+ @base.handle_errors
def show_recordset(self, zone_uuid, recordset_uuid, params=None):
"""Gets a specific recordset related to a specific zone.
:param zone_uuid: Unique identifier of the zone in UUID format.
@@ -87,6 +109,24 @@
'zones/{0}/recordsets'.format(uuid), params=params)
@base.handle_errors
+ def show_zones_recordset(self, recordset_uuid, params=None):
+ """Gets a single recordset, using the cross_zone endpoint
+ :param recordset_uuid: Unique identifier of the recordset in UUID
+ format.
+ :param params: A Python dict that represents the query paramaters to
+ include in the request URI.
+ :return: A tuple with the server response and the response body.
+ """
+ resp, body = self._show_request(
+ 'recordsets', recordset_uuid,
+ params=params)
+
+ # Show recordsets/id should return a HTTP 301
+ self.expected_success(301, resp.status)
+
+ return resp, body
+
+ @base.handle_errors
def list_zones_recordsets(self, params=None):
"""List recordsets across all zones.
:param params: A Python dict that represents the query paramaters to
@@ -95,23 +135,3 @@
"""
return self._list_request(
'recordsets', params=params)
-
- @base.handle_errors
- def update_recordset(self, zone_uuid, recordset_uuid,
- recordset_model, params=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 records in UUID format.
- :param recordset_model: .
- :param params: A Python dict that represents the query paramaters to
- include in the request URI.
- :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=recordset_model, params=params)
-
- # Update Recordset should Return a HTTP 202
- self.expected_success(202, resp.status)
-
- return resp, body
diff --git a/designate_tempest_plugin/tests/api/v2/test_quotas.py b/designate_tempest_plugin/tests/api/v2/test_quotas.py
index 9411270..bd865bb 100644
--- a/designate_tempest_plugin/tests/api/v2/test_quotas.py
+++ b/designate_tempest_plugin/tests/api/v2/test_quotas.py
@@ -75,7 +75,7 @@
LOG.info("Ensuring the response has all quota types")
self.assertExpected(quotas, body, [])
- @decorators.idempotent_id('76d24c87-1b39-4e19-947c-c08e1380dc61')
+ @decorators.idempotent_id('9b09b3e2-7e88-4569-bce3-9be2f7ac70c3')
def test_update_quotas_other_project(self):
project_id = self.quotas_client.tenant_id
diff --git a/designate_tempest_plugin/tests/api/v2/test_recordset.py b/designate_tempest_plugin/tests/api/v2/test_recordset.py
index 44ac45b..d686d94 100644
--- a/designate_tempest_plugin/tests/api/v2/test_recordset.py
+++ b/designate_tempest_plugin/tests/api/v2/test_recordset.py
@@ -209,7 +209,7 @@
cls.client = cls.os.recordset_client
cls.zone_client = cls.os.zones_client
- @decorators.idempotent_id('631d74fd-6909-4684-a61b-5c4d2f92c3e7')
+ @decorators.idempotent_id('98c94f8c-217a-4056-b996-b1f856d0753e')
@ddt.file_data("recordset_data_invalid.json")
def test_create_recordset_invalid(self, name, type, records):
if name is not None:
@@ -325,17 +325,22 @@
self.assertGreater(len(body['recordsets']), 0)
+ @decorators.skip_because(bug="1616892")
+ @decorators.idempotent_id('65ec0495-81d9-4cfb-8007-9d93b32ae883')
+ def test_get_single_zones_recordsets(self):
+ recordset_data = data_utils.rand_recordset_data(
+ record_type='A', zone_name=self.zone['name'], records=['10.1.0.2'])
+
+ LOG.info('Create a Recordset')
+ resp, zone_recordset = self.client.create_recordset(
+ self.zone['id'], recordset_data)
+
+ self.client.show_zones_recordset(zone_recordset['id'])
+
@decorators.idempotent_id('a8e41020-65be-453b-a8c1-2497d539c345')
def test_list_filter_zones_recordsets(self):
- recordset_data = {
- "name": self.zone['name'],
- "description": "This is an example record set.",
- "type": "A",
- "ttl": 3600,
- "records": [
- "10.1.0.2"
- ]
- }
+ recordset_data = data_utils.rand_recordset_data(
+ record_type='A', zone_name=self.zone['name'], records=['10.0.1.2'])
LOG.info('Create a Recordset')
resp, zone_recordset = self.client.create_recordset(
@@ -345,9 +350,109 @@
_, zone2 = self.zone_client.create_zone()
self.addCleanup(self.zone_client.delete_zone, zone2['id'])
+ LOG.info('Create another Recordset')
+ recordset_data = data_utils.rand_recordset_data(
+ record_type='A', zone_name=zone2['name'],
+ records=['10.0.1.3'])
+ resp, zone_recordset2 = self.client.create_recordset(
+ zone2['id'], recordset_data)
+
LOG.info('List recordsets')
- _, body = self.client.list_zones_recordsets(params={"data": "10.1.*"})
+ _, body = self.client.list_zones_recordsets(params={"data": "10.0.*"})
recordsets = body['recordsets']
- self.assertEqual(zone_recordset['id'], recordsets[0]['id'])
+ ids = [r['id'] for r in recordsets]
+ self.assertIn(zone_recordset['id'], ids)
+ self.assertIn(zone_recordset2['id'], ids)
+ # Ensure that every rrset has a record with the filtered data
+ for r in recordsets:
+ one_record_has_data = False
+ for record in r['records']:
+ if record.startswith('10.0.'):
+ one_record_has_data = True
+ self.assertTrue(one_record_has_data)
+
+ @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()
+ self.addCleanup(self.zone_client.delete_zone, zone2['id'])
+
+ LOG.info('List recordsets')
+ _, body = self.client.list_zones_recordsets()
+
+ recordsets = body['recordsets']
+ zone_names = set()
+ for r in recordsets:
+ zone_names.add(r['zone_name'])
+
+ self.assertGreaterEqual(len(zone_names), 2)
+
+
+class RecordsetOwnershipTest(BaseRecordsetsTest):
+
+ credentials = ['primary', 'alt']
+
+ @classmethod
+ def setup_clients(cls):
+ super(RecordsetOwnershipTest, cls).setup_clients()
+
+ cls.client = cls.os.recordset_client
+ cls.zone_client = cls.os.zones_client
+ cls.alt_zone_client = cls.os_alt.zones_client
+ cls.alt_client = cls.os_alt.recordset_client
+
+ @decorators.idempotent_id('9c0f58ad-1b31-4899-b184-5380720604e5')
+ def test_no_create_recordset_by_alt_tenant(self):
+ # try with name=A123456.zone.com.
+ recordset_data = data_utils.rand_recordset_data(
+ record_type='A', zone_name=self.zone['name'])
+ resp, rrset = self.client.create_recordset(
+ self.zone['id'], recordset_data)
+ self.assertRaises(
+ lib_exc.RestClientException,
+ lambda: self.alt_client.create_recordset(
+ self.zone['id'], recordset_data)
+ )
+
+ @decorators.idempotent_id('d4a9aad9-c778-429b-9a0c-4cd2b61a0a01')
+ def test_no_create_super_recordsets(self):
+ 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)
+ self.addCleanup(self.zone_client.delete_zone, zone['id'])
+
+ rrset_data = data_utils.rand_recordset_data(
+ record_type='A', zone_name=zone_name)
+
+ LOG.info('Create a zone as an alt user with existing superdomain')
+ self.assertRaises(
+ lib_exc.NotFound,
+ self.alt_client.create_recordset,
+ self.zone['id'], rrset_data)
+
+ @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()
+
+ # alt attempts to create record with name A12345.{zone}
+ recordset_data = data_utils.rand_recordset_data(
+ record_type='A', zone_name=zone['name'])
+
+ self.assertRaises(
+ lib_exc.RestClientException,
+ lambda: self.alt_client.create_recordset(
+ zone['id'],
+ recordset_data
+ )
+ )
+ self.assertRaises(
+ lib_exc.RestClientException,
+ lambda: self.alt_client.create_recordset(
+ alt_zone['id'],
+ recordset_data
+ )
+ )
diff --git a/designate_tempest_plugin/tests/api/v2/test_unauthed.py b/designate_tempest_plugin/tests/api/v2/test_unauthed.py
index e788a3b..b48cfd7 100644
--- a/designate_tempest_plugin/tests/api/v2/test_unauthed.py
+++ b/designate_tempest_plugin/tests/api/v2/test_unauthed.py
@@ -17,7 +17,7 @@
import ddt
from designate_tempest_plugin.tests import base
-from designate_tempest_plugin.clients import ManagerV2Unauthed
+from designate_tempest_plugin import clients
LOG = logging.getLogger(__name__)
@@ -25,7 +25,7 @@
@ddt.ddt
class TestDnsUnauthed(base.BaseDnsV2Test):
- client_manager = ManagerV2Unauthed
+ client_manager = clients.ManagerV2Unauthed
credentials = ["primary"]
@classmethod
diff --git a/designate_tempest_plugin/tests/scenario/v2/test_zones.py b/designate_tempest_plugin/tests/scenario/v2/test_zones.py
index c98a551..ccbfc6c 100644
--- a/designate_tempest_plugin/tests/scenario/v2/test_zones.py
+++ b/designate_tempest_plugin/tests/scenario/v2/test_zones.py
@@ -87,6 +87,7 @@
waiters.wait_for_zone_404(self.client, zone['id'])
@test.attr(type='slow')
+ @decorators.skip_because(bug='1623576')
@decorators.idempotent_id('ad8d1f5b-da66-46a0-bbee-14dc84a5d791')
@config.skip_unless_config('dns', 'nameservers')
def test_zone_create_propagates_to_nameservers(self):
@@ -98,6 +99,7 @@
waiters.wait_for_query(self.query_client, zone['name'], "SOA")
@test.attr(type='slow')
+ @decorators.skip_because(bug='1623576')
@decorators.idempotent_id('d13d3095-c78f-4aae-8fe3-a74ccc335c84')
@config.skip_unless_config('dns', 'nameservers')
def test_zone_delete_propagates_to_nameservers(self):