|
- from realms import config, app, cli, db
- from realms.lib.util import random_string
- from subprocess import call, Popen
- from multiprocessing import cpu_count
- import click
- import json
- import sys
- import os
-
-
- def check_su(f):
- if not in_virtualenv() and not is_su():
- # This does not account for people the have user level python installs
- # that aren't virtual environments! Should be rare I think
- red("This command requires root privileges, use sudo or run as root.")
- sys.exit()
- return f
-
-
- def get_user():
- for name in ('SUDO_USER', 'LOGNAME', 'USER', 'LNAME', 'USERNAME'):
- user = os.environ.get(name)
- if user:
- return user
-
-
- def in_virtualenv():
- return hasattr(sys, 'real_prefix')
-
-
- def is_su():
- return os.geteuid() == 0
-
-
- def get_pid():
- try:
- with file(config.PIDFILE) as f:
- pid = f.read().strip()
- return pid if pid and int(pid) > 0 and not call(['kill', '-s', '0', pid]) else False
- except IOError:
- return False
-
-
- def module_exists(module_name):
- try:
- __import__(module_name)
- except ImportError:
- return False
- else:
- return True
-
-
- def green(s):
- click.secho(s, fg='green')
-
-
- def yellow(s):
- click.secho(s, fg='yellow')
-
-
- def red(s):
- click.secho(s, fg='red')
-
-
- @cli.command()
- @check_su
- @click.option('--site-title',
- default=config.SITE_TITLE,
- prompt='Enter site title.')
- @click.option('--base_url',
- default=config.BASE_URL,
- prompt='Enter base URL.')
- @click.option('--port',
- default=config.PORT,
- prompt='Enter port number.')
- @click.option('--secret-key',
- default=config.SECRET_KEY if config.SECRET_KEY != "CHANGE_ME" else random_string(64),
- prompt='Enter secret key.')
- @click.option('--wiki-path',
- default=config.WIKI_PATH,
- prompt='Enter wiki data directory.',
- help='Wiki Directory (git repo)')
- @click.option('--allow-anon',
- default=config.ALLOW_ANON,
- is_flag=True,
- prompt='Allow anonymous edits?')
- @click.option('--registration-enabled',
- default=config.REGISTRATION_ENABLED,
- is_flag=True,
- prompt='Enable registration?')
- @click.option('--cache-type',
- default=config.CACHE_TYPE,
- type=click.Choice([None, 'simple', 'redis', 'memcached']),
- prompt='Cache type?')
- @click.option('--db-uri',
- default=config.DB_URI,
- prompt='Database URI? Examples: http://goo.gl/RyW0cl')
- @click.pass_context
- def setup(ctx, **kw):
- """ Start setup wizard
- """
-
- conf = {}
-
- for k, v in kw.items():
- conf[k.upper()] = v
-
- conf_path = config.update(conf)
-
- if conf['CACHE_TYPE'] == 'redis':
- ctx.invoke(setup_redis)
- elif conf['CACHE_TYPE'] == 'memcached':
- ctx.invoke(setup_memcached)
-
- green('Config saved to %s' % conf_path)
- yellow('Type "realms-wiki start" to start server')
- yellow('Type "realms-wiki dev" to start server in development mode')
-
-
- @click.command()
- @click.option('--cache-redis-host',
- default=getattr(config, 'CACHE_REDIS_HOST', "127.0.0.1"),
- prompt='Redis host')
- @click.option('--cache-redis-port',
- default=getattr(config, 'CACHE_REDIS_POST', 6379),
- prompt='Redis port')
- @click.option('--cache-redis-password',
- default=getattr(config, 'CACHE_REDIS_PASSWORD', None),
- prompt='Redis password')
- @click.option('--cache-redis-db',
- default=getattr(config, 'CACHE_REDIS_DB', 0),
- prompt='Redis db')
- def setup_redis(**kw):
- conf = {}
-
- for k, v in kw.items():
- conf[k.upper()] = v
-
- config.update(conf)
- install_redis()
-
-
- def get_prefix():
- return sys.prefix
-
-
- def get_pip():
- """ Get virtualenv path for pip
- """
- if in_virtualenv():
- return get_prefix() + '/bin/pip'
- else:
- return 'pip'
-
-
- @cli.command()
- @check_su
- @click.argument('cmd', nargs=-1)
- def pip(cmd):
- """ Execute pip commands, useful for virtualenvs
- """
- call(get_pip() + ' ' + ' '.join(cmd), shell=True)
-
-
- def install_redis():
- call([get_pip(), 'install', 'redis'])
-
-
- def install_mysql():
- call([get_pip(), 'install', 'MySQL-Python'])
-
-
- def install_postgres():
- call([get_pip(), 'install', 'psycopg2'])
-
-
- def install_memcached():
- call([get_pip(), 'install', 'python-memcached'])
-
-
- @click.command()
- @click.option('--cache-memcached-servers',
- default=getattr(config, 'CACHE_MEMCACHED_SERVERS', ["127.0.0.1:11211"]),
- type=click.STRING,
- prompt='Memcached servers, separate with a space')
- def setup_memcached(**kw):
- conf = {}
-
- for k, v in kw.items():
- conf[k.upper()] = v
-
- config.update(conf)
-
-
- @cli.command()
- @check_su
- @click.option('--user',
- default=get_user(),
- type=click.STRING,
- prompt='Run as which user? (it must exist)')
- @click.option('--port',
- default=config.PORT,
- type=click.INT,
- prompt='What port to listen on?')
- @click.option('--workers',
- default=cpu_count() * 2 + 1,
- type=click.INT,
- prompt="Number of workers? (defaults to ncpu*2+1)")
- def setup_upstart(**kwargs):
- """ Start upstart conf creation wizard
- """
- from realms.lib.util import upstart_script
-
- if in_virtualenv():
- app_dir = get_prefix()
- path = '/'.join(sys.executable.split('/')[:-1])
- else:
- # Assumed root install, not sure if this matters?
- app_dir = '/'
- path = None
-
- kwargs.update(dict(app_dir=app_dir, path=path))
-
- conf_file = '/etc/init/realms-wiki.conf'
-
- with open('/etc/init/realms-wiki.conf', 'w') as f:
- f.write(upstart_script(**kwargs))
-
- green('Wrote file to %s' % conf_file)
- green("Type 'sudo start realms-wiki' to start")
- green("Type 'sudo stop realms-wiki' to stop")
- green("Type 'sudo restart realms-wiki' to restart")
-
-
- @cli.command()
- @click.argument('json_string')
- def configure(json_string):
- """ Set config.json, expects JSON encoded string
- """
- try:
- config.update(json.loads(json_string))
- except ValueError, e:
- red('Config value should be valid JSON')
-
-
- @cli.command()
- @click.option('--port', default=5000)
- def dev(port):
- """ Run development server
- """
- green("Starting development server")
- app.run(host="0.0.0.0",
- port=port,
- debug=True)
-
-
- def start_server():
- if get_pid():
- yellow("Server is already running")
- return
-
- flags = '--daemon --pid %s' % config.PIDFILE
-
- green("Server started. Port: %s" % config.PORT)
-
- Popen('gunicorn realms:app -b 0.0.0.0:%s -k gevent %s' %
- (config.PORT, flags), shell=True, executable='/bin/bash')
-
-
- def stop_server():
- pid = get_pid()
- if not pid:
- yellow("Server is not running")
- else:
- yellow("Shutting down server")
- call(['kill', pid])
-
-
- @cli.command()
- def run():
- """ Run production server (alias for start)
- """
- start_server()
-
-
- @cli.command()
- def start():
- """ Run server daemon
- """
- start_server()
-
-
- @cli.command()
- def stop():
- """ Stop server
- """
- stop_server()
-
-
- @cli.command()
- def restart():
- """ Restart server
- """
- stop_server()
- start_server()
-
-
- @cli.command()
- def status():
- """ Get server status
- """
- pid = get_pid()
- if not pid:
- yellow("Server is not running")
- else:
- green("Server is running PID: %s" % pid)
-
-
- @cli.command()
- def create_db():
- """ Creates DB tables
- """
- green("Creating all tables")
- db.create_all()
-
-
- @cli.command()
- @click.confirmation_option(help='Are you sure you want to drop the db?')
- def drop_db():
- """ Drops DB tables
- """
- yellow("Dropping all tables")
- db.drop_all()
-
-
- @cli.command()
- def test():
- """ Run tests
- """
- for mod in [('flask.ext.testing', 'Flask-Testing'), ('nose', 'nose')]:
- if not module_exists(mod[0]):
- call([get_pip(), 'install', mod[1]])
-
- nosetests = get_prefix() + "/bin/nosetests" if in_virtualenv() else "nosetests"
-
- call([nosetests, config.APP_PATH])
-
-
- @cli.command()
- def version():
- """ Output version
- """
- with open('VERSION') as f:
- return f.read().strip()
-
-
- if __name__ == '__main__':
- cli()
|