Merge "Adds new scenario test to the Zones suite + minor refactoring"
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 2f12417..20b6fcf 100644
--- a/designate_tempest_plugin/services/dns/v2/json/recordset_client.py
+++ b/designate_tempest_plugin/services/dns/v2/json/recordset_client.py
@@ -53,7 +53,8 @@
         self.expected_success(202, resp.status)
 
         if wait_until:
-            waiters.wait_for_recordset_status(self, body['id'], wait_until)
+            waiters.wait_for_recordset_status(
+                self, zone_uuid, body['id'], wait_until)
 
         return resp, body
 
diff --git a/designate_tempest_plugin/services/dns/v2/json/tsigkey_client.py b/designate_tempest_plugin/services/dns/v2/json/tsigkey_client.py
index 683c1bb..61c632a 100644
--- a/designate_tempest_plugin/services/dns/v2/json/tsigkey_client.py
+++ b/designate_tempest_plugin/services/dns/v2/json/tsigkey_client.py
@@ -28,8 +28,9 @@
         :param resource_id: Pool id or Zone id.
         :param name: name of the tsigkey.
         :param algorithm: TSIG algorithm e.g hmac-md5, hmac-sha256 etc.
-        :param secret: represents TSIG secret.
-        :param scope: represents TSIG scope.
+        :param secret: represents TSIG secret. If provided value is empty
+                       it will use empty string (Needed for negative testing)
+        :param scope: represents TSIG scope. Default is ZONE
         :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 tsigkey.
@@ -38,9 +39,12 @@
                  "name": name or data_utils.rand_name('test-tsig'),
                  "algorithm": algorithm or utils.rand_tsig_algorithm(),
                  "secret": secret or data_utils.rand_name("secret"),
-                 "scope": scope or utils.rand_tsig_scope(),
+                 "scope": scope or 'ZONE',
                  "resource_id": resource_id}
 
+        if secret == '':
+            tsig['secret'] = ''
+
         resp, body = self._create_request('tsigkeys', data=tsig,
                                           params=params)
 
@@ -49,23 +53,28 @@
         return resp, body
 
     @base.handle_errors
-    def list_tsigkeys(self, params=None):
+    def list_tsigkeys(self, params=None, headers=None):
         """Gets a list of tsigkeys.
         :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 tsigkeys as a list.
         """
-        return self._list_request('tsigkeys', params=params)
+        return self._list_request('tsigkeys', params=params, headers=headers)
 
     @base.handle_errors
-    def show_tsigkey(self, uuid, params=None):
+    def show_tsigkey(self, uuid=None, params=None, headers=None):
         """Gets a specific tsigkey.
         :param uuid: Unique identifier of the tsigkey in UUID format.
+                     Default value is None (it's possible to use "marker" in
+                     URL query instead of UUID)
         :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 tsigkey as a dictionary.
         """
-        return self._show_request('tsigkeys', uuid, params=params)
+        return self._show_request(
+            'tsigkeys', uuid, params=params, headers=headers)
 
     @base.handle_errors
     def update_tsigkey(self, uuid, name=None, algorithm=None,
diff --git a/designate_tempest_plugin/tests/api/v2/test_recordset.py b/designate_tempest_plugin/tests/api/v2/test_recordset.py
index c9e17ed..f6e9a4a 100644
--- a/designate_tempest_plugin/tests/api/v2/test_recordset.py
+++ b/designate_tempest_plugin/tests/api/v2/test_recordset.py
@@ -402,6 +402,32 @@
             self.client, self.zone['id'],
             body['id'], const.ACTIVE)
 
+    @decorators.idempotent_id('f15e583e-e479-11eb-8e5a-74e5f9e2a801')
+    def test_delete_zone_with_existing_recordset(self):
+
+        LOG.info('Create a Zone')
+        zone = self.zone_client.create_zone(wait_until=const.ACTIVE)[1]
+        self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
+
+        LOG.info('Create a Recordset')
+        recordset_data = data_utils.rand_recordset_data(
+            record_type='A', zone_name=zone['name'])
+        record = self.client.create_recordset(
+            zone['id'], recordset_data, wait_until=const.ACTIVE)[1]
+
+        LOG.info("Delete a Zone and wait till it's done")
+        body = self.zone_client.delete_zone(zone['id'])[1]
+        LOG.info('Ensure we respond with DELETE+PENDING')
+        self.assertEqual(const.DELETE, body['action'])
+        self.assertEqual(const.PENDING, body['status'])
+
+        LOG.info('Ensure successful deletion of Zone')
+        waiters.wait_for_zone_404(self.zone_client, zone['id'])
+
+        LOG.info('Ensure successful deletion of Recordset')
+        self.assertRaises(lib_exc.NotFound,
+            lambda: self.client.show_recordset(zone['id'], record['id']))
+
 
 @ddt.ddt
 class RecordsetsNegativeTest(BaseRecordsetsTest):
@@ -700,11 +726,13 @@
                     record_type='A', zone_name=zone['name'])
                 resp, body = self.client.create_recordset(
                     zone['id'], recordset_data)
+
                 self.addCleanup(
                     self.wait_recordset_delete, self.client,
                     self.zone['id'], body['id'])
                 self.assertEqual(const.PENDING, body['status'],
                                  'Failed, expected status is PENDING')
+
                 LOG.info('Wait until the recordset is active')
                 waiters.wait_for_recordset_status(
                     self.client, zone['id'],
@@ -728,11 +756,13 @@
                     record_type='A', zone_name=alt_zone['name'])
                 resp, body = self.alt_client.create_recordset(
                     alt_zone['id'], recordset_data)
+
                 self.addCleanup(
                     self.wait_recordset_delete, self.client,
                     self.zone['id'], body['id'])
                 self.assertEqual(const.PENDING, body['status'],
                                  'Failed, expected status is PENDING')
+
                 LOG.info('Wait until the recordset is active')
                 waiters.wait_for_recordset_status(
                     self.alt_client, alt_zone['id'],
@@ -742,6 +772,7 @@
                 recordset_data['project_id'] = alt_zone['project_id']
                 recordsets_created['alt'] = recordset_data
 
+        LOG.info('Created resordsets are {}:'.format(recordsets_created))
         return recordsets_created
 
     @decorators.idempotent_id('9c0f58ad-1b31-4899-b184-5380720604e5')
diff --git a/designate_tempest_plugin/tests/api/v2/test_tsigkey.py b/designate_tempest_plugin/tests/api/v2/test_tsigkey.py
index 292b821..69e537f 100644
--- a/designate_tempest_plugin/tests/api/v2/test_tsigkey.py
+++ b/designate_tempest_plugin/tests/api/v2/test_tsigkey.py
@@ -19,6 +19,7 @@
 from tempest.lib import exceptions as lib_exc
 
 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__)
@@ -42,55 +43,309 @@
         super(TsigkeyAdminTest, cls).setup_clients()
         if CONF.enforce_scope.designate:
             cls.admin_client = cls.os_system_admin.dns_v2.TsigkeyClient()
+            cls.pool_admin_client = cls.os_system_admin.dns_v2.PoolClient()
         else:
             cls.admin_client = cls.os_admin.dns_v2.TsigkeyClient()
+            cls.pool_admin_client = cls.os_admin.dns_v2.PoolClient()
+
         cls.zone_client = cls.os_primary.dns_v2.ZonesClient()
+        cls.primary_client = cls.os_primary.dns_v2.TsigkeyClient()
 
     @decorators.idempotent_id('e7b484e3-7ed5-4840-89d7-1e696986f8e4')
-    def test_create_tsigkey(self):
+    def test_create_tsigkey_for_zone(self):
         LOG.info('Create a resource')
-        _, zone = self.zone_client.create_zone()
+        zone = self.zone_client.create_zone()[1]
         self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
 
         tsigkey_data = {
-                        "name": "Example tsigkey",
+                        "name": dns_data_utils.rand_zone_name(
+                            'test_create_tsigkey_for_zone'),
                         "algorithm": "hmac-sha256",
                         "secret": "SomeSecretKey",
-                        "scope": "POOL",
+                        "scope": "ZONE",
                         "resource_id": zone['id']}
 
         LOG.info('Create a tsigkey')
-        _, tsigkey = self.admin_client.create_tsigkey(
+        tsigkey = self.admin_client.create_tsigkey(
                          tsigkey_data['resource_id'],
                          tsigkey_data['name'], tsigkey_data['algorithm'],
-                         tsigkey_data['secret'], tsigkey_data['scope'])
+                         tsigkey_data['secret'], tsigkey_data['scope'])[1]
         self.addCleanup(self.admin_client.delete_tsigkey, tsigkey['id'])
 
         self.assertEqual(tsigkey_data["name"], tsigkey['name'])
+        self.assertEqual(tsigkey_data["scope"], 'ZONE')
+
+    @decorators.idempotent_id('45975fa6-d726-11eb-beba-74e5f9e2a801')
+    def test_create_tsigkey_for_pool(self):
+        LOG.info('Get the valid pool ID from list of pools')
+        pool = self.pool_admin_client.list_pools()[1]['pools'][0]
+
+        LOG.info('Create a tsigkey')
+        tsigkey_data = {
+                        "name": dns_data_utils.rand_zone_name('Example_Key'),
+                        "algorithm": "hmac-sha256",
+                        "secret": "SomeSecretKey",
+                        "scope": "POOL",
+                        "resource_id": pool['id']}
+        tsigkey = self.admin_client.create_tsigkey(
+                         tsigkey_data['resource_id'],
+                         tsigkey_data['name'], tsigkey_data['algorithm'],
+                         tsigkey_data['secret'], tsigkey_data['scope'])[1]
+        self.addCleanup(self.admin_client.delete_tsigkey, tsigkey['id'])
+        self.assertEqual(tsigkey_data["name"], tsigkey['name'])
+        self.assertEqual(tsigkey_data["scope"], 'POOL')
 
     @decorators.idempotent_id('d46e5e86-a18c-4315-aa0c-95a00e816fbf')
     def test_list_tsigkey(self):
         LOG.info('Create a resource')
-        _, 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 tsigkey')
-        _, tsigkey = self.admin_client.create_tsigkey(resource_id=zone['id'])
+        tsigkey = self.admin_client.create_tsigkey(resource_id=zone['id'])[1]
         self.addCleanup(self.admin_client.delete_tsigkey, tsigkey['id'])
-        _, body = self.admin_client.list_tsigkeys()
+        body = self.admin_client.list_tsigkeys()[1]
         self.assertGreater(len(body['tsigkeys']), 0)
 
+    @decorators.idempotent_id('d46e5e86-a18c-4315-aa0c-95a00e816fbf')
+    def test_list_tsigkeys_limit_results(self):
+        for i in range(3):
+            LOG.info('As Primary user create a zone: {} '.format(i))
+            zone = self.zone_client.create_zone()[1]
+            self.addCleanup(
+                self.wait_zone_delete, self.zone_client, zone['id'])
+            LOG.info('As Admin user create a tsigkey: {} '.format(i))
+            tsigkey = self.admin_client.create_tsigkey(
+                resource_id=zone['id'])[1]
+            self.addCleanup(self.admin_client.delete_tsigkey, tsigkey['id'])
+        LOG.info('As Admin client, list all tsigkey using '
+                 'URL query: "limit=2"')
+        body = self.admin_client.list_tsigkeys(params={'limit': 2})[1]
+        self.assertEqual(len(body['tsigkeys']), 2)
+
+    @decorators.idempotent_id('f31447b0-d817-11eb-b95a-74e5f9e2a801')
+    def test_list_tsigkeys_using_marker(self):
+        test_tsigkeys_name = 'marker_tsigkey_'
+        test_tsigkeys_names = [test_tsigkeys_name + str(i) for i in range(4)]
+
+        LOG.info('Create tsigkeys named: {}'.format(test_tsigkeys_names))
+        created_tsigkeys = []
+        for name in test_tsigkeys_names:
+            LOG.info('As Primary user create a zone to be used '
+                     'for {}'.format(name))
+            zone = self.zone_client.create_zone()[1]
+            self.addCleanup(
+                self.wait_zone_delete, self.zone_client, zone['id'])
+            LOG.info('As Admin user create "{}" tsigkey'.format(name))
+            tsigkey = self.admin_client.create_tsigkey(
+                resource_id=zone['id'], name=name)[1]
+            self.addCleanup(self.admin_client.delete_tsigkey, tsigkey['id'])
+            created_tsigkeys.append(tsigkey['id'])
+
+        LOG.info('As Admin, list all tsigkeys using url queries:"limit=2" '
+                 'and "name={}*"'.format(test_tsigkeys_name))
+        body = self.admin_client.list_tsigkeys(
+            params={
+                'limit': 2, 'name': test_tsigkeys_name + '*'})[1]
+        tsigkeys = body['tsigkeys']
+        self.assertEqual(2, len(tsigkeys),
+                         'Failed, response is not limited as expected')
+
+        LOG.info('Get the marker to be used for subsequent request')
+        first_set_of_ids = [item['id'] for item in tsigkeys]
+        links = body['links']
+        marker = links['next'].split('marker=')[-1]
+
+        LOG.info('Use marker for subsequent request to get the rest of '
+                 'tsigkeys that contains "{}*" in their '
+                 'names'.format(test_tsigkeys_name))
+        tsigkeys = self.admin_client.list_tsigkeys(
+            params={'marker': marker, 'limit': 2,
+                    'name': test_tsigkeys_name + '*'})[1]['tsigkeys']
+        self.assertEqual(2, len(tsigkeys),
+                         'Failed, response is not limited as expected')
+        second_set_of_ids = [item['id'] for item in tsigkeys]
+
+        LOG.info('Make sure that the merge of tsigkeys IDs received in two '
+                 'phases using "marker" url query, contains all the IDs '
+                 'created within the test')
+        self.assertEqual(
+            sorted(first_set_of_ids + second_set_of_ids),
+            sorted(created_tsigkeys),
+            'Failed, tsigkeys IDs received in two phases are not as expected')
+
+    @decorators.idempotent_id('d5c6dfcc-d8af-11eb-b95a-74e5f9e2a801')
+    def test_list_tsigkey_sort_key_with_sort_direction(self):
+        names_to_create = [data_utils.rand_name(name) for name in
+                           ['bbb_tsgikey', 'aaa_tsgikey', 'ccc_tsgikey']]
+        created_tsigkey_ids = []
+        for name in names_to_create:
+            LOG.info('As Primary user create a zone for: {} '.format(name))
+            zone = self.zone_client.create_zone()[1]
+            self.addCleanup(
+                self.wait_zone_delete, self.zone_client, zone['id'])
+            LOG.info('As Admin user create a tsigkey: {} '.format(name))
+            tsigkey = self.admin_client.create_tsigkey(
+                resource_id=zone['id'], name=name)[1]
+            self.addCleanup(self.admin_client.delete_tsigkey, tsigkey['id'])
+            created_tsigkey_ids.append(tsigkey['id'])
+
+        LOG.info('As Admin, list all tsigkeys using "asc" to sort by names')
+        sorted_tsigkeys = self.admin_client.list_tsigkeys(
+            params={'sort_dir': 'asc', 'sort_key': 'name'})[1]['tsigkeys']
+        sorted_by_names = [item['name'] for item in sorted_tsigkeys]
+        self.assertEqual(
+            sorted(sorted_by_names),
+            sorted_by_names,
+            'Failed, tsgikeys names are not sorted in "asc" as expected')
+
+        LOG.info('As Admin, list all tsigkey using "desc" to sort by names')
+        sorted_tsigkeys = self.admin_client.list_tsigkeys(
+            params={'sort_dir': 'desc', 'sort_key': 'name'})[1]['tsigkeys']
+        sorted_by_names = [item['name'] for item in sorted_tsigkeys]
+        self.assertEqual(
+            sorted(sorted_by_names, reverse=True),
+            sorted_by_names,
+            'Failed, tsgikeys names are not sorted in "desc" as expected')
+
+        LOG.info('As Admin, list all tsigkeys using "asc" to sort by ID')
+        sorted_tsigkeys = self.admin_client.list_tsigkeys(
+            params={'sort_dir': 'asc', 'sort_key': 'id'})[1]['tsigkeys']
+        sorted_by_ids = [item['id'] for item in sorted_tsigkeys]
+        self.assertEqual(
+            sorted(sorted_by_ids),
+            sorted_by_ids,
+            'Failed, tsgikeys IDs are not sorted in "asc" as expected')
+
+        LOG.info('As Admin, list all tsigkeys using "zababun" direction '
+                 'to sort by names, expected: "invalid_sort_dir"')
+        self.assertRaisesDns(
+            lib_exc.BadRequest, 'invalid_sort_dir', 400,
+            self.admin_client.list_tsigkeys,
+            params={'sort_dir': 'zababun', 'sort_key': 'name'})
+
+        LOG.info('As Admin, list all tsigkeys using "zababun" as a key value,'
+                 'expected: "invalid_sort_key"')
+        self.assertRaisesDns(
+            lib_exc.BadRequest, 'invalid_sort_key', 400,
+            self.admin_client.list_tsigkeys,
+            params={'sort_dir': 'asc', 'sort_key': 'zababun'})
+
+    @decorators.idempotent_id('4162a840-d8b2-11eb-b95a-74e5f9e2a801')
+    def test_list_tsigkey_filter_by_name(self):
+        tsigkey_name = data_utils.rand_name('ddd_tsgikey')
+        LOG.info('As Primary user create a zone for: {} '.format(tsigkey_name))
+        zone = self.zone_client.create_zone()[1]
+        self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
+        LOG.info('As Admin user create a tsigkey: {} '.format(tsigkey_name))
+        tsigkey = self.admin_client.create_tsigkey(
+            resource_id=zone['id'], name=tsigkey_name)[1]
+        self.addCleanup(self.admin_client.delete_tsigkey, tsigkey['id'])
+
+        LOG.info('As Admin, list all tsigkeys named:{}'.format(tsigkey_name))
+        listed_tsigkeys = self.admin_client.list_tsigkeys(
+            params={'name': tsigkey_name})[1]['tsigkeys']
+        self.assertEqual(
+            1, len(listed_tsigkeys),
+            'Failed, only a single tsigkey, named: {} should be '
+            'listed.'.format(tsigkey_name))
+
+        LOG.info('As Admin, list all tsigkeys named:"zababun"')
+        listed_tsigkeys = self.admin_client.list_tsigkeys(
+            params={'name': 'zababun'})[1]['tsigkeys']
+        self.assertEqual(
+            0, len(listed_tsigkeys), 'Failed, no tsigkey should be listed')
+
+    @decorators.idempotent_id('e8bcf80a-d8b4-11eb-b95a-74e5f9e2a801')
+    def test_list_tsigkey_filter_by_scope(self):
+
+        LOG.info('Create tsigkey for a pool')
+        pool = self.pool_admin_client.create_pool(
+            project_id=self.os_admin.credentials.project_id)[1]
+        self.addCleanup(
+            self.pool_admin_client.delete_pool, pool['id'],
+            headers={
+                'x-auth-sudo-project-id':
+                    self.os_admin.credentials.project_id})
+        pool_tsigkey = self.admin_client.create_tsigkey(
+            resource_id=pool['id'], scope='POOL')[1]
+        self.addCleanup(self.admin_client.delete_tsigkey, pool_tsigkey['id'])
+
+        LOG.info('Create tsigkey for a zone')
+        zone = self.zone_client.create_zone()[1]
+        self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
+        zone_tsigkey = self.admin_client.create_tsigkey(
+            resource_id=zone['id'], scope='ZONE')[1]
+        self.addCleanup(self.admin_client.delete_tsigkey, zone_tsigkey['id'])
+
+        LOG.info('List all "scope=POOL" tsigkeys')
+        listed_pool_scopes = [
+            item['scope'] for item in self.admin_client.list_tsigkeys(
+                params={'scope': 'POOL'})[1]['tsigkeys']]
+        self.assertEqual(
+            {'POOL'}, set(listed_pool_scopes),
+            'Failed, the only scopes expected to be listed are: "POOL"')
+
+        LOG.info('List all "scope=ZONE" tsigkeys')
+        listed_zone_scopes = [
+            item['scope'] for item in self.admin_client.list_tsigkeys(
+                params={'scope': 'ZONE'})[1]['tsigkeys']]
+        self.assertEqual(
+            {'ZONE'}, set(listed_zone_scopes),
+            'Failed, the only scopes expected to be listed are: "ZONE"')
+
+        LOG.info('List all "scope=zababun" tsigkeys')
+        listed_zone_scopes = [
+            item['scope'] for item in self.admin_client.list_tsigkeys(
+                params={'scope': 'zababun'})[1]['tsigkeys']]
+        self.assertEqual(
+            0, len(listed_zone_scopes),
+            'Failed, no tsigkey is expected to be listed')
+
+    @decorators.idempotent_id('794554f0-d8b8-11eb-b95a-74e5f9e2a801')
+    def test_list_tsigkey_filter_by_algorithm(self):
+
+        LOG.info('Create tsigkey for a pool')
+        algorithm = 'hmac-sha256'
+        pool = self.pool_admin_client.create_pool(
+            project_id=self.os_admin.credentials.project_id)[1]
+        self.addCleanup(
+            self.pool_admin_client.delete_pool, pool['id'],
+            headers={
+                'x-auth-sudo-project-id':
+                    self.os_admin.credentials.project_id})
+        pool_tsigkey = self.admin_client.create_tsigkey(
+            resource_id=pool['id'], algorithm=algorithm)[1]
+        self.addCleanup(self.admin_client.delete_tsigkey, pool_tsigkey['id'])
+
+        LOG.info('List all "algorithm={}" tsigkeys '.format(algorithm))
+        listed_tsigkeys = [
+            item['algorithm'] for item in self.admin_client.list_tsigkeys(
+                params={'algorithm': algorithm})[1]['tsigkeys']]
+        self.assertEqual(
+            {algorithm}, set(listed_tsigkeys),
+            'Failed, the only tsigkeys expected to be listed must '
+            'have algorithm:{} '.format(algorithm))
+
+        LOG.info('List all "algorithm=zababun" tsigkeys')
+        listed_tsigkeys = [
+            item['algorithm'] for item in self.admin_client.list_tsigkeys(
+                params={'algorithm': 'zababun'})[1]['tsigkeys']]
+        self.assertEqual(
+            0, len(listed_tsigkeys),
+            "Failed, no tsigkey is expectedto be listed")
+
     @decorators.idempotent_id('c5d7facf-0f05-47a2-a4fb-87f203860880')
     def test_show_tsigkey(self):
         LOG.info('Create a resource')
-        _, 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 tsigkey')
-        _, tsigkey = self.admin_client.create_tsigkey(resource_id=zone['id'])
+        tsigkey = self.admin_client.create_tsigkey(resource_id=zone['id'])[1]
         self.addCleanup(self.admin_client.delete_tsigkey, tsigkey['id'])
 
         LOG.info('Fetch the tsigkey')
-        _, body = self.admin_client.show_tsigkey(tsigkey['id'])
+        body = self.admin_client.show_tsigkey(tsigkey['id'])[1]
 
         LOG.info('Ensure the fetched response matches the created tsigkey')
         self.assertExpected(tsigkey, body, self.excluded_keys)
@@ -98,39 +353,36 @@
     @decorators.idempotent_id('d09dc0dd-dd72-41ee-9085-2afb2bf35459')
     def test_update_tsigkey(self):
         LOG.info('Create a resource')
-        _, 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 tsigkey')
-        _, tsigkey = self.admin_client.create_tsigkey(resource_id=zone['id'])
+        tsigkey = self.admin_client.create_tsigkey(resource_id=zone['id'])[1]
         self.addCleanup(self.admin_client.delete_tsigkey, tsigkey['id'])
 
         tsigkey_data = {
                         "name": "Patch tsigkey",
-                        "secret": "NewSecretKey",
-                        "scope": "POOL"}
+                        "secret": "NewSecretKey"}
 
         LOG.info('Update the tsigkey')
-        _, patch_tsigkey = self.admin_client.update_tsigkey(tsigkey['id'],
+        patch_tsigkey = self.admin_client.update_tsigkey(tsigkey['id'],
                                name=tsigkey_data['name'],
-                               secret=tsigkey_data['secret'],
-                               scope=tsigkey_data['scope'])
+                               secret=tsigkey_data['secret'])[1]
 
         self.assertEqual(tsigkey_data['name'], patch_tsigkey['name'])
         self.assertEqual(tsigkey_data['secret'], patch_tsigkey['secret'])
-        self.assertEqual(tsigkey_data['scope'], patch_tsigkey['scope'])
 
     @decorators.idempotent_id('9cdffbd2-bc67-4a25-8eb7-4be8635c88a3')
     def test_delete_tsigkey(self):
         LOG.info('Create a resource')
-        _, 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 tsigkey')
-        _, tsigkey = self.admin_client.create_tsigkey(resource_id=zone['id'])
+        tsigkey = self.admin_client.create_tsigkey(resource_id=zone['id'])[1]
 
         LOG.info('Delete the tsigkey')
-        _, body = self.admin_client.delete_tsigkey(tsigkey['id'])
+        self.admin_client.delete_tsigkey(tsigkey['id'])
 
         self.assertRaises(lib_exc.NotFound,
            lambda: self.admin_client.show_tsigkey(tsigkey['id']))
@@ -191,7 +443,7 @@
 
 class TestTsigkeyInvalidIdAdmin(BaseTsigkeyTest):
 
-    credentials = ["admin", "system_admin"]
+    credentials = ["admin", "primary", "system_admin"]
 
     @classmethod
     def setup_credentials(cls):
@@ -204,8 +456,11 @@
         super(TestTsigkeyInvalidIdAdmin, cls).setup_clients()
         if CONF.enforce_scope.designate:
             cls.admin_client = cls.os_system_admin.dns_v2.TsigkeyClient()
+            cls.pool_admin_client = cls.os_system_admin.dns_v2.PoolClient()
         else:
             cls.admin_client = cls.os_admin.dns_v2.TsigkeyClient()
+            cls.pool_admin_client = cls.os_admin.dns_v2.PoolClient()
+        cls.zone_client = cls.os_primary.dns_v2.ZonesClient()
 
     @decorators.idempotent_id('2a8dfc75-9884-4b1c-8f1f-ed835d96f2fe')
     def test_show_tsigkey_invalid_uuid(self):
@@ -234,3 +489,107 @@
         self.assertEqual("invalid_uuid", resp_body['type'])
         self.assertEqual("Invalid UUID tsigkey_id: foo",
                          resp_body['message'])
+
+    @decorators.idempotent_id('f94af13a-d743-11eb-beba-74e5f9e2a801')
+    def test_create_tsigkey_for_zone_invalid_algorithm(self):
+        zone = self.zone_client.create_zone()[1]
+        self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
+        tsigkey_data = {
+                        "name": dns_data_utils.rand_zone_name('Example_Key'),
+                        "algorithm": "zababun",
+                        "secret": "SomeSecretKey",
+                        "scope": "ZONE",
+                        "resource_id": zone['id']}
+        self.assertRaisesDns(
+            lib_exc.BadRequest, 'invalid_object', 400,
+            self.admin_client.create_tsigkey,
+            tsigkey_data['resource_id'],
+            tsigkey_data['name'], tsigkey_data['algorithm'],
+            tsigkey_data['secret'], tsigkey_data['scope'])
+
+    @decorators.idempotent_id('4df903d8-d745-11eb-beba-74e5f9e2a801')
+    def test_create_tsigkey_for_zone_invalid_name(self):
+        LOG.info('Create a zone resource')
+        zone = self.zone_client.create_zone()[1]
+        self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
+        tsigkey_data = {
+                        "name": dns_data_utils.rand_zone_name(
+                            'Example_Key') * 1000,
+                        "algorithm": "hmac-sha256",
+                        "secret": "SomeSecretKey",
+                        "scope": "ZONE",
+                        "resource_id": zone['id']}
+        self.assertRaisesDns(
+            lib_exc.BadRequest, 'invalid_object', 400,
+            self.admin_client.create_tsigkey,
+            tsigkey_data['resource_id'],
+            tsigkey_data['name'], tsigkey_data['algorithm'],
+            tsigkey_data['secret'], tsigkey_data['scope'])
+
+    @decorators.idempotent_id('5d6b8a84-d745-11eb-beba-74e5f9e2a801')
+    @decorators.skip_because(bug="1933760")
+    def test_create_tsigkey_for_zone_empty_secret(self):
+        LOG.info('Create a zone resource')
+        zone = self.zone_client.create_zone()[1]
+        self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
+        tsigkey_data = {
+                        "name": dns_data_utils.rand_zone_name('Example_Key'),
+                        "algorithm": "hmac-sha256",
+                        "secret": '',
+                        "scope": "ZONE",
+                        "resource_id": zone['id']}
+        self.assertRaisesDns(
+            lib_exc.BadRequest, 'invalid_object', 400,
+            self.admin_client.create_tsigkey,
+            tsigkey_data['resource_id'],
+            tsigkey_data['name'], tsigkey_data['algorithm'],
+            tsigkey_data['secret'], tsigkey_data['scope'])
+
+    @decorators.idempotent_id('dfca9268-d745-11eb-beba-74e5f9e2a801')
+    def test_create_tsigkey_for_zone_invalid_scope(self):
+        LOG.info('Create a zone resource')
+        zone = self.zone_client.create_zone()[1]
+        self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
+        tsigkey_data = {
+                        "name": dns_data_utils.rand_zone_name('Example_Key'),
+                        "algorithm": "hmac-sha256",
+                        "secret": "SomeSecretKey",
+                        "scope": "zababun",
+                        "resource_id": zone['id']}
+        self.assertRaisesDns(
+            lib_exc.BadRequest, 'invalid_object', 400,
+            self.admin_client.create_tsigkey,
+            tsigkey_data['resource_id'],
+            tsigkey_data['name'], tsigkey_data['algorithm'],
+            tsigkey_data['secret'], tsigkey_data['scope'])
+
+    @decorators.idempotent_id('57255858-d74a-11eb-beba-74e5f9e2a801')
+    def test_create_tsigkey_for_zone_invalid_zone_id(self):
+        LOG.info('Create a resource')
+        zone = self.zone_client.create_zone()[1]
+        self.addCleanup(self.wait_zone_delete, self.zone_client, zone['id'])
+        tsigkey_data = {
+                        "name": dns_data_utils.rand_zone_name('Example_Key'),
+                        "algorithm": "hmac-sha256",
+                        "secret": "SomeSecretKey",
+                        "scope": "ZONE",
+                        "resource_id": data_utils.rand_uuid}
+        self.assertRaisesDns(
+            lib_exc.BadRequest, 'invalid_object', 400,
+            self.admin_client.create_tsigkey,
+            tsigkey_data['resource_id'],
+            tsigkey_data['name'], tsigkey_data['algorithm'],
+            tsigkey_data['secret'], tsigkey_data['scope'])
+
+    @decorators.idempotent_id('0dfbc2f8-d8bb-11eb-b95a-74e5f9e2a801')
+    @decorators.skip_because(bug="1934120")
+    def test_create_tsigkey_for_pool_with_scope_zone(self):
+        pool = self.pool_admin_client.create_pool()[1]
+        self.addCleanup(self.pool_admin_client.delete_pool, pool['id'])
+
+        LOG.info('Try to create a tsigkey using pool ID and "scope:ZONE", '
+                 'should fail because ID is for pool, but scope is ZONE')
+        self.assertRaisesDns(
+            lib_exc.BadRequest, 'invalid_object', 400,
+            self.admin_client.create_tsigkey,
+            resource_id=pool['id'], scope='ZONE')