diff --git a/modoboa/core/commands/deploy.py b/modoboa/core/commands/deploy.py index e3802e229..6c426be39 100644 --- a/modoboa/core/commands/deploy.py +++ b/modoboa/core/commands/deploy.py @@ -5,9 +5,14 @@ import getpass import os import shutil +import subprocess import sys -import subprocess +try: + import pip +except ImportError: + sys.stderr.write("Error: pip is required to install extensions.\n") + sys.exit(2) import django from django.core import management @@ -45,20 +50,13 @@ class DeployCommand(Command): super(DeployCommand, self).__init__(*args, **kwargs) self._parser.add_argument('name', type=str, help='The name of your Modoboa instance') - self._parser.add_argument( - '--with-amavis', action='store_true', default=False, - help='Include amavis configuration' - ) self._parser.add_argument( '--collectstatic', action='store_true', default=False, help='Run django collectstatic command' ) self._parser.add_argument( - '--dburl', type=str, nargs=1, default=None, - help='The database-url for your modoboa instance') - self._parser.add_argument( - '--amavis_dburl', type=str, nargs=1, default=None, - help='The database-url for your amavis instance') + '--dburl', type=str, nargs="+", default=None, + help='A database-url with a name') self._parser.add_argument( '--domain', type=str, default=None, help='The domain under which you want to deploy modoboa') @@ -74,6 +72,10 @@ class DeployCommand(Command): '--devel', action='store_true', default=False, help='Create a development instance' ) + self._parser.add_argument( + '--extensions', type=str, nargs='*', + help="The list of extension to deploy" + ) def _exec_django_command(self, name, cwd, *args): """Run a django command for the freshly created project @@ -136,6 +138,27 @@ class DeployCommand(Command): info['PASSWORD'] = getpass.getpass('Password: ') return info + def install_extensions(self, extensions): + """Install one or more extensions. + + Return the list of extensions providing settings we must + include in the final configuration. + + """ + if "all" in extensions: + # Retrieve official extension list from the API + return + pip_args = ["install"] + extensions + pip.main(pip_args) + extra_settings = [] + for extension in extensions: + module = __import__(extension, locals(), globals(), []) + basedir = os.path.dirname(module.__file__) + if not os.path.exists("{0}/settings.py".format(basedir)): + continue + extra_settings.append(extension) + return extra_settings + def handle(self, parsed_args): django.setup() management.call_command( @@ -144,40 +167,24 @@ class DeployCommand(Command): path = "%(name)s/%(name)s" % {'name': parsed_args.name} sys.path.append(parsed_args.name) - t = Template(DBCONN_TPL) - + conn_tpl = Template(DBCONN_TPL) + connections = {} if parsed_args.dburl: - info = dj_database_url.config(default=parsed_args.dburl[0]) - # In case the user fails to supply a valid database url, - # fallback to manual mode - if not info: - print "There was a problem with your database-url. \n" - info = self.ask_db_info() - # If we set this earlier, our fallback method will never - # be triggered - info['conn_name'] = 'default' + for dburl in parsed_args.dburl: + conn_name, url = dburl.split(":", 1) + info = dj_database_url.config(default=url) + # In case the user fails to supply a valid database url, + # fallback to manual mode + if not info: + print "There was a problem with your database-url. \n" + info = self.ask_db_info(conn_name) + # If we set this earlier, our fallback method will never + # be triggered + info['conn_name'] = conn_name + connections[conn_name] = conn_tpl.render(Context(info)) else: - info = self.ask_db_info() - - default_conn = t.render(Context(info)) - - if parsed_args.with_amavis: - if parsed_args.amavis_dburl: - amavis_info = dj_database_url.config( - default=parsed_args.amavis_dburl[0]) - # In case the user fails to supply a valid database - # url, fallback to manual mode - if not amavis_info: - amavis_info = self.ask_db_info('amavis') - # If we set this earlier, our fallback method will - # never be triggered - amavis_info['conn_name'] = 'amavis' - else: - amavis_info = self.ask_db_info('amavis') - - amavis_conn = t.render(Context(amavis_info)) - else: - amavis_conn = None + connections["default"] = conn_tpl.render( + Context(self.ask_db_info())) if parsed_args.domain: allowed_host = parsed_args.domain @@ -188,6 +195,10 @@ class DeployCommand(Command): if not allowed_host: allowed_host = "localhost" + extra_settings = [] + if parsed_args.extensions: + extra_settings = self.install_extensions(parsed_args.extensions) + bower_components_dir = os.path.realpath( os.path.join(os.path.dirname(__file__), "../../bower_components") ) @@ -195,14 +206,16 @@ class DeployCommand(Command): mod = __import__(parsed_args.name, globals(), locals(), ['settings']) tpl = self._render_template( "%s/settings.py.tpl" % self._templates_dir, { - 'default_conn': default_conn, 'amavis_conn': amavis_conn, + 'db_connections': connections, 'secret_key': mod.settings.SECRET_KEY, 'name': parsed_args.name, 'allowed_host': allowed_host, 'lang': parsed_args.lang, 'timezone': parsed_args.timezone, 'bower_components_dir': bower_components_dir, - 'devmode': parsed_args.devel + 'devmode': parsed_args.devel, + 'extensions': parsed_args.extensions, + 'extra_settings': extra_settings } ) with open("%s/settings.py" % path, "w") as fp: diff --git a/modoboa/core/commands/templates/settings.py.tpl b/modoboa/core/commands/templates/settings.py.tpl index c4ef22677..8ba295fc8 100644 --- a/modoboa/core/commands/templates/settings.py.tpl +++ b/modoboa/core/commands/templates/settings.py.tpl @@ -57,9 +57,8 @@ MODOBOA_APPS = ( 'modoboa.core', 'modoboa.lib', # Modoboa extensions here. - - # Tools from here - #'modoboa.tools.pfxadmin_migrate', +{% for extension in extensions %} '{{ extension }}', +{% endfor %} ) INSTALLED_APPS += MODOBOA_APPS @@ -95,21 +94,8 @@ WSGI_APPLICATION = '{{ name }}.wsgi.application' # Database # https://docs.djangoproject.com/en/1.6/ref/settings/#databases -DATABASES = { {{ default_conn|safe }} - # "pfxadmin" : { - # "ENGINE" : "django.db.backends.", - # "NAME" : "", - # "USER" : "", - # "PASSWORD" : "" - # },{% if not amavis_conn %} - # "amavis": { - # "ENGINE" : "django.db.backends.", - # "HOST" : "", - # "NAME" : "", - # "USER" : "", - # "PASSWORD" : "" - # }{% else %} - {{ amavis_conn|safe }}{% endif %} +DATABASES = { + {% for conn in db_connections.values %}{{ conn|safe }}{% endfor %} } # Internationalization @@ -177,3 +163,6 @@ LOGGING = { } } } +{% for extension in extra_settings %} +import {{ extension }}.settings +{% endfor %}