django-orchestra/orchestra/management/commands/setuppostgres.py

123 lines
5.6 KiB
Python
Raw Normal View History

2014-05-08 16:59:35 +00:00
import os
2015-10-01 18:57:31 +00:00
import textwrap
2014-05-08 16:59:35 +00:00
from optparse import make_option
2015-10-02 09:31:32 +00:00
from django.conf import settings
2014-05-08 16:59:35 +00:00
from django.core.management.base import BaseCommand
from orchestra.utils.paths import get_project_dir
2015-10-02 09:31:32 +00:00
from orchestra.utils.python import random_ascii
2015-04-05 10:46:24 +00:00
from orchestra.utils.sys import run, check_root
2014-05-08 16:59:35 +00:00
class Command(BaseCommand):
def __init__(self, *args, **kwargs):
super(Command, self).__init__(*args, **kwargs)
2015-10-02 09:31:32 +00:00
# Get defaults from settings, if exists
try:
defaults = settings.DATABASES['default']
except (AttributeError, KeyError):
defaults = {}
else:
if defaults['ENGINE'] != 'django.db.backends.postgresql_psycopg2':
defaults = {}
2014-05-08 16:59:35 +00:00
self.option_list = BaseCommand.option_list + (
2015-10-02 09:31:32 +00:00
make_option('--db_name', dest='db_name',
default=defaults.get('DB_NAME', 'orchestra'),
2014-05-08 16:59:35 +00:00
help='Specifies the database to create.'),
2015-10-02 09:31:32 +00:00
make_option('--db_user', dest='db_user',
default=defaults.get('DB_USER', 'orchestra'),
2014-05-08 16:59:35 +00:00
help='Specifies the database to create.'),
2015-10-02 09:31:32 +00:00
make_option('--db_password', dest='db_password',
2015-10-02 09:39:58 +00:00
default=defaults.get('PASSWORD', ''),
2015-10-02 09:31:32 +00:00
help='Specifies the database password, random if not specified.'),
make_option('--db_host', dest='db_host',
default=defaults.get('HOST', 'localhost'),
2014-05-08 16:59:35 +00:00
help='Specifies the database to create.'),
2015-10-02 09:31:32 +00:00
make_option('--db_port', dest='db_port',
default=defaults.get('PORT', '5432'),
2014-05-08 16:59:35 +00:00
help='Specifies the database to create.'),
make_option('--noinput', action='store_false', dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind. '
'You must use --username with --noinput, and must contain the '
'cleeryd process owner, which is the user how will perform tincd updates'),
)
option_list = BaseCommand.option_list
help = 'Setup PostgreSQL database.'
2015-10-02 09:31:32 +00:00
def run_postgres(self, cmd, *args, **kwargs):
2015-10-02 11:14:24 +00:00
return run('su postgres -c "psql -c \\"%s\\""' % cmd, *args, display=True, **kwargs)
2015-10-02 09:31:32 +00:00
2014-05-08 16:59:35 +00:00
@check_root
def handle(self, *args, **options):
2015-10-02 09:31:32 +00:00
interactive = options.get('interactive')
db_password = options.get('db_password')
2014-05-08 16:59:35 +00:00
context = {
'db_name': options.get('db_name'),
'db_user': options.get('db_user'),
2015-10-02 09:31:32 +00:00
'db_password': db_password,
2014-05-08 16:59:35 +00:00
'db_host': options.get('db_host'),
2015-10-01 18:57:31 +00:00
'db_port': options.get('db_port'),
2015-10-02 09:31:32 +00:00
'default_db_password': db_password or random_ascii(10),
2015-10-01 18:57:31 +00:00
}
2014-05-08 16:59:35 +00:00
2015-10-02 09:46:33 +00:00
create_user = "CREATE USER %(db_user)s PASSWORD '%(default_db_password)s';"
2015-10-02 09:31:32 +00:00
alter_user = "ALTER USER %(db_user)s WITH PASSWORD '%(db_password)s';"
create_database = "CREATE DATABASE %(db_name)s OWNER %(db_user)s;"
# Create or update user
if self.run_postgres(create_user % context, valid_codes=(0,1)).exit_code == 1:
2015-10-02 09:46:33 +00:00
if interactive and not db_password:
2015-10-02 09:31:32 +00:00
msg = ("Postgres user '%(db_user)s' already exists, "
"please provide a password [%(default_db_password)s]: " % context)
context['db_password'] = input(msg) or context['default_db_password']
2015-10-02 09:37:25 +00:00
self.run_postgres(alter_user % context)
msg = "Updated Postgres user '%(db_user)s' password: '%(db_password)s'"
2015-10-02 09:46:33 +00:00
self.stdout.write(msg % context)
elif db_password:
2015-10-02 09:37:25 +00:00
self.run_postgres(alter_user % context)
msg = "Updated Postgres user '%(db_user)s' password: '%(db_password)s'"
2015-10-02 09:46:33 +00:00
self.stdout.write(msg % context)
2015-10-02 09:31:32 +00:00
else:
raise CommandError("Postgres user '%(db_user)s' already exists and "
"--db_pass has not been provided." % context)
2015-10-02 09:46:33 +00:00
else:
msg = "Created new Postgres user '%(db_user)s' with password '%(default_db_password)s'"
self.stdout.write(msg % context)
self.run_postgres(create_database % context, valid_codes=(0,1))
2015-10-02 09:31:32 +00:00
2015-10-01 18:57:31 +00:00
context.update({
'settings': os.path.join(get_project_dir(), 'settings.py')
})
2014-05-08 16:59:35 +00:00
2015-10-01 18:57:31 +00:00
if run("grep '^DATABASES\s*=\s*{' %(settings)s" % context, valid_codes=(0,1)).exit_code == 0:
2014-05-08 16:59:35 +00:00
# Update existing settings_file
2015-10-02 09:31:32 +00:00
run(textwrap.dedent("""sed -i \\
-e "s/'ENGINE':[^#]*/'ENGINE': 'django.db.backends.postgresql_psycopg2', /" \\
-e "s/'NAME':[^#]*/'NAME': '%(db_name)s', /" \\
-e "s/'USER':[^#]*/'USER': '%(db_user)s', /" \\
-e "s/'PASSWORD':[^#]*/'PASSWORD': '%(db_password)s', /" \\
-e "s/'HOST':[^#]*/'HOST': '%(db_host)s', /" \\
-e "s/'PORT':[^#]*/'PORT': '%(db_port)s', /" %(settings)s\
2015-10-01 18:57:31 +00:00
""") % context
)
2014-05-08 16:59:35 +00:00
else:
2015-10-01 18:57:31 +00:00
db_config = textwrap.dedent("""\
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': '%(db_name)s',
'USER': '%(db_user)s',
'PASSWORD': '%(db_password)s',
'HOST': '%(db_host)s',
'PORT': '%(db_port)s',
'ATOMIC_REQUESTS': True,
}
}""") % context
2015-10-02 09:31:32 +00:00
context.update({
'db_config': db_config
})
2014-05-08 16:59:35 +00:00
run('echo "%(db_config)s" >> %(settings)s' % context)