Beispiel #1
0
    def choose(self):
        if self.args.action in ['start', 'stop', 'restart']:
            if not self.args.pidfile:
                print colors.red("The --pidfile option is required"
                                 " with [start, stop, restart] commands",
                                 bold=1)
                exit(1)
            super(AgentNode, self).__init__(self.args.pidfile)

        getattr(self, self.args.action, 'run')()
Beispiel #2
0
    def choose(self):
        if self.args.action in ['start', 'stop', 'restart']:
            if not self.args.pidfile:
                print colors.red(
                    "The --pidfile option is required"
                    " with [start, stop, restart] commands",
                    bold=1)
                exit(1)
            super(AgentNode, self).__init__(self.args.pidfile)

        getattr(self, self.args.action, 'run')()
Beispiel #3
0
class TriggerManager(Daemon):
    """
        Main dispatcher. Receives requests from clients
        and runs them on the specified nodes
    """
    def __init__(self, *_args, **kwargs):
        self.arg_parser = argparse.ArgumentParser()

        controllers = self.arg_parser.add_subparsers(dest='action',
                                                     help='Shell commands')
        service = controllers.add_parser(
            'service', help='Start trigger monitoring service')

        service.add_argument('-p',
                             '--pidfile',
                             dest='pidfile',
                             help='Daemonize process with the '
                             'given pid file')
        service.add_argument('-c', '--config', help='Config file')
        service.add_argument(
            'action',
            choices=['start', 'stop', 'restart', 'run'],
            help='Apply action on the daemonized process\n'
            'For the actions [start, stop, restart] - pass a pid file\n'
            'Run - start process in debug mode\n')

        exec_ = controllers.add_parser('exec', help='Execute cron job')
        exec_.add_argument('job_name', help='Job name')
        exec_.add_argument('-t', '--tags', help='Comma-separated tags')
        exec_.add_argument('-e', '--env', help='Environment')

        setattr(self, 'exec', self.run_job)
        if _args:
            self.args = self.arg_parser.parse_args(_args)

        global CONFIG
        if 'config' in kwargs:
            CONFIG = Config(kwargs['config'])

    def parse_cli(self):
        self.args = self.arg_parser.parse_args()

        try:
            argcomplete.autocomplete(self.arg_parser)
        except Exception, ex:
            LOG.warn(ex)
            pass

        if hasattr(self.args, 'pidfile'):
            super(TriggerManager, self).__init__(self.args.pidfile,
                                                 stdout='/tmp/log')
        elif self.args.action in ['start', 'stop', 'restart']:
            print colors.red(
                "The --pidfile option is required"
                " with [start, stop, restart] commands",
                bold=1)
            exit(1)
Beispiel #4
0
    def remove(self, common_name=None, fingerprint=None):
        if not common_name and not fingerprint:
            print colors.red("You should specify either common name or "
                             "fingerprint to be removed.")
            return False

        keys = []
        with open(self.store_fn, 'r') as f:
            for l in f:
                cn, _, fp = l.strip().rpartition(self.SEP)
                if common_name != cn and fingerprint != fp:
                    keys.append("%s%s%s" % (cn, self.SEP, fp))

        f = open(self.store_fn, 'w')
        f.write('\n'.join(keys))
        f.close()
        print colors.blue("Fingerprint/Common name %s/%s was removed" %
                          (common_name, fingerprint))
        self.reload()
        return True
Beispiel #5
0
    def remove(self, common_name=None, fingerprint=None):
        if not common_name and not fingerprint:
            print colors.red("You should specify either common name or "
                             "fingerprint to be removed.")
            return False

        keys = []
        with open(self.store_fn, 'r') as f:
            for l in f:
                cn, _, fp = l.strip().rpartition(self.SEP)
                if common_name != cn and fingerprint != fp:
                    keys.append("%s%s%s" % (cn, self.SEP, fp))

        f = open(self.store_fn, 'w')
        f.write('\n'.join(keys))
        f.close()
        print colors.blue("Fingerprint/Common name %s/%s was removed" %
                          (common_name, fingerprint))
        self.reload()
        return True
Beispiel #6
0
    def load_transport_class(self):
        self.transport_class = None

        # Defaults to Single-user transport
        transport_class = CONFIG.transport or \
            'cloudrunner.plugins.transport.node_transport.NodeTransport'

        (mod, _, klass) = transport_class.rpartition('.')
        transport_module = load_plugins_from(mod, [TransportBackend])
        if not transport_module:
            print colors.red("Cannot find module for transport plugin: %s" %
                             mod)
            exit(1)
        for _klass in transport_module:
            if _klass.__name__ == klass:
                self.transport_class = _klass
                break

        if not self.transport_class:
            print colors.red("Cannot find transport class %s from module %s" %
                             (klass, mod))
            exit(1)
Beispiel #7
0
    def load_transport_class(self):
        self.transport_class = None

        # Defaults to Single-user transport
        transport_class = CONFIG.transport or \
            'cloudrunner.plugins.transport.node_transport.NodeTransport'

        (mod, _, klass) = transport_class.rpartition('.')
        transport_module = load_plugins_from(mod, [TransportBackend])
        if not transport_module:
            print colors.red("Cannot find module for transport plugin: %s" %
                             mod)
            exit(1)
        for _klass in transport_module:
            if _klass.__name__ == klass:
                self.transport_class = _klass
                break

        if not self.transport_class:
            print colors.red(
                "Cannot find transport class %s from module %s" % (klass,
                                                                   mod))
            exit(1)
Beispiel #8
0
    def insert(self, common_name, fingerprint):
        access_key = "%s%s%s" % (common_name, self.SEP, fingerprint)

        with open(self.store_fn, 'r') as f:
            for l in f:
                cn, _, fp = l.partition(self.SEP)
                if fp == fingerprint:
                    print colors.red(
                        "The specified fingerprint already exists. "
                        "You should first unregister it.")
                    return False
                if cn == common_name and fp != fingerprint:
                    print colors.red(
                        "The specified common name already exists. "
                        "You should first unregister it.")
                    return False

        with open(self.store_fn, 'a') as f:
            f.write('\n%s' % access_key)
            f.close()
            print colors.blue("Fingerprint for %s was added" % common_name)
        self.reload()
        return True
Beispiel #9
0
    def __init__(self):
        super(Daemon, self).__init__()

        self._parser = _parser()
        try:
            argcomplete.autocomplete(self._parser)
        except:
            pass

        self.args = self._parser.parse_args()

        if 'NO_COLORS' in os.environ:
            colors.disable()

        # Defaults to Single-user transport
        transport_class = CONFIG.transport or \
            'cloudrunner.plugins.transport.node_transport.NodeTransport'

        (mod, _, klass) = transport_class.rpartition('.')
        self.transport_class = None
        transport_module = load_plugins_from(mod, [TransportBackend])
        if not transport_module:
            print colors.red("Cannot find module for transport plugin: %s" %
                             mod)
            exit(1)
        for _klass in transport_module:
            if _klass.__name__ == klass:
                self.transport_class = _klass
                break

        if not self.transport_class:
            print colors.red("Cannot find transport class %s from module %s" %
                            (klass, mod))
            exit(1)

        assert self.transport_class
        load_plugins(CONFIG)
Beispiel #10
0
    def insert(self, common_name, fingerprint):
        access_key = "%s%s%s" % (common_name, self.SEP, fingerprint)

        with open(self.store_fn, 'r') as f:
            for l in f:
                cn, _, fp = l.partition(self.SEP)
                if fp == fingerprint:
                    print colors.red(
                        "The specified fingerprint already exists. "
                        "You should first unregister it.")
                    return False
                if cn == common_name and fp != fingerprint:
                    print colors.red(
                        "The specified common name already exists. "
                        "You should first unregister it.")
                    return False

        with open(self.store_fn, 'a') as f:
            f.write('\n%s' % access_key)
            f.close()
            print colors.blue("Fingerprint for %s was added" %
                              common_name)
        self.reload()
        return True
Beispiel #11
0
def main():
    parser = argparse.ArgumentParser(description='CloudRunner CLI tool')

    _common = argparse.ArgumentParser(add_help=False)
    _common.add_argument('-c', '--config', help="Config file")

    commands = parser.add_subparsers(dest='controller', help='Commands')

    def _eval_config():
        global __CONFIG__
        if not __CONFIG__:
            try:
                if sys.argv.index('-c') >= 0:
                    __CONFIG__ = Config(sys.argv[sys.argv.index('-c') + 1])
                elif sys.argv.index('--config') >= 0:
                    __CONFIG__ = Config(sys.argv[sys.argv.index('--config') +
                                                 1])
            except:
                __CONFIG__ = Config(CONFIG_LOCATION)

        return __CONFIG__

    def _list_active_nodes(prefix, parsed_args, **kwargs):
        global __ACT_NODES__
        if not __ACT_NODES__:
            _config = _eval_config()
            __ACT_NODES__ = functions.CertController(_config).\
                list_all_approved()
        return (c for c in __ACT_NODES__ if c.startswith(prefix))

    def _list_pending_nodes(prefix, parsed_args, **kwargs):
        global __PEND_NODES__
        if not __PEND_NODES__:
            _config = _eval_config()
            __PEND_NODES__ = functions.CertController(_config).list_pending()
        return (c for c in __PEND_NODES__ if c.startswith(prefix))

    def _list_sub_ca(prefix, parsed_args, **kwargs):
        global __CA__
        if not __CA__:
            _config = _eval_config()
            __CA__ = functions.CertController(_config).list_ca()
        return (c[1] for c in __CA__ if c[1].startswith(prefix))

    # Cert command
    cert = commands.add_parser('cert', parents=[_common],
                               help='Manage node certificates')

    c_subcmd = cert.add_subparsers(dest='action', help='Cert actions help')

    c_subcmd.add_parser('list',
                        help='List all node certificates')

    cert_sign = c_subcmd.add_parser('sign',
                                    help='Sign a pending node certificate')
    cert_sign.add_argument('nodes', nargs="+",
                           help='Node common names').completer = \
        _list_pending_nodes

    sign_opts = cert_sign.add_mutually_exclusive_group(required=True)
    sign_opts.add_argument('--ca', help='Node organization/Sub-CA name').\
        completer = _list_sub_ca
    sign_opts.add_argument('--auto', action='store_true',
                           help='Get organization from client request')

    cert_ca = c_subcmd.add_parser('create_ca',
                                  help='Create an organization CA certificate')
    cert_ca.add_argument('ca',
                         help='Org/Sub-CA name')

    c_subcmd.add_parser('list_ca', help='List organizations/'
                        'Sub-CA certificates')

    cert_update_ca = c_subcmd.add_parser('update_ca', help='Update CA keys')

    cert_update_ca.add_argument('ca', help='Org/Sub-CA name')
    cert_update_ca.add_argument('-k', '--ca-key', help='Org/Sub-CA key file')
    cert_update_ca.add_argument('-c', '--ca-cert', help='Org/Sub-CA cert file')

    cert_auto_sign = c_subcmd.add_parser('autosign',
                                         help='Automatically sign a node '
                                         'certificate with the specified name,'
                                         ' when it arrives')
    cert_auto_sign.add_argument('node',
                                help='Node common name')

    cert_auto_sign.add_argument(
        '--expires', default=20,
        help='Set expiration of the auto-sign notice in minutes. '
        'Default is %d(default) min')

    cert_revoke = c_subcmd.add_parser('revoke',
                                      help='Revoke already issued certificate')
    cert_revoke.add_argument('nodes', nargs="+", help='Node common names').\
        completer = _list_active_nodes

    cert_revoke.add_argument('--ca', required=True,
                             help='Node organization/Sub-CA name').\
        completer = _list_sub_ca

    cert_revoke_ca = c_subcmd.add_parser('revoke_ca',
                                         help='Revoke existing Sub-CA')
    cert_revoke_ca.add_argument('ca',
                                help='Sub-CA name').completer = _list_sub_ca

    cert_auto = c_subcmd.add_parser('autosign',
                                    help='Automatically sign new cert request '
                                         'in a limited time frame.')
    cert_auto.add_argument('node',
                           help='Node common name')

    cert_auto.add_argument('-t', '--timeout', default=120,
                           help='Allowed time frame in seconds'
                           ' to wait for node to make request.'
                           ' Default is %(default)s sec.',
                           required=False)

    clear_req = c_subcmd.add_parser('clear_req',
                                    help='Clear pending node request')
    clear_req.add_argument('nodes', nargs="+", help='Node common names').\
        completer = _list_pending_nodes

    clear_req.add_argument('--ca', help='Node organization/Sub-CA name',
                           required=True).completer = _list_sub_ca

    # Configure command

    config = commands.add_parser('config', parents=[_common],
                                 help='Initial certificate configuration')

    config_actions = config.add_subparsers(dest='action',
                                           help='Manage CloudRunner dispatcher'
                                           ' configuration')

    config_actions.add_parser('check',
                              help='Check if config is missing '
                              'and initiate fresh configuration')

    config_new = config_actions.add_parser('create',
                                           help='Create new configuration')

    config_new.add_argument('-p', '--path',
                            help='Create initial configuration'
                            ' at the specified location. '
                            'This will make all currently '
                            'registered nodes to stop working'
                            'and all signed certificates will '
                            'be no longer valid',
                            required=False)

    config_new.add_argument('-o', '--overwrite',
                            action='store_true',
                            help='Overwrite any existing '
                            'configuration. Use with caution!',
                            required=False)

    config_new.add_argument('-k', '--key-size', default=2048,
                            help='Default size of keys for '
                            'CA/Server. Default is %(default)s',
                            required=False)

    config_actions.add_parser('show',
                              help='Printing current configuration')

    conf_set = config_actions.add_parser('set',
                                         help='Set config values')

    conf_set.add_argument('Section.key=value',
                          help='Section.key=value')

    conf_get = config_actions.add_parser('get',
                                         help='Get config values')

    conf_get.add_argument('Section.key',
                          help='Section.key')

    # Users command

    def _list_users(prefix, parsed_args, **kwargs):
        global __USERS__
        if not __USERS__:
            __USERS__ = []
            _config = _eval_config()
            for u in functions.UserController(_config, to_print=False).list():
                if u[0] == functions.DATA:
                    __USERS__.extend(u[1])
        return (c for c in __USERS__ if c.startswith(prefix))

    def _list_org(prefix, parsed_args, **kwargs):
        global __ORG__
        if not __ORG__:
            __ORG__ = []
            _config = _eval_config()
            for u in functions.UserController(_config,
                                              to_print=False).list_orgs():
                if u[0] == functions.DATA:
                    __ORG__.extend(u[1])
        return (c[0] for c in __ORG__ if c[0].startswith(prefix))

    def _list_tiers(prefix, parsed_args, **kwargs):
        global __TIERS__
        if not __TIERS__:
            __TIERS__ = []
            _config = _eval_config()
            for u in functions.TierController(_config,
                                              to_print=False).list_tiers():
                if u[0] == functions.DATA:
                    __TIERS__.extend(u[1])
        return (c[0] for c in __TIERS__ if c[0].startswith(prefix))

    orgs = commands.add_parser('org', parents=[_common],
                               help='Organization management')
    orgs_actions = orgs.add_subparsers(dest='action',
                                       help='Manage Organizations')

    orgs_actions.add_parser('list',
                            help='List all organizations')

    org_add = orgs_actions.add_parser('create',
                                      help='Create new organization')
    org_add.add_argument('name', help='Organization name')
    org_add.add_argument('tier', help='Tier name')

    org_remove = orgs_actions.add_parser('remove',
                                         help='Remove organization/Sub-CA')

    org_remove.add_argument('name', help='Organization/Sub-CA name').\
        completer = _list_org

    org_activate = orgs_actions.add_parser('activate',
                                           help='Activate organization')
    org_activate.add_argument('name', help='Organization name').\
        completer = _list_org

    org_deactivate = orgs_actions.add_parser(
        'deactivate', help='Deactivate organization')

    org_deactivate.add_argument('name', help='Organization name').\
        completer = _list_org

    org_tier = orgs_actions.add_parser(
        'assign_tier', help='Assign usage tier to Organization')

    org_tier.add_argument('name', help='Organization name').\
        completer = _list_org

    org_tier.add_argument('tier', help='Tier name').\
        completer = _list_tiers

    users = commands.add_parser('users', parents=[_common],
                                help='User management')

    users_actions = users.add_subparsers(dest='action',
                                         help='Manage CloudRunner users')

    users_actions.add_parser('list', help='List all users')

    users_actions.add_parser('list_orgs', help='List all organizations')

    users_add = users_actions.add_parser('create',
                                         help='Create new user')

    users_add.add_argument('username', help='User name')
    users_add.add_argument('password', help='Auth password')
    users_add.add_argument('--org', required=True, help='Organization')

    users_perm = users_actions.add_parser('add_perm',
                                          help='Create new auth permission')

    users_perm.add_argument('username',
                            help='User name').completer = _list_users

    users_perm.add_argument('permission', help="Permission name")

    users_perms = users_actions.add_parser('permissions',
                                           help='List permissions for user')

    users_perms.add_argument('username',
                             help='User name').completer = _list_users

    users_rm_perm = users_actions.add_parser(
        'rm_perm', help='Remove permission for user')

    users_rm_perm.add_argument('username',
                               help='User name').completer = _list_users

    users_rm_perm.add_argument('permission', help="Permission name")

    users_remove = users_actions.add_parser('remove',
                                            help='Create new user')

    users_remove.add_argument('username', help='User name')

    tiers = commands.add_parser('tiers', parents=[_common],
                                help='Usage tier management')
    tiers_actions = tiers.add_subparsers(dest='action',
                                         help='Manage Usage Tiers')

    tiers_actions.add_parser('list',
                             help='List all usage tiers')

    tier_add = tiers_actions.add_parser('create',
                                        help='Create new usage tier')
    tier_add.add_argument('name', help='Tier name')
    tier_add.add_argument('title', help='Tier title')
    tier_add.add_argument('description', help='Tier description',)
    tier_add.add_argument('--total_repos', help='Tier total repos',
                          required=True)
    tier_add.add_argument('--external_repos', help='Tier external repos',
                          required=True, action='store_true')
    tier_add.add_argument('--nodes', help='Tier max nodes',
                          required=True)
    tier_add.add_argument('--users', help='Tier max users',
                          required=True)
    tier_add.add_argument('--groups', help='Tier max groups',
                          required=True)
    tier_add.add_argument('--roles', help='Tier max roles',
                          required=True)
    tier_add.add_argument('--max_timeout', help='Tier max timeout',
                          required=True)
    tier_add.add_argument('--max_concurrent_tasks', help='Tier max tasks',
                          required=True)
    tier_add.add_argument('--log_retention_days',
                          help='Tier log retention days',
                          required=True)
    tier_add.add_argument('--cron_jobs', help='Tier cron jobs',
                          required=True)
    tier_add.add_argument('--api_keys', help='Api keys',
                          required=True)
    tier_add.add_argument('--deployments', help='Deployments',
                          required=True)
    tier_add.add_argument('--cloud_profiles', help='Cloud profiles',
                          required=True)

    tier_edit = tiers_actions.add_parser('edit',
                                         help='Edit usage tier')
    tier_edit.add_argument('name', help='Tier name').completer = _list_tiers
    tier_edit.add_argument('--title', help='Tier title')
    tier_edit.add_argument('--description', help='Tier description',)
    tier_edit.add_argument('--total_repos', help='Tier total repos')
    tier_edit.add_argument('--external_repos', help='Tier external repos',
                           choices=['1', '0'], default=None)
    tier_edit.add_argument('--nodes', help='Tier max nodes')
    tier_edit.add_argument('--users', help='Tier max users')
    tier_edit.add_argument('--groups', help='Tier max groups')
    tier_edit.add_argument('--roles', help='Tier max roles')
    tier_edit.add_argument('--max_timeout', help='Tier max timeout')
    tier_edit.add_argument('--max_concurrent_tasks', help='Tier max tasks')
    tier_edit.add_argument('--log_retention_days',
                           help='Tier log retention days')
    tier_edit.add_argument('--cron_jobs', help='Tier cron jobs')
    tier_edit.add_argument('--api_keys', help='Api keys')

    tier_remove = tiers_actions.add_parser('remove',
                                           help='Remove usage tier')
    tier_remove.add_argument('name', help='Tier name').completer = _list_tiers

    try:
        argcomplete.autocomplete(parser)
    except:
        pass

    args = parser.parse_args()
    kwargs = vars(args)
    action = kwargs.pop("action")
    controller = kwargs.pop("controller")
    _config = kwargs.pop("config")

    class OrgController(object):

        def __init__(self, config):
            self.cont = functions.UserController(config)

        def create(self, name, tier, **kwargs):
            return self.cont.create_org(name, tier)

        def activate(self, name, **kwargs):
            return self.cont.activate_org(name)

        def deactivate(self, name, **kwargs):
            return self.cont.deactivate_org(name)

        def list(self, **kwargs):
            return self.cont.list_orgs()

        def assign_tier(self, name, tier):
            return self.cont.assign_tier(name, tier)

        def remove(self, name, **kwargs):
            return self.cont.remove_org(name)

    controllers = {'cert': functions.CertController,
                   'init': functions.ConfigController,
                   'config': functions.ConfigController,
                   'users': functions.UserController,
                   'tiers': functions.TierController,
                   'org': OrgController}
    config = Config(_config or CONFIG_LOCATION)

    printers = {
        functions.TAG: lambda *args: colors.yellow(*args, bold=1),
        functions.DATA: colors.blue,
        functions.ERR: lambda *args: colors.red(*args, bold=1),
        functions.NOTE: colors.grey,
        functions.EMPTY: colors.blue,
    }
    try:
        items = getattr(controllers[controller](config),
                        action)(**kwargs)
        if not items:
            return
        for line in items:
            _type, printables = line
            if isinstance(printables, (list, tuple)):
                for i in range(len(printables)):
                    if isinstance(printables[i], list):
                        printables[i] = '\n'.join(
                            concat(p) for p in printables[i])
                printables = [concat(p) for p in printables]
                print printers[_type]('\n'.join([p for p in printables]))
            else:
                print printables
    except Exception, ex:
        print colors.red("%r" % ex)
Beispiel #12
0
def main():
    parser = argparse.ArgumentParser(description='CloudRunner CLI tool')

    _common = argparse.ArgumentParser(add_help=False)
    _common.add_argument('-c', '--config', help="Config file")

    commands = parser.add_subparsers(dest='controller', help='Commands')

    def _eval_config():
        global __CONFIG__
        if not __CONFIG__:
            try:
                if sys.argv.index('-c') >= 0:
                    __CONFIG__ = Config(sys.argv[sys.argv.index('-c') + 1])
                elif sys.argv.index('--config') >= 0:
                    __CONFIG__ = Config(sys.argv[sys.argv.index('--config') +
                                                 1])
            except:
                __CONFIG__ = Config(CONFIG_LOCATION)

        return __CONFIG__

    def _list_active_nodes(prefix, parsed_args, **kwargs):
        global __ACT_NODES__
        if not __ACT_NODES__:
            _config = _eval_config()
            __ACT_NODES__ = functions.CertController(_config).\
                list_all_approved()
        return (c for c in __ACT_NODES__ if c.startswith(prefix))

    def _list_pending_nodes(prefix, parsed_args, **kwargs):
        global __PEND_NODES__
        if not __PEND_NODES__:
            _config = _eval_config()
            __PEND_NODES__ = functions.CertController(_config).list_pending()
        return (c for c in __PEND_NODES__ if c.startswith(prefix))

    def _list_sub_ca(prefix, parsed_args, **kwargs):
        global __CA__
        if not __CA__:
            _config = _eval_config()
            __CA__ = functions.CertController(_config).list_ca()
        return (c[1] for c in __CA__ if c[1].startswith(prefix))

    # Cert command
    cert = commands.add_parser('cert',
                               parents=[_common],
                               help='Manage node certificates')

    c_subcmd = cert.add_subparsers(dest='action', help='Cert actions help')

    c_subcmd.add_parser('list', help='List all node certificates')

    cert_sign = c_subcmd.add_parser('sign',
                                    help='Sign a pending node certificate')
    cert_sign.add_argument('nodes', nargs="+",
                           help='Node common names').completer = \
        _list_pending_nodes

    sign_opts = cert_sign.add_mutually_exclusive_group(required=True)
    sign_opts.add_argument('--ca', help='Node organization/Sub-CA name').\
        completer = _list_sub_ca
    sign_opts.add_argument('--auto',
                           action='store_true',
                           help='Get organization from client request')

    cert_ca = c_subcmd.add_parser('create_ca',
                                  help='Create an organization CA certificate')
    cert_ca.add_argument('ca', help='Org/Sub-CA name')

    c_subcmd.add_parser('list_ca',
                        help='List organizations/'
                        'Sub-CA certificates')

    cert_update_ca = c_subcmd.add_parser('update_ca', help='Update CA keys')

    cert_update_ca.add_argument('ca', help='Org/Sub-CA name')
    cert_update_ca.add_argument('-k', '--ca-key', help='Org/Sub-CA key file')
    cert_update_ca.add_argument('-c', '--ca-cert', help='Org/Sub-CA cert file')

    cert_auto_sign = c_subcmd.add_parser('autosign',
                                         help='Automatically sign a node '
                                         'certificate with the specified name,'
                                         ' when it arrives')
    cert_auto_sign.add_argument('node', help='Node common name')

    cert_auto_sign.add_argument(
        '--expires',
        default=20,
        help='Set expiration of the auto-sign notice in minutes. '
        'Default is %d(default) min')

    cert_revoke = c_subcmd.add_parser('revoke',
                                      help='Revoke already issued certificate')
    cert_revoke.add_argument('nodes', nargs="+", help='Node common names').\
        completer = _list_active_nodes

    cert_revoke.add_argument('--ca', required=True,
                             help='Node organization/Sub-CA name').\
        completer = _list_sub_ca

    cert_revoke_ca = c_subcmd.add_parser('revoke_ca',
                                         help='Revoke existing Sub-CA')
    cert_revoke_ca.add_argument('ca',
                                help='Sub-CA name').completer = _list_sub_ca

    cert_auto = c_subcmd.add_parser('autosign',
                                    help='Automatically sign new cert request '
                                    'in a limited time frame.')
    cert_auto.add_argument('node', help='Node common name')

    cert_auto.add_argument('-t',
                           '--timeout',
                           default=120,
                           help='Allowed time frame in seconds'
                           ' to wait for node to make request.'
                           ' Default is %(default)s sec.',
                           required=False)

    clear_req = c_subcmd.add_parser('clear_req',
                                    help='Clear pending node request')
    clear_req.add_argument('nodes', nargs="+", help='Node common names').\
        completer = _list_pending_nodes

    clear_req.add_argument('--ca',
                           help='Node organization/Sub-CA name',
                           required=True).completer = _list_sub_ca

    # Configure command

    config = commands.add_parser('config',
                                 parents=[_common],
                                 help='Initial certificate configuration')

    config_actions = config.add_subparsers(dest='action',
                                           help='Manage CloudRunner dispatcher'
                                           ' configuration')

    config_actions.add_parser('check',
                              help='Check if config is missing '
                              'and initiate fresh configuration')

    config_new = config_actions.add_parser('create',
                                           help='Create new configuration')

    config_new.add_argument('-p',
                            '--path',
                            help='Create initial configuration'
                            ' at the specified location. '
                            'This will make all currently '
                            'registered nodes to stop working'
                            'and all signed certificates will '
                            'be no longer valid',
                            required=False)

    config_new.add_argument('-o',
                            '--overwrite',
                            action='store_true',
                            help='Overwrite any existing '
                            'configuration. Use with caution!',
                            required=False)

    config_new.add_argument('-k',
                            '--key-size',
                            default=2048,
                            help='Default size of keys for '
                            'CA/Server. Default is %(default)s',
                            required=False)

    config_actions.add_parser('show', help='Printing current configuration')

    conf_set = config_actions.add_parser('set', help='Set config values')

    conf_set.add_argument('Section.key=value', help='Section.key=value')

    conf_get = config_actions.add_parser('get', help='Get config values')

    conf_get.add_argument('Section.key', help='Section.key')

    # Users command

    def _list_users(prefix, parsed_args, **kwargs):
        global __USERS__
        if not __USERS__:
            __USERS__ = []
            _config = _eval_config()
            for u in functions.UserController(_config, to_print=False).list():
                if u[0] == functions.DATA:
                    __USERS__.extend(u[1])
        return (c for c in __USERS__ if c.startswith(prefix))

    def _list_org(prefix, parsed_args, **kwargs):
        global __ORG__
        if not __ORG__:
            __ORG__ = []
            _config = _eval_config()
            for u in functions.UserController(_config,
                                              to_print=False).list_orgs():
                if u[0] == functions.DATA:
                    __ORG__.extend(u[1])
        return (c[0] for c in __ORG__ if c[0].startswith(prefix))

    def _list_tiers(prefix, parsed_args, **kwargs):
        global __TIERS__
        if not __TIERS__:
            __TIERS__ = []
            _config = _eval_config()
            for u in functions.TierController(_config,
                                              to_print=False).list_tiers():
                if u[0] == functions.DATA:
                    __TIERS__.extend(u[1])
        return (c[0] for c in __TIERS__ if c[0].startswith(prefix))

    orgs = commands.add_parser('org',
                               parents=[_common],
                               help='Organization management')
    orgs_actions = orgs.add_subparsers(dest='action',
                                       help='Manage Organizations')

    orgs_actions.add_parser('list', help='List all organizations')

    org_add = orgs_actions.add_parser('create', help='Create new organization')
    org_add.add_argument('name', help='Organization name')
    org_add.add_argument('tier', help='Tier name')

    org_remove = orgs_actions.add_parser('remove',
                                         help='Remove organization/Sub-CA')

    org_remove.add_argument('name', help='Organization/Sub-CA name').\
        completer = _list_org

    org_activate = orgs_actions.add_parser('activate',
                                           help='Activate organization')
    org_activate.add_argument('name', help='Organization name').\
        completer = _list_org

    org_deactivate = orgs_actions.add_parser('deactivate',
                                             help='Deactivate organization')

    org_deactivate.add_argument('name', help='Organization name').\
        completer = _list_org

    org_tier = orgs_actions.add_parser(
        'assign_tier', help='Assign usage tier to Organization')

    org_tier.add_argument('name', help='Organization name').\
        completer = _list_org

    org_tier.add_argument('tier', help='Tier name').\
        completer = _list_tiers

    users = commands.add_parser('users',
                                parents=[_common],
                                help='User management')

    users_actions = users.add_subparsers(dest='action',
                                         help='Manage CloudRunner users')

    users_actions.add_parser('list', help='List all users')

    users_actions.add_parser('list_orgs', help='List all organizations')

    users_add = users_actions.add_parser('create', help='Create new user')

    users_add.add_argument('username', help='User name')
    users_add.add_argument('password', help='Auth password')
    users_add.add_argument('--org', required=True, help='Organization')

    users_perm = users_actions.add_parser('add_perm',
                                          help='Create new auth permission')

    users_perm.add_argument('username',
                            help='User name').completer = _list_users

    users_perm.add_argument('permission', help="Permission name")

    users_perms = users_actions.add_parser('permissions',
                                           help='List permissions for user')

    users_perms.add_argument('username',
                             help='User name').completer = _list_users

    users_rm_perm = users_actions.add_parser('rm_perm',
                                             help='Remove permission for user')

    users_rm_perm.add_argument('username',
                               help='User name').completer = _list_users

    users_rm_perm.add_argument('permission', help="Permission name")

    users_remove = users_actions.add_parser('remove', help='Create new user')

    users_remove.add_argument('username', help='User name')

    tiers = commands.add_parser('tiers',
                                parents=[_common],
                                help='Usage tier management')
    tiers_actions = tiers.add_subparsers(dest='action',
                                         help='Manage Usage Tiers')

    tiers_actions.add_parser('list', help='List all usage tiers')

    tier_add = tiers_actions.add_parser('create', help='Create new usage tier')
    tier_add.add_argument('name', help='Tier name')
    tier_add.add_argument('title', help='Tier title')
    tier_add.add_argument(
        'description',
        help='Tier description',
    )
    tier_add.add_argument('--total_repos',
                          help='Tier total repos',
                          required=True)
    tier_add.add_argument('--external_repos',
                          help='Tier external repos',
                          required=True,
                          action='store_true')
    tier_add.add_argument('--nodes', help='Tier max nodes', required=True)
    tier_add.add_argument('--users', help='Tier max users', required=True)
    tier_add.add_argument('--groups', help='Tier max groups', required=True)
    tier_add.add_argument('--roles', help='Tier max roles', required=True)
    tier_add.add_argument('--max_timeout',
                          help='Tier max timeout',
                          required=True)
    tier_add.add_argument('--max_concurrent_tasks',
                          help='Tier max tasks',
                          required=True)
    tier_add.add_argument('--log_retention_days',
                          help='Tier log retention days',
                          required=True)
    tier_add.add_argument('--cron_jobs', help='Tier cron jobs', required=True)
    tier_add.add_argument('--api_keys', help='Api keys', required=True)
    tier_add.add_argument('--deployments', help='Deployments', required=True)
    tier_add.add_argument('--cloud_profiles',
                          help='Cloud profiles',
                          required=True)

    tier_edit = tiers_actions.add_parser('edit', help='Edit usage tier')
    tier_edit.add_argument('name', help='Tier name').completer = _list_tiers
    tier_edit.add_argument('--title', help='Tier title')
    tier_edit.add_argument(
        '--description',
        help='Tier description',
    )
    tier_edit.add_argument('--total_repos', help='Tier total repos')
    tier_edit.add_argument('--external_repos',
                           help='Tier external repos',
                           choices=['1', '0'],
                           default=None)
    tier_edit.add_argument('--nodes', help='Tier max nodes')
    tier_edit.add_argument('--users', help='Tier max users')
    tier_edit.add_argument('--groups', help='Tier max groups')
    tier_edit.add_argument('--roles', help='Tier max roles')
    tier_edit.add_argument('--max_timeout', help='Tier max timeout')
    tier_edit.add_argument('--max_concurrent_tasks', help='Tier max tasks')
    tier_edit.add_argument('--log_retention_days',
                           help='Tier log retention days')
    tier_edit.add_argument('--cron_jobs', help='Tier cron jobs')
    tier_edit.add_argument('--api_keys', help='Api keys')

    tier_remove = tiers_actions.add_parser('remove', help='Remove usage tier')
    tier_remove.add_argument('name', help='Tier name').completer = _list_tiers

    try:
        argcomplete.autocomplete(parser)
    except:
        pass

    args = parser.parse_args()
    kwargs = vars(args)
    action = kwargs.pop("action")
    controller = kwargs.pop("controller")
    _config = kwargs.pop("config")

    class OrgController(object):
        def __init__(self, config):
            self.cont = functions.UserController(config)

        def create(self, name, tier, **kwargs):
            return self.cont.create_org(name, tier)

        def activate(self, name, **kwargs):
            return self.cont.activate_org(name)

        def deactivate(self, name, **kwargs):
            return self.cont.deactivate_org(name)

        def list(self, **kwargs):
            return self.cont.list_orgs()

        def assign_tier(self, name, tier):
            return self.cont.assign_tier(name, tier)

        def remove(self, name, **kwargs):
            return self.cont.remove_org(name)

    controllers = {
        'cert': functions.CertController,
        'init': functions.ConfigController,
        'config': functions.ConfigController,
        'users': functions.UserController,
        'tiers': functions.TierController,
        'org': OrgController
    }
    config = Config(_config or CONFIG_LOCATION)

    printers = {
        functions.TAG: lambda *args: colors.yellow(*args, bold=1),
        functions.DATA: colors.blue,
        functions.ERR: lambda *args: colors.red(*args, bold=1),
        functions.NOTE: colors.grey,
        functions.EMPTY: colors.blue,
    }
    try:
        items = getattr(controllers[controller](config), action)(**kwargs)
        if not items:
            return
        for line in items:
            _type, printables = line
            if isinstance(printables, (list, tuple)):
                for i in range(len(printables)):
                    if isinstance(printables[i], list):
                        printables[i] = '\n'.join(
                            concat(p) for p in printables[i])
                printables = [concat(p) for p in printables]
                print printers[_type]('\n'.join([p for p in printables]))
            else:
                print printables
    except Exception, ex:
        print colors.red("%r" % ex)