diff --git a/src/wuttafarm/app.py b/src/wuttafarm/app.py index bafbdad..7d63a40 100644 --- a/src/wuttafarm/app.py +++ b/src/wuttafarm/app.py @@ -32,6 +32,7 @@ class WuttaFarmAppHandler(base.AppHandler): """ default_auth_handler_spec = "wuttafarm.auth:WuttaFarmAuthHandler" + default_install_handler_spec = "wuttafarm.install:WuttaFarmInstallHandler" def get_farmos_handler(self): """ diff --git a/src/wuttafarm/install.py b/src/wuttafarm/install.py new file mode 100644 index 0000000..b67b6e2 --- /dev/null +++ b/src/wuttafarm/install.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# WuttaFarm --Web app to integrate with and extend farmOS +# Copyright © 2026 Lance Edgar +# +# This file is part of WuttaFarm. +# +# WuttaFarm is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# WuttaFarm. If not, see . +# +################################################################################ +""" +Install handler for WuttaFarm +""" + +from wuttjamaican import install as base + + +class WuttaFarmInstallHandler(base.InstallHandler): + """ + Custom install handler for WuttaFarm + """ + + template_paths = ["wuttafarm:installer-templates"] + + def prompt_user_for_context(self): + context = super().prompt_user_for_context() + + context["farmos_url"] = self.prompt_generic("farmos_url", required=True) + + return context diff --git a/src/wuttafarm/templates/install/upgrade.sh.mako b/src/wuttafarm/templates/install/upgrade.sh.mako new file mode 100755 index 0000000..aadc31a --- /dev/null +++ b/src/wuttafarm/templates/install/upgrade.sh.mako @@ -0,0 +1,29 @@ +#!/bin/sh -e +<%text>################################################## +# +# ${app_title} - upgrade script +# +<%text>################################################## + +if [ "$1" = "--verbose" ]; then + VERBOSE='--verbose' + QUIET= +else + VERBOSE= + QUIET='--quiet' +fi + +cd ${envdir} + +PIP='bin/pip' +ALEMBIC='bin/alembic' + +# upgrade pip and friends +$PIP install $QUIET --disable-pip-version-check --upgrade pip +$PIP install $QUIET --upgrade setuptools wheel + +# upgrade app proper +$PIP install $QUIET --upgrade --upgrade-strategy eager '${pypi_name}' + +# migrate schema +$ALEMBIC -c app/wutta.conf upgrade heads diff --git a/src/wuttafarm/templates/install/web.conf.mako b/src/wuttafarm/templates/install/web.conf.mako new file mode 100644 index 0000000..4d2b3c7 --- /dev/null +++ b/src/wuttafarm/templates/install/web.conf.mako @@ -0,0 +1,90 @@ +## -*- mode: conf; -*- + +<%text>############################################################ +# +# ${app_title} - web app config +# +<%text>############################################################ + + +<%text>############################## +# wutta +<%text>############################## + +${self.section_wutta_config()} + + +<%text>############################## +# pyramid +<%text>############################## + +${self.section_app_main()} + +${self.section_server_main()} + + +<%text>############################## +# logging +<%text>############################## + +${self.sectiongroup_logging()} + + +###################################################################### +## section templates below +###################################################################### + +<%def name="section_wutta_config()"> +[wutta.config] +require = %(here)s/wutta.conf + + +<%def name="section_app_main()"> +[app:main] +#use = egg:wuttaweb +use = egg:${egg_name} + +pyramid.reload_templates = true +pyramid.debug_all = true +pyramid.default_locale_name = en +#pyramid.includes = pyramid_debugtoolbar + +beaker.session.type = file +beaker.session.data_dir = %(here)s/cache/sessions/data +beaker.session.lock_dir = %(here)s/cache/sessions/lock +beaker.session.secret = ${beaker_secret} +beaker.session.key = ${beaker_key} + +exclog.extra_info = true + +# required for wuttaweb +wutta.config = %(__file__)s + + +<%def name="section_server_main()"> +[server:main] +use = egg:waitress#main +host = ${pyramid_host} +port = ${pyramid_port} + +# NOTE: this is needed for local reverse proxy stuff to work with HTTPS +# https://docs.pylonsproject.org/projects/waitress/en/latest/reverse-proxy.html +# https://docs.pylonsproject.org/projects/waitress/en/latest/arguments.html +trusted_proxy = 127.0.0.1 +trusted_proxy_headers = x-forwarded-for x-forwarded-host x-forwarded-proto x-forwarded-port +clear_untrusted_proxy_headers = True + +# TODO: leave this empty if proxy serves as root site, e.g. https://wutta.example.com/ +# url_prefix = + +# TODO: or, if proxy serves as subpath of root site, e.g. https://wutta.example.com/backend/ +# url_prefix = /backend + + +<%def name="sectiongroup_logging()"> +[handler_console] +level = INFO + +[handler_file] +args = (${repr(os.path.join(appdir, 'log', 'web.log'))}, 'a', 1000000, 100, 'utf_8') + diff --git a/src/wuttafarm/templates/install/wutta.conf.mako b/src/wuttafarm/templates/install/wutta.conf.mako new file mode 100644 index 0000000..5049808 --- /dev/null +++ b/src/wuttafarm/templates/install/wutta.conf.mako @@ -0,0 +1,171 @@ +## -*- mode: conf; -*- + +<%text>############################################################ +# +# ${app_title} - base config +# +<%text>############################################################ + + +[farmos] +url.base = ${farmos_url} + + +<%text>############################## +# wutta +<%text>############################## + +${self.section_wutta()} + +${self.section_wutta_config()} + +${self.section_wutta_db()} + +${self.section_wutta_mail()} + +${self.section_wutta_upgrades()} + + +<%text>############################## +# alembic +<%text>############################## + +${self.section_alembic()} + + +<%text>############################## +# logging +<%text>############################## + +${self.sectiongroup_logging()} + + +###################################################################### +## section templates below +###################################################################### + +<%def name="section_wutta()"> +[wutta] +#app_title = ${app_title} + + +<%def name="section_wutta_config()"> +[wutta.config] +#require = /etc/wutta/wutta.conf +configure_logging = true +usedb = true +preferdb = true + + +<%def name="section_wutta_db()"> +[wutta.db] +default.url = ${db_url} + +% if wants_continuum: +[wutta_continuum] +enable_versioning = true +% endif + + +<%def name="section_wutta_mail()"> +[wutta.mail] + +# this is the global email shutoff switch +#send_emails = false + +# recommended setup is to always talk to postfix on localhost and then +# it can handle any need complexities, e.g. sending to relay +smtp.server = localhost + +# by default only email templates from wuttjamaican are used +templates = wuttjamaican:templates/mail + +## TODO +## # this is the "default" email profile, from which all others initially +## # inherit, but most/all profiles will override these values +## default.prefix = [${app_title}] +## default.from = wutta@localhost +## default.to = root@localhost +# nb. in test environment it can be useful to disable by default, and +# then selectively enable certain (e.g. feedback, upgrade) emails +#default.enabled = false + + +<%def name="section_wutta_upgrades()"> +## TODO +## [wutta.upgrades] +## command = ${os.path.join(appdir, 'upgrade.sh')} --verbose +## files = ${os.path.join(appdir, 'data', 'upgrades')} + + +<%def name="section_alembic()"> +[alembic] +script_location = wuttjamaican.db:alembic +% if wants_continuum: +version_locations = ${pkg_name}.db:alembic/versions wutta_continuum.db:alembic/versions wuttjamaican.db:alembic/versions +% else: +version_locations = ${pkg_name}.db:alembic/versions wuttjamaican.db:alembic/versions +% endif + + +<%def name="sectiongroup_logging()"> +[loggers] +keys = root, beaker, exc_logger, sqlalchemy, txn + +[handlers] +keys = file, console, email + +[formatters] +keys = generic, console + +[logger_root] +handlers = file, console +level = DEBUG + +[logger_beaker] +qualname = beaker +handlers = +level = INFO + +[logger_exc_logger] +qualname = exc_logger +handlers = email +level = ERROR + +[logger_sqlalchemy] +qualname = sqlalchemy.engine +handlers = +# handlers = file +# level = INFO + +[logger_txn] +qualname = txn +handlers = +level = INFO + +[handler_file] +class = handlers.RotatingFileHandler +args = (${repr(os.path.join(appdir, 'log', 'wutta.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', 'wutta@localhost', ['root@localhost'], "[${app_title}] 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 +