Exemple #1
0
 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'))
Exemple #4
0
 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
Exemple #5
0
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
Exemple #6
0
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'], {})
Exemple #7
0
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'], {})
Exemple #8
0
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