Source code for squaresdb.utils.install

#!/usr/bin/env python

import argparse
import getpass
import os
import os.path
import random
import subprocess
import sys

BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

[docs] def parse_args(): parser = argparse.ArgumentParser() parser.add_argument('--dry-run', action='store_true', help="Report planned changes but don't make them") parser.add_argument('--scripts', action='store_true', help="Set up web_scripts index.fcgi and media symlinks") parser.add_argument('--locker', type=str, default=getpass.getuser(), help="Locker name to use on scripts") parser.add_argument('--instance', type=str, help="Name of install instance to use. Used to name " "web_scripts subdir and sql.mit.edu database") parser.add_argument('--email', type=str, required=True, help="Set the forced recipient address to use") args = parser.parse_args() if args.scripts and not args.instance: _pre, dj_mid, post = BASE_DIR.partition('/Scripts/django/') if not dj_mid: parser.error("in scripts.mit.edu mode, but instance was not " "provided and path doesn't include /Scripts/django/ " "so couldn't guess") instance, slash, post = post.partition('/') if slash: args.instance = instance else: parser.error("could not autodetect instance") if '@' not in args.email: parser.error("email must contain local part and domain") return args
[docs] def write_file(dry_run, filename, contents): if dry_run: print("Would write file '%s':" % (filename, )) print('"""') print(contents) print('"""') print("\n\n") else: with open(filename, 'wt', encoding='utf-8') as file_obj: file_obj.write(contents)
[docs] def check_call(dry_run, cmd_args): if dry_run: print("Would call %s" % (cmd_args, )) else: subprocess.check_call(cmd_args)
SCRIPTS_SETTINGS = """ DATABASES = {{ 'default': {{ 'ENGINE': 'django.db.backends.mysql', 'NAME': '{locker}+{instance}', 'OPTIONS': {{ 'read_default_file' : os.path.expanduser('~/.my.cnf'), }}, }} }} ALLOWED_HOSTS = [ 'tech-squares.mit.edu', '{locker}.scripts.mit.edu', 's-a.mit.edu', ] SITE_SERVER = 'https://{locker}.scripts.mit.edu' # XXX: FIXME SITE_WEB_PATH = '/{instance}' # XXX: FIXME SITE_URL_BASE = SITE_SERVER COOKIES_PREFIX = "{instance}_" # XXX: FIXME ADMIN_MEDIA_PREFIX = '/__scripts/django/media/' STATIC_URL = '/__scripts/django/static/' """ RUNSERVER_SETTINGS = """ SITE_SERVER = 'http://localhost:8007' """
[docs] def read_file(dirname, filename): """Read a file from a directory and return contents""" filepath = os.path.join(dirname, filename) with open(filepath, 'rt', encoding='utf-8') as file_obj: return file_obj.read()
[docs] def init_settings(args): settings_dir = os.path.join(BASE_DIR, "squaresdb", "settings") tmpl_text = read_file(settings_dir, 'local.dev-template.py') choices = 'abcdefghijklmnopqrstuvwxyz0123456789@#%-_=+' rand = random.SystemRandom() key = ''.join([rand.choice(choices) for i in range(50)]) text = tmpl_text.replace("#SECRET_KEY = something", 'SECRET_KEY = "%s"' % key) text = text.replace("squares-db-forced-recipient@mit.edu", args.email) if args.scripts: custom_prelude = SCRIPTS_SETTINGS.format( locker=args.locker, instance=args.instance, ) else: custom_prelude = RUNSERVER_SETTINGS insert_after = "import os\n\n" text = text.replace(insert_after, insert_after+custom_prelude) local_file = os.path.join(settings_dir, 'local.py') write_file(args.dry_run, local_file, text)
[docs] def init_fcgi(args): util_dir = os.path.join(BASE_DIR, "squaresdb", "utils") tmpl_text = read_file(util_dir, 'scripts.tmpl.fcgi') text = tmpl_text.format(executable=sys.executable, base=BASE_DIR) web_scripts = os.path.expanduser("~/web_scripts") instance_dir = os.path.join(web_scripts, args.instance) if not args.dry_run: os.mkdir(instance_dir) index_file = os.path.join(instance_dir, "index.fcgi") write_file(args.dry_run, index_file, text) if not args.dry_run: os.chmod(index_file, 0o755)
SCRIPTS_HTACCESS = r"""RewriteEngine On # Require HTTPS RewriteCond %{HTTPS} off RewriteCond %{THE_REQUEST} ^[^\ ]*\ (.*)\ .* RewriteRule ^ https://%{SERVER_NAME}%1 [L,R] # Empty goes to Django (index.fcgi) RewriteRule ^$ index.fcgi/ [QSA,L] # Non-existent paths go to index.fcgi RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.fcgi/$1 [QSA,L] """
[docs] def init_htaccess(args): web_scripts = os.path.expanduser("~/web_scripts") htaccess_file = os.path.join(web_scripts, args.instance, ".htaccess") write_file(args.dry_run, htaccess_file, SCRIPTS_HTACCESS)
[docs] def init_db(args): def call(cmd_args): check_call(args.dry_run, cmd_args) if args.scripts: call(['/mit/scripts/sql/bin/create-database', args.instance]) manage = os.path.join(BASE_DIR, "manage.py") call(["python", manage, "migrate"]) call(["python", manage, "createinitialrevisions", "--comment=Initial revision (in setup script)", "membership"])
# TODO(django-3.0): Run createsuperuser and set a password ourselves? # Perhaps check if DJANGO_SUPERUSER_PASSWORD is set, and if so run # createsuperuser so the account is created. # https://docs.djangoproject.com/en/dev/ref/django-admin/#django-admin-createsuperuser NEXT_STEPS = """ Possible next steps: - Clone the membership database (on Athena: /mit/tech-squares/club-private/signin/git/) and import it: membership/parsedb.py legacy2csv --csv membership/club-db/club.csv < membership/club-db/club.db membership/parsedb.py csv2django --csv membership/club-db/club.csv - Create a superuser account: ../manage.py createsuperuser --email {email} --username $USER """
[docs] def write_instructions(args): if args.scripts: tmpl = "Visit the server at https://{locker}.scripts.mit.edu/{instance}/" msg = tmpl.format(locker=args.locker, instance=args.instance) else: msg = "Run the server with\n./manage.py runserver 8007\nor similar" print("\nDone! " + msg) print(NEXT_STEPS.format(email=args.email))
[docs] def init(): args = parse_args() init_settings(args) if args.scripts: init_fcgi(args) init_htaccess(args) init_db(args) write_instructions(args)
if __name__ == '__main__': init()