Execution operations by admin user
Partially implements: blueprint qinling-admin-operations Change-Id: Ie2f7572b61b0a88a488f8dcceea35e8d7c689abe
This commit is contained in:
parent
939ba95cc4
commit
e120058fbe
|
@ -9,6 +9,7 @@
|
|||
"runtime:delete": "rule:context_is_admin",
|
||||
|
||||
"function:get_all:all_projects": "rule:context_is_admin",
|
||||
|
||||
"function_worker:get_all": "rule:context_is_admin",
|
||||
|
||||
"execution:get_all:all_projects": "rule:context_is_admin",
|
||||
}
|
||||
|
|
|
@ -18,8 +18,10 @@ from pecan import rest
|
|||
from wsme import types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from qinling.api import access_control as acl
|
||||
from qinling.api.controllers.v1 import resources
|
||||
from qinling.api.controllers.v1 import types
|
||||
from qinling import context
|
||||
from qinling.db import api as db_api
|
||||
from qinling import rpc
|
||||
from qinling.utils import executions
|
||||
|
@ -62,13 +64,33 @@ class ExecutionsController(rest.RestController):
|
|||
return resources.Execution.from_dict(db_model.to_dict())
|
||||
|
||||
@rest_utils.wrap_wsme_controller_exception
|
||||
@wsme_pecan.wsexpose(resources.Executions, wtypes.text)
|
||||
def get_all(self, function_id=None):
|
||||
filters = rest_utils.get_filters(function_id=function_id)
|
||||
@wsme_pecan.wsexpose(resources.Executions, wtypes.text, bool, wtypes.text)
|
||||
def get_all(self, function_id=None, all_projects=False, project_id=None):
|
||||
"""Return a list of executions.
|
||||
|
||||
:param function_id: Optional. Filtering executions by function_id.
|
||||
:param project_id: Optional. Admin user can query other projects
|
||||
resources, the param is ignored for normal user.
|
||||
:param all_projects: Optional. Get resources of all projects.
|
||||
"""
|
||||
ctx = context.get_ctx()
|
||||
if project_id and not ctx.is_admin:
|
||||
project_id = context.ctx().projectid
|
||||
if project_id and ctx.is_admin:
|
||||
all_projects = True
|
||||
|
||||
if all_projects:
|
||||
acl.enforce('execution:get_all:all_projects', ctx)
|
||||
|
||||
filters = rest_utils.get_filters(
|
||||
function_id=function_id,
|
||||
project_id=project_id,
|
||||
)
|
||||
LOG.info("Get all %ss. filters=%s", self.type, filters)
|
||||
|
||||
db_execs = db_api.get_executions(insecure=all_projects, **filters)
|
||||
executions = [resources.Execution.from_dict(db_model.to_dict())
|
||||
for db_model in db_api.get_executions(**filters)]
|
||||
for db_model in db_execs]
|
||||
|
||||
return resources.Executions(executions=executions)
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ from oslo_utils import strutils
|
|||
import pecan
|
||||
from pecan import rest
|
||||
from webob.static import FileIter
|
||||
from wsme import types as wtypes
|
||||
import wsmeext.pecan as wsme_pecan
|
||||
|
||||
from qinling.api import access_control as acl
|
||||
|
@ -193,7 +194,7 @@ class FunctionsController(rest.RestController):
|
|||
return resources.Function.from_dict(func_db.to_dict()).to_dict()
|
||||
|
||||
@rest_utils.wrap_wsme_controller_exception
|
||||
@wsme_pecan.wsexpose(resources.Functions, bool, types.uuid)
|
||||
@wsme_pecan.wsexpose(resources.Functions, bool, wtypes.text)
|
||||
def get_all(self, all_projects=False, project_id=None):
|
||||
"""Return a list of functions.
|
||||
|
||||
|
@ -210,11 +211,10 @@ class FunctionsController(rest.RestController):
|
|||
if all_projects:
|
||||
acl.enforce('function:get_all:all_projects', ctx)
|
||||
|
||||
LOG.info("Get all functions.")
|
||||
|
||||
filters = rest_utils.get_filters(
|
||||
project_id=project_id,
|
||||
)
|
||||
LOG.info("Get all %ss. filters=%s", self.type, filters)
|
||||
|
||||
db_functions = db_api.get_functions(insecure=all_projects, **filters)
|
||||
functions = [resources.Function.from_dict(db_model.to_dict())
|
||||
|
|
|
@ -20,6 +20,7 @@ import futurist
|
|||
from oslo_serialization import jsonutils
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions
|
||||
|
||||
from qinling_tempest_plugin.tests import base
|
||||
|
||||
|
@ -122,6 +123,42 @@ class ExecutionsTest(base.BaseQinlingTest):
|
|||
|
||||
self.assertEqual(204, resp.status)
|
||||
|
||||
@decorators.idempotent_id('2199d1e6-de7d-4345-8745-a8184d6022b1')
|
||||
def test_get_all_admin(self):
|
||||
"""Admin user can get executions of other projects"""
|
||||
self.await_runtime_available(self.runtime_id)
|
||||
self._create_function()
|
||||
|
||||
resp, body = self.client.create_execution(self.function_id,
|
||||
input={'name': 'Qinling'})
|
||||
self.assertEqual(201, resp.status)
|
||||
|
||||
execution_id = body['id']
|
||||
self.addCleanup(self.client.delete_resource, 'executions',
|
||||
execution_id, ignore_notfound=True)
|
||||
|
||||
resp, body = self.admin_client.get_resources(
|
||||
'executions?all_projects=true'
|
||||
)
|
||||
self.assertEqual(200, resp.status)
|
||||
self.assertIn(
|
||||
execution_id,
|
||||
[execution['id'] for execution in body['executions']]
|
||||
)
|
||||
|
||||
@decorators.idempotent_id('009fba47-957e-4de5-82e8-a032386d3ac0')
|
||||
def test_get_all_not_allowed(self):
|
||||
# Get other projects functions by normal user
|
||||
context = self.assertRaises(
|
||||
exceptions.Forbidden,
|
||||
self.client.get_resources,
|
||||
'executions?all_projects=true'
|
||||
)
|
||||
self.assertIn(
|
||||
'Operation not allowed',
|
||||
context.resp_body.get('faultstring')
|
||||
)
|
||||
|
||||
@decorators.idempotent_id('8096cc52-64d2-4660-a657-9ac0bdd743ae')
|
||||
def test_execution_async(self):
|
||||
self.await_runtime_available(self.runtime_id)
|
||||
|
|
Loading…
Reference in New Issue