Merge "Api support for action_list2"

This commit is contained in:
Jenkins 2016-11-11 04:27:26 +00:00 committed by Gerrit Code Review
commit 62dc971fa6
2 changed files with 87 additions and 86 deletions

View File

@ -11,6 +11,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import jsonschema
import six
from webob import exc
from senlin.api.common import util
@ -18,6 +20,8 @@ from senlin.api.common import wsgi
from senlin.common import consts
from senlin.common.i18n import _
from senlin.common import utils
from senlin.objects import base as obj_base
from senlin.objects.requests import actions as vora
class ActionData(object):
@ -56,40 +60,35 @@ class ActionController(wsgi.Controller):
@util.policy_enforce
def index(self, req):
filter_whitelist = {
whitelist = {
consts.ACTION_NAME: 'mixed',
consts.ACTION_TARGET: 'mixed',
consts.ACTION_ACTION: 'mixed',
consts.ACTION_STATUS: 'mixed',
}
param_whitelist = {
consts.PARAM_LIMIT: 'single',
consts.PARAM_MARKER: 'single',
consts.PARAM_SORT: 'single',
consts.PARAM_GLOBAL_PROJECT: 'single',
}
for key in req.params.keys():
if (key not in param_whitelist.keys() and key not in
filter_whitelist.keys()):
if key not in 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)
params = util.get_allowed_params(req.params, whitelist)
key = consts.PARAM_LIMIT
if key in params:
params[key] = utils.parse_int_param(key, params[key])
project_safe = not utils.parse_bool_param(
consts.PARAM_GLOBAL_PROJECT,
params.pop(consts.PARAM_GLOBAL_PROJECT, False))
params['project_safe'] = project_safe
key = consts.PARAM_GLOBAL_PROJECT
if key in params:
global_project = utils.parse_bool_param(key, params[key])
params.pop(key)
params['project_safe'] = not global_project
try:
norm_req = obj_base.SenlinObject.normalize_req(
'ActionListRequest', params)
obj = vora.ActionListRequest.obj_from_primitive(norm_req)
jsonschema.validate(norm_req, obj.to_json_schema())
except (ValueError) as ex:
raise exc.HTTPBadRequest(six.text_type(ex))
if not filters:
filters = None
actions = self.rpc_client.action_list(req.context, filters=filters,
**params)
actions = self.rpc_client.call2(req.context, "action_list2", obj)
return {'actions': actions}

View File

@ -18,6 +18,7 @@ from senlin.api.middleware import fault
from senlin.api.openstack.v1 import actions
from senlin.common import exception as senlin_exc
from senlin.common import policy
from senlin.objects.requests import actions as vora
from senlin.rpc import client as rpc_client
from senlin.tests.unit.api import shared
from senlin.tests.unit.common import base
@ -62,44 +63,50 @@ class ActionControllerTest(shared.ControllerTest, base.SenlinTestCase):
}
]
mock_call = self.patchobject(rpc_client.EngineClient, 'call',
mock_call = self.patchobject(rpc_client.EngineClient, 'call2',
return_value=engine_resp)
result = self.controller.index(req)
default_args = {'limit': None, 'marker': None, 'sort': None,
'filters': None, 'project_safe': True}
mock_call.assert_called_with(req.context,
('action_list', default_args))
expected = {'actions': engine_resp}
self.assertEqual(expected, result)
mock_call.assert_called_with(req.context,
'action_list2', mock.ANY)
@mock.patch.object(rpc_client.EngineClient, 'call')
request = mock_call.call_args[0][2]
self.assertIsInstance(request, vora.ActionListRequest)
self.assertTrue(request.project_safe)
@mock.patch.object(rpc_client.EngineClient, 'call2')
def test_action_index_whitelists_params(self, mock_call, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
marker_uuid = '8216a86c-1bdc-442e-b493-329385d37cbc'
params = {
'name': 'NODE_CREATE',
'status': 'SUCCEEDED',
'limit': 10,
'marker': 'fake marker',
'sort': 'fake sorting option',
'marker': marker_uuid,
'sort': 'status',
'global_project': True,
}
req = self._get('/actions', params=params)
mock_call.return_value = []
self.controller.index(req)
result = self.controller.index(req)
expected = {'actions': []}
self.assertEqual(expected, result)
mock_call.assert_called_with(req.context,
'action_list2', mock.ANY)
request = mock_call.call_args[0][2]
self.assertIsInstance(request, vora.ActionListRequest)
self.assertEqual(['NODE_CREATE'], request.name)
self.assertEqual(['SUCCEEDED'], request.status)
self.assertEqual(10, request.limit)
self.assertEqual(marker_uuid, request.marker)
self.assertEqual('status', request.sort)
self.assertFalse(request.project_safe)
rpc_call_args, _ = mock_call.call_args
engine_args = rpc_call_args[1][1]
self.assertEqual(5, len(engine_args))
self.assertIn('limit', engine_args)
self.assertIn('marker', engine_args)
self.assertIn('sort', engine_args)
self.assertIn('project_safe', engine_args)
@mock.patch.object(rpc_client.EngineClient, 'call')
@mock.patch.object(rpc_client.EngineClient, 'call2')
def test_action_index_whitelists_invalid_params(self, mock_call,
mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
@ -114,58 +121,53 @@ class ActionControllerTest(shared.ControllerTest, base.SenlinTestCase):
str(ex))
self.assertFalse(mock_call.called)
@mock.patch.object(rpc_client.EngineClient, 'call')
@mock.patch.object(rpc_client.EngineClient, 'call2')
def test_action_index_limit_not_int(self, mock_call, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
params = {'limit': 'not-int'}
req = self._get('/actions', params=params)
ex = self.assertRaises(senlin_exc.InvalidParameter,
self.controller.index, req)
self.assertEqual("Invalid value 'not-int' specified for 'limit'",
six.text_type(ex))
self.assertFalse(mock_call.called)
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_action_index_whitelist_filter_params(self, mock_call,
mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
params = {
'name': 'fake name',
'target': '1111-2222-3333',
'action': 'CLUSTER_CREATE',
'status': 'SUCCEEDED'
}
req = self._get('/actions', params=params)
mock_call.return_value = []
self.controller.index(req)
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(4, len(filters))
self.assertIn('name', filters)
self.assertIn('action', filters)
self.assertIn('target', filters)
self.assertIn('status', filters)
@mock.patch.object(rpc_client.EngineClient, 'call')
def test_action_index_whitelist_filter_invalid_params(self, mock_call,
mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
params = {
'balrog': 'you shall not pass!'
}
req = self._get('/actions', params=params)
ex = self.assertRaises(exc.HTTPBadRequest,
self.controller.index, req)
self.assertEqual("Invalid parameter balrog",
str(ex))
self.assertEqual("invalid literal for int() with base 10: 'not-int'",
six.text_type(ex))
self.assertFalse(mock_call.called)
@mock.patch.object(rpc_client.EngineClient, 'call2')
def test_action_index_global_project_true(self, mock_call, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
params = {'global_project': 'True'}
req = self._get('/actions', params=params)
self.controller.index(req)
request = mock_call.call_args[0][2]
self.assertFalse(request.project_safe)
@mock.patch.object(rpc_client.EngineClient, 'call2')
def test_action_index_global_project_false(self, mock_call, mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
params = {'global_project': 'False'}
req = self._get('/actions', params=params)
self.controller.index(req)
request = mock_call.call_args[0][2]
self.assertTrue(request.project_safe)
@mock.patch.object(rpc_client.EngineClient, 'call2')
def test_action_index_global_project_not_bool(self, mock_call,
mock_enforce):
self._mock_enforce_setup(mock_enforce, 'index', True)
params = {'global_project': 'No'}
req = self._get('/actions', params=params)
ex = self.assertRaises(senlin_exc.InvalidParameter,
self.controller.index, req)
self.assertEqual("Invalid value 'No' specified for 'global_project'",
six.text_type(ex))
self.assertFalse(mock_call.called)
def test_action_index_denied_policy(self, mock_enforce):