Commit 3e43c7db70021cf7a78677047aa0d15b1eeb0156

Authored by Sergio Oliveira
1 parent 721677c8

Refactored colab-admin command

Allow to run celery from colab-admin

Signed-off-by: Sergio Oliveira <sergio@tracy.com.br>
README.rst
... ... @@ -64,7 +64,7 @@ To run Colab with development server you will have to:
64 64  
65 65 .. code-block::
66 66  
67   - colab-init-config > /etc/colab/settings.yaml
  67 + colab-admin initconfig > /etc/colab/settings.yaml
68 68  
69 69 2- Edit the configuration file. Make sure you set everything you need including **database** credentials.
70 70  
... ... @@ -92,4 +92,4 @@ How to run the tests
92 92 Follow the steps below:
93 93  
94 94 * Go to vagrant/colab/
95   -* run: ./runtests.sh
96 95 \ No newline at end of file
  96 +* run: ./runtests.sh
... ...
colab/management/__init__.py
... ... @@ -1,20 +0,0 @@
1   -
2   -import os
3   -
4   -from django.core.management import ManagementUtility
5   -
6   -from .initconfig import initconfig
7   -
8   -
9   -def execute_from_command_line(argv=None):
10   - """
11   - A simple method that runs a ManagementUtility.
12   - """
13   - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "colab.settings")
14   -
15   - utility = ManagementUtility(argv)
16   - utility.execute()
17   -
18   -
19   -def run_colab_config(argv=None):
20   - initconfig()
colab/management/commands/__init__.py 0 → 100644
colab/management/commands/celery.py 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +from __future__ import absolute_import, unicode_literals
  2 +
  3 +from celery.bin import celery
  4 +
  5 +from colab.celery import app
  6 +from colab.queue.command import CeleryCommand
  7 +
  8 +base = celery.CeleryCommand(app=app)
  9 +
  10 +
  11 +# this is a reimplementation of the djcelery 'celery' command
  12 +# taken from Sentry
  13 +class Command(CeleryCommand):
  14 + """The celery command."""
  15 + help = 'celery commands, see celery help'
  16 + options = (CeleryCommand.options
  17 + + base.get_options()
  18 + + base.preload_options)
  19 +
  20 + def run_from_argv(self, argv):
  21 + argv = self.handle_default_options(argv)
  22 + if self.requires_system_checks:
  23 + self.validate()
  24 + base.execute_from_commandline(
  25 + ['{0[0]} {0[1]}'.format(argv)] + argv[2:],
  26 + )
... ...
colab/management/commands/initconfig.py 0 → 100644
... ... @@ -0,0 +1,124 @@
  1 +
  2 +from django.core.management.base import BaseCommand
  3 +from django.utils.crypto import get_random_string
  4 +
  5 +
  6 +CONFIG_TEMPLATE = """
  7 +## Set to false in production
  8 +DEBUG = True
  9 +TEMPLATE_DEBUG = True
  10 +
  11 +## System admins
  12 +ADMINS = [['John Foo', 'john@example.com'], ['Mary Bar', 'mary@example.com']]
  13 +
  14 +MANAGERS = ADMINS
  15 +
  16 +COLAB_FROM_ADDRESS = '"Colab" <noreply@example.com>'
  17 +SERVER_EMAIL = '"Colab" <noreply@example.com>'
  18 +
  19 +EMAIL_HOST = 'localhost'
  20 +EMAIL_PORT = 25
  21 +EMAIL_SUBJECT_PREFIX = '[colab]'
  22 +
  23 +SECRET_KEY = '{secret_key}'
  24 +
  25 +ALLOWED_HOSTS = [
  26 + 'localhost',
  27 +# 'example.com',
  28 +# 'example.org',
  29 +# 'example.net',
  30 +]
  31 +
  32 +### Uncomment to enable social networks fields profile
  33 +# SOCIAL_NETWORK_ENABLED = True
  34 +
  35 +## Database settings
  36 +##
  37 +## When DEBUG is True colab will create the DB on
  38 +## the repository root. In case of production settings
  39 +## (DEBUG False) the DB settings must be set.
  40 +##
  41 +# DATABASES = {{
  42 +# 'default': {{
  43 +# 'ENGINE': 'django.db.backends.sqlite3',
  44 +# 'NAME': '/path/to/colab.sqlite3',
  45 +# }}
  46 +# }}
  47 +
  48 +## Disable indexing
  49 +ROBOTS_NOINDEX = False
  50 +
  51 +LOGGING = {{
  52 + 'version': 1,
  53 +
  54 + 'handlers': {{
  55 + 'null': {{
  56 + 'level': 'DEBUG',
  57 + 'class': 'logging.NullHandler',
  58 + }},
  59 + }},
  60 +
  61 + 'loggers': {{
  62 + 'colab.mailman': {{
  63 + 'handlers': ['null'],
  64 + 'propagate': False,
  65 + }},
  66 + 'haystack': {{
  67 + 'handlers': ['null'],
  68 + 'propagate': False,
  69 + }},
  70 + 'pysolr': {{
  71 + 'handlers': ['null'],
  72 + 'propagate': False,
  73 + }},
  74 + }},
  75 +}}
  76 +
  77 +
  78 +## Gitlab plugin - Put this in plugins.d/gitlab.py to actiate ##
  79 +# from django.utils.translation import ugettext_lazy as _
  80 +# from colab.plugins.utils.menu import colab_url_factory
  81 +#
  82 +# name = 'colab.plugins.gitlab'
  83 +# verbose_name = 'Gitlab Proxy'
  84 +#
  85 +# upstream = 'localhost'
  86 +# #middlewares = []
  87 +#
  88 +# urls = {{
  89 +# 'include': 'colab.plugins.gitlab.urls',
  90 +# 'namespace': 'gitlab',
  91 +# 'prefix': 'gitlab',
  92 +# }}
  93 +#
  94 +# menu_title = _('Code')
  95 +#
  96 +# url = colab_url_factory('gitlab')
  97 +#
  98 +# menu_urls = (
  99 +# url(display=_('Public Projects'), viewname='gitlab',
  100 +# kwargs={{'path': '/public/projects'}}, auth=False),
  101 +# url(display=_('Profile'), viewname='gitlab',
  102 +# kwargs={{'path': '/profile'}}, auth=True),
  103 +# url(display=_('New Project'), viewname='gitlab',
  104 +# kwargs={{'path': '/projects/new'}}, auth=True),
  105 +# url(display=_('Projects'), viewname='gitlab',
  106 +# kwargs={{'path': '/dashboard/projects'}}, auth=True),
  107 +# url(display=_('Groups'), viewname='gitlab',
  108 +# kwargs={{'path': '/profile/groups'}}, auth=True),
  109 +# url(display=_('Issues'), viewname='gitlab',
  110 +# kwargs={{'path': '/dashboard/issues'}}, auth=True),
  111 +# url(display=_('Merge Requests'), viewname='gitlab',
  112 +# kwargs={{'path': '/merge_requests'}}, auth=True),
  113 +#
  114 +# )
  115 +"""
  116 +
  117 +
  118 +class Command(BaseCommand):
  119 + help = 'Returns an example config file for Colab'
  120 +
  121 + def handle(self, *args, **kwargs):
  122 + chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
  123 + secret_key = get_random_string(50, chars)
  124 + print(CONFIG_TEMPLATE.format(secret_key=secret_key))
... ...
colab/management/initconfig.py
... ... @@ -1,120 +0,0 @@
1   -
2   -from django.utils.crypto import get_random_string
3   -
4   -
5   -CONFIG_TEMPLATE = """
6   -## Set to false in production
7   -DEBUG = True
8   -TEMPLATE_DEBUG = True
9   -
10   -## System admins
11   -ADMINS = [['John Foo', 'john@example.com'], ['Mary Bar', 'mary@example.com']]
12   -
13   -MANAGERS = ADMINS
14   -
15   -COLAB_FROM_ADDRESS = '"Colab" <noreply@example.com>'
16   -SERVER_EMAIL = '"Colab" <noreply@example.com>'
17   -
18   -EMAIL_HOST = 'localhost'
19   -EMAIL_PORT = 25
20   -EMAIL_SUBJECT_PREFIX = '[colab]'
21   -
22   -SECRET_KEY = '{secret_key}'
23   -
24   -ALLOWED_HOSTS = [
25   - 'localhost',
26   -# 'example.com',
27   -# 'example.org',
28   -# 'example.net',
29   -]
30   -
31   -### Uncomment to enable social networks fields profile
32   -# SOCIAL_NETWORK_ENABLED = True
33   -
34   -## Database settings
35   -##
36   -## When DEBUG is True colab will create the DB on
37   -## the repository root. In case of production settings
38   -## (DEBUG False) the DB settings must be set.
39   -##
40   -# DATABASES = {{
41   -# 'default': {{
42   -# 'ENGINE': 'django.db.backends.sqlite3',
43   -# 'NAME': '/path/to/colab.sqlite3',
44   -# }}
45   -# }}
46   -
47   -## Disable indexing
48   -ROBOTS_NOINDEX = False
49   -
50   -LOGGING = {{
51   - 'version': 1,
52   -
53   - 'handlers': {{
54   - 'null': {{
55   - 'level': 'DEBUG',
56   - 'class': 'logging.NullHandler',
57   - }},
58   - }},
59   -
60   - 'loggers': {{
61   - 'colab.mailman': {{
62   - 'handlers': ['null'],
63   - 'propagate': False,
64   - }},
65   - 'haystack': {{
66   - 'handlers': ['null'],
67   - 'propagate': False,
68   - }},
69   - 'pysolr': {{
70   - 'handlers': ['null'],
71   - 'propagate': False,
72   - }},
73   - }},
74   -}}
75   -
76   -
77   -## Gitlab plugin - Put this in plugins.d/gitlab.py to actiate ##
78   -# from django.utils.translation import ugettext_lazy as _
79   -# from colab.plugins.utils.menu import colab_url_factory
80   -#
81   -# name = 'colab.plugins.gitlab'
82   -# verbose_name = 'Gitlab Proxy'
83   -#
84   -# upstream = 'localhost'
85   -# #middlewares = []
86   -#
87   -# urls = {{
88   -# 'include': 'colab.plugins.gitlab.urls',
89   -# 'namespace': 'gitlab',
90   -# 'prefix': 'gitlab',
91   -# }}
92   -#
93   -# menu_title = _('Code')
94   -#
95   -# url = colab_url_factory('gitlab')
96   -#
97   -# menu_urls = (
98   -# url(display=_('Public Projects'), viewname='gitlab',
99   -# kwargs={{'path': '/public/projects'}}, auth=False),
100   -# url(display=_('Profile'), viewname='gitlab',
101   -# kwargs={{'path': '/profile'}}, auth=True),
102   -# url(display=_('New Project'), viewname='gitlab',
103   -# kwargs={{'path': '/projects/new'}}, auth=True),
104   -# url(display=_('Projects'), viewname='gitlab',
105   -# kwargs={{'path': '/dashboard/projects'}}, auth=True),
106   -# url(display=_('Groups'), viewname='gitlab',
107   -# kwargs={{'path': '/profile/groups'}}, auth=True),
108   -# url(display=_('Issues'), viewname='gitlab',
109   -# kwargs={{'path': '/dashboard/issues'}}, auth=True),
110   -# url(display=_('Merge Requests'), viewname='gitlab',
111   -# kwargs={{'path': '/merge_requests'}}, auth=True),
112   -#
113   -# )
114   -"""
115   -
116   -
117   -def initconfig():
118   - chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
119   - secret_key = get_random_string(50, chars)
120   - print(CONFIG_TEMPLATE.format(secret_key=secret_key))
colab/queue/__init__.py 0 → 100644
colab/queue/command.py 0 → 100644
... ... @@ -0,0 +1,103 @@
  1 +from __future__ import absolute_import
  2 +
  3 +import celery
  4 +import os
  5 +import sys
  6 +
  7 +from django.core.management.base import BaseCommand
  8 +
  9 +DB_SHARED_THREAD = """\
  10 +DatabaseWrapper objects created in a thread can only \
  11 +be used in that same thread. The object with alias '%s' \
  12 +was created in thread id %s and this is thread id %s.\
  13 +"""
  14 +
  15 +
  16 +def patch_thread_ident():
  17 + # monkey patch django.
  18 + # This patch make sure that we use real threads to get the ident which
  19 + # is going to happen if we are using gevent or eventlet.
  20 + # -- patch taken from gunicorn
  21 + if getattr(patch_thread_ident, 'called', False):
  22 + return
  23 + try:
  24 + from django.db.backends import BaseDatabaseWrapper, DatabaseError
  25 +
  26 + if 'validate_thread_sharing' in BaseDatabaseWrapper.__dict__:
  27 + import thread
  28 + _get_ident = thread.get_ident
  29 +
  30 + __old__init__ = BaseDatabaseWrapper.__init__
  31 +
  32 + def _init(self, *args, **kwargs):
  33 + __old__init__(self, *args, **kwargs)
  34 + self._thread_ident = _get_ident()
  35 +
  36 + def _validate_thread_sharing(self):
  37 + if (not self.allow_thread_sharing
  38 + and self._thread_ident != _get_ident()):
  39 + raise DatabaseError(
  40 + DB_SHARED_THREAD % (
  41 + self.alias, self._thread_ident, _get_ident()),
  42 + )
  43 +
  44 + BaseDatabaseWrapper.__init__ = _init
  45 + BaseDatabaseWrapper.validate_thread_sharing = \
  46 + _validate_thread_sharing
  47 +
  48 + patch_thread_ident.called = True
  49 + except ImportError:
  50 + pass
  51 +patch_thread_ident()
  52 +
  53 +
  54 +class CeleryCommand(BaseCommand):
  55 + options = BaseCommand.option_list
  56 + skip_opts = ['--app', '--loader', '--config']
  57 + keep_base_opts = False
  58 +
  59 + def get_version(self):
  60 + return 'celery %s' % (celery.__version__)
  61 +
  62 + def execute(self, *args, **options):
  63 + broker = options.get('broker')
  64 + if broker:
  65 + self.set_broker(broker)
  66 + super(CeleryCommand, self).execute(*args, **options)
  67 +
  68 + def set_broker(self, broker):
  69 + os.environ['CELERY_BROKER_URL'] = broker
  70 +
  71 + def run_from_argv(self, argv):
  72 + self.handle_default_options(argv[2:])
  73 + return super(CeleryCommand, self).run_from_argv(argv)
  74 +
  75 + def handle_default_options(self, argv):
  76 + acc = []
  77 + broker = None
  78 + for i, arg in enumerate(argv):
  79 + if '--settings=' in arg:
  80 + _, settings_module = arg.split('=')
  81 + os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
  82 + elif '--pythonpath=' in arg:
  83 + _, pythonpath = arg.split('=')
  84 + sys.path.insert(0, pythonpath)
  85 + elif '--broker=' in arg:
  86 + _, broker = arg.split('=')
  87 + elif arg == '-b':
  88 + broker = argv[i + 1]
  89 + else:
  90 + acc.append(arg)
  91 + if broker:
  92 + self.set_broker(broker)
  93 + return argv if self.keep_base_opts else acc
  94 +
  95 + def die(self, msg):
  96 + sys.stderr.write(msg)
  97 + sys.stderr.write('\n')
  98 + sys.exit()
  99 +
  100 + @property
  101 + def option_list(self):
  102 + return [x for x in self.options
  103 + if x._long_opts[0] not in self.skip_opts]
... ...
colab/settings.py
... ... @@ -49,6 +49,7 @@ INSTALLED_APPS = (
49 49 'taggit',
50 50  
51 51 # Own apps
  52 + 'colab',
52 53 'colab.home',
53 54 'colab.plugins',
54 55 'colab.super_archives',
... ...
colab/utils/runner.py 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +
  2 +import os
  3 +
  4 +from django.core.management import ManagementUtility
  5 +
  6 +
  7 +def execute_from_command_line(argv=None):
  8 + """
  9 + A simple method that runs a ManagementUtility.
  10 + """
  11 + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "colab.settings")
  12 +
  13 + utility = ManagementUtility(argv)
  14 + utility.execute()
... ...
setup.py
... ... @@ -55,8 +55,7 @@ setup(
55 55 packages=find_packages(exclude=EXCLUDE_FROM_PACKAGES),
56 56 include_package_data=True,
57 57 entry_points={'console_scripts': [
58   - 'colab-admin = colab.management:execute_from_command_line',
59   - 'colab-init-config = colab.management:initconfig',
  58 + 'colab-admin = colab.utils.runner:execute_from_command_line',
60 59 ]},
61 60 zip_safe=False,
62 61 long_description=open('README.rst').read(),
... ...
vagrant/provision.sh
... ... @@ -36,7 +36,7 @@ sudo mkdir -p /etc/colab
36 36 sudo chown vagrant:vagrant /etc/colab
37 37  
38 38 if [ ! -s /etc/colab/settings.py ]; then
39   - colab-init-config > /etc/colab/settings.py
  39 + colab-admin initconfig > /etc/colab/settings.py
40 40 fi
41 41  
42 42 colab-admin migrate
... ...