Skip to content

Commit

Permalink
CLI/clustershell: allow to disable progress bars
Browse files Browse the repository at this point in the history
* Expose in the clustershell module the possibility to disable the show
  of the progress bars during execution.
* Allow to disable the progress bars also in the CLI with a
  --no-progress flag.

Bug: T212783
Change-Id: Id745f0c86c82f909546f4654715566ae5afa19d5
  • Loading branch information
volans- committed Apr 27, 2021
1 parent 1fcb359 commit d7e90c7
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 1 deletion.
2 changes: 2 additions & 0 deletions cumin/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ def get_parser():
parser.add_argument('--dry-run', action='store_true',
help=('Do not execute any command, just return the list of matching hosts and exit. '
'[default: False]'))
parser.add_argument('--no-progress', action='store_true', help='Do not show the progress bars during execution.')
parser.add_argument('--version', action='version', version='%(prog)s {version}'.format(version=cumin.__version__))
parser.add_argument('-d', '--debug', action='store_true',
help=('Set log level to DEBUG. See also log_file in the configuration. [default: False]'))
Expand Down Expand Up @@ -401,6 +402,7 @@ def run(args, config):
for command in args.commands]
worker.timeout = args.global_timeout
worker.handler = args.mode
worker.progress_bars = not args.no_progress
if args.output is not None: # TODO: set the reporter to tqdm when releasing v5.0.0
worker.reporter = TqdmQuietReporter
worker.success_threshold = args.success_percentage / 100
Expand Down
11 changes: 11 additions & 0 deletions cumin/tests/unit/transports/test_clustershell.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,17 @@ class InvalidReporter:
with pytest.raises(WorkerError, match='reporter must be a subclass of'):
self.worker.reporter = InvalidReporter

def test_progress_bars_getter(self):
"""Access to the progress_bars getter should return the current value."""
assert self.worker.progress_bars # Current default
self.worker.progress_bars = False
assert not self.worker.progress_bars

def test_progress_bars_setter_invalid(self):
"""Raise WorkerError if trying to set the progress_bars to an invalid value."""
with pytest.raises(WorkerError, match='progress_bars must be a boolean'):
self.worker.progress_bars = 'invalid'

@staticmethod
def iter_buffers():
"""A generator to simulate the buffer iteration of ClusterShell objects."""
Expand Down
17 changes: 16 additions & 1 deletion cumin/transports/clustershell.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(self, config: dict, target: Target) -> None:
self.task = Task.task_self() # Initialize a ClusterShell task
self._handler_instance: Optional[Event.EventHandler] = None
self._reporter: Type[BaseReporter] = TqdmReporter # TODO: change this to NullReporter when releasing v5.0.0
self._progress_bars: bool = True # TODO: change this to False when releasing v5.0.0

# Set any ClusterShell task options
for key, value in config.get('clustershell', {}).items():
Expand All @@ -70,7 +71,8 @@ def execute(self) -> int:
# Schedule only the first command for the first batch, the following ones must be handled by the EventHandler
reporter = self._reporter() # Instantiate a new Reporter at each execution
self._handler_instance = self.handler( # pylint: disable=not-callable
self.target, self.commands, reporter=reporter, success_threshold=self.success_threshold)
self.target, self.commands, reporter=reporter, success_threshold=self.success_threshold,
progress_bars=self._progress_bars)

self.logger.info(
"Executing commands %s on '%d' hosts: %s", self.commands, len(self.target.hosts), self.target.hosts)
Expand Down Expand Up @@ -151,6 +153,19 @@ def reporter(self, value: Type['BaseReporter']) -> None:

self._reporter = value

@property
def progress_bars(self) -> bool:
"""Getter for the boolean progress_bars property."""
return self._progress_bars

@progress_bars.setter
def progress_bars(self, value: bool) -> None:
"""Setter for the `progress_bars` property. The relative documentation is in the getter."""
if not isinstance(value, bool):
raise_error('progress_bars', 'must be a boolean', value)

self._progress_bars = value


class Node:
"""Node class to represent each target node.
Expand Down
2 changes: 2 additions & 0 deletions doc/source/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ More complex example fine-tuning many of the parameters::
# Change the worker's default reporter from the current default that outputs to stdout all commands stdout/err
# outputs to the empty reporter that does nothing.
worker.reporter = NullReporter
# Suppress the progress bars during execution
worker.progress_bars = False
exit_code = worker.execute()
for nodes, output in worker.get_results():
print(nodes)
Expand Down

0 comments on commit d7e90c7

Please sign in to comment.