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:
huangtianhua 2014-07-07 17:24:26 +08:00
parent a98c1f3617
commit 6eb45625e5
4 changed files with 107 additions and 5 deletions

View File

@ -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',

View File

@ -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()

View File

@ -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.

View File

@ -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: