Coverage for lib/ansible/plugins/callback/dense.py : 28%
 
         
         
    Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
| # (c) 2016, Dag Wieers <dag@wieers.com> # (c) 2017 Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 
 
 callback: dense type: stdout short_description: minimal stdout output extends_documentation_fragment: - default_callback description: - When in verbose mode it will act the same as the default callback version_added: "2.3" requirements: - set as stdout in configuation ''' 
 
 except ImportError: pass 
 
 except ImportError: from ansible.utils.display import Display display = Display() 
 
 # Design goals: # # + On screen there should only be relevant stuff # - How far are we ? (during run, last line) # - What issues occurred # - What changes occurred # - Diff output (in diff-mode) # # + If verbosity increases, act as default output # So that users can easily switch to default for troubleshooting # # + Rewrite the output during processing # - We use the cursor to indicate where in the task we are. # Output after the prompt is the output of the previous task. # - If we would clear the line at the start of a task, there would often # be no information at all, so we leave it until it gets updated # # + Use the same color-conventions of Ansible # # + Ensure the verbose output (-v) is also dense. # Remove information that is not essential (eg. timestamps, status) 
 
 # TODO: # # + Properly test for terminal capabilities, and fall back to default # + Modify Ansible mechanism so we don't need to use sys.stdout directly # + Find an elegant solution for progress bar line wrapping 
 
 # FIXME: Importing constants as C simply does not work, beats me :-/ # from ansible import constants as C 
 
 # Taken from Dstat 
 
 
 
 # clearline = '\033[K' 
 
 
 ok=vt100.darkgreen, changed=vt100.darkyellow, skipped=vt100.darkcyan, ignored=vt100.cyanbg + vt100.red, failed=vt100.darkred, unreachable=vt100.red, ) 
 
 
 
 ''' This is the dense callback interface, where screen estate is still valued. ''' 
 
 
 # From CallbackModule self._display = display 
 if HAS_OD: 
 self.disabled = False self.super_ref = super(CallbackModule, self) self.super_ref.__init__() 
 # Attributes to remove from results for more density self.removed_attributes = ( # 'changed', 'delta', # 'diff', 'end', 'failed', 'failed_when_result', 'invocation', 'start', 'stdout_lines', ) 
 # Initiate data structures self.hosts = OrderedDict() self.keep = False self.shown_title = False self.count = dict(play=0, handler=0, task=0) self.type = 'foo' 
 # Start immediately on the first line sys.stdout.write(vt100.reset + vt100.save + vt100.clearline) sys.stdout.flush() else: display.warning("The 'dense' callback plugin requires OrderedDict which is not available in this version of python, disabling.") self.disabled = True 
 sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline) 
 name = result._host.get_name() 
 # Add a new status in case a failed task is ignored if status == 'failed' and result._task.ignore_errors: status = 'ignored' 
 # Check if we have to update an existing state (when looping over items) if name not in self.hosts: self.hosts[name] = dict(state=status) elif states.index(self.hosts[name]['state']) < states.index(status): self.hosts[name]['state'] = status 
 # Store delegated hostname, if needed delegated_vars = result._result.get('_ansible_delegated_vars', None) if delegated_vars: self.hosts[name]['delegate'] = delegated_vars['ansible_host'] 
 # Print progress bar self._display_progress(result) 
 # # Ensure that tasks with changes/failures stay on-screen, and during diff-mode # if status in ['changed', 'failed', 'unreachable'] or (result.get('_diff_mode', False) and result._resultget('diff', False)): # Ensure that tasks with changes/failures stay on-screen if status in ['changed', 'failed', 'unreachable']: self.keep = True 
 if self._display.verbosity == 1: # Print task title, if needed self._display_task_banner() self._display_results(result, status) 
 # Remove non-essential atributes for attr in self.removed_attributes: if attr in result: del(result[attr]) 
 # Remove empty attributes (list, dict, str) for attr in result.copy(): if isinstance(result[attr], (MutableSequence, MutableMapping, binary_type, text_type)): if not result[attr]: del(result[attr]) 
 if 'exception' in result: # Remove the exception from the result so it's not shown every time del result['exception'] 
 if self._display.verbosity == 1: return "An exception occurred during task execution. To see the full traceback, use -vvv." 
 # Always rewrite the complete line sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline + vt100.nolinewrap + vt100.underline) sys.stdout.write('%s %d:' % (self.type, self.count[self.type])) sys.stdout.write(vt100.reset) sys.stdout.flush() 
 # Print out each host in its own status-color for name in self.hosts: sys.stdout.write(' ') if self.hosts[name].get('delegate', None): sys.stdout.write(self.hosts[name]['delegate'] + '>') sys.stdout.write(colors[self.hosts[name]['state']] + name + vt100.reset) sys.stdout.flush() 
 # if result._result.get('diff', False): # sys.stdout.write('\n' + vt100.linewrap) sys.stdout.write(vt100.linewrap) 
 # self.keep = True 
 if not self.shown_title: self.shown_title = True sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline + vt100.underline) sys.stdout.write('%s %d: %s' % (self.type, self.count[self.type], self.task.get_name().strip())) sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline) sys.stdout.flush() else: sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline) self.keep = False 
 # Leave the previous task on screen (as it has changes/errors) if self._display.verbosity == 0 and self.keep: sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline) else: sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline) self.keep = False 
 self._clean_results(result._result) 
 dump = '' if result._task.action == 'include': return elif status == 'ok': return elif status == 'ignored': dump = self._handle_exceptions(result._result) elif status == 'failed': dump = self._handle_exceptions(result._result) elif status == 'unreachable': dump = result._result['msg'] 
 if not dump: dump = self._dump_results(result._result) 
 if result._task.loop and 'results' in result._result: self._process_items(result) else: sys.stdout.write(colors[status] + status + ': ') 
 delegated_vars = result._result.get('_ansible_delegated_vars', None) if delegated_vars: sys.stdout.write(vt100.reset + result._host.get_name() + '>' + colors[status] + delegated_vars['ansible_host']) else: sys.stdout.write(result._host.get_name()) 
 sys.stdout.write(': ' + dump + '\n') sys.stdout.write(vt100.reset + vt100.save + vt100.clearline) sys.stdout.flush() 
 if status == 'changed': self._handle_warnings(result._result) 
 # Leave the previous task on screen (as it has changes/errors) if self._display.verbosity == 0 and self.keep: sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline + vt100.bold) else: sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline + vt100.bold) 
 # Reset at the start of each play self.keep = False self.count.update(dict(handler=0, task=0)) self.count['play'] += 1 self.play = play 
 # Write the next play on screen IN UPPERCASE, and make it permanent name = play.get_name().strip() if not name: name = 'unnamed' sys.stdout.write('PLAY %d: %s' % (self.count['play'], name.upper())) sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline) sys.stdout.flush() 
 # Leave the previous task on screen (as it has changes/errors) if self._display.verbosity == 0 and self.keep: sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline + vt100.underline) else: # Do not clear line, since we want to retain the previous output sys.stdout.write(vt100.restore + vt100.reset + vt100.underline) 
 # Reset at the start of each task self.keep = False self.shown_title = False self.hosts = OrderedDict() self.task = task self.type = 'task' 
 # Enumerate task if not setup (task names are too long for dense output) if task.get_name() != 'setup': self.count['task'] += 1 
 # Write the next task on screen (behind the prompt is the previous output) sys.stdout.write('%s %d.' % (self.type, self.count[self.type])) sys.stdout.write(vt100.reset) sys.stdout.flush() 
 # Leave the previous task on screen (as it has changes/errors) if self._display.verbosity == 0 and self.keep: sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline + vt100.underline) else: sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline + vt100.underline) 
 # Reset at the start of each handler self.keep = False self.shown_title = False self.hosts = OrderedDict() self.task = task self.type = 'handler' 
 # Enumerate handler if not setup (handler names may be too long for dense output) if task.get_name() != 'setup': self.count[self.type] += 1 
 # Write the next task on screen (behind the prompt is the previous output) sys.stdout.write('%s %d.' % (self.type, self.count[self.type])) sys.stdout.write(vt100.reset) sys.stdout.flush() 
 # TBD sys.stdout.write('cleanup.') sys.stdout.flush() 
 self._add_host(result, 'failed') 
 if result._result.get('changed', False): self._add_host(result, 'changed') else: self._add_host(result, 'ok') 
 self._add_host(result, 'skipped') 
 self._add_host(result, 'unreachable') 
 pass 
 sys.stdout.write(vt100.bold) self.super_ref.v2_runner_on_file_diff(result, diff) sys.stdout.write(vt100.reset) 
 sys.stdout.write(vt100.bold) self.super_ref.v2_on_file_diff(result) sys.stdout.write(vt100.reset) 
 # Old definition in v2.0 self.v2_runner_item_on_ok(result) 
 if result._result.get('changed', False): self._add_host(result, 'changed') else: self._add_host(result, 'ok') 
 # Old definition in v2.0 self.v2_runner_item_on_failed(result) 
 self._add_host(result, 'failed') 
 # Old definition in v2.0 self.v2_runner_item_on_skipped(result) 
 self._add_host(result, 'skipped') 
 if self._display.verbosity == 0 and self.keep: sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline) else: sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline) self.keep = False 
 sys.stdout.write(vt100.white + vt100.redbg + 'NO MORE HOSTS LEFT') sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline) sys.stdout.flush() 
 pass 
 if self._display.verbosity == 0 and self.keep: sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline) else: sys.stdout.write(vt100.restore + vt100.reset + vt100.clearline) 
 # In normal mode screen output should be sufficient, summary is redundant if self._display.verbosity == 0: return 
 sys.stdout.write(vt100.bold + vt100.underline) sys.stdout.write('SUMMARY') 
 sys.stdout.write(vt100.restore + vt100.reset + '\n' + vt100.save + vt100.clearline) sys.stdout.flush() 
 hosts = sorted(stats.processed.keys()) for h in hosts: t = stats.summarize(h) self._display.display(u"%s : %s %s %s %s" % ( hostcolor(h, t), colorize(u'ok', t['ok'], C.COLOR_OK), colorize(u'changed', t['changed'], C.COLOR_CHANGED), colorize(u'unreachable', t['unreachable'], C.COLOR_UNREACHABLE), colorize(u'failed', t['failures'], C.COLOR_ERROR)), screen_only=True ) 
 # When using -vv or higher, simply do the default action else: CallbackModule = CallbackModule_dense |