Glad-I-Was-Here (Python, Mariadb)
/docs/gears/developer/toyapps/gladiwashere-python-mysql/
Introduction
The Python version of Glad-I-Was-Here is functionally equivalent to Glad-I-Was-Here (PHP, Mariadb). However, it is implemented in Python and interacts with the web server through WSGI, as many Python web applications do.
If you have not already read through Glad-I-Was-Here (PHP, Mariadb) of Glad-I-Was-Here, we recommend you do so first as we’ll only discuss things in this section that were not covered before.
% git clone https://gitlab.com/ubos/ubos-toyapps
Go to subdirectory gladiwashere-python-mysql
.
Package lifecycle and App deployment
Like all other Apps on UBOS including Hello World,
gladiwashere-python-mysql
is built with makepkg
, installed with
pacman
and deployed with ubos-admin
.
% makepkg -f
% sudo pacman -U gladiwashere-python-mysql-*-any.pkg.tar.xz
% sudo ubos-admin createsite --selfsigned
Specify gladiwashere-python-mysql
as the name of the App.
As you will see below, this App specifies that it cannot run without being
protected by TLS.
So ubos-admin createsite
above will not deploy the App unless we tell
it where to get a certificate from. Here, we specify --selfsigned
, which means
that UBOS will automatically create a self-signed certificate before deploying.
Because of the constraints of TLS certificates, you also cannot deploy to *
,
the UBOS wildcard hostname. If you are using the recommended UBOS container setup
for development, it is easiest to specify the name of the container (e.g. ubosdev-yellow
)
as the hostname.
Manifest JSON
Let’s examine this App’s UBOS Manifest file. It is similar to
that of gladiwashere-php-mysql
, but there are a few differences:
- It declares the App as requiring TLS. This means the user cannot deploy it to a Site unless the Site uses TLS (i.e. it is a HTTPS-only site).
- It specifies dependencies on Python instead of PHP modules,
- It keeps application files out of the Apache document root. This is good security practice, and somewhat easier with WSGI than with PHP:
{
"type" : "app",
"requirestls" : true,
"roles" : {
"apache2" : {
"defaultcontext" : "/guestbook",
"depends" : [
"mod_wsgi",
"python-mysql-connector"
],
"apache2modules" : [
"wsgi"
],
"appconfigitems" : [
{
"type" : "directory",
"name" : "${appconfig.datadir}"
},
{
"type" : "file",
"name" : "${appconfig.datadir}/config.py",
"template" : "tmpl/config.py.tmpl",
"templatelang" : "varsubst"
},
{
"type" : "file",
"name" : "${appconfig.apache2.appconfigfragmentfile}",
"template" : "tmpl/htaccess.tmpl",
"templatelang" : "varsubst"
}
]
},
"mysql" : {
"appconfigitems" : [
{
"type" : "database",
"name" : "maindb",
"retentionpolicy" : "keep",
"retentionbucket" : "maindb",
"privileges" : "select, insert"
},
{
"name" : "maindb",
"type" : "sqlscript",
"source" : "sql/create.sql"
}
]
}
}
}
Let’s first note what is the same as in the PHP version:
-
The
type
isapp
for both, of course. -
The
defaultcontext
is the same. -
The entire
mysql
section is the same, including database permissions and database initialization.
Here are the differences:
-
Apache now needs to use modules
wsgi
, which allow Apache to invoke Python. Because there is no more PHP involved, the Apache PHP modules are not needed any more. -
Instead of having the PHP files as
appconfigitems
, there is only one Apache configuration fragment file that configures Apache’s WSGI module. This file is in the package as a template, so UBOS can correctly parameterize it for the particular AppConfiguration (see below). -
Just as in the PHP case, we generate a Python file that contains AppConfiguration-specific parameters (the database name, username and credentials) and import that into our application.
WSGI configuration
The Apache WSGI configuration could be different, as WSGI has many options, but in this example it is this:
WSGIScriptAlias ${appconfig.contextorslash} ${package.codedir}/web/index.py
WSGIDaemonProcess gladiwashere-python-mysql-${appconfig.appconfigid} processes=2 threads=10 \
umask=0007 inactivity-timeout=900 maximum-requests=1000 \
python-path=${package.codedir}/web:${appconfig.datadir}:/usr/lib/python3.8/site-packages/
WSGIProcessGroup gladiwashere-python-mysql-${appconfig.appconfigid}
# Can't do this because there may be more than one WSGI :term:`App`:
# WSGIApplicationGroup %{GLOBAL}
<Directory "${package.codedir}">
Require all granted
</Directory>
<Directory "${appconfig.datadir}">
Require all granted
</Directory>
At deployment time, UBOS will replace the variables in this template and save the
resulting file as .htaccess
in the web server directory, such as:
WSGIScriptAlias /guestbook /usr/share/gladiwashere-python-mysql/web/index.py
WSGIDaemonProcess gladiwashere-python-mysql-a1234567890123456789012345678901234567890 processes=2 threads=10 \
umask=0007 inactivity-timeout=900 maximum-requests=1000 \
python-path=/ubos/share/gladiwashere-python-mysql/web:/ubos/lib/gladiwashere-python-mysql/a1234567890123456789012345678901234567890:/usr/lib/python3.6/site-packages/
WSGIProcessGroup gladiwashere-python-mysql-a1234567890123456789012345678901234567890
# Can't do this because there may be more than one WSGI App:
# WSGIApplicationGroup %{GLOBAL}
<Directory "/ubos/share/gladiwashere-python-mysql">
Require all granted
</Directory>
<Directory "/ubos/lib/gladiwashere-python-mysql/a1234567890123456789012345678901234567890">
Require all granted
</Directory>
Let’s go through these lines step by step:
-
WSGIScriptAlias
maps all incoming requests to theindex.py
script, which is the entry point to the application. -
WSGIDaemonProcess
specifies parameters to the WSGI setup, such as how many processes to spawn for our application. Thepython-path
argument must list all locations for Python files that are being included by the application. Here, we specify a location in the application package (/ubos/share/gladiwashere-python-mysql/web
), a location in the AppConfiguration’s data directory (/ubos/lib/gladiwashere-python-mysql/a1234567890123456789012345678901234567890
) where we save the generated/parameterized code, and the default location for Python packages on the system (/usr/lib/python3.8/site-packages/
) -
WSGIProcessGroup
puts all processes for this AppConfiguration into the same Linux process group. This is optional. -
The two
Directory
declarations are allowing access to these directories, otherwise Apache will prevent access.