def print_list(l, exclude=(), indent=0, with_enumeration=False, recursive_enumeration=False, out=stdout): """Pretty-print a list of items <indent>key: <non iterable item> <indent>key: <indent + INDENT_TAB><pretty-print iterable> :param l: (list) :param exclude: (iterable of strings) items to exclude from printing :param indent: (int) initial indentation (recursive) :param with_enumeration: (bool) enumerate 1st-level items :param recursive_enumeration: (bool) recursively enumerate iterables (does not enumerate 1st level keys) :param out: Input/Output stream to dump values into :raises CLIError: if preconditions fail """ assert isinstance(l, list) or isinstance( l, tuple), ('print_list prinbts a list or tuple') assert indent >= 0, 'print_list indent must be >= 0' for i, item in enumerate(l): print_str = ' ' * indent print_str += '%s.' % (i + 1) if with_enumeration else '' if isinstance(item, dict): if with_enumeration: out.write(escape_ctrl_chars(print_str) + u'\n') elif i and i < len(l): out.write(u'\n') print_dict(item, exclude, indent + (INDENT_TAB if with_enumeration else 0), recursive_enumeration, recursive_enumeration, out) elif isinstance(item, list) or isinstance(item, tuple): if with_enumeration: out.write(escape_ctrl_chars(print_str) + u'\n') elif i and i < len(l): out.write(u'\n') print_list(item, exclude, indent + INDENT_TAB, recursive_enumeration, recursive_enumeration, out) else: item = ('%s' % item).strip() if item in exclude: continue out.write(escape_ctrl_chars(u'%s%s' % (print_str, item))) out.write(u'\n')
def print_list( l, exclude=(), indent=0, with_enumeration=False, recursive_enumeration=False, out=stdout): """Pretty-print a list of items <indent>key: <non iterable item> <indent>key: <indent + INDENT_TAB><pretty-print iterable> :param l: (list) :param exclude: (iterable of strings) items to exclude from printing :param indent: (int) initial indentation (recursive) :param with_enumeration: (bool) enumerate 1st-level items :param recursive_enumeration: (bool) recursively enumerate iterables (does not enumerate 1st level keys) :param out: Input/Output stream to dump values into :raises CLIError: if preconditions fail """ assert isinstance(l, list) or isinstance(l, tuple), ( 'print_list prinbts a list or tuple') assert indent >= 0, 'print_list indent must be >= 0' for i, item in enumerate(l): print_str = ' ' * indent print_str += '%s.' % (i + 1) if with_enumeration else '' if isinstance(item, dict): if with_enumeration: out.write(escape_ctrl_chars(print_str) + u'\n') elif i and i < len(l): out.write(u'\n') print_dict( item, exclude, indent + (INDENT_TAB if with_enumeration else 0), recursive_enumeration, recursive_enumeration, out) elif isinstance(item, list) or isinstance(item, tuple): if with_enumeration: out.write(escape_ctrl_chars(print_str) + u'\n') elif i and i < len(l): out.write(u'\n') print_list( item, exclude, indent + INDENT_TAB, recursive_enumeration, recursive_enumeration, out) else: item = ('%s' % item).strip() if item in exclude: continue out.write(escape_ctrl_chars(u'%s%s' % (print_str, item))) out.write(u'\n')
def print_error_message(cli_err, out=stderr): errmsg = escape_ctrl_chars(('%s' % cli_err).strip('\n')).encode( pref_enc, 'replace') if cli_err.importance == 1: errmsg = magenta(errmsg) elif cli_err.importance == 2: errmsg = yellow(errmsg) elif cli_err.importance > 2: errmsg = red(errmsg) out.write(errmsg) out.write('\n') for errmsg in cli_err.details: out.write('| %s\n' % escape_ctrl_chars(u'%s' % errmsg).encode( pref_enc, 'replace')) out.flush()
def _check_config_version(cnf): guess = cnf.guess_version() if exists(cnf.path) and guess < 0.12: print('Config file format version >= 0.12 is required (%s found)' % (guess)) print('Configuration file: %s' % cnf.path) print('Attempting to fix this:') print('Calculating changes while preserving information') lost_terms = cnf.rescue_old_file() print('... DONE') if lost_terms: print 'The following information will NOT be preserved:' print '\t', '\n\t'.join(lost_terms) print('Kamaki is ready to convert the config file') stdout.write('Create (overwrite) file %s ? [y/N] ' % escape_ctrl_chars(cnf.path)) from sys import stdin reply = stdin.readline() if reply in ('Y\n', 'y\n'): cnf.write() print('... DONE') else: print('... ABORTING') raise CLIError('Invalid format for config file %s' % cnf.path, importance=3, details=[ 'Please, update config file', 'For automatic conversion, rerun and say Y' ])
def print_error_message(cli_err, out=stderr): errmsg = escape_ctrl_chars( ('%s' % cli_err).strip('\n')).encode(pref_enc, 'replace') if cli_err.importance == 1: errmsg = magenta(errmsg) elif cli_err.importance == 2: errmsg = yellow(errmsg) elif cli_err.importance > 2: errmsg = red(errmsg) out.write(errmsg) out.write('\n') for errmsg in cli_err.details: out.write( '| %s\n' % escape_ctrl_chars(u'%s' % errmsg).encode(pref_enc, 'replace')) out.flush()
def test_escape_ctrl_chars(self): gr_synnefo = u'\u03c3\u03cd\u03bd\u03bd\u03b5\u03c6\u03bf' gr_kamaki = u'\u03ba\u03b1\u03bc\u03ac\u03ba\u03b9' char_pairs = ( ('\b', '\\x08'), ('\n', '\\n'), ('\a', '\\x07'), ('\f', '\\x0c'), ('\t', '\\t'), ('\v', '\\x0b'), ('\r', '\\r'), ('\072', ':'), ('\016', '\\x0e'), ('\\', '\\'), ('\\n', '\\n'), ("'", '\''), ('"', '"'), (u'\u039f\x89', u'\u039f\\x89'), ) for orig_char, esc_char in char_pairs: for word1, word2 in product(('synnefo', gr_kamaki), ('kamaki', gr_synnefo)): orig_str = word1 + orig_char + word2 esc_str = word1 + esc_char + word2 self.assertEqual(utils.escape_ctrl_chars(orig_str), esc_str)
def _check_config_version(cnf): guess = cnf.guess_version() if exists(cnf.path) and guess < 0.12: print('Config file format version >= 0.12 is required (%s found)' % ( guess)) print('Configuration file: %s' % cnf.path) print('Attempting to fix this:') print('Calculating changes while preserving information') lost_terms = cnf.rescue_old_file() print('... DONE') if lost_terms: print 'The following information will NOT be preserved:' print '\t', '\n\t'.join(lost_terms) print('Kamaki is ready to convert the config file') stdout.write('Create (overwrite) file %s ? [y/N] ' % escape_ctrl_chars( cnf.path)) from sys import stdin reply = stdin.readline() if reply in ('Y\n', 'y\n'): cnf.write() print('... DONE') else: print('... ABORTING') raise CLIError( 'Invalid format for config file %s' % cnf.path, importance=3, details=[ 'Please, update config file', 'For automatic conversion, rerun and say Y'])
def print_dict(d, exclude=(), indent=0, with_enumeration=False, recursive_enumeration=False, out=stdout): """Pretty-print a dictionary object <indent>key: <non iterable item> <indent>key: <indent + INDENT_TAB><pretty-print iterable> :param d: (dict) :param exclude: (iterable of strings) keys to exclude from printing :param indent: (int) initial indentation (recursive) :param with_enumeration: (bool) enumerate 1st-level keys :param recursive_enumeration: (bool) recursively enumerate iterables (does not enumerate 1st level keys) :param out: Input/Output stream to dump values into :raises CLIError: if preconditions fail """ assert isinstance(d, dict), 'print_dict input must be a dict' assert indent >= 0, 'print_dict indent must be >= 0' for i, (k, v) in enumerate(d.items()): k = ('%s' % k).strip() if k in exclude: continue print_str = ' ' * indent print_str += '%s.' % (i + 1) if with_enumeration else '' print_str += '%s:' % k if isinstance(v, dict): out.write(escape_ctrl_chars(print_str) + u'\n') print_dict(v, exclude, indent + INDENT_TAB, recursive_enumeration, recursive_enumeration, out) elif isinstance(v, list) or isinstance(v, tuple): out.write(escape_ctrl_chars(print_str) + u'\n') print_list(v, exclude, indent + INDENT_TAB, recursive_enumeration, recursive_enumeration, out) else: out.write(escape_ctrl_chars(u'%s %s' % (print_str, v))) out.write(u'\n')
def print_dict( d, exclude=(), indent=0, with_enumeration=False, recursive_enumeration=False, out=stdout): """Pretty-print a dictionary object <indent>key: <non iterable item> <indent>key: <indent + INDENT_TAB><pretty-print iterable> :param d: (dict) :param exclude: (iterable of strings) keys to exclude from printing :param indent: (int) initial indentation (recursive) :param with_enumeration: (bool) enumerate 1st-level keys :param recursive_enumeration: (bool) recursively enumerate iterables (does not enumerate 1st level keys) :param out: Input/Output stream to dump values into :raises CLIError: if preconditions fail """ assert isinstance(d, dict), 'print_dict input must be a dict' assert indent >= 0, 'print_dict indent must be >= 0' for i, (k, v) in enumerate(d.items()): k = ('%s' % k).strip() if k in exclude: continue print_str = ' ' * indent print_str += '%s.' % (i + 1) if with_enumeration else '' print_str += '%s:' % k if isinstance(v, dict): out.write(escape_ctrl_chars(print_str) + u'\n') print_dict( v, exclude, indent + INDENT_TAB, recursive_enumeration, recursive_enumeration, out) elif isinstance(v, list) or isinstance(v, tuple): out.write(escape_ctrl_chars(print_str) + u'\n') print_list( v, exclude, indent + INDENT_TAB, recursive_enumeration, recursive_enumeration, out) else: out.write(escape_ctrl_chars(u'%s %s' % (print_str, v))) out.write(u'\n')
def _get_response(self): if self._request_performed: return pool_kw = dict(size=self.poolsize) if self.poolsize else dict() for retries in range(1, self.CONNECTION_TRY_LIMIT + 1): try: with https.PooledHTTPConnection(self.request.netloc, self.request.scheme, **pool_kw) as connection: self.request.LOG_TOKEN = self.LOG_TOKEN self.request.LOG_DATA = self.LOG_DATA self.request.LOG_PID = self.LOG_PID r = self.request.perform(connection) plog = '' if self.LOG_PID: recvlog.log( DEBUGV, '\n%s <-- %s <-- [req: %s]\n' % (self, r, self.request)) plog = '\t[%s]' % self self._request_performed = True self._status_code, self._status = r.status, unquote( r.reason) recvlog.log( DEBUGV, '%d %s%s' % (self.status_code, self.status, plog)) self._headers = dict() r_headers = r.getheaders() enc_headers = self._get_headers_to_decode(r_headers) for k, v in r_headers: self._headers[k] = unquote(v).decode('utf-8') if ( k.lower()) in enc_headers else v recvlog.log(DEBUGV, ' %s: %s%s' % (k, v, plog)) self._content = r.read() recvlog.log( DEBUGV, 'data size: %s%s' % (len(self._content) if self._content else 0, plog)) if self.LOG_DATA and self._content: data = '%s%s' % (self._content, plog) data = utils.escape_ctrl_chars(data) if self._token: data = data.replace(self._token, '...') recvlog.log(DEBUGV, data) break except Exception as err: if isinstance(err, HTTPException): if retries >= self.CONNECTION_TRY_LIMIT: raise ClientError( 'Connection to %s failed %s times (%s: %s )' % (self.request.url, retries, type(err), err)) else: from traceback import format_stack recvlog.log(DEBUGV, '\n'.join(['%s' % type(err)] + format_stack())) raise
def _get_response(self): if self._request_performed: return pool_kw = dict(size=self.poolsize) if self.poolsize else dict() for retries in range(1, self.CONNECTION_TRY_LIMIT + 1): try: with https.PooledHTTPConnection( self.request.netloc, self.request.scheme, **pool_kw) as connection: self.request.LOG_TOKEN = self.LOG_TOKEN self.request.LOG_DATA = self.LOG_DATA self.request.LOG_PID = self.LOG_PID r = self.request.perform(connection) plog = '' if self.LOG_PID: recvlog.log(DEBUGV, '\n%s <-- %s <-- [req: %s]\n' % ( self, r, self.request)) plog = '\t[%s]' % self self._request_performed = True self._status_code, self._status = r.status, unquote( r.reason) recvlog.log( DEBUGV, '%d %s%s' % (self.status_code, self.status, plog)) self._headers = dict() r_headers = r.getheaders() enc_headers = self._get_headers_to_decode(r_headers) for k, v in r_headers: self._headers[k] = unquote(v).decode('utf-8') if ( k.lower()) in enc_headers else v recvlog.log(DEBUGV, ' %s: %s%s' % (k, v, plog)) self._content = r.read() recvlog.log(DEBUGV, 'data size: %s%s' % ( len(self._content) if self._content else 0, plog)) if self.LOG_DATA and self._content: data = '%s%s' % (self._content, plog) data = utils.escape_ctrl_chars(data) if self._token: data = data.replace(self._token, '...') recvlog.log(DEBUGV, data) break except Exception as err: if isinstance(err, HTTPException): if retries >= self.CONNECTION_TRY_LIMIT: raise ClientError( 'Connection to %s failed %s times (%s: %s )' % ( self.request.url, retries, type(err), err)) else: from traceback import format_stack recvlog.log( DEBUGV, '\n'.join(['%s' % type(err)] + format_stack())) raise
def print_items(items, title=('id', 'name'), with_enumeration=False, with_redundancy=False, out=stdout): """print dict or list items in a list, using some values as title Objects of next level don't inherit enumeration (default: off) or titles :param items: (list) items are lists or dict :param title: (tuple) keys to use their values as title :param with_enumeration: (boolean) enumerate items (order id on title) :param with_redundancy: (boolean) values in title also appear on body :param out: Input/Output stream to dump values into """ if not items: return if not (isinstance(items, dict) or isinstance(items, list) or isinstance(items, tuple)): out.write(escape_ctrl_chars(u'%s' % items)) out.write(u'\n') return for i, item in enumerate(items): if with_enumeration: out.write(u'%s. ' % (i + 1)) if isinstance(item, dict): item = dict(item) title = sorted(set(title).intersection(item)) pick = item.get if with_redundancy else item.pop header = escape_ctrl_chars(' '.join('%s' % pick(key) for key in title)) out.write((unicode(bold(header) if header else '') + '\n')) print_dict(item, indent=INDENT_TAB, out=out) elif isinstance(item, list) or isinstance(item, tuple): print_list(item, indent=INDENT_TAB, out=out) else: out.write(u' %s\n' % escape_ctrl_chars(item))
def print_items( items, title=('id', 'name'), with_enumeration=False, with_redundancy=False, out=stdout): """print dict or list items in a list, using some values as title Objects of next level don't inherit enumeration (default: off) or titles :param items: (list) items are lists or dict :param title: (tuple) keys to use their values as title :param with_enumeration: (boolean) enumerate items (order id on title) :param with_redundancy: (boolean) values in title also appear on body :param out: Input/Output stream to dump values into """ if not items: return if not (isinstance(items, dict) or isinstance(items, list) or isinstance( items, tuple)): out.write(escape_ctrl_chars(u'%s' % items)) out.write(u'\n') return for i, item in enumerate(items): if with_enumeration: out.write(u'%s. ' % (i + 1)) if isinstance(item, dict): item = dict(item) title = sorted(set(title).intersection(item)) pick = item.get if with_redundancy else item.pop header = escape_ctrl_chars( ' '.join('%s' % pick(key) for key in title)) out.write((unicode(bold(header) if header else '') + '\n')) print_dict(item, indent=INDENT_TAB, out=out) elif isinstance(item, list) or isinstance(item, tuple): print_list(item, indent=INDENT_TAB, out=out) else: out.write(u' %s\n' % escape_ctrl_chars(item))
def ask_user(msg, true_resp=('y', ), **kwargs): """Print msg and read user response :param true_resp: (tuple of chars) :returns: (bool) True if reponse in true responses, False otherwise """ yep = u', '.join(true_resp) nope = u'<not %s>' % yep if 'n' in true_resp or 'N' in true_resp else 'N' msg = escape_ctrl_chars(msg).encode(pref_enc, 'replace') yep = yep.encode(pref_enc, 'replace') nope = nope.encode(pref_enc, 'replace') user_response = raw_input('%s [%s/%s]: ' % (msg, yep, nope)) return user_response[0].lower() in [s.lower() for s in true_resp]
def ask_user(msg, true_resp=('y', ), **kwargs): """Print msg and read user response :param true_resp: (tuple of chars) :returns: (bool) True if reponse in true responses, False otherwise """ yep = u', '.join(true_resp) nope = u'<not %s>' % yep if 'n' in true_resp or 'N' in true_resp else 'N' msg = escape_ctrl_chars(msg).encode(pref_enc, 'replace') yep = yep.encode(pref_enc, 'replace') nope = nope.encode(pref_enc, 'replace') user_response = raw_input( '%s [%s/%s]: ' % (msg, yep, nope)) return user_response[0].lower() in [s.lower() for s in true_resp]
def dump_log(self): plog = ('\t[%s]' % self) if self.LOG_PID else '' sendlog.log(DEBUGV, '%s %s://%s%s%s' % ( self.method, self.scheme, self.netloc, self.path, plog)) for key, val in self.headers.items(): if key.lower() in ('x-auth-token', ) and not self.LOG_TOKEN: self._token, val = val, '...' sendlog.log(DEBUGV, ' %s: %s%s' % (key, val, plog)) if self.data: sendlog.log(DEBUGV, 'data size: %s%s' % (len(self.data), plog)) if self.LOG_DATA: sendlog.log(DEBUGV, utils.escape_ctrl_chars(self.data.replace( self._token, '...') if self._token else self.data)) else: sendlog.log(DEBUGV, 'data size: 0%s' % plog)
def test_escape_ctrl_chars(self): gr_synnefo = u'\u03c3\u03cd\u03bd\u03bd\u03b5\u03c6\u03bf' gr_kamaki = u'\u03ba\u03b1\u03bc\u03ac\u03ba\u03b9' char_pairs = ( ('\b', '\\x08'), ('\n', '\\n'), ('\a', '\\x07'), ('\f', '\\x0c'), ('\t', '\\t'), ('\v', '\\x0b'), ('\r', '\\r'), ('\072', ':'), ('\016', '\\x0e'), ('\\', '\\'), ('\\n', '\\n'), ("'", '\''), ('"', '"'), (u'\u039f\x89', u'\u039f\\x89'), ) for orig_char, esc_char in char_pairs: for word1, word2 in product( ('synnefo', gr_kamaki), ('kamaki', gr_synnefo)): orig_str = word1 + orig_char + word2 esc_str = word1 + esc_char + word2 self.assertEqual(utils.escape_ctrl_chars(orig_str), esc_str)
def error(self, s=''): esc_s = escape_ctrl_chars(s) self._err.write(('%s\n' % esc_s).encode(pref_enc, 'replace')) self._err.flush()
def wrap(): try: exe = basename(argv[0]) internal_argv = [] for i, a in enumerate(argv): try: internal_argv.append(a.decode(pref_enc)) except UnicodeDecodeError as ude: raise CLIError( 'Invalid encoding in command', importance=3, details=[ 'The invalid term is #%s (with "%s" being 0)' % (i, exe), 'Encoding is invalid with current locale settings ' '(%s)' % pref_enc, '( %s )' % ude ]) for i, a in enumerate(internal_argv): argv[i] = a logger.add_stream_logger( __name__, logging.WARNING, fmt='%(levelname)s (%(name)s): %(message)s') _config_arg = ConfigArgument('Path to a custom config file') parser = ArgumentParseManager( exe, arguments=dict( config=_config_arg, cloud=ValueArgument('Chose a cloud to connect to', ('--cloud')), help=Argument(0, 'Show help message', ('-h', '--help')), debug=FlagArgument('Include debug output', ('-d', '--debug')), verbose=FlagArgument( 'Show HTTP requests and responses, without HTTP body', ('-v', '--verbose')), verbose_with_data=FlagArgument( 'Show HTTP requests and responses, including HTTP body', ('-vv', '--verbose-with-data')), version=VersionArgument('Print current version', ('-V', '--version')), options=RuntimeConfigArgument( _config_arg, 'Override a config option (not persistent)', ('-o', '--options')), ignore_ssl=FlagArgument( 'Allow connections to SSL sites without certs', ('-k', '--ignore-ssl', '--insecure')), ca_file=ValueArgument( 'CA certificates for SSL authentication', '--ca-certs'), )) if parser.arguments['version'].value: exit(0) _cnf = parser.arguments['config'] log_file = _cnf.get('global', 'log_file') if log_file: logger.set_log_filename(log_file) filelog = logger.add_file_logger(__name__.split('.')[0]) filelog.info('%s\n- - -' % ' '.join(argv)) _colors = _cnf.value.get('global', 'colors') exclude = ['ansicolors'] if not _colors == 'on' else [] suggest_missing(exclude=exclude) func(exe, parser) except CLIError as err: print_error_message(err) if _debug: raise err exit(1) except KamakiSSLError as err: ca_arg = parser.arguments.get('ca_file') ca = ca_arg.value if ca_arg and ca_arg.value else _cnf.get( 'global', 'ca_certs') stderr.write(red('SSL Authentication failed\n')) if ca: stderr.write('Path used for CA certifications file: %s\n' % (escape_ctrl_chars(ca))) stderr.write('Please make sure the path is correct\n') if not (ca_arg and ca_arg.value): stderr.write('| To set the correct path:\n') stderr.write('| kamaki config set ca_certs CA_FILE\n') else: stderr.write('| To use a CA certifications file:\n') stderr.write('| kamaki config set ca_certs CA_FILE\n') stderr.write('| OR run with --ca-certs=FILE_LOCATION\n') stderr.write('| To ignore SSL errors and move on (%s):\n' % (red('insecure'))) stderr.write('| kamaki config set ignore_ssl on\n') stderr.write('| OR run with --ignore-ssl\n') stderr.flush() if _debug: raise stderr.write('| %s: %s\n' % (type(err), escape_ctrl_chars('%s' % err))) stderr.flush() exit(1) except KeyboardInterrupt: print('Canceled by user') exit(1) except Exception as er: print('Unknown Error: %s' % er) if _debug: raise exit(1)
def wrap(): try: exe = basename(argv[0]) internal_argv = [] for i, a in enumerate(argv): try: internal_argv.append(a.decode(pref_enc)) except UnicodeDecodeError as ude: raise CLIError( 'Invalid encoding in command', importance=3, details=[ 'The invalid term is #%s (with "%s" being 0)' % ( i, exe), 'Encoding is invalid with current locale settings ' '(%s)' % pref_enc, '( %s )' % ude]) for i, a in enumerate(internal_argv): argv[i] = a logger.add_stream_logger( __name__, logging.WARNING, fmt='%(levelname)s (%(name)s): %(message)s') _config_arg = ConfigArgument('Path to config file') parser = ArgumentParseManager(exe, arguments=dict( config=_config_arg, cloud=ValueArgument( 'Chose a cloud to connect to', ('--cloud')), help=Argument(0, 'Show help message', ('-h', '--help')), debug=FlagArgument('Include debug output', ('-d', '--debug')), verbose=FlagArgument( 'More info at response', ('-v', '--verbose')), version=VersionArgument( 'Print current version', ('-V', '--version')), options=RuntimeConfigArgument( _config_arg, 'Override a config value', ('-o', '--options')), ignore_ssl=FlagArgument( 'Allow connections to SSL sites without certs', ('-k', '--ignore-ssl', '--insecure')), ca_file=ValueArgument( 'CA certificates for SSL authentication', '--ca-certs'),) ) if parser.arguments['version'].value: exit(0) _cnf = parser.arguments['config'] log_file = _cnf.get('global', 'log_file') if log_file: logger.set_log_filename(log_file) filelog = logger.add_file_logger(__name__.split('.')[0]) filelog.info('%s\n- - -' % ' '.join(argv)) _colors = _cnf.value.get('global', 'colors') exclude = ['ansicolors'] if not _colors == 'on' else [] suggest_missing(exclude=exclude) func(exe, parser) except CLIError as err: print_error_message(err) if _debug: raise err exit(1) except KamakiSSLError as err: ca_arg = parser.arguments.get('ca_file') ca = ca_arg.value if ca_arg and ca_arg.value else _cnf.get( 'global', 'ca_certs') stderr.write(red('SSL Authentication failed\n')) if ca: stderr.write('Path used for CA certifications file: %s\n' % ( escape_ctrl_chars(ca))) stderr.write('Please make sure the path is correct\n') if not (ca_arg and ca_arg.value): stderr.write('| To set the correct path:\n') stderr.write('| kamaki config set ca_certs CA_FILE\n') else: stderr.write('| To use a CA certifications file:\n') stderr.write('| kamaki config set ca_certs CA_FILE\n') stderr.write('| OR run with --ca-certs=FILE_LOCATION\n') stderr.write('| To ignore SSL errors and move on (%s):\n' % ( red('insecure'))) stderr.write('| kamaki config set ignore_ssl on\n') stderr.write('| OR run with --ignore-ssl\n') stderr.flush() if _debug: raise stderr.write('| %s: %s\n' % ( type(err), escape_ctrl_chars('%s' % err))) stderr.flush() exit(1) except KeyboardInterrupt: print('Canceled by user') exit(1) except Exception as er: print('Unknown Error: %s' % er) if _debug: raise exit(1)