Merge "Add missing keystone clients"
diff --git a/releasenotes/notes/add-keystone-ep-clients-eeefd0904fbbe151.yaml b/releasenotes/notes/add-keystone-ep-clients-eeefd0904fbbe151.yaml
new file mode 100644
index 0000000..2b407ae
--- /dev/null
+++ b/releasenotes/notes/add-keystone-ep-clients-eeefd0904fbbe151.yaml
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    Added missing client methods for keystone's OS-ENDPOINT-POLICY and
+    OS-EP-FILTER APIs.
diff --git a/tempest/lib/services/identity/v3/endpoint_filter_client.py b/tempest/lib/services/identity/v3/endpoint_filter_client.py
index ce84869..2d5c8c9 100644
--- a/tempest/lib/services/identity/v3/endpoint_filter_client.py
+++ b/tempest/lib/services/identity/v3/endpoint_filter_client.py
@@ -66,3 +66,57 @@
             % (project_id, endpoint_id))
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
+
+    def list_endpoint_groups_for_project(self, project_id):
+        """List Endpoint Groups Associated with Project."""
+        resp, body = self.get(
+            self.ep_filter + '/projects/%s/endpoint_groups'
+            % project_id)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def list_projects_for_endpoint_group(self, endpoint_group_id):
+        """List Projects Associated with Endpoint Group."""
+        resp, body = self.get(
+            self.ep_filter + '/endpoint_groups/%s/projects'
+            % endpoint_group_id)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def list_endpoints_for_endpoint_group(self, endpoint_group_id):
+        """List Endpoints Associated with Endpoint Group."""
+        resp, body = self.get(
+            self.ep_filter + '/endpoint_groups/%s/endpoints'
+            % endpoint_group_id)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def add_endpoint_group_to_project(self, endpoint_group_id, project_id):
+        """Create Endpoint Group to Project Association."""
+        body = None
+        resp, body = self.put(
+            self.ep_filter + '/endpoint_groups/%s/projects/%s'
+            % (endpoint_group_id, project_id), body)
+        self.expected_success(204, resp.status)
+        return rest_client.ResponseBody(resp, body)
+
+    def show_endpoint_group_for_project(self, endpoint_group_id, project_id):
+        """Get Endpoint Group to Project Association."""
+        resp, body = self.get(
+            self.ep_filter + '/endpoint_groups/%s/projects/%s'
+            % (endpoint_group_id, project_id))
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def delete_endpoint_group_from_project(
+        self, endpoint_group_id, project_id):
+        """Delete Endpoint Group to Project Association."""
+        resp, body = self.delete(
+            self.ep_filter + '/endpoint_groups/%s/projects/%s'
+            % (endpoint_group_id, project_id))
+        self.expected_success(204, resp.status)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/identity/v3/policies_client.py b/tempest/lib/services/identity/v3/policies_client.py
index 31c0d18..41def38 100644
--- a/tempest/lib/services/identity/v3/policies_client.py
+++ b/tempest/lib/services/identity/v3/policies_client.py
@@ -185,3 +185,27 @@
         resp, body = self.delete(url)
         self.expected_success(204, resp.status)
         return rest_client.ResponseBody(resp, body)
+
+    def list_endpoints_for_policy(self, policy_id):
+        """List policy and service endpoint associations.
+
+        API reference:
+        https://docs.openstack.org/api-ref/identity/v3-ext/#list-policy-and-service-endpoint-associations
+        """
+        url = "policies/{0}/OS-ENDPOINT-POLICY/endpoints".format(policy_id)
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
+
+    def show_policy_for_endpoint(self, endpoint_id):
+        """Show the effective policy associated with an endpoint
+
+        API reference:
+        https://docs.openstack.org/api-ref/identity/v3-ext/#show-the-effective-policy-associated-with-an-endpoint
+        """
+        url = "endpoints/{0}/OS-ENDPOINT-POLICY/policy".format(endpoint_id)
+        resp, body = self.get(url)
+        self.expected_success(200, resp.status)
+        body = json.loads(body)
+        return rest_client.ResponseBody(resp, body)
diff --git a/tempest/tests/lib/services/identity/v3/test_endpoint_filter_client.py b/tempest/tests/lib/services/identity/v3/test_endpoint_filter_client.py
index 7faf6a0..e5f7a66 100644
--- a/tempest/tests/lib/services/identity/v3/test_endpoint_filter_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_endpoint_filter_client.py
@@ -83,6 +83,36 @@
         }
     }
 
+    FAKE_LIST_ENDPOINT_GROUPS_FOR_PROJECT = {
+        "endpoint_groups": [
+            {
+                "endpoint_group": {
+                    "description": "endpoint group description #2",
+                    "filters": {
+                        "interface": "admin"
+                    },
+                    "id": "3de68c",
+                    "name": "endpoint group name #2"
+                }
+            }
+            ],
+        "links": {
+            "self": "https://url/identity/v3/OS-EP-FILTER/endpoint_groups",
+        }
+    }
+
+    FAKE_PROJECT_INFO = {
+        "project": {
+            "domain_id": "1789d1",
+            "id": "263fd9",
+            "links": {
+                "self": "http://example.com/identity/v3/projects/263fd9"
+            },
+            "name": "project name #1",
+            "description": "project description #1"
+        }
+    }
+
     def setUp(self):
         super(TestEndPointsFilterClient, self).setUp()
         fake_auth = fake_auth_provider.FakeAuthProvider()
@@ -137,6 +167,52 @@
             project_id=3,
             endpoint_id=4)
 
+    def _test_list_endpoint_groups_for_project(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_endpoint_groups_for_project,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_ENDPOINT_GROUPS_FOR_PROJECT,
+            bytes_body,
+            status=200,
+            project_id=3)
+
+    def _test_list_projects_for_endpoint_group(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_projects_for_endpoint_group,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_PROJECTS_FOR_ENDPOINTS,
+            bytes_body,
+            status=200,
+            endpoint_group_id=5)
+
+    def _test_list_endpoints_for_endpoint_group(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_endpoints_for_endpoint_group,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_LIST_ENDPOINTS_FOR_PROJECTS,
+            bytes_body,
+            status=200,
+            endpoint_group_id=5)
+
+    def _test_add_endpoint_group_to_project(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.add_endpoint_group_to_project,
+            'tempest.lib.common.rest_client.RestClient.put',
+            {},
+            bytes_body,
+            status=204,
+            endpoint_group_id=5,
+            project_id=6)
+
+    def _test_show_endpoint_group_for_project(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_endpoint_group_for_project,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_PROJECT_INFO,
+            bytes_body,
+            endpoint_group_id=5,
+            project_id=6)
+
     def test_add_endpoint_to_project_with_str_body(self):
         self._test_add_endpoint_to_project()
 
@@ -163,3 +239,43 @@
 
     def test_delete_endpoint_from_project(self):
         self._test_delete_endpoint_from_project()
+
+    def test_list_endpoint_groups_for_project_with_str_body(self):
+        self._test_list_endpoint_groups_for_project()
+
+    def test_list_endpoint_groups_for_project_with_bytes_body(self):
+        self._test_list_endpoint_groups_for_project(bytes_body=True)
+
+    def test_list_projects_for_endpoint_group_with_str_body(self):
+        self._test_list_projects_for_endpoint_group()
+
+    def test_list_projects_for_endpoint_group_with_bytes_body(self):
+        self._test_list_projects_for_endpoint_group(bytes_body=True)
+
+    def test_list_endpoints_for_endpoint_group_with_str_body(self):
+        self._test_list_endpoints_for_endpoint_group()
+
+    def test_list_endpoints_for_endpoint_group_with_bytes_body(self):
+        self._test_list_endpoints_for_endpoint_group(bytes_body=True)
+
+    def test_add_endpoint_group_to_project_with_str_body(self):
+        self._test_add_endpoint_group_to_project()
+
+    def test_add_endpoint_group_to_project_with_bytes_body(self):
+        self._test_add_endpoint_group_to_project(bytes_body=True)
+
+    def test_show_endpoint_group_for_project_with_str_body(self):
+        self._test_show_endpoint_group_for_project()
+
+    def test_show_endpoint_group_for_project_with_bytes_body(self):
+        self._test_show_endpoint_group_for_project(bytes_body=True)
+
+    def test_delete_endpoint_group_from_project(self):
+        self.check_service_client_function(
+            self.client.delete_endpoint_group_from_project,
+            'tempest.lib.common.rest_client.RestClient.delete',
+            {},
+            False,
+            status=204,
+            endpoint_group_id=5,
+            project_id=5)
diff --git a/tempest/tests/lib/services/identity/v3/test_policies_client.py b/tempest/tests/lib/services/identity/v3/test_policies_client.py
index 0237475..4fc800a 100644
--- a/tempest/tests/lib/services/identity/v3/test_policies_client.py
+++ b/tempest/tests/lib/services/identity/v3/test_policies_client.py
@@ -44,6 +44,34 @@
             }
         }
 
+    FAKE_ENDPOINT_INFO = {
+        "endpoints": [
+            {
+                "id": "1",
+                "interface": "public",
+                "links": {
+                    "self": "http://example.com/identity/v3/endpoints/1"
+                },
+                "region": "north",
+                "service_id": "9242e05f0c23467bbd1cf1f7a6e5e596",
+                "url": "http://example.com/identity/"
+            },
+            {
+                "id": "1",
+                "interface": "internal",
+                "links": {
+                    "self": "http://example.com/identity/v3/endpoints/1"
+                },
+                "region": "south",
+                "service_id": "9242e05f0c23467bbd1cf1f7a6e5e596",
+                "url": "http://example.com/identity/"
+            }
+        ],
+        "links": {
+            "self": "http://exmp.com/identity/v3/OS-ENDPOINT-POLICY/policies/1"
+        }
+    }
+
     FAKE_LIST_POLICIES = {
         "links": {
             "next": None,
@@ -238,3 +266,33 @@
             service_id=self.FAKE_SERVICE_ID,
             region_id=self.FAKE_REGION_ID,
             status=204)
+
+    def _test_list_endpoints_for_policy(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.list_endpoints_for_policy,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_ENDPOINT_INFO,
+            bytes_body,
+            policy_id=self.FAKE_POLICY_ID,
+            status=200)
+
+    def test_list_endpoints_for_policy_with_str_body(self):
+        self._test_list_endpoints_for_policy()
+
+    def test_list_endpoints_for_policy_with_bytes_body(self):
+        self._test_list_endpoints_for_policy(bytes_body=True)
+
+    def _test_list_policy_for_endpoint(self, bytes_body=False):
+        self.check_service_client_function(
+            self.client.show_policy_for_endpoint,
+            'tempest.lib.common.rest_client.RestClient.get',
+            self.FAKE_POLICY_INFO,
+            bytes_body,
+            endpoint_id=self.FAKE_ENDPOINT_ID,
+            status=200)
+
+    def test_list_policy_for_endpoint_with_str_body(self):
+        self._test_list_policy_for_endpoint()
+
+    def test_list_policy_for_endpoint_with_bytes_body(self):
+        self._test_list_policy_for_endpoint(bytes_body=True)