Add pool_client's methods and tests to Designate tempest plugin

Partially-Implements: blueprint designate-tempest-plugin

Change-Id: Id758b52d30018a7dea363979d167a879a57f09c7
diff --git a/designate_tempest_plugin/clients.py b/designate_tempest_plugin/clients.py
index db1c61f..5edc75a 100644
--- a/designate_tempest_plugin/clients.py
+++ b/designate_tempest_plugin/clients.py
@@ -26,6 +26,8 @@
     ZoneExportsClient
 from designate_tempest_plugin.services.dns.v2.json.recordset_client import \
     RecordsetClient
+from designate_tempest_plugin.services.dns.v2.json.pool_client import \
+    PoolClient
 
 CONF = config.CONF
 
@@ -52,3 +54,5 @@
                                                      **params)
         self.recordset_client = RecordsetClient(self.auth_provider,
                                                 **params)
+        self.pool_client = PoolClient(self.auth_provider,
+                                      **params)
diff --git a/designate_tempest_plugin/data_utils.py b/designate_tempest_plugin/data_utils.py
index 322e506..d3c72cc 100644
--- a/designate_tempest_plugin/data_utils.py
+++ b/designate_tempest_plugin/data_utils.py
@@ -196,3 +196,13 @@
     name = "*.{0}".format(zone_name)
     records = ["ns.example.com."]
     return rand_recordset_data('NS', zone_name, name, records)
+
+
+def rand_ns_records():
+    ns_zone = rand_zone_name()
+    records = []
+    for i in range(0, 2):
+        records.append("ns%s.%s" % (i, ns_zone))
+    ns_records = [{"hostname": x, "priority": random.randint(1, 999)}
+                  for x in records]
+    return ns_records
diff --git a/designate_tempest_plugin/services/dns/v2/json/pool_client.py b/designate_tempest_plugin/services/dns/v2/json/pool_client.py
new file mode 100644
index 0000000..cd7c540
--- /dev/null
+++ b/designate_tempest_plugin/services/dns/v2/json/pool_client.py
@@ -0,0 +1,108 @@
+# Copyright 2016 NEC Corporation.  All rights reserved.
+#
+#    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 tempest.lib.common.utils import data_utils
+
+from designate_tempest_plugin import data_utils as dns_data_utils
+from designate_tempest_plugin.services.dns.v2.json import base
+
+
+class PoolClient(base.DnsClientV2Base):
+    """API V2 Tempest REST client for Pool API"""
+
+    @base.handle_errors
+    def create_pool(self, pool_name=None, ns_records=None, params=None):
+        """Create a pool with the specified parameters.
+        :param pool_name: name of the pool.
+            Default: Random Value.
+        :param ns_records: A dictionary representing the nameservers detail
+                           with priority.
+        :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 pool.
+        """
+        pool = {
+                 "name": pool_name or data_utils.rand_name(name="Demo pool"),
+                 "ns_records": ns_records or dns_data_utils.rand_ns_records()
+        }
+
+        resp, body = self._create_request('pools', object_dict=pool,
+                                          params=params)
+
+        # Create Pool should Return a HTTP 201
+        self.expected_success(201, resp.status)
+
+        return resp, body
+
+    @base.handle_errors
+    def show_pool(self, uuid, params=None):
+        """Gets a specific pool.
+        :param uuid: Unique identifier of the pool in UUID format.
+        :param params: A Python dict that represents the query paramaters to
+                       include in the request URI.
+        :return: Serialized pool as a dictionary.
+        """
+        return self._show_request('pools', uuid, params=params)
+
+    @base.handle_errors
+    def list_pools(self, params=None):
+        """Gets a list of pools.
+        :param params: A Python dict that represents the query paramaters to
+                       include in the request URI.
+        :return: Serialized pools as a list.
+        """
+        return self._list_request('pools', params=params)
+
+    @base.handle_errors
+    def delete_pool(self, uuid, params=None):
+        """Deletes a pool having the specified UUID.
+        :param uuid: The unique identifier of the pool.
+        :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._delete_request('pools', uuid, params=params)
+
+        # Delete Pool should Return a HTTP 204
+        self.expected_success(204, resp.status)
+
+        return resp, body
+
+    @base.handle_errors
+    def update_pool(self, uuid, pool_name=None, ns_records=None,
+                    params=None):
+        """Update a pool with the specified parameters.
+        :param uuid: The unique identifier of the pool.
+        :param pool_name: name of the pool.
+            Default: Random Value.
+        :param pool: A dictionary represening the nameservers detail with
+                     priority.
+            Default: Random Value.
+        :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 updated pool.
+        """
+
+        pool = {
+                 "name": pool_name or data_utils.rand_name(name="Demo pool"),
+                 "ns_records": ns_records or dns_data_utils.rand_ns_records()
+        }
+
+        resp, body = self._update_request('pools', uuid, pool,
+                                          params=params)
+
+        # Update Pool should Return a HTTP 202
+        self.expected_success(202, resp.status)
+
+        return resp, body
diff --git a/designate_tempest_plugin/tests/api/v2/test_pool.py b/designate_tempest_plugin/tests/api/v2/test_pool.py
new file mode 100644
index 0000000..47e3324
--- /dev/null
+++ b/designate_tempest_plugin/tests/api/v2/test_pool.py
@@ -0,0 +1,122 @@
+# Copyright 2016 NEC Corporation.  All rights reserved.
+#
+#    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 operator import itemgetter
+
+from oslo_log import log as logging
+from tempest import test
+from tempest.lib import exceptions as lib_exc
+
+from designate_tempest_plugin.tests import base
+
+LOG = logging.getLogger(__name__)
+
+
+class BasePoolTest(base.BaseDnsTest):
+    excluded_keys = ['created_at', 'updated_at', 'links', 'ns_records']
+
+    def _assertExpectedNSRecords(self, expected, actual, expected_key):
+        sort_expected = sorted(expected, key=itemgetter(expected_key))
+        sort_actual = sorted(actual, key=itemgetter(expected_key))
+        self.assertEqual(sort_expected, sort_actual)
+
+
+class PoolAdminTest(BasePoolTest):
+    credentials = ['admin']
+
+    @classmethod
+    def setup_clients(cls):
+        super(PoolAdminTest, cls).setup_clients()
+
+        cls.admin_client = cls.os_adm.pool_client
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('69257f7c-b3d5-4e1b-998e-0677ad12f125')
+    def test_create_pool(self):
+        pool_data = {
+                      "name": "Example Pool",
+                      "ns_records": [{
+                          "hostname": "ns1.example.org.",
+                          "priority": 1}
+                      ]
+                    }
+        LOG.info('Create a pool')
+        _, pool = self.admin_client.create_pool(pool_name=pool_data["name"],
+                      ns_records=pool_data["ns_records"])
+        self.addCleanup(self.admin_client.delete_pool, pool['id'])
+
+        self.assertEqual(pool_data["name"], pool['name'])
+        self.assertExpected(pool_data, pool, self.excluded_keys)
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('e80eb70a-8ee5-40eb-b06e-599597a8ab7e')
+    def test_show_pool(self):
+        LOG.info('Create a pool')
+        _, pool = self.admin_client.create_pool()
+        self.addCleanup(self.admin_client.delete_pool, pool['id'])
+
+        LOG.info('Fetch the pool')
+        _, body = self.admin_client.show_pool(pool['id'])
+
+        LOG.info('Ensure the fetched response matches the created pool')
+        self.assertExpected(pool, body, self.excluded_keys)
+        self._assertExpectedNSRecords(pool["ns_records"], body["ns_records"],
+                                expected_key="priority")
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('d8c4c377-5d88-452d-a4d2-c004d72e1abe')
+    def test_delete_pool(self):
+        LOG.info('Create a pool')
+        _, pool = self.admin_client.create_pool()
+        self.addCleanup(self.admin_client.delete_pool, pool['id'],
+                        ignore_errors=lib_exc.NotFound)
+
+        LOG.info('Delete the pool')
+        _, body = self.admin_client.delete_pool(pool['id'])
+
+        self.assertRaises(lib_exc.NotFound,
+           lambda: self.admin_client.show_pool(pool['id']))
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('77c85b40-83b2-4c17-9fbf-e6d516cfce90')
+    def test_list_pools(self):
+        LOG.info('Create a pool')
+        _, pool = self.admin_client.create_pool()
+        self.addCleanup(self.admin_client.delete_pool, pool['id'])
+
+        LOG.info('List pools')
+        _, body = self.admin_client.list_pools()
+
+        self.assertGreater(len(body['pools']), 0)
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('fdcc84ce-af65-4af6-a5fc-6c50acbea0f0')
+    def test_update_pool(self):
+        LOG.info('Create a pool')
+        _, pool = self.admin_client.create_pool()
+        self.addCleanup(self.admin_client.delete_pool, pool['id'])
+
+        LOG.info('Update the pool')
+        _, patch_pool = self.admin_client.update_pool(
+            pool['id'], pool_name="foo")
+
+        self.assertEqual("foo", patch_pool["name"])
+
+    @test.attr(type='smoke')
+    @test.idempotent_id('41ad6a84-00ce-4a04-9fd5-b7c15c31e2db')
+    def test_list_pools_dot_json_fails(self):
+        uri = self.admin_client.get_uri('pools.json')
+
+        self.assertRaises(lib_exc.NotFound,
+            lambda: self.admin_client.get(uri))