diff --git a/src/azure-cli-core/azure/cli/core/__init__.py b/src/azure-cli-core/azure/cli/core/__init__.py index c2b62d8b81d..54b3809a318 100644 --- a/src/azure-cli-core/azure/cli/core/__init__.py +++ b/src/azure-cli-core/azure/cli/core/__init__.py @@ -115,12 +115,12 @@ def refresh_request_id(self): import uuid self.data['headers']['x-ms-client-request-id'] = str(uuid.uuid1()) - def get_progress_controller(self, det=False): + def get_progress_controller(self, det=False, spinner=None): import azure.cli.core.commands.progress as progress if not self.progress_controller: self.progress_controller = progress.ProgressHook() - self.progress_controller.init_progress(progress.get_progress_view(det)) + self.progress_controller.init_progress(progress.get_progress_view(det, spinner=spinner)) return self.progress_controller def get_cli_version(self): diff --git a/src/azure-cli-core/azure/cli/core/commands/__init__.py b/src/azure-cli-core/azure/cli/core/commands/__init__.py index 087557cf1c1..aa02fd83f74 100644 --- a/src/azure-cli-core/azure/cli/core/commands/__init__.py +++ b/src/azure-cli-core/azure/cli/core/commands/__init__.py @@ -30,7 +30,7 @@ get_command_type_kwarg, read_file_content, get_arg_list, poller_classes) from azure.cli.core.local_context import LocalContextAction import azure.cli.core.telemetry as telemetry - +from azure.cli.core.commands.progress import IndeterminateProgressBar from knack.arguments import CLICommandArgument from knack.commands import CLICommand, CommandGroup, PREVIEW_EXPERIMENTAL_CONFLICT_ERROR @@ -869,7 +869,8 @@ def _validate_arg_level(self, ns, **_): # pylint: disable=no-self-use class LongRunningOperation: # pylint: disable=too-few-public-methods - def __init__(self, cli_ctx, start_msg='', finish_msg='', poller_done_interval_ms=1000.0): + def __init__(self, cli_ctx, start_msg='', finish_msg='', poller_done_interval_ms=500.0, + progress_bar=None): self.cli_ctx = cli_ctx self.start_msg = start_msg @@ -877,6 +878,7 @@ def __init__(self, cli_ctx, start_msg='', finish_msg='', poller_done_interval_ms self.poller_done_interval_ms = poller_done_interval_ms self.deploy_dict = {} self.last_progress_report = datetime.datetime.now() + self.progress_bar = progress_bar if progress_bar is not None else IndeterminateProgressBar(cli_ctx) def _delay(self): time.sleep(self.poller_done_interval_ms / 1000.0) @@ -948,16 +950,17 @@ def __call__(self, poller): from msrest.exceptions import ClientException correlation_message = '' - self.cli_ctx.get_progress_controller().begin() + self.progress_bar.begin() correlation_id = None cli_logger = get_logger() # get CLI logger which has the level set through command lines is_verbose = any(handler.level <= logs.INFO for handler in cli_logger.handlers) + telemetry.poll_start() poll_flag = False while not poller.done(): poll_flag = True - self.cli_ctx.get_progress_controller().add(message='Running') + try: # pylint: disable=protected-access correlation_id = json.loads( @@ -975,9 +978,10 @@ def __call__(self, poller): except Exception as ex: # pylint: disable=broad-except logger.warning('%s during progress reporting: %s', getattr(type(ex), '__name__', type(ex)), ex) try: + self.progress_bar.update_progress() self._delay() except KeyboardInterrupt: - self.cli_ctx.get_progress_controller().stop() + self.progress_bar.stop() logger.error('Long-running operation wait cancelled. %s', correlation_message) raise @@ -985,12 +989,13 @@ def __call__(self, poller): result = poller.result() except ClientException as client_exception: from azure.cli.core.commands.arm import handle_long_running_operation_exception - self.cli_ctx.get_progress_controller().stop() + self.progress_bar.stop() handle_long_running_operation_exception(client_exception) - self.cli_ctx.get_progress_controller().end() + self.progress_bar.end() if poll_flag: telemetry.poll_end() + return result diff --git a/src/azure-cli-core/azure/cli/core/commands/progress.py b/src/azure-cli-core/azure/cli/core/commands/progress.py index 20c70c733b9..94bab249a6d 100644 --- a/src/azure-cli-core/azure/cli/core/commands/progress.py +++ b/src/azure-cli-core/azure/cli/core/commands/progress.py @@ -103,10 +103,10 @@ def is_running(self): class IndeterminateStandardOut(ProgressViewBase): """ custom output for progress reporting """ - def __init__(self, out=None): + def __init__(self, out=None, spinner=None): super(IndeterminateStandardOut, self).__init__( out if out else sys.stderr) - self.spinner = None + self.spinner = spinner def write(self, args): """ @@ -166,8 +166,33 @@ def flush(self): self.out.flush() -def get_progress_view(determinant=False, outstream=sys.stderr): +def get_progress_view(determinant=False, outstream=sys.stderr, spinner=None): """ gets your view """ if determinant: return DeterminateStandardOut(out=outstream) - return IndeterminateStandardOut(out=outstream) + return IndeterminateStandardOut(out=outstream, spinner=spinner) + + +class IndeterminateProgressBar: + """ Define progress bar update view """ + def __init__(self, cli_ctx, message="Running"): + self.cli_ctx = cli_ctx + self.message = message + self.hook = self.cli_ctx.get_progress_controller( + det=False, + spinner=humanfriendly.Spinner( # pylint: disable=no-member + label='Running', + stream=sys.stderr, + hide_cursor=False)) + + def begin(self): + self.hook.begin() + + def stop(self): + self.hook.stop() + + def update_progress(self): + self.hook.add(message=self.message) + + def end(self): + self.hook.end() diff --git a/src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource_custom.py b/src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource_custom.py index e6eae1d0ae5..43178834752 100644 --- a/src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource_custom.py +++ b/src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource_custom.py @@ -412,7 +412,7 @@ def test_what_if_exclude_change_types(self, long_running_operation_stub): ]) # Act. - result = _what_if_deploy_arm_template_core(cmd, mock.MagicMock(), True, ["create", "igNoRE"]) + result = _what_if_deploy_arm_template_core(cmd.cli_ctx, mock.MagicMock(), True, ["create", "igNoRE"]) # Assert. self.assertEqual(1, len(result.changes))