Hi all. I wrote a blog post. I would be interested in reactions from this crowd.<br><br><a href="http://blog.ianbicking.org/2011/03/31/python-webapp-package/">http://blog.ianbicking.org/2011/03/31/python-webapp-package/</a><br>
<br>Copied to allow responses:<br><br><div class="document">
<p>At PyCon there was an open space about deployment, and the idea of drop-in applications (<a class="reference external" href="http://en.wikipedia.org/wiki/WAR_file_format_%28Sun%29">Java-WAR-style</a>).</p>
<p>I generally get pessimistic about 80% solutions, and dropping in a
WAR file feels like an 80% solution to me. I’ve used the Hudson/Jenkins
installer (which I think is <em>specifically</em> a project that got
WARs on people’s minds), and in a lot of ways that installer is nice,
but it’s also kind of wonky, it makes configuration unclear, it’s not
always clear when it installs or configures itself through the web, and
when you have to do this at the system level, nor is it clear where it
puts files and data, etc. So a great initial experience doesn’t feel
like a great ongoing experience to me — and <em>it doesn’t have to be that way</em>. If those were <em>necessary</em> compromises, sure, but they aren’t. And because we <em>don’t have</em> WAR files, if we’re proposing to make something new, then we have every opportunity to make things better.</p>
<p>So the question then is what we’re trying to make. To me: we want
applications that are easy to install, that are self-describing,
self-configuring (or at least guide you through configuration), reliable
with respect to their environment (not dependent on system tweaking),
upgradable, and respectful of persistence (the data that outlives the
application install). A lot of this can be done by the "container" (to
use Java parlance; or "environment") — if you just have the app packaged
in a nice way, the container (server environment, hosting service, etc)
can handle all the system-specific things to make the application
actually work.</p>
<p>At which point I am of course reminded of my <a class="reference external" href="http://cloudsilverlining.org/">Silver Lining</a> project, which defines something very much like this. Silver Lining isn’t <em>just</em>
an application format, and things aren’t fully extracted along these
lines, but it’s pretty close and it addresses a lot of important issues
in the lifecycle of an application. To be clear: Silver Lining is an
application packaging format, a server configuration library, a cloud
server management tool, a persistence management tool, and a tool to
manage the application with respect to all these services over time. It
is a bunch of things, maybe too many things, so it is not unreasonable
to pick out a smaller subset to focus on. Maybe an easy place to start
(and good for Silver Lining itself) would be to separate at least the
application format (and tools to manage applications in that state,
e.g., installing new libraries) from the tools that make use of such
applications (deploy, etc).</p>
<p>Some opinions I have on this format, exemplified in Silver Lining:</p>
<ul class="simple"><li>It’s not zipped or a single file, unlike WARs. Uploading zip files
is not a great API. Geez. I know there’s this desire to "just drop in a
file"; but there’s no getting around the fact that "dropping a file"
becomes a <em>deployment protocol</em> <strong>and</strong> <em>it’s an incredibly impoverished protocol</em>. The format is also not subtly git-based (ala Heroku) because <tt class="docutils literal"><span class="pre">git</span> <span class="pre">push</span></tt> is not a good deployment protocol.</li>
<li>But of course there isn’t really any deployment protocol inferred by
a format anyway, so maybe I’m getting ahead of myself ;) I’m saying a
tool that deploys should take as an argument a directory, not a single
file. (If the tool then zips it up and uploads it, fine!)</li><li>Configuration "comes from the outside". That is, an application requests services, and the <em>container</em>
tells the application where those services are. For Silver Lining I’ve
used environmental variables. I think this one point is really
important — the container <em>tells</em> the application. As a counter-example, an application that comes with a Puppet deployment recipe is essentially <em>telling</em> the server how to arrange itself to suit the application. This will never be reliable or simple!</li>
<li>The application indicates what "services" it wants; for instance, it
may want to have access to a MySQL database. The container then
provides this to the application. In practice this means installing the
actual packages, but also creating a database and setting up
permissions appropriately. The alternative is never having <em>any</em>
dependencies, meaning you have to use SQLite databases or ad hoc
structures, etc. But in fact installing databases really isn’t that
hard these days.</li><li><em>All</em> persistence has to use a service of some kind. If you
want to be able to write to files, you need to use a file service. This
means the container is fully aware of everything the application is
leaving behind. All the various paths an application should use are
given in different environmental variables (many of which don’t need to
be invented anew, e.g., <tt class="docutils literal"><span class="pre">$TMPDIR</span></tt>).</li><li>It uses vendor libraries exclusively for Python libraries. That
means the application bundles all the libraries it requires. Nothing
ever gets installed at deploy-time. This is in contrast to using a <tt class="docutils literal"><span class="pre">requirements.txt</span></tt> list of packages at deployment time. If you want to use those tools for development that’s fine, just not for deployment.</li>
<li>There <em>is</em> also a way to indicate other libraries you might require; e.g., you might <tt class="docutils literal"><span class="pre">lxml</span></tt>, or even something that isn’t quite a library, like <tt class="docutils literal"><span class="pre">git</span></tt>
(if you are making a github clone). You can’t do those as vendor
libraries (they include non-portable binaries). Currently in Silver
Lining the application description can contain a list of Ubuntu package
names to install. Of course that would have to be abstracted some.</li><li>You can ask for scripts or a request to be invoked for an
application after an installation or deployment. It’s lame to try to
test if is-this-app-installed on <em>every</em> request, which is the frequent alternative. Also, it gives the application the chance to signal that the installation failed.</li><li>It has a very simple (possibly/probably too simple) sense of
configuration. You don’t have to use this if you make your app
self-configuring (i.e., build in a web-accessible settings screen), but
in practice it felt like some simple sense of configuration would be
helpful.</li></ul>
<p>Things that could be improved:</p>
<ul class="simple"><li>There are some places where you might be encouraged to use routines from the <tt class="docutils literal"><span class="pre">silversupport</span></tt> package. There are very few! But maybe an alternative could be provided for these cases.</li>
<li>A little convention-over-configuration is probably suitable for the
bundled libraries; silver includes tools to manage things, but it gets a
little twisty. When creating a new project I find myself creating
several <tt class="docutils literal"><span class="pre">.pth</span></tt> files, special customizing modules, etc. Managing vendor libraries is also not obvious.</li><li><a class="reference external" href="http://cloudsilverlining.org/services.html">Services</a> are IMHO quite important and useful, but also need to be carefully specified.</li>
<li>There’s a bunch of runtime expectations that aren’t part of the
format, but in practice would be part of how the application is written.
For instance, I make sure each app has its own temporary directory,
and that it is cleared on update. If you keep session files in that
location, and you expect the environment to clean up old sessions —
well, either all environments should do that, or none should.</li><li>The process model is not entirely clear. I tried to simply define
one process model (unthreaded, multiple processes), but I’m not sure
that’s suitable — most notably, multiple processes have a significant
memory impact compared to threads. An application should at least be
able to indicate what process models it accepts and prefers.</li><li>Static files are <em>all</em> convention over configuration — you put static files under <tt class="docutils literal"><span class="pre">static/</span></tt> and then they are available. So <tt class="docutils literal"><span class="pre">static/style.css</span></tt> would be at <tt class="docutils literal"><span class="pre">/style.css</span></tt>. I think this is generally <em>good</em>, but putting all static files under one URL path (e.g., <tt class="docutils literal"><span class="pre">/media/</span></tt>) can be good for other reasons as well. Maybe there should be conventions for both.</li>
<li>Cron jobs are important. Though maybe they could just be yet
another kind of service? Many extra features could be new services.</li><li>Logging is also important; Silver Lining attempts to handle that somewhat, but it could be specified much better.</li><li>Silver Lining also supports PHP, which seemed to cause a bit of stress. But just ignore that. It’s really easy to ignore.</li>
</ul>
<p>There is a <a class="reference external" href="http://cloudsilverlining.org/appconfig.html">description of the configuration file for apps</a>. The <a class="reference external" href="http://cloudsilverlining.org/envvariables.html">environmental variables</a>
are also notably part of the application’s expectations. The file
layout is explained (together with a bunch of Silver Lining-specific
concepts) in <a class="reference external" href="http://cloudsilverlining.org/devpatterns.html">Development Patterns</a>.
Besides all that there is admittedly some other stuff that is only
really specified in code; but in Silver Lining’s defense, specified in
code is better than unspecified ;) App Engine provides another example
of an application format, and would be worth using as a point of
discussion or contrast (I did that myself when writing Silver Lining).</p>
<p>Discussing WSGI stuff with Ben Bangert at PyCon he noted that he
didn’t really feel like the WSGI pieces needed that much more work, or
at least that’s not where the interesting work was — the interesting
work is in the tooling. An application format could provide a great
basis for building this tooling. And I honestly think that the tooling
has been held back more by divergent patterns of development than by the
difficulty of writing the tools themselves; and a good, general
application format could fix that.</p>
</div><br>