Implement events pagination, sorting and filtering
It supports pagination for events-list. Implements blueprint events-pagination-heatclient Change-Id: I11ca89b0a203435ba3793d061d7d06cb458d61eb
This commit is contained in:
parent
a98c1f3617
commit
6eb45625e5
|
@ -65,6 +65,29 @@ class EventManagerTest(testtools.TestCase):
|
|||
manager._list.assert_called_once_with('/stacks/teststack/'
|
||||
'events', "events")
|
||||
|
||||
def test_list_event_with_kwargs(self):
|
||||
stack_id = 'teststack',
|
||||
resource_name = 'testresource'
|
||||
kwargs = {'limit': 2,
|
||||
'marker': '6d6935f4-0ae5',
|
||||
'filters': {
|
||||
'resource_action': 'CREATE',
|
||||
'resource_status': 'COMPLETE'
|
||||
}}
|
||||
manager = EventManager(None)
|
||||
self.m.StubOutWithMock(manager, '_resolve_stack_id')
|
||||
manager._resolve_stack_id(stack_id).AndReturn('teststack/abcd1234')
|
||||
self.m.ReplayAll()
|
||||
manager._list = MagicMock()
|
||||
manager.list(stack_id, resource_name, **kwargs)
|
||||
# Make sure url is correct.
|
||||
manager._list.assert_called_once_with('/stacks/teststack%2Fabcd1234/'
|
||||
'resources/testresource/events'
|
||||
'?marker=6d6935f4-0ae5&limit=2'
|
||||
'&resource_action=CREATE&'
|
||||
'resource_status=COMPLETE',
|
||||
"events")
|
||||
|
||||
def test_get_event(self):
|
||||
fields = {'stack_id': 'teststack',
|
||||
'resource_name': 'testresource',
|
||||
|
|
|
@ -1258,6 +1258,60 @@ class ShellTestEvents(ShellBase):
|
|||
for r in required:
|
||||
self.assertRegexpMatches(event_list_text, r)
|
||||
|
||||
@httpretty.activate
|
||||
def test_event_list_pagination(self):
|
||||
self.register_keystone_auth_fixture()
|
||||
# test for pagination
|
||||
resp_dict = {"events": [
|
||||
{"event_time": "2013-12-05T14:14:30Z",
|
||||
"id": self.event_id_one,
|
||||
"links": [{"href": "http://heat.example.com:8004/foo",
|
||||
"rel": "self"},
|
||||
{"href": "http://heat.example.com:8004/foo2",
|
||||
"rel": "resource"},
|
||||
{"href": "http://heat.example.com:8004/foo3",
|
||||
"rel": "stack"}],
|
||||
"logical_resource_id": "aResource",
|
||||
"physical_resource_id": None,
|
||||
"resource_name": "aResource",
|
||||
"resource_status": "CREATE_IN_PROGRESS",
|
||||
"resource_status_reason": "state changed"}]
|
||||
}
|
||||
params = {'limit': 1,
|
||||
'resource_action': 'CREATE',
|
||||
'resource_status': 'IN_PROGRESS'}
|
||||
resp = fakes.FakeHTTPResponse(
|
||||
200,
|
||||
'OK',
|
||||
{'content-type': 'application/json'},
|
||||
jsonutils.dumps(resp_dict))
|
||||
stack_id = 'teststack/1'
|
||||
url = '/stacks/%s/events' % stack_id
|
||||
url += '?%s' % parse.urlencode(params, True)
|
||||
http.HTTPClient.json_request('GET', url).AndReturn((resp, resp_dict))
|
||||
self.m.ReplayAll()
|
||||
|
||||
event_list_text = self.shell('event-list {0} -l 1 '
|
||||
'-f resource_status=IN_PROGRESS '
|
||||
'-f resource_action=CREATE'.format(
|
||||
stack_id))
|
||||
|
||||
required = [
|
||||
'resource_name',
|
||||
'id',
|
||||
'resource_status_reason',
|
||||
'resource_status',
|
||||
'event_time',
|
||||
'aResource',
|
||||
self.event_id_one,
|
||||
'state changed',
|
||||
'CREATE_IN_PROGRESS',
|
||||
'2013-12-05T14:14:30Z',
|
||||
]
|
||||
|
||||
for r in required:
|
||||
self.assertRegexpMatches(event_list_text, r)
|
||||
|
||||
@httpretty.activate
|
||||
def test_event_show(self):
|
||||
self.register_keystone_auth_fixture()
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import six
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from heatclient.openstack.common.apiclient import base
|
||||
|
@ -39,20 +40,32 @@ class Event(base.Resource):
|
|||
class EventManager(stacks.StackChildManager):
|
||||
resource_class = Event
|
||||
|
||||
def list(self, stack_id, resource_name=None):
|
||||
def list(self, stack_id, resource_name=None, **kwargs):
|
||||
"""Get a list of events.
|
||||
:param stack_id: ID of stack the events belong to
|
||||
:param resource_name: Optional name of resources to filter events by
|
||||
:rtype: list of :class:`Event`
|
||||
"""
|
||||
params = {}
|
||||
if 'filters' in kwargs:
|
||||
filters = kwargs.pop('filters')
|
||||
params.update(filters)
|
||||
|
||||
for key, value in six.iteritems(kwargs):
|
||||
if value:
|
||||
params[key] = value
|
||||
|
||||
if resource_name is None:
|
||||
url = '/stacks/%s/events' % stack_id
|
||||
else:
|
||||
stack_id = self._resolve_stack_id(stack_id)
|
||||
url = '/stacks/%s/resources/%s/events' % (
|
||||
parse.quote(stack_id, ''),
|
||||
parse.quote(strutils.safe_encode(resource_name), ''))
|
||||
return self._list(url, "events")
|
||||
parse.quote(stack_id, ''),
|
||||
parse.quote(strutils.safe_encode(resource_name), ''))
|
||||
if params:
|
||||
url += '?%s' % parse.urlencode(params, True)
|
||||
|
||||
return self._list(url, 'events')
|
||||
|
||||
def get(self, stack_id, resource_name, event_id):
|
||||
"""Get the details for a specific event.
|
||||
|
|
|
@ -698,10 +698,22 @@ def do_resource_signal(hc, args):
|
|||
help='Name or ID of stack to show the events for.')
|
||||
@utils.arg('-r', '--resource', metavar='<RESOURCE>',
|
||||
help='Name of the resource to filter events by.')
|
||||
@utils.arg('-f', '--filters', metavar='<KEY1=VALUE1;KEY2=VALUE2...>',
|
||||
help='Filter parameters to apply on returned events. '
|
||||
'This can be specified multiple times, or once with parameters '
|
||||
'separated by a semicolon.',
|
||||
action='append')
|
||||
@utils.arg('-l', '--limit', metavar='<LIMIT>',
|
||||
help='Limit the number of events returned.')
|
||||
@utils.arg('-m', '--marker', metavar='<ID>',
|
||||
help='Only return events that appear after the given event ID.')
|
||||
def do_event_list(hc, args):
|
||||
'''List events for a stack.'''
|
||||
fields = {'stack_id': args.id,
|
||||
'resource_name': args.resource}
|
||||
'resource_name': args.resource,
|
||||
'limit': args.limit,
|
||||
'marker': args.marker,
|
||||
'filters': utils.format_parameters(args.filters)}
|
||||
try:
|
||||
events = hc.events.list(**fields)
|
||||
except exc.HTTPNotFound as ex:
|
||||
|
|
Loading…
Reference in New Issue