Skip to content

Commit

Permalink
Merge pull request #2841 from StackStorm/feature/exposition
Browse files Browse the repository at this point in the history
Making jsexpose more flexible
  • Loading branch information
enykeev authored Aug 1, 2016
2 parents 569c5ac + 1383f0b commit ecf6b90
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 43 deletions.
2 changes: 1 addition & 1 deletion st2api/st2api/controllers/v1/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def post(self, action):

@request_user_has_resource_db_permission(permission_type=PermissionType.ACTION_MODIFY)
@jsexpose(arg_types=[str], body_cls=ActionCreateAPI)
def put(self, action_ref_or_id, action):
def put(self, action, action_ref_or_id):
action_db = self._get_by_ref_or_id(ref_or_id=action_ref_or_id)

# Assert permissions
Expand Down
2 changes: 1 addition & 1 deletion st2api/st2api/controllers/v1/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def post(self, api_key_api):

@request_user_has_resource_db_permission(permission_type=PermissionType.API_KEY_MODIFY)
@jsexpose(arg_types=[str], body_cls=ApiKeyAPI)
def put(self, api_key_id_or_key, api_key_api):
def put(self, api_key_api, api_key_id_or_key):
api_key_db = ApiKey.get_by_key_or_id(api_key_id_or_key)

LOG.debug('PUT /apikeys/ lookup with api_key_id_or_key=%s found object: %s',
Expand Down
2 changes: 1 addition & 1 deletion st2api/st2api/controllers/v1/keyvalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def get_all(self, prefix=None, scope=SYSTEM_SCOPE, user=None, decrypt=False, **k
return kvp_apis

@jsexpose(arg_types=[str, str, str], body_cls=KeyValuePairSetAPI)
def put(self, name, kvp, scope=SYSTEM_SCOPE):
def put(self, kvp, name, scope=SYSTEM_SCOPE):
"""
Create a new entry or update an existing one.
"""
Expand Down
2 changes: 1 addition & 1 deletion st2api/st2api/controllers/v1/policies.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def post(self, instance):
return self.model.from_model(db_model)

@jsexpose(arg_types=[str], body_cls=PolicyAPI)
def put(self, ref_or_id, instance):
def put(self, instance, ref_or_id):
op = 'PUT /policies/%s/' % ref_or_id

db_model = self._get_by_ref_or_id(ref_or_id=ref_or_id)
Expand Down
2 changes: 1 addition & 1 deletion st2api/st2api/controllers/v1/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def post(self, rule):

@request_user_has_resource_db_permission(permission_type=PermissionType.RULE_MODIFY)
@jsexpose(arg_types=[str], body_cls=RuleAPI)
def put(self, rule_ref_or_id, rule):
def put(self, rule, rule_ref_or_id):
rule_db = self._get_by_ref_or_id(rule_ref_or_id)
LOG.debug('PUT /rules/ lookup with id=%s found object: %s', rule_ref_or_id, rule_db)

Expand Down
2 changes: 1 addition & 1 deletion st2api/st2api/controllers/v1/runnertypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def get_one(self, name_or_id):

@request_user_has_resource_db_permission(permission_type=PermissionType.RUNNER_MODIFY)
@jsexpose(arg_types=[str], body_cls=RunnerTypeAPI)
def put(self, name_or_id, runner_type_api):
def put(self, runner_type_api, name_or_id):
# Note: We only allow "enabled" attribute of the runner to be changed
runner_type_db = self._get_by_name_or_id(name_or_id=name_or_id)
old_runner_type_db = runner_type_db
Expand Down
4 changes: 2 additions & 2 deletions st2api/st2api/controllers/v1/triggers.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def post(self, triggertype):
return triggertype_api

@jsexpose(arg_types=[str], body_cls=TriggerTypeAPI)
def put(self, triggertype_ref_or_id, triggertype):
def put(self, triggertype, triggertype_ref_or_id):
triggertype_db = self._get_by_ref_or_id(ref_or_id=triggertype_ref_or_id)
triggertype_id = triggertype_db.id

Expand Down Expand Up @@ -238,7 +238,7 @@ def post(self, trigger):
return trigger_api

@jsexpose(arg_types=[str], body_cls=TriggerAPI)
def put(self, trigger_id, trigger):
def put(self, trigger, trigger_id):
trigger_db = TriggerController.__get_by_id(trigger_id)
try:
if trigger.id is not None and trigger.id is not '' and trigger.id != trigger_id:
Expand Down
59 changes: 30 additions & 29 deletions st2common/st2common/models/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ def get_controller_args_for_types(func, arg_types, args, kwargs):
return result_args, result_kwargs


def jsexpose(arg_types=None, body_cls=None, status_code=None, content_type='application/json'):
def jsexpose(arg_types=None, body_cls=None, status_code=None, content_type='application/json',
method=None):
"""
:param arg_types: A list of types for the function arguments (e.g. [str, str, int, bool]).
:type arg_types: ``list``
Expand Down Expand Up @@ -232,6 +233,34 @@ def cast_func(value):
result = cast_func(value)
return result

if body_cls:
if pecan.request.body:
data = pecan.request.json

obj = body_cls(**data)
try:
obj = obj.validate()
except (jsonschema.ValidationError, ValueError) as e:
raise exc.HTTPBadRequest(detail=e.message,
comment=traceback.format_exc())
except Exception as e:
raise exc.HTTPInternalServerError(detail=e.message,
comment=traceback.format_exc())

# Set default pack if one is not provided for resource create
if function_name == 'post' and not hasattr(obj, 'pack'):
extra = {
'resource_api': obj,
'default_pack_name': DEFAULT_PACK_NAME
}
LOG.debug('Pack not provided in the body, setting a default pack name',
extra=extra)
setattr(obj, 'pack', DEFAULT_PACK_NAME)
else:
obj = None

more.append(obj)

if arg_types:
# Cast and transform arguments based on the provided arg_types specification
result_args, result_kwargs = get_controller_args_for_types(func=f,
Expand All @@ -241,34 +270,6 @@ def cast_func(value):
more = more + result_args
kwargs.update(result_kwargs)

if body_cls:
if pecan.request.body:
data = pecan.request.json
else:
data = {}

obj = body_cls(**data)
try:
obj = obj.validate()
except (jsonschema.ValidationError, ValueError) as e:
raise exc.HTTPBadRequest(detail=e.message,
comment=traceback.format_exc())
except Exception as e:
raise exc.HTTPInternalServerError(detail=e.message,
comment=traceback.format_exc())

# Set default pack if one is not provided for resource create
if function_name == 'post' and not hasattr(obj, 'pack'):
extra = {
'resource_api': obj,
'default_pack_name': DEFAULT_PACK_NAME
}
LOG.debug('Pack not provided in the body, setting a default pack name',
extra=extra)
setattr(obj, 'pack', DEFAULT_PACK_NAME)

more.append(obj)

args = tuple(more) + tuple(args)

noop_codes = [http_client.NOT_IMPLEMENTED,
Expand Down
12 changes: 6 additions & 6 deletions st2common/tests/unit/test_api_model_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,26 +144,26 @@ def test_expose_body_and_arguments_type_casting(self):
APIModelMock = mock.MagicMock()

@base.jsexpose(arg_types=[int], body_cls=APIModelMock)
def f(self, id, body, *args, **kwargs):
self.f(self, id, body, args, kwargs)
def f(self, body, id, *args, **kwargs):
self.f(self, body, id, args, kwargs)

f(self, '11')

APIModelMock.assert_called_once_with(a='b')
self.f.assert_called_once_with(self, 11, APIModelMock().validate(), (), {})
self.f.assert_called_once_with(self, APIModelMock().validate(), 11, (), {})

@unittest.skip
def test_expose_body_and_typed_arguments_unused(self):
APIModelMock = mock.MagicMock()

@base.jsexpose(arg_types=[int], body_cls=APIModelMock)
def f(self, id, body, *args, **kwargs):
self.f(self, id, body, args, kwargs)
def f(self, body, id, *args, **kwargs):
self.f(self, body, id, args, kwargs)

f(self, '11', 'some')

APIModelMock.assert_called_once_with(a='b')
self.f.assert_called_once_with(self, 11, APIModelMock().validate(), ('some', ), {})
self.f.assert_called_once_with(self, APIModelMock().validate(), 11, ('some', ), {})

@unittest.skip
def test_expose_body_and_typed_kw_unused(self):
Expand Down

0 comments on commit ecf6b90

Please sign in to comment.