Implement RestAPIs of trigger.
Includes create/delete/get/list APIs. Change-Id: I03deb689e48d30b44eadc6badf41f1b6d6f6c935 Closes-Bug: #1551569
This commit is contained in:
parent
4ddbe722f6
commit
d1d69da052
@ -24,5 +24,11 @@
|
||||
"provider:checkpoint_get": "rule:admin_or_owner",
|
||||
"provider:checkpoint_get_all": "rule:admin_or_owner",
|
||||
"provider:checkpoint_create": "rule:admin_or_owner",
|
||||
"provider:checkpoint_delete": "rule:admin_or_owner"
|
||||
"provider:checkpoint_delete": "rule:admin_or_owner",
|
||||
|
||||
"trigger:create": "",
|
||||
"trigger:delete": "rule:admin_or_owner",
|
||||
"trigger:update": "rule:admin_or_owner",
|
||||
"trigger:get": "rule:admin_or_owner",
|
||||
"trigger:list": ""
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ def _get_limit_param(params, max_limit=None):
|
||||
except ValueError:
|
||||
msg = _('limit param must be an integer')
|
||||
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||
if limit < 0:
|
||||
if limit <= 0:
|
||||
msg = _('limit param must be positive')
|
||||
raise webob.exc.HTTPBadRequest(explanation=msg)
|
||||
limit = min(limit, max_limit)
|
||||
|
@ -16,6 +16,7 @@ from smaug.api.v1 import protectables
|
||||
from smaug.api.v1 import providers
|
||||
from smaug.api.v1 import restores
|
||||
from smaug.api.v1 import scheduled_operations
|
||||
from smaug.api.v1 import triggers
|
||||
from smaug.wsgi import common as wsgi_common
|
||||
|
||||
|
||||
@ -29,7 +30,9 @@ class APIRouter(wsgi_common.Router):
|
||||
restores_resources = restores.create_resource()
|
||||
protectables_resources = protectables.create_resource()
|
||||
providers_resources = providers.create_resource()
|
||||
trigger_resources = triggers.create_resource()
|
||||
scheduled_operation_resources = scheduled_operations.create_resource()
|
||||
|
||||
mapper.resource("plan", "plans",
|
||||
controller=plans_resources,
|
||||
collection={},
|
||||
@ -74,6 +77,10 @@ class APIRouter(wsgi_common.Router):
|
||||
controller=providers_resources,
|
||||
action='checkpoints_delete',
|
||||
conditions={"method": ['DELETE']})
|
||||
mapper.resource("trigger", "triggers",
|
||||
controller=trigger_resources,
|
||||
collection={},
|
||||
member={'action': 'POST'})
|
||||
mapper.resource("scheduled_operation", "scheduled_operations",
|
||||
controller=scheduled_operation_resources,
|
||||
collection={'detail': 'GET'},
|
||||
|
242
smaug/api/v1/triggers.py
Normal file
242
smaug/api/v1/triggers.py
Normal file
@ -0,0 +1,242 @@
|
||||
# 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.
|
||||
|
||||
"""The triggers api."""
|
||||
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
import uuid
|
||||
from webob import exc
|
||||
|
||||
from smaug.api import common
|
||||
from smaug.api.openstack import wsgi
|
||||
from smaug import exception
|
||||
from smaug.i18n import _
|
||||
from smaug import objects
|
||||
from smaug.operationengine import api as operationengine_api
|
||||
from smaug import policy
|
||||
from smaug import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def check_policy(context, action, target_obj=None):
|
||||
_action = 'trigger:%s' % action
|
||||
policy.enforce(context, _action, target_obj)
|
||||
|
||||
|
||||
class TriggerViewBuilder(common.ViewBuilder):
|
||||
"""Model a trigger API response as a python dictionary."""
|
||||
|
||||
_collection_name = "triggers"
|
||||
|
||||
def detail(self, request, trigger):
|
||||
"""Detailed view of a single trigger."""
|
||||
|
||||
trigger_ref = {
|
||||
'trigger_info': {
|
||||
'id': trigger.get('id'),
|
||||
'name': trigger.get('name'),
|
||||
'type': trigger.get('type'),
|
||||
'properties': trigger.get('properties'),
|
||||
}
|
||||
}
|
||||
return trigger_ref
|
||||
|
||||
def detail_list(self, request, triggers):
|
||||
"""Detailed view of a list of triggers."""
|
||||
return self._list_view(self.detail, request, triggers)
|
||||
|
||||
def _list_view(self, func, request, triggers):
|
||||
triggers_list = [func(request, item)['trigger_info']
|
||||
for item in triggers]
|
||||
|
||||
triggers_links = self._get_collection_links(request,
|
||||
triggers,
|
||||
self._collection_name,
|
||||
)
|
||||
ret = {'triggers': triggers_list}
|
||||
if triggers_links:
|
||||
ret['triggers_links'] = triggers_links
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
class TriggersController(wsgi.Controller):
|
||||
"""The Triggers API controller for the OpenStack API."""
|
||||
|
||||
_view_builder_class = TriggerViewBuilder
|
||||
|
||||
def __init__(self):
|
||||
self.operationengine_api = operationengine_api.API()
|
||||
super(TriggersController, self).__init__()
|
||||
|
||||
def create(self, req, body):
|
||||
"""Creates a new trigger."""
|
||||
|
||||
LOG.debug('Create trigger start')
|
||||
|
||||
if not self.is_valid_body(body, 'trigger_info'):
|
||||
raise exc.HTTPUnprocessableEntity()
|
||||
LOG.debug('Create a trigger, request body: %s', body)
|
||||
|
||||
context = req.environ['smaug.context']
|
||||
check_policy(context, 'create')
|
||||
trigger_info = body['trigger_info']
|
||||
|
||||
trigger_name = trigger_info.get("name", None)
|
||||
trigger_type = trigger_info.get("type", None)
|
||||
trigger_property = trigger_info.get("properties", None)
|
||||
if not trigger_name or not trigger_type or not trigger_property:
|
||||
msg = _("Trigger name or type or property is not provided.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
self.validate_name_and_description(trigger_info)
|
||||
|
||||
trigger_definition = {
|
||||
'id': str(uuid.uuid4()),
|
||||
'name': trigger_name,
|
||||
'project_id': context.project_id,
|
||||
'type': trigger_type,
|
||||
'properties': trigger_property,
|
||||
}
|
||||
try:
|
||||
trigger = objects.Trigger(context=context, **trigger_definition)
|
||||
self.operationengine_api.create_trigger(context, trigger)
|
||||
trigger.create()
|
||||
except exception.Invalid as ex:
|
||||
raise exc.HTTPBadRequest(explanation=ex.msg)
|
||||
except Exception as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
return self._view_builder.detail(req, trigger)
|
||||
|
||||
def delete(self, req, id):
|
||||
"""Delete a trigger."""
|
||||
|
||||
LOG.debug('Delete trigger(%s) start', id)
|
||||
|
||||
context = req.environ['smaug.context']
|
||||
trigger = self._get_trigger_by_id(context, id)
|
||||
|
||||
check_policy(context, 'delete', trigger)
|
||||
|
||||
try:
|
||||
self.operationengine_api.delete_trigger(context, id)
|
||||
except exception.TriggerNotFound as ex:
|
||||
pass
|
||||
except exception.DeleteTriggerNotAllowed as ex:
|
||||
raise exc.HTTPBadRequest(explanation=ex.msg)
|
||||
except Exception as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
trigger.destroy()
|
||||
|
||||
def update(self, req, id, body):
|
||||
"""Update a trigger"""
|
||||
|
||||
LOG.debug('Update trigger(%s) start', id)
|
||||
|
||||
context = req.environ['smaug.context']
|
||||
trigger = self._get_trigger_by_id(context, id)
|
||||
|
||||
check_policy(context, 'update', trigger)
|
||||
|
||||
trigger_info = body['trigger_info']
|
||||
trigger_name = trigger_info.get("name", None)
|
||||
trigger_property = trigger_info.get("properties", None)
|
||||
|
||||
if trigger_name:
|
||||
self.validate_name_and_description(trigger_info)
|
||||
trigger.name = trigger_name
|
||||
|
||||
if trigger_property:
|
||||
try:
|
||||
trigger.properties = trigger_property
|
||||
self.operationengine_api.update_trigger(context, trigger)
|
||||
except exception.InvalidInput as ex:
|
||||
raise exc.HTTPBadRequest(explanation=ex.msg)
|
||||
except (exception.TriggerNotFound, Exception) as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
try:
|
||||
trigger.save()
|
||||
except Exception as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
return self._view_builder.detail(req, trigger)
|
||||
|
||||
def show(self, req, id):
|
||||
"""Return data about the given trigger."""
|
||||
|
||||
LOG.debug('Get trigger(%s) start', id)
|
||||
|
||||
context = req.environ['smaug.context']
|
||||
trigger = self._get_trigger_by_id(context, id)
|
||||
|
||||
check_policy(context, 'get', trigger)
|
||||
return self._view_builder.detail(req, trigger)
|
||||
|
||||
def index(self, req):
|
||||
"""Returns a list of triggers, transformed through view builder."""
|
||||
|
||||
context = req.environ['smaug.context']
|
||||
check_policy(context, 'list')
|
||||
|
||||
params = req.params.copy()
|
||||
LOG.debug('List triggers start, params=%s', params)
|
||||
marker, limit, offset = common.get_pagination_params(params)
|
||||
sort_keys, sort_dirs = common.get_sort_params(params)
|
||||
filters = params
|
||||
|
||||
valid_filters = ["all_tenants", "name", "type", "properties"]
|
||||
utils.remove_invalid_filter_options(context, filters, valid_filters)
|
||||
utils.check_filters(filters)
|
||||
|
||||
all_tenants = utils.get_bool_param("all_tenants", filters)
|
||||
if not (context.is_admin and all_tenants):
|
||||
filters["project_id"] = context.project_id
|
||||
|
||||
try:
|
||||
triggers = objects.TriggerList.get_by_filters(
|
||||
context, filters, limit, marker, sort_keys, sort_dirs)
|
||||
except Exception as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
return self._view_builder.detail_list(req, triggers)
|
||||
|
||||
def _get_trigger_by_id(self, context, id):
|
||||
if not uuidutils.is_uuid_like(id):
|
||||
msg = _("Invalid trigger id provided.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
try:
|
||||
trigger = objects.Trigger.get_by_id(context, id)
|
||||
except exception.TriggerNotFound as error:
|
||||
raise exc.HTTPNotFound(explanation=error.msg)
|
||||
except Exception as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
return trigger
|
||||
|
||||
def _raise_unknown_exception(self, exception_instance):
|
||||
value = exception_instance.msg if isinstance(
|
||||
exception_instance, exception.SmaugException) else type(
|
||||
exception_instance)
|
||||
msg = (_('Unexpected API Error. Please report this at '
|
||||
'http://bugs.launchpad.net/smaug/ and attach the '
|
||||
'Smaug API log if possible.\n%s') % value)
|
||||
raise exc.HTTPInternalServerError(explanation=msg)
|
||||
|
||||
|
||||
def create_resource():
|
||||
return wsgi.Resource(TriggersController())
|
@ -178,6 +178,18 @@ def trigger_delete(context, id):
|
||||
return IMPL.trigger_delete(context, id)
|
||||
|
||||
|
||||
def trigger_get_all_by_filters_sort(context, filters, limit=None,
|
||||
marker=None, sort_keys=None,
|
||||
sort_dirs=None):
|
||||
"""Get all triggers that match all filters sorted by multiple keys.
|
||||
|
||||
sort_keys and sort_dirs must be a list of strings.
|
||||
"""
|
||||
return IMPL.trigger_get_all_by_filters_sort(
|
||||
context, filters, limit=limit, marker=marker,
|
||||
sort_keys=sort_keys, sort_dirs=sort_dirs)
|
||||
|
||||
|
||||
###################
|
||||
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
import functools
|
||||
import re
|
||||
import six
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
@ -395,6 +396,30 @@ def trigger_delete(context, id):
|
||||
trigger_ref.delete(session=session)
|
||||
|
||||
|
||||
def _trigger_list_process_filters(query, filters):
|
||||
exact_match_filter_names = ['project_id', 'type']
|
||||
query = _list_common_process_exact_filter(models.Trigger, query, filters,
|
||||
exact_match_filter_names)
|
||||
|
||||
regex_match_filter_names = ['name', 'properties']
|
||||
query = _list_common_process_regex_filter(models.Trigger, query, filters,
|
||||
regex_match_filter_names)
|
||||
|
||||
return query
|
||||
|
||||
|
||||
def trigger_get_all_by_filters_sort(context, filters, limit=None, marker=None,
|
||||
sort_keys=None, sort_dirs=None):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
query = _generate_paginate_query(context, session, marker, limit,
|
||||
sort_keys, sort_dirs, filters,
|
||||
paginate_type=models.Trigger,
|
||||
use_model=True)
|
||||
|
||||
return query.all() if query else []
|
||||
|
||||
|
||||
###################
|
||||
|
||||
|
||||
@ -990,21 +1015,105 @@ def _process_restore_filters(query, filters):
|
||||
return None
|
||||
query = query.filter_by(**filters)
|
||||
return query
|
||||
|
||||
|
||||
###############################
|
||||
|
||||
|
||||
@require_context
|
||||
def _list_common_get_query(context, model, session=None):
|
||||
return model_query(context, model, session=session)
|
||||
|
||||
|
||||
def _list_common_process_exact_filter(model, query, filters, legal_keys):
|
||||
"""Applies exact match filtering to a query.
|
||||
|
||||
:param model: model to apply filters to
|
||||
:param query: query to apply filters to
|
||||
:param filters: dictionary of filters; values that are lists,
|
||||
tuples, sets, or frozensets cause an 'IN' test to
|
||||
be performed, while exact matching ('==' operator)
|
||||
is used for other values
|
||||
:param legal_keys: list of keys to apply exact filtering to
|
||||
:returns: the updated query.
|
||||
"""
|
||||
|
||||
filter_dict = {}
|
||||
for key in legal_keys:
|
||||
if key not in filters:
|
||||
continue
|
||||
|
||||
value = filters.get(key)
|
||||
if isinstance(value, (list, tuple, set, frozenset)):
|
||||
if not value:
|
||||
return None # empty IN-predicate; short circuit
|
||||
# Looking for values in a list; apply to query directly
|
||||
column_attr = getattr(model, key)
|
||||
query = query.filter(column_attr.in_(value))
|
||||
else:
|
||||
# OK, simple exact match; save for later
|
||||
filter_dict[key] = value
|
||||
|
||||
# Apply simple exact matches
|
||||
if filter_dict:
|
||||
query = query.filter_by(**filter_dict)
|
||||
|
||||
return query
|
||||
|
||||
|
||||
def _list_common_process_regex_filter(model, query, filters, legal_keys):
|
||||
"""Applies regular expression filtering to a query.
|
||||
|
||||
:param model: model to apply filters to
|
||||
:param query: query to apply filters to
|
||||
:param filters: dictionary of filters with regex values
|
||||
:param legal_keys: list of keys to apply regex filtering to
|
||||
:returns: the updated query.
|
||||
"""
|
||||
|
||||
def _get_regexp_op_for_connection(db_connection):
|
||||
db_string = db_connection.split(':')[0].split('+')[0]
|
||||
regexp_op_map = {
|
||||
'postgresql': '~',
|
||||
'mysql': 'REGEXP',
|
||||
'sqlite': 'REGEXP'
|
||||
}
|
||||
return regexp_op_map.get(db_string, 'LIKE')
|
||||
|
||||
db_regexp_op = _get_regexp_op_for_connection(CONF.database.connection)
|
||||
for key in legal_keys:
|
||||
if key not in filters:
|
||||
continue
|
||||
|
||||
value = filters[key]
|
||||
if not isinstance(value, six.string_types):
|
||||
continue
|
||||
|
||||
column_attr = getattr(model, key)
|
||||
if db_regexp_op == 'LIKE':
|
||||
query = query.filter(column_attr.op(db_regexp_op)(
|
||||
u'%' + value + u'%'))
|
||||
else:
|
||||
query = query.filter(column_attr.op(db_regexp_op)(
|
||||
value))
|
||||
return query
|
||||
|
||||
|
||||
PAGINATION_HELPERS = {
|
||||
models.Plan: (_plan_get_query, _process_plan_filters, _plan_get),
|
||||
models.Restore: (_restore_get_query, _process_restore_filters,
|
||||
_restore_get)
|
||||
_restore_get),
|
||||
models.Trigger: (_list_common_get_query, _trigger_list_process_filters,
|
||||
_trigger_get),
|
||||
}
|
||||
|
||||
|
||||
###############################
|
||||
|
||||
|
||||
def _generate_paginate_query(context, session, marker, limit, sort_keys,
|
||||
sort_dirs, filters, offset=None,
|
||||
paginate_type=models.Plan):
|
||||
paginate_type=models.Plan, use_model=False):
|
||||
"""Generate the query to include the filters and the paginate options.
|
||||
|
||||
Returns a query with sorting / pagination criteria added or None
|
||||
@ -1032,6 +1141,9 @@ def _generate_paginate_query(context, session, marker, limit, sort_keys,
|
||||
sort_keys, sort_dirs = process_sort_params(sort_keys,
|
||||
sort_dirs,
|
||||
default_dir='desc')
|
||||
if use_model:
|
||||
query = get_query(context, session=session, model=paginate_type)
|
||||
else:
|
||||
query = get_query(context, session=session)
|
||||
|
||||
if filters:
|
||||
|
@ -16,8 +16,6 @@ from oslo_serialization import jsonutils
|
||||
from oslo_versionedobjects import fields
|
||||
|
||||
from smaug import db
|
||||
from smaug import exception
|
||||
from smaug.i18n import _
|
||||
from smaug.objects import base
|
||||
|
||||
CONF = cfg.CONF
|
||||
@ -69,10 +67,6 @@ class Trigger(base.SmaugPersistentObject, base.SmaugObject,
|
||||
|
||||
@base.remotable
|
||||
def create(self):
|
||||
if self.obj_attr_is_set('id'):
|
||||
raise exception.ObjectActionError(action='create',
|
||||
reason=_('already created'))
|
||||
|
||||
updates = self.smaug_obj_get_changes()
|
||||
self._convert_properties_to_db_format(updates)
|
||||
db_trigger = db.trigger_create(self._context, updates)
|
||||
|
148
smaug/tests/unit/api/v1/test_triggers.py
Normal file
148
smaug/tests/unit/api/v1/test_triggers.py
Normal file
@ -0,0 +1,148 @@
|
||||
# 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 webob import exc
|
||||
|
||||
from smaug.api.v1 import triggers as trigger_api
|
||||
from smaug import context
|
||||
from smaug import exception
|
||||
from smaug.i18n import _
|
||||
from smaug.tests import base
|
||||
from smaug.tests.unit.api import fakes
|
||||
|
||||
|
||||
class FakeRemoteOperationApi(object):
|
||||
def create_trigger(self, context, trigger):
|
||||
if trigger.type not in ['time']:
|
||||
msg = (_("Invalid trigger type:%s") % trigger.type)
|
||||
raise exception.InvalidInput(msg)
|
||||
|
||||
if trigger.properties['format'] not in ['crontab']:
|
||||
msg = (_("Invalid trigger time format type"))
|
||||
raise exception.InvalidInput(msg)
|
||||
|
||||
def delete_trigger(self, context, trigger_id):
|
||||
pass
|
||||
|
||||
def update_trigger(self, context, trigger):
|
||||
pass
|
||||
|
||||
|
||||
class TriggerApiTest(base.TestCase):
|
||||
def setUp(self):
|
||||
super(TriggerApiTest, self).setUp()
|
||||
self.controller = trigger_api.TriggersController()
|
||||
self.controller.operationengine_api = FakeRemoteOperationApi()
|
||||
self.ctxt = context.RequestContext('admin', 'fakeproject',
|
||||
True)
|
||||
self.req = fakes.HTTPRequest.blank('/v1/triggers')
|
||||
self.default_create_trigger_param = {
|
||||
"name": "123",
|
||||
"type": "time",
|
||||
"properties": {
|
||||
"format": "crontab",
|
||||
"pattern": "* * * * *"
|
||||
},
|
||||
}
|
||||
|
||||
def test_create_trigger_InvalidBody(self):
|
||||
self.assertRaises(exc.HTTPUnprocessableEntity,
|
||||
self.controller.create,
|
||||
self.req, {})
|
||||
|
||||
def test_create_trigger_InvalidName(self):
|
||||
body = self._get_create_trigger_request_body()
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
self.req, body)
|
||||
|
||||
def test_create_trigger_invalid_trigger_type(self):
|
||||
param = self.default_create_trigger_param.copy()
|
||||
param['type'] = "123"
|
||||
body = self._get_create_trigger_request_body(param)
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
self.req, body)
|
||||
|
||||
def test_create_trigger_invalid_trigger_formt_type(self):
|
||||
param = self.default_create_trigger_param.copy()
|
||||
param['properties']['format'] = "123"
|
||||
body = self._get_create_trigger_request_body(param)
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
self.req, body)
|
||||
|
||||
def test_create_trigger(self):
|
||||
name = 'every minutes'
|
||||
param = self.default_create_trigger_param.copy()
|
||||
param['name'] = name
|
||||
body = self._get_create_trigger_request_body(param)
|
||||
trigger = self.controller.create(self.req, body)
|
||||
self.assertEqual(name, trigger['trigger_info']['name'])
|
||||
|
||||
def test_delete_trigger(self):
|
||||
trigger = self._create_one_trigger()
|
||||
self.controller.delete(self.req, trigger['trigger_info']['id'])
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.controller.show,
|
||||
self.req,
|
||||
trigger['trigger_info']['id'])
|
||||
|
||||
def test_update_trigger(self):
|
||||
trigger = self._create_one_trigger()
|
||||
|
||||
name = 'every minutes'
|
||||
param = self.default_create_trigger_param.copy()
|
||||
param['name'] = name
|
||||
param['properties']['window'] = 10
|
||||
body = self._get_create_trigger_request_body(param)
|
||||
trigger1 = self.controller.update(
|
||||
self.req, trigger['trigger_info']['id'], body)
|
||||
|
||||
self.assertEqual(name, trigger1['trigger_info']['name'])
|
||||
self.assertEqual(10, int(
|
||||
trigger1['trigger_info']['properties']['window']))
|
||||
|
||||
def test_show_trigger_not_exist(self):
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.controller.show,
|
||||
self.req,
|
||||
'2a9ce1f3-cc1a-4516-9435-0ebb13caa398')
|
||||
|
||||
def test_show_trigger_invalid_id(self):
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.show,
|
||||
self.req, 1)
|
||||
|
||||
def test_show_trigger(self):
|
||||
trigger = self._create_one_trigger()
|
||||
trigger1 = self.controller.show(self.req,
|
||||
trigger['trigger_info']['id'])
|
||||
self.assertEqual(trigger['trigger_info']['id'],
|
||||
trigger1['trigger_info']['id'])
|
||||
|
||||
def test_list_trigger(self):
|
||||
trigger = self._create_one_trigger()
|
||||
triggers = self.controller.index(self.req)
|
||||
for item in triggers['triggers']:
|
||||
if item['id'] == trigger['trigger_info']['id']:
|
||||
self.assertTrue(1)
|
||||
|
||||
self.assertFalse(0)
|
||||
|
||||
def _create_one_trigger(self):
|
||||
param = self.default_create_trigger_param.copy()
|
||||
body = self._get_create_trigger_request_body(param)
|
||||
return self.controller.create(self.req, body)
|
||||
|
||||
def _get_create_trigger_request_body(self, param={}):
|
||||
return {"trigger_info": param}
|
@ -6,5 +6,10 @@
|
||||
"admin_api": "is_admin:True",
|
||||
|
||||
"plan:create": "",
|
||||
"plan:delete": "rule:admin_or_owner"
|
||||
"plan:delete": "rule:admin_or_owner",
|
||||
|
||||
"trigger:create": "",
|
||||
"trigger:delete": "rule:admin_or_owner",
|
||||
"trigger:get": "rule:admin_or_owner",
|
||||
"trigger:list": ""
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user