def get_diff_commands(running, intent, dev_os): ''' Args: running: list of device running commands intent: list of device intent commands style: device CLI command style, example, set-style Return: a diff of running and intent config ''' style = { 'cumulus': 'net', 'vyos': 'set' } _diff = difflib.unified_diff( sorted(running), sorted(intent), fromfile='running', tofile='intent', lineterm="") diff = [] for item in _diff: if item.startswith('+%s' % style[dev_os]): diff.append(stringc(item, 'green')) elif item.startswith('-%s' % style[dev_os]): diff.append(stringc(item, 'red')) elif item.startswith(' '): diff.append(stringc(item, 'normal')) else: diff.append(stringc(item, 'blue')) return diff
def get_credentials(self): display.display(u'\n\n' + "We need your " + stringc("Github login", 'bright cyan') + " to identify you.", screen_only=True) display.display("This information will " + stringc("not be sent to Galaxy", 'bright cyan') + ", only to " + stringc("api.github.com.", "yellow"), screen_only=True) display.display("The password will not be displayed." + u'\n\n', screen_only=True) display.display("Use " + stringc("--github-token", 'yellow') + " if you do not want to enter your password." + u'\n\n', screen_only=True) try: self.github_username = raw_input("Github Username: "******"Password for %s: " % self.github_username) except: pass if not self.github_username or not self.github_password: raise AnsibleError( "Invalid Github credentials. Username and password are required." )
def _display_debug_msg(self, task, result): #if (self._display.verbosity > 0 or '_ansible_verbose_always' in result) and '_ansible_verbose_override' not in result: if task.args.get('msg'): color = C.COLOR_OK msg = result.get('msg', '') if task.args.get('var'): var_key = task.args.get('var') if isinstance(var_key, (list, dict)): var_key = to_text(type(var_key)) var_obj = result.get(var_key) self.LogArgs(vt100.bold, "var=%s" % to_text(task.args.get('var')), ", ", stringc(to_text(type(var_obj)), C.COLOR_DEBUG), vt100.reset, "\n") if isinstance(var_obj, (unicode, str, bytes)): color = C.COLOR_OK if 'IS NOT DEFINED' in var_obj: color = C.COLOR_ERROR msg = var_obj else: color = C.COLOR_OK msg = json.dumps(var_obj, indent=4) self.LogArgs(stringc(msg, color), "\n")
def pretty_coverage_runs(runs): ended = [] in_progress = [] for run in runs: if run.get('finishedDate'): ended.append(run) else: in_progress.append(run) for run in sorted(ended, key=lambda x: x['finishedDate']): if run['result'] == "succeeded": print( '🙂 [%s] https://dev.azure.com/ansible/ansible/_build/results?buildId=%s (%s)' % (stringc('PASS', 'green'), run['id'], run['finishedDate'])) else: print( '😢 [%s] https://dev.azure.com/ansible/ansible/_build/results?buildId=%s (%s)' % (stringc('FAIL', 'red'), run['id'], run['finishedDate'])) if in_progress: print('The following runs are ongoing:') for run in in_progress: print( '🤔 [%s] https://dev.azure.com/ansible/ansible/_build/results?buildId=%s' % (stringc('FATE', 'yellow'), run['id']))
def v2_runner_on_failed(self, result, ignore_errors=False): delegated_vars = result._result.get('_ansible_delegated_vars', None) self._clean_results(result._result, result._task.action) if self._last_task_banner != result._task._uuid: self._print_task_banner(result._task) msg = "%s %s" % (stringc(self.cross, C.COLOR_ERROR), result._host) if delegated_vars: self._display.display("%s -> %s" % (msg, delegated_vars['ansible_host'])) else: self._display.display(msg) self._display.display( self.padd_text( stringc(u"\n%s [failed]:" % (self.rightArrow), C.COLOR_ERROR), 2)) self._display.display( self.padd_text( self.rightArrow + " %s" % self._dump_results(result._result, indent=4), 2), C.COLOR_ERROR) self._handle_exception(result._result) self._handle_warnings(result._result) if ignore_errors: self._display.display("...ignoring", color=C.COLOR_SKIP) else: self._display.display("")
def pretty_coverage_runs(runs): ended = [] in_progress = [] for run in runs: if run.get('endedAt'): ended.append(run) else: in_progress.append(run) for run in sorted(ended, key=lambda x: x['endedAt']): if run['statusCode'] == 30: print('🙂 [%s] https://app.shippable.com/github/ansible/ansible/runs/%s (%s)' % ( stringc('PASS', 'green'), run['runNumber'], run['endedAt'])) else: print('😢 [%s] https://app.shippable.com/github/ansible/ansible/runs/%s (%s)' % ( stringc('FAIL', 'red'), run['runNumber'], run['endedAt'])) if in_progress: print('The following runs are ongoing:') for run in in_progress: print('🤔 [%s] https://app.shippable.com/github/ansible/ansible/runs/%s' % ( stringc('FATE', 'yellow'), run['runNumber']))
def _display_msg(self, task, result, color): if task.action in self.SQUASH_LOOP_MODULES and 'results' in result: if len(result['results']) > 0: return self._display_msg(task, result['results'][0], color) # prevent dublication of stdout in case of live_stdout if not self._live_stdout_listener.is_live_stdout(): stdout = result.get('stdout', None) if stdout: self.LogArgs(vt100.bold, "stdout:", vt100.reset, "\n") self.LogArgs(self._indent(' ', stdout), "\n") stderr = result.get('stderr', '') if stderr: self.LogArgs(vt100.bold, "stderr:", vt100.reset, "\n") self.LogArgs( self._indent(' ', stringc(stderr, C.COLOR_ERROR)), "\n") if self._msg_is_needed(task, result): self.LogArgs(stringc(result['msg'], color), "\n") if 'rc' in result: exitCode = result['rc'] exitColor = C.COLOR_OK if exitCode != '0' and exitCode != 0: exitColor = C.COLOR_ERROR self.LogArgs(stringc('exit code: %s' % exitCode, exitColor), "\n")
def _get_diff(self, difflist): if not isinstance(difflist, list): difflist = [difflist] ret = [] for diff in difflist: if 'dst_binary' in diff: ret.append(u"diff skipped: destination file appears to be binary\n") if 'src_binary' in diff: ret.append(u"diff skipped: source file appears to be binary\n") if 'dst_larger' in diff: ret.append(u"diff skipped: destination file size is greater than %d\n" % diff['dst_larger']) if 'src_larger' in diff: ret.append(u"diff skipped: source file size is greater than %d\n" % diff['src_larger']) if 'before' in diff and 'after' in diff: # format complex structures into 'files' for x in ['before', 'after']: if isinstance(diff[x], MutableMapping): diff[x] = self._serialize_diff(diff[x]) elif diff[x] is None: diff[x] = '' if 'before_header' in diff: before_header = u"before: %s" % diff['before_header'] else: before_header = u'before' if 'after_header' in diff: after_header = u"after: %s" % diff['after_header'] else: after_header = u'after' before_lines = diff['before'].splitlines(True) after_lines = diff['after'].splitlines(True) if before_lines and not before_lines[-1].endswith(u'\n'): before_lines[-1] += u'\n\\ No newline at end of file\n' if after_lines and not after_lines[-1].endswith('\n'): after_lines[-1] += u'\n\\ No newline at end of file\n' differ = difflib.unified_diff(before_lines, after_lines, fromfile=before_header, tofile=after_header, fromfiledate=u'', tofiledate=u'', n=C.DIFF_CONTEXT) difflines = list(differ) has_diff = False for line in difflines: has_diff = True if line.startswith(u'+'): line = stringc(line, C.COLOR_DIFF_ADD) elif line.startswith(u'-'): line = stringc(line, C.COLOR_DIFF_REMOVE) elif line.startswith(u'@@'): line = stringc(line, C.COLOR_DIFF_LINES) ret.append(line) if has_diff: ret.append('\n') if 'prepared' in diff: ret.append(diff['prepared']) return u''.join(ret)
def colorize(txt, color=None): output = '' if color is None: # rand_start = random.randint(0, len(all_colors)) for (idx, char) in enumerate(txt): output += stringc(char, random.sample(all_colors, 1)[0]) # output += stringc(char, all_colors[(rand_start + idx) % len(all_colors)]) else: output += stringc(txt, color) return output
def _get_diff(self, difflist): if not isinstance(difflist, list): difflist = [difflist] ret = [] for diff in difflist: try: with warnings.catch_warnings(): warnings.simplefilter('ignore') if 'dst_binary' in diff: ret.append("diff skipped: destination file appears to be binary\n") if 'src_binary' in diff: ret.append("diff skipped: source file appears to be binary\n") if 'dst_larger' in diff: ret.append("diff skipped: destination file size is greater than %d\n" % diff['dst_larger']) if 'src_larger' in diff: ret.append("diff skipped: source file size is greater than %d\n" % diff['src_larger']) if 'before' in diff and 'after' in diff: # format complex structures into 'files' for x in ['before', 'after']: if isinstance(diff[x], dict): diff[x] = json.dumps(diff[x], sort_keys=True, indent=4) if 'before_header' in diff: before_header = "before: %s" % diff['before_header'] else: before_header = 'before' if 'after_header' in diff: after_header = "after: %s" % diff['after_header'] else: after_header = 'after' differ = difflib.unified_diff(to_unicode(diff['before']).splitlines(True), to_unicode(diff['after']).splitlines(True), fromfile=before_header, tofile=after_header, fromfiledate='', tofiledate='', n=C.DIFF_CONTEXT) has_diff = False for line in differ: has_diff = True if line.startswith('+'): line = stringc(line, C.COLOR_DIFF_ADD) elif line.startswith('-'): line = stringc(line, C.COLOR_DIFF_REMOVE) elif line.startswith('@@'): line = stringc(line, C.COLOR_DIFF_LINES) ret.append(line) if has_diff: ret.append('\n') if 'prepared' in diff: ret.append(to_unicode(diff['prepared'])) except UnicodeDecodeError: ret.append(">> the files are different, but the diff library cannot compare unicode strings\n\n") return u''.join(ret)
def _format_failed_checks(checks): '''Return pretty-formatted text describing checks that failed.''' failed_check_msgs = [] for check, body in checks.items(): if body.get('failed', False): # only show the failed checks msg = body.get('msg', u"Failed without returning a message") failed_check_msgs.append('check "%s":\n%s' % (check, msg)) if failed_check_msgs: return stringc("\n\n".join(failed_check_msgs), C.COLOR_ERROR) else: # something failed but no checks will admit to it, so dump everything return stringc(pformat(checks), C.COLOR_ERROR)
def _format_summary_for(self, task_result): if task_result["_insights_event_name"] == "passed": icon = stringc("passed", C.COLOR_OK) elif task_result["_insights_event_name"] == "failed": icon = stringc("failed", C.COLOR_ERROR) elif task_result["_insights_event_name"] == "fatal": icon = stringc("ERROR", C.COLOR_ERROR) else: icon = stringc(task_result["_insights_event_name"], C.COLOR_DEBUG) return " %s : %s" % (icon, task_result["_insights_task_title"])
def _format_summary_for(self, check_result): if check_result["result"] == "pass": icon = stringc("pass", C.COLOR_OK) elif check_result["result"] == "fail": icon = stringc("fail", C.COLOR_ERROR) elif check_result["result"] == "fatal": icon = stringc("ERROR", C.COLOR_ERROR) else: icon = stringc(check_result["result"], C.COLOR_DEBUG) return " %s : %s" % (icon, check_result["name"])
def run(self, args): for host in self.get_inventory_hosts(args): group_names = [group.name for group in host.get_groups()] group_names = sorted(group_names) group_string = ", ".join(group_names) host_id = host.vars.get('ec2_id', '') if host_id != '': name_and_id = "%s -- %s" % (stringc(host.name, 'blue'), stringc(host_id, 'blue')) else: name_and_id = "%s" % stringc(host.name, 'blue') display("%s (%s)" % (name_and_id, stringc(group_string, 'green'))) if args.facts: display(self.get_host_facts(host))
def _handle_warnings(self, res): ''' display warnings, if enabled and any exist in the result ''' if C.ACTION_WARNINGS: if 'warnings' in res and res['warnings']: for warning in res['warnings']: self.LogArgs( stringc(u'[WARNING]: %s' % warning, C.COLOR_WARN)) del res['warnings'] if 'deprecations' in res and res['deprecations']: for warning in res['deprecations']: self.LogArgs( stringc(self._deprecated_msg(**warning), C.COLOR_DEPRECATE)) del res['deprecations']
def fabric_ansible_display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): # Display a message to the user # Note: msg *must* be a unicode string to prevent UnicodeError traceback nocolor = msg if color: msg = stringc(msg, color) if not log_only: if not msg.endswith(u'\n'): msg2 = msg + u'\n' else: msg2 = msg msg2 = to_bytes(msg2, encoding=self._output_encoding(stderr=stderr)) if sys.version_info >= (3, ): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_text(msg2, self._output_encoding(stderr=stderr), errors='replace') # Note: After Display() class is refactored need to update the # log capture code in 'bin/ansible-connection' (and other # relevant places). if not stderr: fileobj = sys.stdout else: fileobj = sys.stderr fileobj.write(msg2) try: fileobj.flush() except IOError as e: # Ignore EPIPE in case fileobj has been prematurely closed, eg. # when piping to "head -n1" if e.errno != errno.EPIPE: raise if logger: msg2 = nocolor.lstrip(u'\n') msg2 = to_bytes(msg2) if sys.version_info >= (3, ): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_text(msg2, self._output_encoding(stderr=stderr)) if color == CONST.COLOR_ERROR: logger.error(msg2) else: logger.info(msg2)
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): # FIXME: this needs to be implemented #msg = utils.sanitize_output(msg) msg2 = self._safe_output(msg, stderr=stderr) if color: msg2 = stringc(msg, color) if not log_only: b_msg2 = to_bytes(msg2) if not stderr: print(b_msg2) sys.stdout.flush() else: print(b_msg2, file=sys.stderr) sys.stderr.flush() if logger and not screen_only: while msg.startswith("\n"): msg = msg.replace("\n","") b_msg = to_bytes(msg) if color == 'red': logger.error(b_msg) else: logger.info(b_msg)
def _render_settings(self, config): entries = [] for setting in sorted(config): changed = (config[setting].origin != 'default') if context.CLIARGS['format'] == 'display': if isinstance(config[setting], Setting): # proceed normally if config[setting].origin == 'default': color = 'green' elif config[setting].origin == 'REQUIRED': # should include '_terms', '_input', etc color = 'red' else: color = 'yellow' msg = "%s(%s) = %s" % (setting, config[setting].origin, config[setting].value) else: color = 'green' msg = "%s(%s) = %s" % (setting, 'default', config[setting].get('default')) entry = stringc(msg, color) else: entry = {} for key in config[setting]._fields: entry[key] = getattr(config[setting], key) if not context.CLIARGS['only_changed'] or changed: entries.append(entry) return entries
def execute_dump(self): ''' Shows the current settings, merges ansible.cfg if specified ''' text = [] defaults = self.config.initial_defs.copy() for setting in self.config.data.get_settings(): if setting.name in defaults: defaults[setting.name] = setting for setting in sorted(defaults): if isinstance(defaults[setting], Setting): if defaults[setting].origin == 'default': color = 'green' else: color = 'yellow' msg = "%s(%s) = %s" % (setting, defaults[setting].origin, defaults[setting].value) else: color = 'green' msg = "%s(%s) = %s" % (setting, 'default', defaults[setting].get('default')) text.append(stringc(msg, color)) self.pager(to_text('\n'.join(text), errors='surrogate_or_strict'))
def execute_dump(self): ''' Shows the current settings, merges ansible.cfg if specified ''' # FIXME: deal with plugins, not just base config text = [] defaults = self.config.get_configuration_definitions().copy() for setting in self.config.data.get_settings(): if setting.name in defaults: defaults[setting.name] = setting for setting in sorted(defaults): if isinstance(defaults[setting], Setting): if defaults[setting].origin == 'default': color = 'green' else: color = 'yellow' msg = "%s(%s) = %s" % (setting, defaults[setting].origin, defaults[setting].value) else: color = 'green' msg = "%s(%s) = %s" % (setting, 'default', defaults[setting].get('default')) if not self.options.only_changed or color == 'yellow': text.append(stringc(msg, color)) self.pager(to_text('\n'.join(text), errors='surrogate_or_strict'))
def v2_runner_on_failed(self, result, ignore_errors=False): if not ignore_errors: super(CallbackModule, self).v2_runner_on_failed(result, ignore_errors=ignore_errors) else: self._display.display(stringc('failed (ignored): [%s]' % ( result._host.get_name(), ), C.COLOR_CHANGED))
def v2_runner_item_on_ok(self, result): self._display.v( "TASK action=%s item OK => %s" % (result._task.action, json.dumps(result._result, indent=4))) self._clean_results(result._result, result._task.action) self._handle_warnings(result._result) task = result._task if task.action in self.SQUASH_LOOP_MODULES: return color = C.COLOR_OK if 'changed' in result._result and result._result['changed']: color = C.COLOR_CHANGED # item result info if any if task.action == 'debug': self._display_debug_msg(result._task, result._result) else: self._display_msg(result._task, result._result, color) logboek.LogProcessStepEnd(u''.join([ vt100.reset, vt100.bold, self._clean_str(self._item_details(task, result._result)), vt100.reset, ' ', stringc(u'[OK]', color) ]).encode('utf-8')) # reset live_stdout flag on item end self._live_stdout_listener.set_live_stdout(False)
def execute_dump(self): ''' Shows the current settings, merges ansible.cfg if specified ''' # FIXME: deal with plugins, not just base config text = [] defaults = self.config.get_configuration_definitions().copy() for setting in self.config.data.get_settings(): if setting.name in defaults: defaults[setting.name] = setting for setting in sorted(defaults): if isinstance(defaults[setting], Setting): if defaults[setting].origin == 'default': color = 'green' else: color = 'yellow' msg = "%s(%s) = %s" % (setting, defaults[setting].origin, defaults[setting].value) else: color = 'green' msg = "%s(%s) = %s" % (setting, 'default', defaults[setting].get('default')) if not context.CLIARGS['only_changed'] or color == 'yellow': text.append(stringc(msg, color)) self.pager(to_text('\n'.join(text), errors='surrogate_or_strict'))
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): """ Display a message to the user Note: msg *must* be a unicode string to prevent UnicodeError tracebacks. """ nocolor = msg if color: msg = stringc(msg, color) if not log_only: if not msg.endswith(u'\n'): msg2 = msg + u'\n' else: msg2 = msg msg2 = to_bytes(msg2, encoding=self._output_encoding(stderr=stderr)) if sys.version_info >= (3, ): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_text(msg2, self._output_encoding(stderr=stderr), errors='replace') if not stderr: fileobj = sys.stdout else: fileobj = sys.stderr fileobj.write(msg2) try: fileobj.flush() except IOError as e: # Ignore EPIPE in case fileobj has been prematurely closed, eg. # when piping to "head -n1" if e.errno != errno.EPIPE: raise if logger and not screen_only: msg2 = nocolor.lstrip(u'\n') msg2 = to_bytes(msg2) if sys.version_info >= (3, ): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_text(msg2, self._output_encoding(stderr=stderr)) if color == C.COLOR_ERROR: logger.error(msg2) else: logger.info(msg2)
def format_failure(failure): """Return a list of pretty-formatted text entries describing a failure, including relevant information about it. Expect that the list of text entries will be joined by a newline separator when output to the user.""" if isinstance(failure['host'], string_types): host = failure['host'] else: host = u', '.join(failure['host']) play = failure['play'] task = failure['task'] msg = failure['msg'] if not isinstance(msg, string_types): msg = str(msg) checks = failure['checks'] fields = ( (u'Hosts', host), (u'Play', play), (u'Task', task), (u'Message', stringc(msg, C.COLOR_ERROR)), ) if checks: fields += ((u'Details', format_failed_checks(checks)), ) row_format = '{:10}{}' return [ row_format.format(header + u':', body.encode('utf8')) if PY2 else body for header, body in fields ]
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): # FIXME: this needs to be implemented #msg = utils.sanitize_output(msg) msg2 = msg if color: msg2 = stringc(msg, color) if not log_only: b_msg2 = to_bytes(msg2) if not stderr: print(b_msg2) else: print(b_msg2, file=sys.stderr) if logger and not screen_only: while msg.startswith("\n"): msg = msg.replace("\n", "") b_msg = to_bytes(msg) if color == 'red': logger.error(b_msg) else: logger.info(b_msg)
def _render_settings(self, config): text = [] for setting in sorted(config): changed = False if isinstance(config[setting], Setting): # proceed normally if config[setting].origin == 'default': color = 'green' elif config[setting].origin == 'REQUIRED': # should include '_terms', '_input', etc color = 'red' else: color = 'yellow' changed = True msg = "%s(%s) = %s" % (setting, config[setting].origin, config[setting].value) else: color = 'green' msg = "%s(%s) = %s" % (setting, 'default', config[setting].get('default')) if not context.CLIARGS['only_changed'] or changed: text.append(stringc(msg, color)) return text
def _display_werf_config(self, task): tags = task.tags if not tags or len(tags) == 0: return # last tag is a key to a section dump in dump_config dump_config_section_key = tags[-1] dump_config = self._read_dump_config_doc() dump_config_doc = dump_config.get('dump_config_doc', '') dump_config_sections = dump_config.get('dump_config_sections', {}) dump_config_section = dump_config_sections.get(dump_config_section_key, '') self.LogArgs(u"\n", lColor.COLOR_DEBUG, u"Failed task configuration:\n\n", vt100.reset, stringc(dump_config_section, C.COLOR_DEBUG), u"\n", stringc(dump_config_doc, C.COLOR_DEBUG), u"\n")
def fabric_ansible_display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): """ Display a message to the user Note: msg *must* be a unicode string to prevent UnicodeError tracebacks. """ nocolor = msg if color: msg = stringc(msg, color) if not log_only: if not msg.endswith(u'\n'): msg2 = msg + u'\n' else: msg2 = msg msg2 = to_bytes(msg2, encoding=self._output_encoding(stderr=stderr)) if sys.version_info >= (3,): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_text(msg2, self._output_encoding(stderr=stderr), errors='replace') # Note: After Display() class is refactored need to update the # log capture code in 'bin/ansible-connection' (and other # relevant places). if not stderr: fileobj = sys.stdout else: fileobj = sys.stderr fileobj.write(msg2) try: fileobj.flush() except IOError as e: # Ignore EPIPE in case fileobj has been prematurely closed, eg. # when piping to "head -n1" if e.errno != errno.EPIPE: raise if logger: msg2 = nocolor.lstrip(u'\n') msg2 = to_bytes(msg2) if sys.version_info >= (3,): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_text(msg2, self._output_encoding(stderr=stderr)) if color == CONST.COLOR_ERROR: logger.error(msg2) else: logger.info(msg2)
def _print_task(self, task): color = color_from_task(task) taskstr = "- task: %s" % (task['name']) self._display.display(stringc(taskstr, color)) if task['commands']: cmdstr = "commands:" self._display.display(stringc(" " * 2 + cmdstr, color)) for command in task['commands']: cmdstr = " " * 2 + "- %s" % stringc(command, color) self._display.display(cmdstr) else: cmdstr = " " * 2 + "%s" % stringc("commands: []", color) self._display.display(cmdstr) if self._timestamps: for timestamp in ['start', 'end', 'duration']: tstr = " " * 2 + "%s" % stringc( "%s: %s" % (timestamp, task[timestamp]), color) self._display.display(tstr)
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): if msg and msg != '\n': nowTime = time.time() runTime = nowTime - self._lastTime self._lastTime = nowTime if msg[0] == '\n': msg = '\n(%06.1f) ' % runTime + msg[1:] else: msg = '(%06.1f) ' % runTime + msg nocolor = msg if color: msg = stringc(msg, color) if not log_only and self._isPrint: if not msg.endswith(u'\n'): msg2 = msg + u'\n' else: msg2 = msg msg2 = to_bytes(msg2, encoding=self._output_encoding(stderr=stderr)) if sys.version_info >= (3,): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_text(msg2, self._output_encoding(stderr=stderr), errors='replace') if not stderr: fileobj = sys.stdout else: fileobj = sys.stderr fileobj.write(msg2) try: fileobj.flush() except IOError as e: # Ignore EPIPE in case fileobj has been prematurely closed, eg. # when piping to "head -n1" if e.errno != errno.EPIPE: raise if not screen_only: msg2 = nocolor.lstrip(u'\n') msg2 = to_bytes(msg2) if sys.version_info >= (3,): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_text(msg2, self._output_encoding(stderr=stderr)) if color == C.COLOR_ERROR: self.append('error : ' + msg2) else: self.append(msg2)
def colorize(msg, color): """Given a string add necessary codes to format the string.""" if DONT_COLORIZE: return msg else: color_code = COLORS[color] if '\033' in color_code: return '{}{}{}'.format(color_code, msg, COLORS['endc']) else: return stringc(msg,color_code)
def set_prompt(self): login_user = self.options.remote_user or getpass.getuser() self.selected = self.inventory.list_hosts(self.options.cwd) prompt = "%s@%s (%d)[f:%s]" % (login_user, self.options.cwd, len(self.selected), self.options.forks) if self.options.become and self.options.become_user in [None, 'root']: prompt += "# " color = C.COLOR_ERROR else: prompt += "$ " color = C.COLOR_HIGHLIGHT self.prompt = stringc(prompt, color)
def set_prompt(self): login_user = self.remote_user or getpass.getuser() self.selected = self.inventory.list_hosts(self.cwd) prompt = "%s@%s (%d)[f:%s]" % (login_user, self.cwd, len(self.selected), self.forks) if self.become and self.become_user in [None, 'root']: prompt += "# " color = C.COLOR_ERROR else: prompt += "$ " color = self.NORMAL_PROMPT self.prompt = stringc(prompt, color, wrap_nonvisible_chars=True)
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): """ Display a message to the user Note: msg *must* be a unicode string to prevent UnicodeError tracebacks. """ # FIXME: this needs to be implemented #msg = utils.sanitize_output(msg) nocolor = msg if color: msg = stringc(msg, color) if not log_only: if not msg.endswith(u'\n'): msg2 = msg + u'\n' else: msg2 = msg msg2 = to_bytes(msg2, encoding=self._output_encoding(stderr=stderr)) if sys.version_info >= (3,): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_unicode(msg2, self._output_encoding(stderr=stderr)) if not stderr: fileobj = sys.stdout else: fileobj = sys.stderr fileobj.write(msg2) try: fileobj.flush() except IOError as e: # Ignore EPIPE in case fileobj has been prematurely closed, eg. # when piping to "head -n1" if e.errno != errno.EPIPE: raise if logger and not screen_only: msg2 = nocolor.lstrip(u'\n') msg2 = to_bytes(msg2) if sys.version_info >= (3,): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_unicode(msg2, self._output_encoding(stderr=stderr)) if color == C.COLOR_ERROR: logger.error(msg2) else: logger.info(msg2)
def v2_playbook_on_stats(self, stats): super(CallbackModule, self).v2_playbook_on_stats(stats) # pylint: disable=broad-except; capturing exceptions broadly is # intentional, to isolate arbitrary failures in this callback plugin. try: if self.__failures: self._display.display(failure_summary(self.__failures, self.__playbook_file)) except Exception: msg = stringc( u'An error happened while generating a summary of failures:\n' u'{}'.format(traceback.format_exc()), C.COLOR_WARN) self._display.v(msg)
def get_credentials(self): display.display(u'\n\n' + "We need your " + stringc("Github login",'bright cyan') + " to identify you.", screen_only=True) display.display("This information will " + stringc("not be sent to Galaxy",'bright cyan') + ", only to " + stringc("api.github.com.","yellow"), screen_only=True) display.display("The password will not be displayed." + u'\n\n', screen_only=True) display.display("Use " + stringc("--github-token",'yellow') + " if you do not want to enter your password." + u'\n\n', screen_only=True) try: self.github_username = raw_input("Github Username: "******"Password for %s: " % self.github_username) except: pass if not self.github_username or not self.github_password: raise AnsibleError("Invalid Github credentials. Username and password are required.")
def helpdefault(self, module_name): if module_name in self.modules: in_path = module_loader.find_plugin(module_name) if in_path: oc, a, _ = module_docs.get_docstring(in_path) if oc: display.display(oc['short_description']) display.display('Parameters:') for opt in oc['options'].keys(): display.display(' ' + stringc(opt, C.COLOR_HIGHLIGHT) + ' ' + oc['options'][opt]['description'][0]) else: display.error('No documentation found for %s.' % module_name) else: display.error('%s is not a valid command, use ? to list all valid commands.' % module_name)
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): """ Display a message to the user Note: msg *must* be a unicode string to prevent UnicodeError tracebacks. 上述为系统自带display操作 可以输出信息到屏幕之外,同时写入到日志文件中 此类保留,原有的输出屏幕不变之外。 将对写入日志进行改造,日志内容分为时间和内容两部分,分别储存到不同的文件中,用于进行录像回放。 """ nocolor = msg if color: msg = stringc(msg, color) if not msg.endswith(u'\n'): msg2 = msg + u'\n' else: msg2 = msg msg2 = to_bytes(msg2, encoding=self._output_encoding(stderr=stderr)) if sys.version_info >= (3,): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_unicode(msg2, self._output_encoding(stderr=stderr)) if not stderr: fileobj = sys.stdout else: fileobj = sys.stderr fileobj.write(msg2) # 写入日志 msg3 = msg2.replace(u'\n', u'\r\n') self._log(msg3) try: fileobj.flush() except IOError as e: # Ignore EPIPE in case fileobj has been prematurely closed, eg. # when piping to "head -n1" if e.errno != errno.EPIPE: raise
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): """ Display a message to the user Note: msg *must* be a unicode string to prevent UnicodeError tracebacks. """ # FIXME: this needs to be implemented #msg = utils.sanitize_output(msg) if color: msg = stringc(msg, color) if not log_only: if not msg.endswith(u'\n'): msg2 = msg + u'\n' else: msg2 = msg msg2 = to_bytes(msg2, encoding=self._output_encoding(stderr=stderr)) if sys.version_info >= (3,): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_unicode(msg2, self._output_encoding(stderr=stderr)) if not stderr: sys.stdout.write(msg2) sys.stdout.flush() else: sys.stderr.write(msg2) sys.stderr.flush() if logger and not screen_only: msg2 = msg.lstrip(u'\n') msg2 = to_bytes(msg2) if sys.version_info >= (3,): # Convert back to text string on python3 # We first convert to a byte string so that we get rid of # characters that are invalid in the user's locale msg2 = to_unicode(msg2, self._output_encoding(stderr=stderr)) if color == 'red': logger.error(msg2) else: logger.info(msg2)
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False): msg2 = msg if color: msg2 = stringc(msg, color) if not log_only: if not stderr: try: print msg2 except UnicodeEncodeError: print msg2.encode('utf-8') else: try: print >>sys.stderr, msg2 except UnicodeEncodeError: print >>sys.stderr, msg2.encode('utf-8') if C.DEFAULT_LOG_PATH != '': while msg.startswith("\n"): msg = msg.replace("\n","")
def _format_failure(failure): '''Return a list of pretty-formatted lines describing a failure, including relevant information about it. Line separators are not included.''' result = failure['result'] host = result._host.get_name() play = _get_play(result._task) if play: play = play.get_name() task = result._task.get_name() msg = result._result.get('msg', u'???') rows = ( (u'Host', host), (u'Play', play), (u'Task', task), (u'Message', stringc(msg, C.COLOR_ERROR)), ) row_format = '{:10}{}' return [row_format.format(header + u':', body) for header, body in rows]
def format_failure(failure): """Return a list of pretty-formatted text entries describing a failure, including relevant information about it. Expect that the list of text entries will be joined by a newline separator when output to the user.""" host = u', '.join(failure['host']) play = failure['play'] task = failure['task'] msg = failure['msg'] checks = failure['checks'] fields = ( (u'Hosts', host), (u'Play', play), (u'Task', task), (u'Message', stringc(msg, C.COLOR_ERROR)), ) if checks: fields += ((u'Details', format_failed_checks(checks)),) row_format = '{:10}{}' return [row_format.format(header + u':', body) for header, body in fields]
def _format_failure(failure): '''Return a list of pretty-formatted text entries describing a failure, including relevant information about it. Expect that the list of text entries will be joined by a newline separator when output to the user.''' result = failure['result'] host = result._host.get_name() play = _get_play(result._task) if play: play = play.get_name() task = result._task.get_name() msg = result._result.get('msg', u'???') fields = ( (u'Host', host), (u'Play', play), (u'Task', task), (u'Message', stringc(msg, C.COLOR_ERROR)), ) if 'checks' in result._result: fields += ((u'Details', _format_failed_checks(result._result['checks'])),) row_format = '{:10}{}' return [row_format.format(header + u':', body) for header, body in fields]
def ColorLiteralText(text, color): if not isinstance(text, basestring): text = unicode(text) return LiteralText(stringc(text, color))
def info(message, settings, file=sys.stdout): if settings.log_level <= logging.INFO: print(stringc("INFO: %s" % message, 'green'), file=file)
def human_log(res, task, host, color, indent_with=" ", prefix="", is_handler=False): res = copy.deepcopy(res) item = None item_label = None if hasattr(res, "get"): if res.get("_ansible_no_log") or "_ansible_verbose_override" in res: res = OUTPUT_OMITTED if hasattr(res, "get"): if "_ansible_ignore_errors" in res: del res["_ansible_ignore_errors"] if "_ansible_no_log" in res: del res["_ansible_no_log"] item = res.get("item") if item is not None: del res["item"] item_label = res.get("_ansible_item_label") if item_label is not None: del res["_ansible_item_label"] # The following block transmutes with_items items into a nicer output. if hasattr(item, "keys") and set(item.keys()) == set(["key", "value"]): res["item_value"] = item["value"] item = item["key"] if task.action == "service" and "status" in res: if hasattr(res["status"], "keys") and len(res["status"]) > 3: del res["status"] for x in ['stdout', 'stderr', 'include_variables']: if x in res and res.get(x): res[x] = LiteralText(res[x]) elif x in res: del res[x] unreachable = bool(res.get("unreachable")) skipped = bool(res.get("skipped")) failed = bool(res.get("failed")) changed = bool(res.get("changed")) for o, n in [("_ansible_notify", "notified")]: if o in res: res[n] = res[o] del res[o] if "warnings" in res: if not res["warnings"]: del res["warnings"] else: warnings = res['warnings'] del res['warnings'] for i, v in enumerate(warnings): warnings[i] = LiteralText(stringc(v, C.COLOR_WARN)) res[stringc("warnings", C.COLOR_WARN)] = warnings for banned in ["invocation", "stdout_lines", "stderr_lines", "changed", "failed", "skipped", "unreachable", "_ansible_delegated_vars", "_ansible_parsed", "_ansible_item_result", "_ansible_verbose_always"]: if banned in res: del res[banned] if unreachable: res = res["msg"] elif skipped: if "skip_reason" in res: res = res["skip_reason"] if res == "Conditional check failed": res = OUTPUT_OMITTED elif failed: if len(res) == 1: res = res[res.keys()[0]] elif (len(res.keys()) == 1 and res.keys()[0] not in ["_ansible_notify", "notified"] and task.action != "debug"): # Simplify. If the result contains only one key and value # pair, then make the result the value instead. # Subject to some exceptions, of course. res = res[res.keys()[0]] if "include_role" in res: res["include_role"] = "%s" % res["include_role"] if item is not None or item_label is not None: if not item and item_label is not None: item = item_label if res and res != OUTPUT_OMITTED: try: res = collections.OrderedDict({host: {item: res}}) except TypeError: res = collections.OrderedDict({host: {str(item): res}}) else: try: res = collections.OrderedDict({host: item}) except TypeError: res = collections.OrderedDict({host: str(item)}) else: if res and res != OUTPUT_OMITTED: res = collections.OrderedDict({host: res}) else: res = host banner = task.get_name() if ":" in banner: banner = banner.replace(u":", u"—") if is_handler: typ = "handler" elif banner == "include_role": typ = "include_role" else: typ = "task" if task.get_path(): path = " @ " + task.get_path() else: path = "" banner = banner + stringc(" (%s%s)" % (typ, path), color="bright gray") if prefix: banner = prefix + " " + banner if isinstance(res, (basestring, int, float)): res = ColorLiteralText(res, color) elif len(res) == 1 and hasattr(res, "items"): k ,v = res.keys()[0], res.values()[0] del res[k] if hasattr(v, "items"): v = dict((ColorLiteralText(x, color), y) for x, y in v.items()) res[ColorLiteralText(k, color)] = v banner = LiteralText(stringc(banner, color)) res = {banner: res} c = StringIO.StringIO() d = MyDumper(c) d.open() d.represent(res) d.close() c.seek(0) res_text = c.read().strip() if indent_with: res_text = indent(res_text, indent_with) return res_text
def warn(message, settings, file=sys.stdout): if settings.log_level <= logging.WARNING: print(stringc("WARN: %s" % message, 'yellow'), file=file)
def abort(message, file=sys.stderr): print(stringc("FATAL: %s" % message, 'red'), file=file) sys.exit(1)
def error(message, file=sys.stderr): print(stringc("ERROR: %s" % message, 'red'), file=file)
def warn(message, file=sys.stdout): print(stringc("WARN: %s" % message, 'yellow'), file=file)
def info(message, file=sys.stdout): print(stringc("INFO: %s" % message, 'green'), file=file)
def _get_diff(self, difflist): if not isinstance(difflist, list): difflist = [difflist] ret = [] for diff in difflist: try: with warnings.catch_warnings(): warnings.simplefilter('ignore') if 'dst_binary' in diff: ret.append("diff skipped: destination file appears to be binary\n") if 'src_binary' in diff: ret.append("diff skipped: source file appears to be binary\n") if 'dst_larger' in diff: ret.append("diff skipped: destination file size is greater than %d\n" % diff['dst_larger']) if 'src_larger' in diff: ret.append("diff skipped: source file size is greater than %d\n" % diff['src_larger']) if 'before' in diff and 'after' in diff: # format complex structures into 'files' for x in ['before', 'after']: if isinstance(diff[x], dict): diff[x] = json.dumps(diff[x], sort_keys=True, indent=4, separators=(',', ': ')) + '\n' if 'before_header' in diff: before_header = "before: %s" % diff['before_header'] else: before_header = 'before' if 'after_header' in diff: after_header = "after: %s" % diff['after_header'] else: after_header = 'after' before_lines = to_text(diff['before']).splitlines(True) after_lines = to_text(diff['after']).splitlines(True) if before_lines and not before_lines[-1].endswith('\n'): before_lines[-1] += '\n\\ No newline at end of file\n' if after_lines and not after_lines[-1].endswith('\n'): after_lines[-1] += '\n\\ No newline at end of file\n' differ = difflib.unified_diff(before_lines, after_lines, fromfile=before_header, tofile=after_header, fromfiledate='', tofiledate='', n=C.DIFF_CONTEXT) difflines = list(differ) if len(difflines) >= 3 and sys.version_info[:2] == (2, 6): # difflib in Python 2.6 adds trailing spaces after # filenames in the -- before/++ after headers. difflines[0] = difflines[0].replace(' \n', '\n') difflines[1] = difflines[1].replace(' \n', '\n') # it also treats empty files differently difflines[2] = difflines[2].replace('-1,0', '-0,0').replace('+1,0', '+0,0') has_diff = False for line in difflines: has_diff = True if line.startswith('+'): line = stringc(line, C.COLOR_DIFF_ADD) elif line.startswith('-'): line = stringc(line, C.COLOR_DIFF_REMOVE) elif line.startswith('@@'): line = stringc(line, C.COLOR_DIFF_LINES) ret.append(line) if has_diff: ret.append('\n') if 'prepared' in diff: ret.append(to_text(diff['prepared'])) except UnicodeDecodeError: ret.append(">> the files are different, but the diff library cannot compare unicode strings\n\n") return u''.join(ret)
def format_failed_checks(checks): """Return pretty-formatted text describing checks that failed.""" messages = [] for name, message in checks: messages.append(u'check "{}":\n{}'.format(name, message)) return stringc(u'\n\n'.join(messages), C.COLOR_ERROR)