Implement RestAPIs of Scheduled Operation.
Includes create/delete/get/list APIs. Change-Id: I5c2578a810cbbaf65847cdd048a6df6bb91176de Closes-Bug: #1552130
This commit is contained in:
parent
d1d69da052
commit
d54d6835d1
|
@ -30,5 +30,10 @@
|
|||
"trigger:delete": "rule:admin_or_owner",
|
||||
"trigger:update": "rule:admin_or_owner",
|
||||
"trigger:get": "rule:admin_or_owner",
|
||||
"trigger:list": ""
|
||||
"trigger:list": "",
|
||||
|
||||
"scheduled_operation:create": "",
|
||||
"scheduled_operation:delete": "rule:admin_or_owner",
|
||||
"scheduled_operation:get": "rule:admin_or_owner",
|
||||
"scheduled_operation:list": ""
|
||||
}
|
||||
|
|
|
@ -83,6 +83,6 @@ class APIRouter(wsgi_common.Router):
|
|||
member={'action': 'POST'})
|
||||
mapper.resource("scheduled_operation", "scheduled_operations",
|
||||
controller=scheduled_operation_resources,
|
||||
collection={'detail': 'GET'},
|
||||
collection={},
|
||||
member={'action': 'POST'})
|
||||
super(APIRouter, self).__init__(mapper)
|
||||
|
|
|
@ -10,91 +10,255 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""The ScheduledOperations api."""
|
||||
|
||||
"""The scheduled operations api."""
|
||||
|
||||
from oslo_log import log as logging
|
||||
import webob
|
||||
from oslo_utils import uuidutils
|
||||
from webob import exc
|
||||
|
||||
from smaug.api import common
|
||||
from smaug.api.openstack import wsgi
|
||||
from smaug.i18n import _LI
|
||||
from smaug import exception
|
||||
from smaug.i18n import _
|
||||
from smaug import objects
|
||||
from smaug.operationengine import api as operationengine_api
|
||||
from smaug.operationengine import operation_manager
|
||||
from smaug import policy
|
||||
from smaug import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
OPERATION_MANAGER = operation_manager.OperationManager()
|
||||
|
||||
class ScheduledOperationsController(wsgi.Controller):
|
||||
"""The ScheduledOperations API controller for the OpenStack API."""
|
||||
|
||||
def check_policy(context, action, target_obj=None):
|
||||
_action = 'scheduled_operation:%s' % action
|
||||
policy.enforce(context, _action, target_obj)
|
||||
|
||||
|
||||
class ScheduledOperationViewBuilder(common.ViewBuilder):
|
||||
"""Model a server API response as a python dictionary."""
|
||||
|
||||
_collection_name = "scheduled_operations"
|
||||
|
||||
def detail(self, request, operation):
|
||||
"""Detailed view of a single scheduled operation."""
|
||||
|
||||
operation_ref = {
|
||||
'scheduled_operation': {
|
||||
'id': operation.get('id'),
|
||||
'name': operation.get('name'),
|
||||
'operation_type': operation.get('operation_type'),
|
||||
'project_id': operation.get('project_id'),
|
||||
'trigger_id': operation.get('trigger_id'),
|
||||
'operation_definition': operation.get('operation_definition'),
|
||||
}
|
||||
}
|
||||
return operation_ref
|
||||
|
||||
def detail_list(self, request, operations):
|
||||
"""Detailed view of a list of operations."""
|
||||
return self._list_view(self.detail, request, operations)
|
||||
|
||||
def _list_view(self, func, request, operations):
|
||||
operations_list = [func(request, item)['scheduled_operation']
|
||||
for item in operations]
|
||||
|
||||
operations_links = self._get_collection_links(request,
|
||||
operations,
|
||||
self._collection_name,
|
||||
)
|
||||
ret = {'operations': operations_list}
|
||||
if operations_links:
|
||||
ret['operations_links'] = operations_links
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
class ScheduledOperationController(wsgi.Controller):
|
||||
"""The Scheduled Operation API controller for the OpenStack API."""
|
||||
|
||||
_view_builder_class = ScheduledOperationViewBuilder
|
||||
|
||||
def __init__(self):
|
||||
self.operationengine_api = operationengine_api.API()
|
||||
super(ScheduledOperationsController, self).__init__()
|
||||
|
||||
def show(self, req, id):
|
||||
"""Return data about the given scheduled_operation."""
|
||||
context = req.environ['smaug.context']
|
||||
LOG.info(_LI("Show ScheduledOperation with id: %s"), id,
|
||||
context=context)
|
||||
# TODO(chenying)
|
||||
return {'Smaug': "ScheduledOperations show."}
|
||||
|
||||
def delete(self, req, id):
|
||||
"""Delete a scheduled_operation."""
|
||||
context = req.environ['smaug.context']
|
||||
|
||||
LOG.info(_LI("Delete ScheduledOperations with id: %s"), id,
|
||||
context=context)
|
||||
|
||||
# TODO(chenying)
|
||||
return webob.Response(status_int=202)
|
||||
|
||||
def index(self, req):
|
||||
"""Returns a summary list of ScheduledOperations."""
|
||||
|
||||
# TODO(chenying)
|
||||
|
||||
return {'scheduled_operation': "ScheduledOperations index."}
|
||||
|
||||
def detail(self, req):
|
||||
"""Returns a detailed list of ScheduledOperations."""
|
||||
|
||||
# TODO(chenying)
|
||||
|
||||
return {'scheduled_operation': "ScheduledOperations detail."}
|
||||
super(ScheduledOperationController, self).__init__()
|
||||
|
||||
def create(self, req, body):
|
||||
"""Creates a new ScheduledOperation."""
|
||||
"""Creates a new scheduled operation."""
|
||||
|
||||
LOG.debug('Create ScheduledOperations request body: %s', body)
|
||||
context = req.environ['smaug.context']
|
||||
request_spec = {'resource': 'ScheduledOperations',
|
||||
'method': 'create'}
|
||||
self.operationengine_api.create_scheduled_operation(context,
|
||||
request_spec)
|
||||
LOG.debug('Create ScheduledOperations request context: %s', context)
|
||||
LOG.debug('Create scheduled operation start')
|
||||
|
||||
# TODO(chenying)
|
||||
|
||||
return {'scheduled_operation': "Create a ScheduledOperation."}
|
||||
|
||||
def update(self, req, id, body):
|
||||
"""Update a scheduled_operation."""
|
||||
context = req.environ['smaug.context']
|
||||
|
||||
if not body:
|
||||
if not self.is_valid_body(body, 'scheduled_operation'):
|
||||
raise exc.HTTPUnprocessableEntity()
|
||||
LOG.debug('Create a scheduled operation, request body: %s', body)
|
||||
|
||||
if 'scheduled_operation' not in body:
|
||||
raise exc.HTTPUnprocessableEntity()
|
||||
context = req.environ['smaug.context']
|
||||
check_policy(context, 'create')
|
||||
operation_info = body['scheduled_operation']
|
||||
|
||||
scheduled_operation = body['scheduled_operation']
|
||||
name = operation_info.get("name", None)
|
||||
operation_type = operation_info.get("operation_type", None)
|
||||
operation_definition = operation_info.get(
|
||||
"operation_definition", None)
|
||||
if name is None:
|
||||
msg = _("Operation name or type or definition is not provided.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
LOG.info(_LI("Update ScheduledOperation : %s"), scheduled_operation,
|
||||
context=context)
|
||||
self.validate_name_and_description(operation_info)
|
||||
|
||||
return {'scheduled_operation': "Update a ScheduledOperation."}
|
||||
try:
|
||||
OPERATION_MANAGER.check_operation_definition(
|
||||
operation_type, operation_definition)
|
||||
except exception.Invalid as ex:
|
||||
raise exc.HTTPBadRequest(explanation=ex.msg)
|
||||
except Exception as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
trigger_id = operation_info.get("trigger_id", None)
|
||||
trigger = self._get_trigger_by_id(context, trigger_id)
|
||||
if context.project_id != trigger.project_id:
|
||||
msg = _("Invalid trigger id provided.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
operation_obj = {
|
||||
'name': operation_info.get('name', None),
|
||||
'operation_type': operation_type,
|
||||
'project_id': context.project_id,
|
||||
'trigger_id': trigger_id,
|
||||
'operation_definition': operation_definition,
|
||||
}
|
||||
try:
|
||||
operation = objects.ScheduledOperation(context=context,
|
||||
**operation_obj)
|
||||
operation.create()
|
||||
except Exception as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
try:
|
||||
self._create_scheduled_operation(context, operation.id,
|
||||
trigger_id)
|
||||
except Exception:
|
||||
try:
|
||||
operation.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
raise
|
||||
|
||||
return self._view_builder.detail(req, operation)
|
||||
|
||||
def delete(self, req, id):
|
||||
"""Delete a scheduled operation."""
|
||||
|
||||
LOG.debug('Delete scheduled operation(%s) start', id)
|
||||
|
||||
context = req.environ['smaug.context']
|
||||
operation = self._get_operation_by_id(context, id, ['trigger'])
|
||||
trigger = operation.trigger
|
||||
|
||||
check_policy(context, 'delete', operation)
|
||||
|
||||
try:
|
||||
self.operationengine_api.delete_scheduled_operation(
|
||||
context, id, trigger.id)
|
||||
|
||||
except (exception.ScheduledOperationStateNotFound,
|
||||
exception.TriggerNotFound,
|
||||
Exception) as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
operation.destroy()
|
||||
|
||||
def show(self, req, id):
|
||||
"""Return data about the given operation."""
|
||||
|
||||
LOG.debug('Get scheduled operation(%s) start', id)
|
||||
|
||||
context = req.environ['smaug.context']
|
||||
operation = self._get_operation_by_id(context, id)
|
||||
check_policy(context, 'get', operation)
|
||||
|
||||
return self._view_builder.detail(req, operation)
|
||||
|
||||
def index(self, req):
|
||||
"""Returns a list of operations, transformed through view builder."""
|
||||
|
||||
context = req.environ['smaug.context']
|
||||
check_policy(context, 'list')
|
||||
|
||||
params = req.params.copy()
|
||||
LOG.debug('List scheduled operation 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", "operation_type",
|
||||
"trigger_id", "operation_definition"]
|
||||
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:
|
||||
operations = objects.ScheduledOperationList.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, operations)
|
||||
|
||||
def _get_operation_by_id(self, context, id, expect_attrs=[]):
|
||||
if not uuidutils.is_uuid_like(id):
|
||||
msg = _("Invalid operation id provided.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
|
||||
try:
|
||||
operation = objects.ScheduledOperation.get_by_id(
|
||||
context, id, expect_attrs)
|
||||
except exception.ScheduledOperationNotFound as error:
|
||||
raise exc.HTTPNotFound(explanation=error.msg)
|
||||
except Exception as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
return operation
|
||||
|
||||
def _get_trigger_by_id(self, context, trigger_id):
|
||||
if not uuidutils.is_uuid_like(trigger_id):
|
||||
msg = _("Invalid trigger id provided.")
|
||||
raise exc.HTTPBadRequest(explanation=msg)
|
||||
try:
|
||||
trigger = objects.Trigger.get_by_id(context, trigger_id)
|
||||
except exception.NotFound as ex:
|
||||
raise exc.HTTPNotFound(explanation=ex.msg)
|
||||
except Exception as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
return trigger
|
||||
|
||||
def _create_scheduled_operation(self, context, operation_id, trigger_id):
|
||||
try:
|
||||
self.operationengine_api.create_scheduled_operation(
|
||||
context, operation_id, trigger_id)
|
||||
|
||||
except (exception.InvalidInput,
|
||||
exception.TriggerIsInvalid) as ex:
|
||||
raise exc.HTTPBadRequest(explanation=ex.msg)
|
||||
|
||||
except (exception.TriggerNotFound, Exception) as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
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(ScheduledOperationsController())
|
||||
return wsgi.Resource(ScheduledOperationController())
|
||||
|
|
|
@ -131,13 +131,23 @@ class TriggersController(wsgi.Controller):
|
|||
|
||||
check_policy(context, 'delete', trigger)
|
||||
|
||||
try:
|
||||
operations = objects.ScheduledOperationList.get_by_filters(
|
||||
context, {"trigger_id": id}, limit=1)
|
||||
except Exception as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
if operations:
|
||||
msg = _("There are more than one scheduled operations binded "
|
||||
"with this trigger, please delete them first")
|
||||
raise exc.HTTPMethodNotAllowed(explanation=msg)
|
||||
|
||||
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:
|
||||
except (exception.DeleteTriggerNotAllowed,
|
||||
Exception) as ex:
|
||||
self._raise_unknown_exception(ex)
|
||||
|
||||
trigger.destroy()
|
||||
|
|
|
@ -250,6 +250,18 @@ def scheduled_operation_delete(context, id):
|
|||
return IMPL.scheduled_operation_delete(context, id)
|
||||
|
||||
|
||||
def scheduled_operation_get_all_by_filters_sort(
|
||||
context, filters, limit=None,
|
||||
marker=None, sort_keys=None, sort_dirs=None):
|
||||
"""Get all operations that match all filters sorted by multiple keys.
|
||||
|
||||
sort_keys and sort_dirs must be a list of strings.
|
||||
"""
|
||||
return IMPL.scheduled_operation_get_all_by_filters_sort(
|
||||
context, filters, limit=limit, marker=marker,
|
||||
sort_keys=sort_keys, sort_dirs=sort_dirs)
|
||||
|
||||
|
||||
###################
|
||||
|
||||
|
||||
|
|
|
@ -476,6 +476,35 @@ def scheduled_operation_delete(context, id):
|
|||
session.flush()
|
||||
|
||||
|
||||
def _scheduled_operation_list_process_filters(query, filters):
|
||||
exact_match_filter_names = ['project_id', 'operation_type', 'trigger_id']
|
||||
query = _list_common_process_exact_filter(
|
||||
models.ScheduledOperation, query, filters,
|
||||
exact_match_filter_names)
|
||||
|
||||
regex_match_filter_names = ['name', 'operation_definition']
|
||||
query = _list_common_process_regex_filter(
|
||||
models.ScheduledOperation, query, filters,
|
||||
regex_match_filter_names)
|
||||
|
||||
return query
|
||||
|
||||
|
||||
def scheduled_operation_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.ScheduledOperation,
|
||||
use_model=True)
|
||||
|
||||
return query.all() if query else []
|
||||
|
||||
|
||||
###################
|
||||
|
||||
|
||||
|
@ -1105,6 +1134,9 @@ PAGINATION_HELPERS = {
|
|||
_restore_get),
|
||||
models.Trigger: (_list_common_get_query, _trigger_list_process_filters,
|
||||
_trigger_get),
|
||||
models.ScheduledOperation: (_list_common_get_query,
|
||||
_scheduled_operation_list_process_filters,
|
||||
_scheduled_operation_get),
|
||||
}
|
||||
|
||||
|
||||
|
@ -1153,7 +1185,7 @@ def _generate_paginate_query(context, session, marker, limit, sort_keys,
|
|||
|
||||
marker_object = None
|
||||
if marker is not None:
|
||||
marker_object = get(context, marker, session)
|
||||
marker_object = get(context, marker, session=session)
|
||||
|
||||
return sqlalchemyutils.paginate_query(query, paginate_type, limit,
|
||||
sort_keys,
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
# 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 scheduled_operations as operation_api
|
||||
from smaug.api.v1 import triggers as trigger_api
|
||||
from smaug import context
|
||||
from smaug import exception
|
||||
from smaug.tests import base
|
||||
from smaug.tests.unit.api import fakes
|
||||
from smaug.tests.unit.api.v1 import test_triggers
|
||||
|
||||
|
||||
class FakeRemoteOperationApi(object):
|
||||
def __init__(self):
|
||||
self._create_operation_exception = None
|
||||
self._delete_operation_exception = None
|
||||
|
||||
def create_scheduled_operation(self, context, operation_id, trigger_id):
|
||||
if self._create_operation_exception:
|
||||
raise self._create_operation_exception
|
||||
|
||||
def delete_scheduled_operation(self, context, operation_id, trigger_id):
|
||||
if self._delete_operation_exception:
|
||||
raise self._delete_operation_exception
|
||||
|
||||
|
||||
class ScheduledOperationApiTest(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ScheduledOperationApiTest, self).setUp()
|
||||
|
||||
self.remote_operation_api = FakeRemoteOperationApi()
|
||||
self.controller = operation_api.ScheduledOperationController()
|
||||
self.controller.operationengine_api = self.remote_operation_api
|
||||
|
||||
self.ctxt = context.RequestContext('admin', 'fakeproject', True)
|
||||
self.req = fakes.HTTPRequest.blank('/v1/scheduled_operations')
|
||||
|
||||
trigger = self._create_trigger()
|
||||
self.default_create_operation_param = {
|
||||
"name": "123",
|
||||
"operation_type": "protect",
|
||||
"trigger_id": trigger['trigger_info']['id'],
|
||||
"operation_definition": {
|
||||
"plan_id": ""
|
||||
},
|
||||
}
|
||||
|
||||
def test_create_operation_InvalidBody(self):
|
||||
self.assertRaises(exc.HTTPUnprocessableEntity,
|
||||
self.controller.create,
|
||||
self.req, {})
|
||||
|
||||
def test_create_operation_InvalidName(self):
|
||||
body = self._get_create_operation_request_body()
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
self.req, body)
|
||||
|
||||
def test_create_operation_invalid_operation_type(self):
|
||||
param = self.default_create_operation_param.copy()
|
||||
param['operation_type'] = "123"
|
||||
body = self._get_create_operation_request_body(param)
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
self.req, body)
|
||||
|
||||
def test_create_operation_invalid_trigger(self):
|
||||
param = self.default_create_operation_param.copy()
|
||||
param['trigger_id'] = 123
|
||||
body = self._get_create_operation_request_body(param)
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
self.req, body)
|
||||
|
||||
def test_create_operation_invalid_operation_definition(self):
|
||||
param = self.default_create_operation_param.copy()
|
||||
del param['operation_definition']['plan_id']
|
||||
body = self._get_create_operation_request_body(param)
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
self.req, body)
|
||||
|
||||
def test_create_operation_recieve_invalid_except(self):
|
||||
self.remote_operation_api._create_operation_exception =\
|
||||
exception.TriggerIsInvalid(trigger_id=None)
|
||||
|
||||
param = self.default_create_operation_param.copy()
|
||||
body = self._get_create_operation_request_body(param)
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.create,
|
||||
self.req, body)
|
||||
|
||||
self.remote_operation_api._create_operation_exception = None
|
||||
|
||||
def test_create_operation_recieve_unknown_except(self):
|
||||
self.remote_operation_api._create_operation_exception =\
|
||||
exception.TriggerNotFound(id=None)
|
||||
|
||||
param = self.default_create_operation_param.copy()
|
||||
body = self._get_create_operation_request_body(param)
|
||||
self.assertRaises(exc.HTTPInternalServerError,
|
||||
self.controller.create,
|
||||
self.req, body)
|
||||
|
||||
self.remote_operation_api._create_operation_exception = None
|
||||
|
||||
def test_create_operation(self):
|
||||
name = 'my protect'
|
||||
param = self.default_create_operation_param.copy()
|
||||
param['name'] = name
|
||||
body = self._get_create_operation_request_body(param)
|
||||
operation = self.controller.create(self.req, body)
|
||||
self.assertEqual(name, operation['scheduled_operation']['name'])
|
||||
|
||||
def test_delete_operation_recieve_NotFound_except(self):
|
||||
self.remote_operation_api._delete_operation_exception =\
|
||||
exception.ScheduledOperationStateNotFound(op_id=None)
|
||||
|
||||
operation = self._create_one_operation()
|
||||
self.assertRaises(exc.HTTPInternalServerError,
|
||||
self.controller.delete,
|
||||
self.req,
|
||||
operation['scheduled_operation']['id'])
|
||||
|
||||
self.remote_operation_api._delete_operation_exception = None
|
||||
|
||||
def test_delete_operation(self):
|
||||
operation = self._create_one_operation()
|
||||
self.controller.delete(self.req,
|
||||
operation['scheduled_operation']['id'])
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.controller.show,
|
||||
self.req,
|
||||
operation['scheduled_operation']['id'])
|
||||
|
||||
def test_show_operation_not_exist(self):
|
||||
self.assertRaises(exc.HTTPNotFound,
|
||||
self.controller.show,
|
||||
self.req,
|
||||
'2a9ce1f3-cc1a-4516-9435-0ebb13caa398')
|
||||
|
||||
def test_show_operation_invalid_id(self):
|
||||
self.assertRaises(exc.HTTPBadRequest,
|
||||
self.controller.show,
|
||||
self.req, 1)
|
||||
|
||||
def test_show_operation(self):
|
||||
operation = self._create_one_operation()
|
||||
operation1 = self.controller.show(
|
||||
self.req, operation['scheduled_operation']['id'])
|
||||
self.assertEqual(operation['scheduled_operation']['id'],
|
||||
operation1['scheduled_operation']['id'])
|
||||
|
||||
def test_list_operation(self):
|
||||
operation = self._create_one_operation()
|
||||
operations = self.controller.index(self.req)
|
||||
for item in operations['operations']:
|
||||
if item['id'] == operation['scheduled_operation']['id']:
|
||||
self.assertTrue(1)
|
||||
|
||||
self.assertFalse(0)
|
||||
|
||||
def _create_one_operation(self):
|
||||
param = self.default_create_operation_param.copy()
|
||||
body = self._get_create_operation_request_body(param)
|
||||
return self.controller.create(self.req, body)
|
||||
|
||||
def _get_create_operation_request_body(self, param={}):
|
||||
return {"scheduled_operation": param}
|
||||
|
||||
def _create_trigger(self):
|
||||
create_trigger_param = {
|
||||
"trigger_info": {
|
||||
"name": "123",
|
||||
"type": "time",
|
||||
"properties": {
|
||||
"format": "crontab",
|
||||
"pattern": "* * * * *"
|
||||
},
|
||||
}
|
||||
}
|
||||
controller = trigger_api.TriggersController()
|
||||
controller.operationengine_api = test_triggers.\
|
||||
FakeRemoteOperationApi()
|
||||
req = fakes.HTTPRequest.blank('/v1/triggers')
|
||||
return controller.create(req, create_trigger_param)
|
|
@ -16,6 +16,7 @@ from smaug.api.v1 import triggers as trigger_api
|
|||
from smaug import context
|
||||
from smaug import exception
|
||||
from smaug.i18n import _
|
||||
from smaug import objects
|
||||
from smaug.tests import base
|
||||
from smaug.tests.unit.api import fakes
|
||||
|
||||
|
@ -89,6 +90,16 @@ class TriggerApiTest(base.TestCase):
|
|||
trigger = self.controller.create(self.req, body)
|
||||
self.assertEqual(name, trigger['trigger_info']['name'])
|
||||
|
||||
def test_delete_trigger_binded_with_operation(self):
|
||||
trigger = self._create_one_trigger()
|
||||
trigger_id = trigger['trigger_info']['id']
|
||||
self._create_scheduled_operation(trigger_id)
|
||||
|
||||
self.assertRaises(exc.HTTPMethodNotAllowed,
|
||||
self.controller.delete,
|
||||
self.req,
|
||||
trigger_id)
|
||||
|
||||
def test_delete_trigger(self):
|
||||
trigger = self._create_one_trigger()
|
||||
self.controller.delete(self.req, trigger['trigger_info']['id'])
|
||||
|
@ -146,3 +157,17 @@ class TriggerApiTest(base.TestCase):
|
|||
|
||||
def _get_create_trigger_request_body(self, param={}):
|
||||
return {"trigger_info": param}
|
||||
|
||||
def _create_scheduled_operation(self, trigger_id):
|
||||
operation_info = {
|
||||
"name": "123",
|
||||
"operation_type": "protect",
|
||||
"project_id": "123",
|
||||
"trigger_id": trigger_id,
|
||||
"operation_definition": {
|
||||
"plan_id": ""
|
||||
},
|
||||
}
|
||||
operation = objects.ScheduledOperation(self.ctxt, **operation_info)
|
||||
operation.create()
|
||||
return operation
|
||||
|
|
|
@ -11,5 +11,10 @@
|
|||
"trigger:create": "",
|
||||
"trigger:delete": "rule:admin_or_owner",
|
||||
"trigger:get": "rule:admin_or_owner",
|
||||
"trigger:list": ""
|
||||
"trigger:list": "",
|
||||
|
||||
"scheduled_operation:create": "",
|
||||
"scheduled_operation:delete": "rule:admin_or_owner",
|
||||
"scheduled_operation:get": "rule:admin_or_owner",
|
||||
"scheduled_operation:list": ""
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue