예제 #1
0
def init():
    """Return top level command handler."""
    @click.group(cls=cli.make_multi_command('treadmill.cli.manage'))
    def manage():
        """Manage applications."""
        pass

    return manage
예제 #2
0
def init():
    """Return top level command handler."""
    @click.group(cls=cli.make_multi_command(__name__))
    @click.pass_context
    def run(_ctxp):
        """Manage Kerberos tickets."""

    return run
예제 #3
0
def init():
    """Return top level command handler."""
    @click.group(cls=cli.make_multi_command(__name__))
    def run():
        """Cross-cell supervision tools."""
        cli.init_logger('daemon.conf')

    return run
예제 #4
0
def init():
    """Return top level command handler."""
    @click.group(cls=cli.make_multi_command(__name__))
    @click.option('--install-dir',
                  required=True,
                  help='Target installation directory.',
                  envvar='TREADMILL_APPROOT')
    @click.option('--cell', required=True, envvar='TREADMILL_CELL')
    @click.option('--config',
                  required=False,
                  type=click.Path(exists=True, readable=True, allow_dash=True),
                  multiple=True)
    @click.option('--override', required=False, type=cli.DICT)
    @click.pass_context
    def install(ctx, install_dir, cell, config, override):
        """Installs Treadmill."""
        if cell == '-':
            cell = None

        if cell:
            context.GLOBAL.cell = cell
            context.GLOBAL.resolve(cell)

        ctx.obj['PARAMS'] = {
            'cell': cell,
            'zookeeper': context.GLOBAL.zk.url,
            'ldap': context.GLOBAL.ldap.url,
            'dns_domain': context.GLOBAL.dns_domain,
            'ldap_suffix': context.GLOBAL.ldap.ldap_suffix,
            'treadmill': treadmill.TREADMILL,
            'dir': install_dir,
        }

        for conf in config:
            if conf == '-':
                ctx.obj['PARAMS'].update(yaml.load(stream=sys.stdin))
            else:
                with open(conf, 'r') as fd:
                    ctx.obj['PARAMS'].update(yaml.load(stream=fd))

        if override:
            ctx.obj['PARAMS'].update(override)

        # XXX: hack - templates use treadmillid, but it is defined as
        #      "username" in cell object.
        ctx.obj['PARAMS']['treadmillid'] = ctx.obj['PARAMS'].get('username')

        os.environ['TREADMILL'] = treadmill.TREADMILL

    return install
예제 #5
0
def init():
    """Return top level command handler."""
    @click.group(cls=cli.make_multi_command('treadmill.sproc'))
    @click.option('--cgroup', help='Create separate cgroup for the service.')
    @click.option('--cell',
                  required=True,
                  envvar='TREADMILL_CELL',
                  callback=cli.handle_context_opt,
                  expose_value=False)
    @click.option('--zookeeper',
                  required=False,
                  envvar='TREADMILL_ZOOKEEPER',
                  callback=cli.handle_context_opt,
                  expose_value=False)
    @click.pass_context
    def run(ctx, cgroup):
        """Run system processes"""
        # Default logging to cli.yml, at CRITICAL, unless --debug
        log_conf_file = os.path.join(treadmill.TREADMILL, 'etc', 'logging',
                                     'daemon.yml')
        try:
            with open(log_conf_file, 'r') as fh:
                log_config = yaml.load(fh)
                logging.config.dictConfig(log_config)

        except IOError:
            with tempfile.NamedTemporaryFile(delete=False) as f:
                traceback.print_exc(file=f)
                click.echo('Unable to load log conf: %s [ %s ]' %
                           (log_conf_file, f.name),
                           err=True)

        log_level = None
        if ctx.obj.get('logging.debug'):
            log_level = logging.DEBUG
        else:
            log_level = logging.DEBUG

        logging.getLogger('kazoo').setLevel(log_level)
        logging.getLogger('treadmill').setLevel(log_level)
        logging.getLogger().setLevel(log_level)

        if cgroup:
            if cgroup == '.':
                service_name = os.path.basename(os.path.realpath(cgroup))
            else:
                service_name = cgroup
            _configure_core_cgroups(service_name)

    return run
예제 #6
0
def init():
    """Top level command handler."""
    @click.group(cls=cli.make_multi_command(__name__,
                                            chain=True,
                                            invoke_without_command=True))
    @click.option('--cell',
                  required=True,
                  envvar='TREADMILL_CELL',
                  callback=cli.handle_context_opt,
                  expose_value=False)
    @click.option('--verbose', is_flag=True, default=False)
    @click.option('--html', is_flag=True, default=False)
    def run(verbose, html):
        """Run interactive checkout."""
        del verbose
        del html

    @run.resultcallback()
    def run_tests(tests, verbose, html):
        """Run interactive checkout."""
        verbosity = 1
        if verbose:
            verbosity = 2

        suite = unittest.TestSuite()
        loader = unittest.TestLoader()

        for factory in tests:
            tests = factory()
            if isinstance(tests, collections.Iterable):
                for test in tests:
                    suite.addTests(loader.loadTestsFromTestCase(test))
            else:
                suite.addTests(loader.loadTestsFromTestCase(tests))

        if html:
            runner = HtmlTestRunner.HtmlTestRunner(
                stream=sys.stdout,
                title='Treadmill cell checkout',
                description='Treamdill cell checkout tests')
        else:
            runner = unittest.TextTestRunner(verbosity=verbosity)

        runner.run(suite)

    # commands.init(run)

    del run_tests

    return run
예제 #7
0
def init():
    """Return top level command handler."""
    @click.group(cls=cli.make_multi_command(__name__))
    @click.option('--ldap', envvar='TREADMILL_LDAP')
    @click.pass_context
    def run(ctx, ldap):
        """Admin commands."""
        cli.init_logger('admin.yml')

        log_level = logging.WARN
        if ctx.obj.get('logging.debug'):
            log_level = logging.DEBUG

        logging.getLogger('treadmill').setLevel(log_level)
        logging.getLogger().setLevel(log_level)

        if ldap:
            context.GLOBAL.ldap.url = ldap

    return run
예제 #8
0
def init():
    """Return top level command handler."""
    @click.group(cls=cli.make_multi_command(__name__))
    @click.option('--zookeeper',
                  required=False,
                  envvar='TREADMILL_ZOOKEEPER',
                  callback=cli.handle_context_opt,
                  expose_value=False)
    @click.pass_context
    def run(ctx):
        """Admin commands."""
        cli.init_logger('admin.conf')

        log_level = logging.WARN
        if ctx.obj.get('logging.debug'):
            log_level = logging.DEBUG

        logging.getLogger('treadmill').setLevel(log_level)
        logging.getLogger().setLevel(log_level)

    return run
예제 #9
0
def init():
    """Return top level command handler."""
    @click.group(cls=cli.make_multi_command('treadmill.sproc'))
    @click.option('--cgroup', help='Create separate cgroup for the service.')
    @click.option('--cell',
                  required=True,
                  envvar='TREADMILL_CELL',
                  callback=cli.handle_context_opt,
                  expose_value=False)
    @click.option('--zookeeper',
                  required=False,
                  envvar='TREADMILL_ZOOKEEPER',
                  callback=cli.handle_context_opt,
                  expose_value=False)
    @click.pass_context
    def run(ctx, cgroup):
        """Run system processes"""
        # Default logging to daemon.conf, at CRITICAL, unless --debug
        cli.init_logger('daemon.conf')

        log_level = None
        if ctx.obj.get('logging.debug'):
            log_level = logging.DEBUG
        else:
            log_level = logging.DEBUG

        logging.getLogger('kazoo').setLevel(log_level)
        logging.getLogger('treadmill').setLevel(log_level)
        logging.getLogger().setLevel(log_level)

        if cgroup:
            if cgroup == '.':
                service_name = os.path.basename(os.path.realpath(cgroup))
            else:
                service_name = cgroup
            _configure_core_cgroups(service_name)

    return run
예제 #10
0
import requests

# pylint complains about imports from treadmill not grouped, but import
# dependencies need to come first.
#
# pylint: disable=C0412
from treadmill import cli


# pylint complains "No value passed for parameter 'ldap' in function call".
# This is ok, as these parameters come from click decorators.
#
# pylint: disable=E1120
#
# TODO: add options to configure logging.
@click.group(cls=cli.make_multi_command('treadmill.cli'))
@click.option('--dns-domain',
              required=False,
              envvar='TREADMILL_DNS_DOMAIN',
              callback=cli.handle_context_opt,
              is_eager=True,
              expose_value=False)
@click.option('--dns-server',
              required=False,
              envvar='TREADMILL_DNS_SERVER',
              callback=cli.handle_context_opt,
              is_eager=True,
              expose_value=False)
@click.option('--ldap',
              required=False,
              envvar='TREADMILL_LDAP',
예제 #11
0
def init():
    """Return top level command handler."""

    @click.group(cls=cli.make_multi_command('treadmill.cli.admin.checkout',
                                            chain=True,
                                            invoke_without_command=True))
    @click.option('--outdir', help='Output directory.',
                  required=True, type=click.Path(exists=True))
    @click.option('--interval', help='Interval between tests.',
                  required=False, type=int, default=(60 * 5))
    @click.option('--randomize',
                  help='Optional random interval between tests.',
                  required=False, type=int, default=(60 * 5))
    @click.option('--age',
                  help='Max report age to keep.',
                  default='1d')
    @click.option('--plugin',
                  help='Result processing plugin.')
    @click.option('--port', type=int,
                  help='Web server port.')
    def run(outdir, interval, randomize, age, plugin, port):
        """Test treadmill infrastructure."""
        del outdir
        del interval
        del randomize
        del age
        del plugin
        del port

    @run.resultcallback()
    def run_tests(tests, outdir, interval, randomize, age, plugin, port):
        """Test treadmill infrastructure."""

        if port is not None:
            port = _start_webserver_daemon(outdir, port)

        _LOGGER.info('Starting tests: %s', outdir)
        fs.mkdir_safe(outdir)

        checkout_ext = None
        if plugin:
            try:
                checkout_ext = importlib.import_module(plugin)
            except Exception:  # pylint: disable=W0703
                _LOGGER.exception('Checkout plugin not found.')

        # time.sleep(random.randint(0, 60))

        while True:

            report_name = '%s.html' % datetime.datetime.isoformat(
                datetime.datetime.now()
            )
            report_file = os.path.join(outdir, report_name)
            report_url = 'http://%s:%s/checkout/%s' % (
                sysinfo.hostname(), port, report_name
            )
            _LOGGER.info('Running checkout suite: %s', report_file)

            try:
                loader = unittest.TestLoader()
                suite = unittest.TestSuite()
                for factory in tests:

                    testcases = factory()
                    if not isinstance(testcases, collections.Iterable):
                        testcases = [testcases]

                    for test in testcases:
                        suite.addTests(loader.loadTestsFromTestCase(test))

                with open(report_file, 'w+') as stream:
                    runner = HtmlTestRunner.HtmlTestRunner(
                        stream=stream,
                        title='Treadmill cell checkout',
                        description='Treamdill cell checkout tests'
                    )

                    result = runner.run(suite)
                    if checkout_ext:
                        checkout_ext.process(context.GLOBAL.cell,
                                             report_url, result)

            except Exception as err:  # pylint: disable=W0703
                _LOGGER.exception('Unhandled exception during checkout')
                with open(report_file, 'w+') as stream:
                    stream.write(str(err))
                    traceback.print_exc(file=stream)

                    if checkout_ext:
                        checkout_ext.process(context.GLOBAL.cell,
                                             report_url, None)

            _cleanup(outdir, age)

            total_interval = interval + random.randint(0, randomize)
            _LOGGER.info('Sleep for %s sec.', total_interval)
            time.sleep(total_interval)

    del run_tests
    return run
예제 #12
0
def make_manage_multi_command(module_name, **click_args):
    """Make a Click multicommand from all submodules of the module."""

    old_multi = cli.make_multi_command(module_name, **click_args)
    new_multi = cli.make_commands(module_name, **click_args)

    class MCommand(click.MultiCommand):
        """Treadmill CLI driver."""

        def __init__(self, *args, **kwargs):
            self.old_multi = old_multi(*args, **kwargs)
            self.new_multi = new_multi(*args, **kwargs)
            if kwargs and click_args:
                kwargs.update(click_args)

            click.MultiCommand.__init__(self, *args, **kwargs)

        def list_commands(self, ctx):
            old_commands = set(self.old_multi.list_commands(ctx))
            new_commands = set(self.new_multi.list_commands(ctx))
            return sorted(old_commands | new_commands)

        def invoke(self, ctx):
            """
            invoke the command in a subprocess if it is executable
            otherwise use it in process
            """
            name = ctx.protected_args[0]
            try:
                module = plugin_manager.load(module_name, name)
            except KeyError:
                return super(MCommand, self).invoke(ctx)

            module_path = module.__file__
            if module_path.endswith('pyc'):
                module_path = module_path[:-1]
            # shebang doesn't work on windows
            # we use .cmd or a hardcoded default interpreter
            if os.name == 'nt':
                nt_path = module_path[:-2] + 'cmd'
                if os.path.exists(nt_path):
                    utils.sane_execvp(nt_path, [nt_path] + ctx.args)
                else:
                    _LOGGER.critical(
                        "%s cli is not supported on windows", name)
            else:
                is_exec = os.access(module_path, os.X_OK)
                if not is_exec:
                    return super(MCommand, self).invoke(ctx)
                utils.sane_execvp(module_path,
                                  [os.path.basename(module_path)] + ctx.args)

        def get_command(self, ctx, cmd_name):
            try:
                return self.new_multi.get_command(ctx, cmd_name)
            except click.UsageError:
                pass
            return self.old_multi.get_command(ctx, cmd_name)

        def format_commands(self, ctx, formatter):
            rows = []
            for subcommand in self.list_commands(ctx):
                entry_points = list(pkg_resources.iter_entry_points(
                    module_name, subcommand))
                # Try get the help with importlib if entry_point not found
                if not entry_points:
                    cmd = self.old_multi.get_command(ctx, subcommand)
                    if cmd is None:
                        continue
                    rows.append((subcommand, cmd.short_help or ''))
                else:
                    dist = entry_points[0].dist
                    if dist.has_metadata('cli_help'):
                        help_text = dist.get_metadata('cli_help')
                    else:
                        help_text = ''
                    rows.append((subcommand, help_text))

            if rows:
                with formatter.section('Commands'):
                    formatter.write_dl(rows)

    return MCommand