diff options
-rw-r--r-- | heatclient/common/event_utils.py | 7 | ||||
-rw-r--r-- | heatclient/osc/v1/event.py | 33 | ||||
-rw-r--r-- | heatclient/tests/unit/osc/v1/test_event.py | 26 |
3 files changed, 63 insertions, 3 deletions
diff --git a/heatclient/common/event_utils.py b/heatclient/common/event_utils.py index 3e6b197..1b8b179 100644 --- a/heatclient/common/event_utils.py +++ b/heatclient/common/event_utils.py @@ -75,8 +75,11 @@ def get_events(hc, stack_id, event_args, nested_depth=0, # Slice the list if marker is specified if marker: - marker_index = [e.id for e in events].index(marker) - events = events[marker_index:] + try: + marker_index = [e.id for e in events].index(marker) + events = events[marker_index:] + except ValueError: + pass # Slice the list if limit is specified if limit: diff --git a/heatclient/osc/v1/event.py b/heatclient/osc/v1/event.py index 664b56c..feee81d 100644 --- a/heatclient/osc/v1/event.py +++ b/heatclient/osc/v1/event.py @@ -13,6 +13,7 @@ # Copyright 2015 IBM Corp. import logging +import time from cliff import lister from cliff import show @@ -134,6 +135,11 @@ class ListEvent(lister.Lister): '(default: asc). Specify multiple times to sort on ' 'multiple keys') ) + parser.add_argument( + '--follow', + action='store_true', + help=_('Print events until process is halted') + ) return parser def take_action(self, parsed_args): @@ -149,6 +155,7 @@ class ListEvent(lister.Lister): 'limit': parsed_args.limit, 'marker': parsed_args.marker, 'filters': heat_utils.format_parameters(parsed_args.filter), + 'sort_dir': 'asc' } if parsed_args.resource and parsed_args.nested_depth: @@ -165,6 +172,31 @@ class ListEvent(lister.Lister): else: nested_depth = 0 + if parsed_args.follow: + if parsed_args.formatter != 'value': + msg = _('--follow can only be specified with --format value') + raise exc.CommandError(msg) + + marker = parsed_args.marker + try: + while True: + kwargs['marker'] = marker + events = event_utils.get_events( + client, + stack_id=parsed_args.stack, + event_args=kwargs, + nested_depth=nested_depth, + marker=marker) + if events: + marker = getattr(events[-1], 'id', None) + events_log = heat_utils.event_log_formatter(events) + self.app.stdout.write(events_log) + self.app.stdout.write('\n') + time.sleep(5) + # this loop never exits + except (KeyboardInterrupt, EOFError): # ctrl-c, ctrl-d + return [], [] + events = event_utils.get_events( client, stack_id=parsed_args.stack, event_args=kwargs, nested_depth=nested_depth, marker=parsed_args.marker, @@ -175,7 +207,6 @@ class ListEvent(lister.Lister): if parsed_args.formatter == 'value': events = heat_utils.event_log_formatter(events).split('\n') - events.reverse() return [], [e.split(' ') for e in events] if len(events): diff --git a/heatclient/tests/unit/osc/v1/test_event.py b/heatclient/tests/unit/osc/v1/test_event.py index c18457a..668a62e 100644 --- a/heatclient/tests/unit/osc/v1/test_event.py +++ b/heatclient/tests/unit/osc/v1/test_event.py @@ -111,6 +111,7 @@ class TestEventList(TestEvent): 'limit': None, 'marker': None, 'filters': {}, + 'sort_dir': 'asc' } fields = ['resource_name', 'id', 'resource_status', @@ -199,6 +200,31 @@ class TestEventList(TestEvent): self.event_client.list.assert_called_with(**self.defaults) self.assertEqual(self.fields, columns) + @mock.patch('time.sleep') + def test_event_list_follow(self, sleep): + sleep.side_effect = [None, KeyboardInterrupt()] + arglist = ['--follow', 'my_stack'] + expected = ( + '2015-11-13 10:02:17 [resource1]: ' + 'CREATE_COMPLETE state changed\n' + '2015-11-13 10:02:17 [resource1]: ' + 'CREATE_COMPLETE state changed\n' + ) + parsed_args = self.check_parser(self.cmd, arglist, []) + + columns, data = self.cmd.take_action(parsed_args) + + defaults_with_marker = dict(self.defaults) + defaults_with_marker['marker'] = '1234' + + self.event_client.list.assert_has_calls([ + mock.call(**self.defaults), + mock.call(**defaults_with_marker) + ]) + self.assertEqual([], columns) + self.assertEqual([], data) + self.assertEqual(expected, self.fake_stdout.make_string()) + def test_event_list_value_format(self): arglist = ['my_stack'] expected = ('2015-11-13 10:02:17 [resource1]: CREATE_COMPLETE ' |