Commit 3e43c7db70021cf7a78677047aa0d15b1eeb0156
1 parent
721677c8
Exists in
master
and in
29 other branches
Refactored colab-admin command
Allow to run celery from colab-admin Signed-off-by: Sergio Oliveira <sergio@tracy.com.br>
Showing
12 changed files
with
272 additions
and
145 deletions
Show diff stats
README.rst
@@ -64,7 +64,7 @@ To run Colab with development server you will have to: | @@ -64,7 +64,7 @@ To run Colab with development server you will have to: | ||
64 | 64 | ||
65 | .. code-block:: | 65 | .. code-block:: |
66 | 66 | ||
67 | - colab-init-config > /etc/colab/settings.yaml | 67 | + colab-admin initconfig > /etc/colab/settings.yaml |
68 | 68 | ||
69 | 2- Edit the configuration file. Make sure you set everything you need including **database** credentials. | 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,4 +92,4 @@ How to run the tests | ||
92 | Follow the steps below: | 92 | Follow the steps below: |
93 | 93 | ||
94 | * Go to vagrant/colab/ | 94 | * Go to vagrant/colab/ |
95 | -* run: ./runtests.sh | ||
96 | \ No newline at end of file | 95 | \ No newline at end of file |
96 | +* run: ./runtests.sh |
colab/management/__init__.py
@@ -1,20 +0,0 @@ | @@ -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() |
@@ -0,0 +1,26 @@ | @@ -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 | + ) |
@@ -0,0 +1,124 @@ | @@ -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,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)) |
@@ -0,0 +1,103 @@ | @@ -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
@@ -0,0 +1,14 @@ | @@ -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,8 +55,7 @@ setup( | ||
55 | packages=find_packages(exclude=EXCLUDE_FROM_PACKAGES), | 55 | packages=find_packages(exclude=EXCLUDE_FROM_PACKAGES), |
56 | include_package_data=True, | 56 | include_package_data=True, |
57 | entry_points={'console_scripts': [ | 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 | zip_safe=False, | 60 | zip_safe=False, |
62 | long_description=open('README.rst').read(), | 61 | long_description=open('README.rst').read(), |
vagrant/provision.sh
@@ -36,7 +36,7 @@ sudo mkdir -p /etc/colab | @@ -36,7 +36,7 @@ sudo mkdir -p /etc/colab | ||
36 | sudo chown vagrant:vagrant /etc/colab | 36 | sudo chown vagrant:vagrant /etc/colab |
37 | 37 | ||
38 | if [ ! -s /etc/colab/settings.py ]; then | 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 | fi | 40 | fi |
41 | 41 | ||
42 | colab-admin migrate | 42 | colab-admin migrate |