Add basic dev/bootstrap scripts and config
This commit is contained in:
parent
a1da468629
commit
4980e5784b
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
||||||
tailbone_theo.egg-info/
|
tailbone_theo.egg-info/
|
||||||
|
dev/settings.ini
|
||||||
machines/theo-server/.vagrant/
|
machines/theo-server/.vagrant/
|
||||||
machines/theo-server/fabenv.py
|
machines/theo-server/fabenv.py
|
||||||
machines/theo-server/fabric.yaml
|
machines/theo-server/fabric.yaml
|
||||||
|
|
45
dev/bootstrap.py
Normal file
45
dev/bootstrap.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
"""
|
||||||
|
Bootstrap development for Theo
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
here = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
def bootstrap():
|
||||||
|
|
||||||
|
if not inside_virtualenv():
|
||||||
|
return
|
||||||
|
|
||||||
|
# install invoke, sphinx
|
||||||
|
subprocess.run(['pip', 'install', 'invoke', 'Sphinx'],
|
||||||
|
check=True)
|
||||||
|
|
||||||
|
# run bootstrap task
|
||||||
|
os.chdir(here)
|
||||||
|
try:
|
||||||
|
completed = subprocess.run(['invoke', '--echo', 'bootstrap'])
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.exit(130) # 128 + SIGINT
|
||||||
|
else:
|
||||||
|
sys.exit(completed.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def inside_virtualenv():
|
||||||
|
if not (hasattr(sys, 'real_prefix') or
|
||||||
|
(hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)):
|
||||||
|
print("\nNot running inside a virtual environment!\n\n"
|
||||||
|
"Please create and activate that first, e.g. like:\n\n"
|
||||||
|
" python -m venv /srv/envs/theo\n"
|
||||||
|
" source /srv/envs/theo/bin/activate\n")
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
bootstrap()
|
131
dev/rattail.conf
Normal file
131
dev/rattail.conf
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
#
|
||||||
|
# Development config for Theo
|
||||||
|
#
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# rattail
|
||||||
|
##############################
|
||||||
|
|
||||||
|
[rattail]
|
||||||
|
timezone.default = America/Chicago
|
||||||
|
datadir = <ENVDIR>/app/data
|
||||||
|
batch.files = <ENVDIR>/app/data/batch
|
||||||
|
workdir = <ENVDIR>/app/work
|
||||||
|
|
||||||
|
[rattail.config]
|
||||||
|
# include = /etc/rattail/rattail.conf
|
||||||
|
configure_logging = true
|
||||||
|
usedb = true
|
||||||
|
preferdb = true
|
||||||
|
|
||||||
|
[rattail.db]
|
||||||
|
default.url = postgresql://<DBUSER>:<DBPASS>@<DBHOST>/<DBNAME>
|
||||||
|
versioning.enabled = true
|
||||||
|
|
||||||
|
[rattail.mail]
|
||||||
|
send_emails = false
|
||||||
|
smtp.server = localhost
|
||||||
|
templates = rattail:templates/mail
|
||||||
|
default.prefix = [Rattail]
|
||||||
|
default.from = rattail@localhost
|
||||||
|
default.to = root@localhost
|
||||||
|
# default.enabled = false
|
||||||
|
|
||||||
|
[rattail.pod]
|
||||||
|
pictures.gtin.root_url = https://rattailproject.org/pod/pictures/gtin
|
||||||
|
|
||||||
|
[rattail.upgrades]
|
||||||
|
files = <ENVDIR>/app/data/upgrades
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# alembic
|
||||||
|
##############################
|
||||||
|
|
||||||
|
[alembic]
|
||||||
|
script_location = rattail.db:alembic
|
||||||
|
version_locations = rattail.db:alembic/versions
|
||||||
|
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# logging
|
||||||
|
##############################
|
||||||
|
|
||||||
|
[loggers]
|
||||||
|
keys = root, exc_logger, beaker, txn, sqlalchemy, django_db, flufl_bounce, requests
|
||||||
|
|
||||||
|
[handlers]
|
||||||
|
keys = file, console, email
|
||||||
|
|
||||||
|
[formatters]
|
||||||
|
keys = generic, console
|
||||||
|
|
||||||
|
[logger_root]
|
||||||
|
handlers = file, console
|
||||||
|
level = DEBUG
|
||||||
|
|
||||||
|
[logger_exc_logger]
|
||||||
|
qualname = exc_logger
|
||||||
|
handlers = email
|
||||||
|
level = ERROR
|
||||||
|
|
||||||
|
[logger_beaker]
|
||||||
|
qualname = beaker
|
||||||
|
handlers =
|
||||||
|
level = INFO
|
||||||
|
|
||||||
|
[logger_txn]
|
||||||
|
qualname = txn
|
||||||
|
handlers =
|
||||||
|
level = INFO
|
||||||
|
|
||||||
|
[logger_sqlalchemy]
|
||||||
|
qualname = sqlalchemy.engine
|
||||||
|
handlers =
|
||||||
|
# handlers = file
|
||||||
|
# level = INFO
|
||||||
|
|
||||||
|
[logger_django_db]
|
||||||
|
qualname = django.db.backends
|
||||||
|
handlers =
|
||||||
|
level = INFO
|
||||||
|
# level = DEBUG
|
||||||
|
|
||||||
|
[logger_flufl_bounce]
|
||||||
|
qualname = flufl.bounce
|
||||||
|
handlers =
|
||||||
|
level = WARNING
|
||||||
|
|
||||||
|
[logger_requests]
|
||||||
|
qualname = requests
|
||||||
|
handlers =
|
||||||
|
# level = WARNING
|
||||||
|
|
||||||
|
[handler_file]
|
||||||
|
class = handlers.RotatingFileHandler
|
||||||
|
args = ('<ENVDIR>/app/log/rattail.log', 'a', 1000000, 100, 'utf_8')
|
||||||
|
formatter = generic
|
||||||
|
|
||||||
|
[handler_console]
|
||||||
|
class = StreamHandler
|
||||||
|
args = (sys.stderr,)
|
||||||
|
formatter = console
|
||||||
|
# formatter = generic
|
||||||
|
# level = INFO
|
||||||
|
# level = WARNING
|
||||||
|
|
||||||
|
[handler_email]
|
||||||
|
class = handlers.SMTPHandler
|
||||||
|
args = ('localhost', 'rattail@localhost', ['root@localhost'], "[Rattail] Logging")
|
||||||
|
formatter = generic
|
||||||
|
level = ERROR
|
||||||
|
|
||||||
|
[formatter_generic]
|
||||||
|
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(funcName)s: %(message)s
|
||||||
|
datefmt = %Y-%m-%d %H:%M:%S
|
||||||
|
|
||||||
|
[formatter_console]
|
||||||
|
format = %(levelname)-5.5s [%(name)s][%(threadName)s] %(funcName)s: %(message)s
|
174
dev/tasks.py
Normal file
174
dev/tasks.py
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
"""
|
||||||
|
Development Tasks for Theo
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import configparser
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from invoke import task
|
||||||
|
from sphinx.util.console import bold
|
||||||
|
from sphinx.cmd.quickstart import do_prompt
|
||||||
|
|
||||||
|
from bootstrap import inside_virtualenv
|
||||||
|
|
||||||
|
|
||||||
|
here = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
|
@task
|
||||||
|
def bootstrap(c):
|
||||||
|
"""
|
||||||
|
Bootstrap a development environment.
|
||||||
|
"""
|
||||||
|
if not inside_virtualenv():
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
envdir = sys.prefix
|
||||||
|
upgrade_pip(c)
|
||||||
|
install_app_package(c)
|
||||||
|
appdir = make_appdir(c, envdir)
|
||||||
|
|
||||||
|
info = collect_info()
|
||||||
|
make_configs(c, envdir, appdir, info)
|
||||||
|
check_db(c, envdir, appdir)
|
||||||
|
install_db_schema(c, envdir, appdir)
|
||||||
|
make_admin_user(c, envdir, appdir, info)
|
||||||
|
|
||||||
|
print()
|
||||||
|
print(bold("============================================================"))
|
||||||
|
print()
|
||||||
|
print(bold(" Okay, you should be ready to go!"))
|
||||||
|
print()
|
||||||
|
print(bold("============================================================"))
|
||||||
|
print()
|
||||||
|
print("start your development web app with this command:")
|
||||||
|
print()
|
||||||
|
print(" cd {}".format(envdir))
|
||||||
|
print(" bin/pserve --reload file+ini:app/web.conf")
|
||||||
|
print()
|
||||||
|
print("then check out your development web app at:")
|
||||||
|
print()
|
||||||
|
print(" http://localhost:9080")
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
def collect_info():
|
||||||
|
"""
|
||||||
|
Collect misc. dev info from user
|
||||||
|
"""
|
||||||
|
info = {}
|
||||||
|
print()
|
||||||
|
print(bold("Welcome to Theo, the order system."))
|
||||||
|
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
if config.read(os.path.join(here, 'settings.ini')):
|
||||||
|
if config.has_section('devbootstrap'):
|
||||||
|
info = dict(config.items('devbootstrap'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
print()
|
||||||
|
print("Please enter the details for your Theo database.")
|
||||||
|
print()
|
||||||
|
info['dbhost'] = do_prompt('DB host',
|
||||||
|
default=info.get('dbhost', 'localhost'))
|
||||||
|
info['dbname'] = do_prompt('DB name',
|
||||||
|
default=info.get('dbname', 'theo'))
|
||||||
|
info['dbuser'] = do_prompt('DB user',
|
||||||
|
default=info.get('dbuser', 'rattail'))
|
||||||
|
info['dbpass'] = do_prompt('DB password',
|
||||||
|
default=info.get('dbpass'))
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("Please enter the details for your Theo admin user.")
|
||||||
|
print()
|
||||||
|
info['theouser'] = do_prompt('Theo username',
|
||||||
|
default=info.get('theouser', 'admin'))
|
||||||
|
info['theopass'] = do_prompt('Theo password',
|
||||||
|
default=info.get('theopass'))
|
||||||
|
|
||||||
|
except (KeyboardInterrupt, EOFError):
|
||||||
|
print("\n[Interrupted.]")
|
||||||
|
sys.exit(130) # 128 + SIGINT
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade_pip(c):
|
||||||
|
"""
|
||||||
|
Upgrade pip and friends
|
||||||
|
"""
|
||||||
|
c.run('pip install -U pip')
|
||||||
|
c.run('pip install -U setuptools wheel')
|
||||||
|
|
||||||
|
|
||||||
|
def install_app_package(c):
|
||||||
|
"""
|
||||||
|
Install the Theo app package
|
||||||
|
"""
|
||||||
|
project = os.path.abspath(os.path.join(here, os.pardir))
|
||||||
|
c.run('pip install -e {}'.format(project))
|
||||||
|
c.run('pip install tailbone-theo[app]')
|
||||||
|
|
||||||
|
|
||||||
|
def make_appdir(c, envdir):
|
||||||
|
"""
|
||||||
|
Create the 'app' dir for virtual env
|
||||||
|
"""
|
||||||
|
appdir = os.path.join(envdir, 'app')
|
||||||
|
if not os.path.exists(appdir):
|
||||||
|
c.run('{} make-appdir'.format(os.path.join(envdir, 'bin', 'rattail')))
|
||||||
|
return appdir
|
||||||
|
|
||||||
|
|
||||||
|
def make_configs(c, envdir, appdir, info):
|
||||||
|
"""
|
||||||
|
Create app config files
|
||||||
|
"""
|
||||||
|
# rattail.conf
|
||||||
|
if not os.path.exists(os.path.join(appdir, 'rattail.conf')):
|
||||||
|
with open('rattail.conf') as f:
|
||||||
|
contents = f.read()
|
||||||
|
contents = contents.replace('<ENVDIR>', envdir)
|
||||||
|
contents = contents.replace('<DBHOST>', info['dbhost'])
|
||||||
|
contents = contents.replace('<DBNAME>', info['dbname'])
|
||||||
|
contents = contents.replace('<DBUSER>', info['dbuser'])
|
||||||
|
contents = contents.replace('<DBPASS>', info['dbpass'])
|
||||||
|
with open(os.path.join(appdir, 'rattail.conf'), 'w') as f:
|
||||||
|
f.write(contents)
|
||||||
|
|
||||||
|
# quiet.conf
|
||||||
|
if not os.path.exists(os.path.join(appdir, 'quiet.conf')):
|
||||||
|
c.run('{}/bin/rattail make-config -T quiet -O {}'.format(envdir, appdir))
|
||||||
|
|
||||||
|
# web.conf
|
||||||
|
if not os.path.exists(os.path.join(appdir, 'web.conf')):
|
||||||
|
with open('web.conf') as f:
|
||||||
|
contents = f.read()
|
||||||
|
contents = contents.replace('<ENVDIR>', envdir)
|
||||||
|
with open(os.path.join(appdir, 'web.conf'), 'w') as f:
|
||||||
|
f.write(contents)
|
||||||
|
|
||||||
|
|
||||||
|
def check_db(c, envdir, appdir):
|
||||||
|
"""
|
||||||
|
Do basic sanity checks for Theo database
|
||||||
|
"""
|
||||||
|
c.run('{}/bin/rattail -c {}/quiet.conf --no-versioning checkdb'.format(envdir, appdir))
|
||||||
|
|
||||||
|
|
||||||
|
def install_db_schema(c, envdir, appdir):
|
||||||
|
"""
|
||||||
|
Install the schema for Theo database
|
||||||
|
"""
|
||||||
|
c.run('{}/bin/alembic -c {}/rattail.conf upgrade heads'.format(envdir, appdir))
|
||||||
|
|
||||||
|
|
||||||
|
def make_admin_user(c, envdir, appdir, info):
|
||||||
|
"""
|
||||||
|
Make an admin user in the Theo database
|
||||||
|
"""
|
||||||
|
c.run('{}/bin/rattail -c {}/quiet.conf make-user --admin {} --password {}'.format(
|
||||||
|
envdir, appdir, info['theouser'], info['theopass']))
|
56
dev/web.conf
Normal file
56
dev/web.conf
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
############################################################
|
||||||
|
#
|
||||||
|
# Development web app config for Theo
|
||||||
|
#
|
||||||
|
############################################################
|
||||||
|
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# rattail
|
||||||
|
##############################
|
||||||
|
|
||||||
|
[rattail.config]
|
||||||
|
include = %(here)s/rattail.conf
|
||||||
|
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# pyramid
|
||||||
|
##############################
|
||||||
|
|
||||||
|
[app:main]
|
||||||
|
use = egg:Tailbone_Theo
|
||||||
|
|
||||||
|
pyramid.reload_templates = true
|
||||||
|
pyramid.debug_all = true
|
||||||
|
pyramid.default_locale_name = en
|
||||||
|
# you can enable this if you find it helpful
|
||||||
|
#pyramid.includes = pyramid_debugtoolbar
|
||||||
|
|
||||||
|
beaker.session.type = file
|
||||||
|
beaker.session.data_dir = %(here)s/sessions/data
|
||||||
|
beaker.session.lock_dir = %(here)s/sessions/lock
|
||||||
|
# this secret should only be used in development!
|
||||||
|
beaker.session.secret = b15zXlYNNIfzRjDjjyOL
|
||||||
|
beaker.session.key = rattail
|
||||||
|
|
||||||
|
exclog.extra_info = true
|
||||||
|
|
||||||
|
rattail.config = %(__file__)s
|
||||||
|
|
||||||
|
[server:main]
|
||||||
|
use = egg:waitress#main
|
||||||
|
# to bind to all interfaces, set host to 0.0.0.0
|
||||||
|
host = 127.0.0.1
|
||||||
|
port = 9080
|
||||||
|
|
||||||
|
|
||||||
|
##############################
|
||||||
|
# logging
|
||||||
|
##############################
|
||||||
|
|
||||||
|
[handler_console]
|
||||||
|
level = INFO
|
||||||
|
|
||||||
|
[handler_file]
|
||||||
|
args = ('<ENVDIR>/app/log/web.log', 'a', 1000000, 100, 'utf_8')
|
Loading…
Reference in a new issue