From 10c8220c79164544a8e9adc74716437078b791f0 Mon Sep 17 00:00:00 2001 From: yanyanhu Date: Tue, 7 Jun 2016 23:29:46 -0400 Subject: [PATCH] Fix cluster-policies list API This patch revises cluster-policies list API to make it raise BadRequest exception when incorrect request parameter(s) are provided. This is for keeping consistent with other resource list APIs. Related tempest API test is also added to verify the change. Change-Id: I47b183456277f5af934d934f9a33f7c363ff1761 --- api-ref/source/cluster_policies.inc | 1 + senlin/api/openstack/v1/cluster_policies.py | 8 ++++++ .../test_cluster_policy_list_negative.py | 28 +++++++++++++++++++ .../tests/tempest/common/clustering_client.py | 5 +++- .../api/openstack/v1/test_cluster_policies.py | 26 +++++++---------- 5 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 senlin/tests/tempest/api/cluster_policies/test_cluster_policy_list_negative.py diff --git a/api-ref/source/cluster_policies.inc b/api-ref/source/cluster_policies.inc index bf68b04a..b86e3146 100644 --- a/api-ref/source/cluster_policies.inc +++ b/api-ref/source/cluster_policies.inc @@ -15,6 +15,7 @@ Normal response codes: 200 Error response codes: +- badRequest (400) - unauthorized (401) - forbidden (403) - notFound (404) diff --git a/senlin/api/openstack/v1/cluster_policies.py b/senlin/api/openstack/v1/cluster_policies.py index e57e66eb..28cd1375 100644 --- a/senlin/api/openstack/v1/cluster_policies.py +++ b/senlin/api/openstack/v1/cluster_policies.py @@ -14,9 +14,12 @@ ClusterPolicies endpoint for Senlin v1 ReST API. """ +from webob import exc + from senlin.api.common import util from senlin.api.common import wsgi from senlin.common import consts +from senlin.common.i18n import _ from senlin.common import utils @@ -34,6 +37,11 @@ class ClusterPolicyController(wsgi.Controller): param_whitelist = { consts.PARAM_SORT: 'single', } + for key in req.params.keys(): + if (key not in param_whitelist.keys() and key not in + filter_whitelist.keys()): + raise exc.HTTPBadRequest(_('Invalid parameter %s') % key) + params = util.get_allowed_params(req.params, param_whitelist) filters = util.get_allowed_params(req.params, filter_whitelist) key = consts.CP_ENABLED diff --git a/senlin/tests/tempest/api/cluster_policies/test_cluster_policy_list_negative.py b/senlin/tests/tempest/api/cluster_policies/test_cluster_policy_list_negative.py new file mode 100644 index 00000000..d985ee98 --- /dev/null +++ b/senlin/tests/tempest/api/cluster_policies/test_cluster_policy_list_negative.py @@ -0,0 +1,28 @@ +# 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 import decorators +from tempest.lib import exceptions +from tempest import test + +from senlin.tests.tempest.api import base + + +class TestClusterPolicyListNegativeBadRequest(base.BaseSenlinTest): + + @test.attr(type=['negative']) + @decorators.idempotent_id('7f23de64-60c4-456e-9e24-db86ac89480c') + def test_cluster_policy_list_invalid_params(self): + self.assertRaises(exceptions.BadRequest, + self.client.list_cluster_policies, + '7f23de64-60c4-456e-9e24-db86ac89480c', + {'bogus': 'foo'}) diff --git a/senlin/tests/tempest/common/clustering_client.py b/senlin/tests/tempest/common/clustering_client.py index f43ae089..3adddcb6 100644 --- a/senlin/tests/tempest/common/clustering_client.py +++ b/senlin/tests/tempest/common/clustering_client.py @@ -79,8 +79,11 @@ class ClusteringAPIClient(rest_client.RestClient): return self._parsed_resp(resp, body) - def list_cluster_policies(self, cluster_id): + def list_cluster_policies(self, cluster_id, params=None): uri = '{0}/clusters/{1}/policies'.format(self.version, cluster_id) + if params: + uri += '?{0}'.format(urllib.urlencode(params)) + resp, body = self.get(uri) return self._parsed_resp(resp, body) diff --git a/senlin/tests/unit/api/openstack/v1/test_cluster_policies.py b/senlin/tests/unit/api/openstack/v1/test_cluster_policies.py index 7709a495..b9cd4ccc 100644 --- a/senlin/tests/unit/api/openstack/v1/test_cluster_policies.py +++ b/senlin/tests/unit/api/openstack/v1/test_cluster_policies.py @@ -12,6 +12,7 @@ import mock import six +from webob import exc from senlin.api.middleware import fault from senlin.api.openstack.v1 import cluster_policies as cp_mod @@ -67,14 +68,13 @@ class ClusterPolicyControllerTest(shared.ControllerTest, base.SenlinTestCase): self.assertEqual(expected, result) @mock.patch.object(rpc_client.EngineClient, 'call') - def test_cluster_policy_index_whitelists_params(self, mock_call, - mock_enforce): + def test_cluster_policy_index_valid_filter_params(self, mock_call, + mock_enforce): self._mock_enforce_setup(mock_enforce, 'index', True) cid = 'FAKE_CLUSTER' params = { 'sort': 'fake sorting string', - 'filters': None, - 'balrog': 'you shall not pass!' + 'enabled': 'True', } req = self._get('/cluster_policies/%s' % cid, params=params) mock_call.return_value = [] @@ -90,8 +90,8 @@ class ClusterPolicyControllerTest(shared.ControllerTest, base.SenlinTestCase): self.assertNotIn('balrog', engine_args) @mock.patch.object(rpc_client.EngineClient, 'call') - def test_cluster_policy_index_whitelist_filter_params(self, mock_call, - mock_enforce): + def test_cluster_policy_index_invalid_params(self, mock_call, + mock_enforce): self._mock_enforce_setup(mock_enforce, 'index', True) cid = 'FAKE_CLUSTER' params = { @@ -101,16 +101,10 @@ class ClusterPolicyControllerTest(shared.ControllerTest, base.SenlinTestCase): req = self._get('/cluster_policies/%s' % cid, params=params) mock_call.return_value = [] - self.controller.index(req, cluster_id=cid) - - rpc_call_args, _ = mock_call.call_args - engine_args = rpc_call_args[1][1] - self.assertIn('filters', engine_args) - - filters = engine_args['filters'] - self.assertEqual(1, len(filters)) - self.assertTrue(filters['enabled']) - self.assertNotIn('balrog', filters) + ex = self.assertRaises(exc.HTTPBadRequest, self.controller.index, + req, cluster_id=cid) + self.assertEqual('Invalid parameter balrog', + six.text_type(ex)) def test_cluster_policy_index_denied_policy(self, mock_enforce): self._mock_enforce_setup(mock_enforce, 'index', False)