def setUp(self): self.out = StringIO.StringIO() self.cfg = CLIConfig() self.cfg.register_option('test-section.test-option', 'A test') self.cmd = ConfigSubcommand(stdout=self.out) parser = argparse.ArgumentParser() self.cmd.register(parser.add_subparsers(), self.cfg) self.cmd._write_config = noop
def instance_config_args_to_values(cli_args, mode=INSTANCE_CREATOR_MODE): """ Convenience function for testing instance_config settings :param cli_args: string with args separated by spaces :return the values object as returned from argparser.parse_args() """ parser = argparse.ArgumentParser() config = CLIConfig() config.register_option( 'token', 'The default token to use when encrypting, updating, or launching' ' images') setup_instance_config_args(parser, config, mode) argv = cli_args.split() return parser.parse_args(argv)
def test_env_from_config(self): """ Test that we can use a custom environment that is stored in the config """ config = CLIConfig() env = brkt_cli.brkt_env_from_domain('foo.com') config.set_env('test', env) config.set_current_env('test') for mode in (INSTANCE_CREATOR_MODE, INSTANCE_UPDATER_MODE): brkt_config = _get_brkt_config_for_cli_args( mode=mode, cli_config=config) for attr in ('api', 'hsmproxy', 'network'): endpoint = '%s:%d' % ( getattr(env, attr + '_host'), getattr(env, attr + '_port')) self.assertEqual(endpoint, brkt_config.get(attr + '_host'))
def main(): parser = argparse.ArgumentParser( description='Command-line interface to the Bracket Computing service.', formatter_class=SortingHelpFormatter ) parser.add_argument( '-v', '--verbose', dest='verbose', action='store_true', help='Print status information to the console' ) parser.add_argument( '--version', action='version', version='brkt-cli version %s' % VERSION ) parser.add_argument( '--no-check-version', dest='check_version', action='store_false', default=True, help="Don't check whether this version of brkt-cli is supported" ) # Batch up messages that are logged while loading modules. We don't know # whether to log them yet, since we haven't parsed arguments. argparse # seems to get confused when you parse arguments twice. subcommand_load_messages = [] config = CLIConfig() # Add config options that span multiple commands config.register_option( 'token', 'The default token to use when encrypting, updating, or launching' ' images') # Dynamically load subcommands from modules. subcommands = [] for module_path in SUBCOMMAND_MODULE_PATHS: try: module = importlib.import_module(module_path) subcommands.extend(module.get_subcommands()) except ImportError as e: # Parse the module name from the module path. m = re.match(r'(.*\.)?(.+)', module_path) module_name = None if m: module_name = m.group(2) if module_name and \ e.message == ('No module named ' + module_name): # The subcommand module is not installed. subcommand_load_messages.append( 'Skipping module %s: %s' % (module_path, e)) else: # There is an import problem inside the subcommand module. raise # Use metavar to hide any subcommands that we don't want to expose. exposed_subcommand_names = [s.name() for s in subcommands if s.exposed()] metavar = '{%s}' % ','.join(sorted(exposed_subcommand_names)) subparsers = parser.add_subparsers( dest='subparser_name', metavar=metavar ) # Setup expected config sections/options before we attempt to read from # disk for s in subcommands: s.setup_config(config) # Load defaults from disk. Subcommands are expected to register config # sections at import time so that correct default values can be displayed # to users if they request help. subcommand_load_messages.append( 'Reading config from %s' % (CONFIG_PATH,)) config.read() # Add subcommands to the parser. for s in subcommands: subcommand_load_messages.append( 'Registering subcommand %s' % s.name()) s.register(subparsers, config) argv = sys.argv[1:] values = parser.parse_args(argv) # Find the matching subcommand. subcommand = None for s in subcommands: if s.name() == values.subparser_name: subcommand = s break if not subcommand: raise Exception('Could not find subcommand ' + values.subparser_name) # Initialize logging. Verbose logging can be specified for either # the top-level "brkt" command or one of the subcommands. We support # both because users got confused when "brkt encrypt-ami -v" didn't work. log_level = logging.INFO verbose = values.verbose if subcommand.verbose(values): verbose = True subcommand.init_logging(verbose) if verbose: log_level = logging.DEBUG # Prefix log messages with a compact timestamp, so that the user # knows how long each operation took. fmt = '%(asctime)s %(message)s' datefmt = '%H:%M:%S' # Set the root log level to DEBUG. This passes all log messages to all # handlers. We then filter by log level in each handler. logging.root.setLevel(logging.DEBUG) # Log to stderr at the level specified by the user. stderr_handler = logging.StreamHandler() formatter = logging.Formatter(fmt=fmt, datefmt=datefmt) stderr_handler.setFormatter(formatter) stderr_handler.setLevel(log_level) logging.root.addHandler(stderr_handler) # Optionally log to a temp file at debug level. If the command succeeds, # we delete this file. If the command fails, we keep it around so that # the user can get more details. debug_handler = None debug_log_file = None if subcommand.debug_log_to_temp_file() and log_level != logging.DEBUG: debug_log_file = tempfile.NamedTemporaryFile( delete=False, prefix='brkt_cli') debug_handler = logging.FileHandler(debug_log_file.name) formatter = logging.Formatter(fmt=fmt, datefmt=datefmt) debug_handler.setFormatter(formatter) debug_handler.setLevel(logging.DEBUG) logging.root.addHandler(debug_handler) # Write messages that were logged before logging was initialized. for msg in subcommand_load_messages: log.debug(msg) if values.check_version: if not _check_version(): return 1 result = 1 # Run the subcommand. try: result = subcommand.run(values) if not isinstance(result, (int, long)): raise Exception( '%s did not return an integer result' % subcommand.name()) log.debug('%s returned %d', subcommand.name(), result) except ValidationError as e: print(e, file=sys.stderr) except util.BracketError as e: if values.verbose: log.exception(e.message) else: log.error(e.message) except KeyboardInterrupt: if values.verbose: log.exception('Interrupted by user') else: log.error('Interrupted by user') finally: if debug_handler: if result == 0: os.remove(debug_log_file.name) else: debug_handler.close() logging.root.removeHandler(debug_handler) log.info('Debug log is available at %s', debug_log_file.name) return result
class ConfigCommandTestCase(unittest.TestCase): def setUp(self): self.out = StringIO.StringIO() self.cfg = CLIConfig() self.cfg.register_option('test-section.test-option', 'A test') self.cmd = ConfigSubcommand(stdout=self.out) parser = argparse.ArgumentParser() self.cmd.register(parser.add_subparsers(), self.cfg) self.cmd._write_config = noop def test_get_unknown_option(self): """Verify that we raise an error if the user attempts to fetch an unknown option. """ options = ['no-section', 'test-section.no-option'] for option in options: with self.assertRaises(ValidationError): self.cmd.run(GetValues(option)) def test_set_unknown_option(self): """Verify that we raise an error if the user attempts to set an unknown option. """ args = (('no-section.no-option', 'foo'), ('test-section.no-option', 'foo')) for opt, val in args: with self.assertRaises(ValidationError): self.cmd.run(SetValues(opt, val)) def test_unset_unknown_option(self): """Verify that we raise an error if the user attempts to unset an unknown option. """ options = ['no-section', 'test-section.no-option'] for option in options: with self.assertRaises(ValidationError): self.cmd.run(UnsetValues(option)) def test_set_list_get_unset(self): """Verify that we can successfully set, get, and unset an existing option. """ val = 'test-val' opt = 'test-section.test-option' self.cmd.run(SetValues(opt, val)) self.assertEqual(self.cfg.get_option(opt), val) self.cmd.run(GetValues(opt)) self.assertEqual(self.out.getvalue(), "%s\n" % (val,)) self.cmd.run(ListValues()) self.assertEqual(self.out.getvalue(), "%s\n%s=%s\n" % (val, opt, val)) self.cmd.run(UnsetValues(opt)) self.assertEqual(self.cfg.get_option(opt), None) def test_cleanup_empty_subsections(self): """Verify that we clean up empty subsections of the config""" opt1 = 'a.b.c' opt2 = 'a.d.e' for opt in [opt1, opt2]: self.cfg.register_option(opt, 'test') self.cmd.run(SetValues(opt, 'val')) self.cmd.run(UnsetValues(opt1)) self.assertEquals(self.cfg._config['options'], {'a': {'d': {'e': 'val'}}}) self.cmd.run(UnsetValues(opt2)) self.assertEquals(self.cfg._config['options'], {})
class ConfigCommandTestCase(unittest.TestCase): def setUp(self): self.out = StringIO.StringIO() self.cfg = CLIConfig() self.cfg.register_option('test-section.test-option', 'A test') self.cmd = ConfigSubcommand(stdout=self.out) parser = argparse.ArgumentParser() self.cmd.register(parser.add_subparsers(), self.cfg) self.cmd._write_config = noop def test_get_unknown_option(self): """Verify that we raise an error if the user attempts to fetch an unknown option. """ options = ['no-section', 'test-section.no-option'] for option in options: with self.assertRaises(ValidationError): self.cmd.run(GetValues(option)) def test_set_unknown_option(self): """Verify that we raise an error if the user attempts to set an unknown option. """ args = (('no-section.no-option', 'foo'), ('test-section.no-option', 'foo')) for opt, val in args: with self.assertRaises(ValidationError): self.cmd.run(SetValues(opt, val)) def test_unset_unknown_option(self): """Verify that we raise an error if the user attempts to unset an unknown option. """ options = ['no-section', 'test-section.no-option'] for option in options: with self.assertRaises(ValidationError): self.cmd.run(UnsetValues(option)) def test_set_list_get_unset(self): """Verify that we can successfully set, get, and unset an existing option. """ val = 'test-val' opt = 'test-section.test-option' self.cmd.run(SetValues(opt, val)) self.assertEqual(self.cfg.get_option(opt), val) self.cmd.run(GetValues(opt)) self.assertEqual(self.out.getvalue(), "%s\n" % (val, )) self.cmd.run(ListValues()) self.assertEqual(self.out.getvalue(), "%s\n%s=%s\n" % (val, opt, val)) self.cmd.run(UnsetValues(opt)) self.assertEqual(self.cfg.get_option(opt), None) def test_cleanup_empty_subsections(self): """Verify that we clean up empty subsections of the config""" opt1 = 'a.b.c' opt2 = 'a.d.e' for opt in [opt1, opt2]: self.cfg.register_option(opt, 'test') self.cmd.run(SetValues(opt, 'val')) self.cmd.run(UnsetValues(opt1)) self.assertEquals(self.cfg._config['options'], {'a': { 'd': { 'e': 'val' } }}) self.cmd.run(UnsetValues(opt2)) self.assertEquals(self.cfg._config['options'], {})
def main(): parser = argparse.ArgumentParser( description='Command-line interface to the Bracket Computing service.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='Print status information to the console') parser.add_argument('--version', action='version', version='brkt-cli version %s' % VERSION) parser.add_argument( '--no-check-version', dest='check_version', action='store_false', default=True, help="Don't check whether this version of brkt-cli is supported") # Batch up messages that are logged while loading modules. We don't know # whether to log them yet, since we haven't parsed arguments. argparse # seems to get confused when you parse arguments twice. subcommand_load_messages = [] config = CLIConfig() # Dynamically load subcommands from modules. subcommands = [] for module_path in SUBCOMMAND_MODULE_PATHS: try: module = importlib.import_module(module_path) subcommands.extend(module.get_subcommands()) except ImportError as e: # Parse the module name from the module path. m = re.match(r'(.*\.)?(.+)', module_path) module_name = None if m: module_name = m.group(2) if module_name and \ e.message == ('No module named ' + module_name): # The subcommand module is not installed. subcommand_load_messages.append('Skipping module %s: %s' % (module_path, e)) else: # There is an import problem inside the subcommand module. raise # Use metavar to hide any subcommands that we don't want to expose. exposed_subcommand_names = [s.name() for s in subcommands if s.exposed()] metavar = '{%s}' % ','.join(sorted(exposed_subcommand_names)) subparsers = parser.add_subparsers(dest='subparser_name', metavar=metavar) # Setup expected config sections/options before we attempt to read from # disk for s in subcommands: s.setup_config(config) # Load defaults from disk. Subcommands are expected to register config # sections at import time so that correct default values can be displayed # to users if they request help. subcommand_load_messages.append('Reading config from %s' % (CONFIG_PATH, )) config.read() # Add subcommands to the parser. for s in subcommands: subcommand_load_messages.append('Registering subcommand %s' % s.name()) s.register(subparsers, config) argv = sys.argv[1:] values = parser.parse_args(argv) # Find the matching subcommand. subcommand = None for s in subcommands: if s.name() == values.subparser_name: subcommand = s break if not subcommand: raise Exception('Could not find subcommand ' + values.subparser_name) # Initialize logging. Verbose logging can be specified for either # the top-level "brkt" command or one of the subcommands. We support # both because users got confused when "brkt encrypt-ami -v" didn't work. log_level = logging.INFO verbose = values.verbose if subcommand.verbose(values): verbose = True subcommand.init_logging(verbose) if verbose: log_level = logging.DEBUG # Log messages are written to stderr and are prefixed with a compact # timestamp, so that the user knows how long each operation took. logging.basicConfig(level=log_level, format='%(asctime)s %(message)s', datefmt='%H:%M:%S') # Write messages that were logged before logging was initialized. for msg in subcommand_load_messages: log.debug(msg) if values.check_version: if not _check_version(): return 1 # Run the subcommand. try: result = subcommand.run(values) if not isinstance(result, (int, long)): raise Exception('%s did not return an integer result' % subcommand.name()) log.debug('%s returned %d', subcommand.name(), result) return result except ValidationError as e: print(e, file=sys.stderr) except util.BracketError as e: if values.verbose: log.exception(e.message) else: log.error(e.message) except KeyboardInterrupt: if values.verbose: log.exception('Interrupted by user') else: log.error('Interrupted by user') return 1