PageRenderTime 210ms CodeModel.GetById 116ms app.highlight 10ms RepoModel.GetById 70ms app.codeStats 1ms

/docs/porting.txt

https://bitbucket.org/ianb/silverlining/
Plain Text | 371 lines | 263 code | 108 blank | 0 comment | 0 complexity | cdd7acfaf384b1e3f9108233e98f4018 MD5 | raw file
  1Porting An Application To Silver Lining
  2=======================================
  3
  4This describes some of the steps of taking an existing application and
  5"porting" it to Silver Lining.
  6
  7First steps for a simple Python application
  8-------------------------------------------
  9
 10Imagine you've been developing an application for a while, using your
 11Python framework of choice.  It doesn't matter much *what* framework
 12you used.  You might have to do a little cleanup to start:
 13
 14* Make sure everything runs okay with Python 2.6.
 15* Make sure you've identified all your requirements.
 16
 17It's not required to use a ``setup.py`` file or specify your
 18requirements in ``setup.py`` with ``install_requires``.  These files
 19are good practice, but not necessary.
 20
 21Clean up your ``site-packages``
 22-------------------------------
 23
 24Some people have installed things into their computer as root, e.g.,
 25by using ``sudo easy_install`` or ``sudo pip install``.  This is a bad
 26idea.  This will cause all sorts of weird problems and complications
 27for you, not just with Silver Lining but with everything.
 28
 29I recommend deleting as much from ``/usr/lib/python2.6/site-packages``
 30as you can.  I recommend *keeping* some select stable libraries like
 31PIL, or Database drivers (psycopg, MySQLdb, etc).
 32
 33Create the file layout
 34----------------------
 35
 36Now you are ready to create a location for storing your application.
 37With Silver Lining applications all the code and libraries are stored
 38in a single directory.  I usually name this directory ``mything-app``
 39(where ``mything`` is the name of my application).  So run::
 40
 41    $ silver init mything-app
 42    $ cd mything-app
 43    $ source bin/activate
 44
 45Now you have an activated `virtualenv
 46<http://virtualenv.openplans.org>`_ with some basic Silver Lining
 47layout, though no application.
 48
 49Next, put your application in place::
 50
 51    $ cd src
 52    $ hg/git/svn clone/checkout your-repository mything
 53
 54If you already have your code checked out into, say, ``~/src/mything``
 55then unfortunately you'll either have to move it or deal with two
 56separate checkouts -- the code has to be physically located inside the
 57``mything-app`` directory, because only that directory will be
 58uploaded to the server.  Though you can *probably* do something like
 59this, but I haven't tried it::
 60
 61    $ cd $VIRTUAL_ENV/src
 62    $ ln -s ~/src/mything mything
 63
 64anyway, you probably want to do this work on a branch or separate
 65cloned repository.
 66
 67Next create a new repository for your application's libraries.  You
 68won't install libraries during the regular workflow of developing
 69applications with Silver Lining, even if you are collaborating with
 70other developers or using multiple machines -- you'll only install
 71things when you've actually added, updated, or removed a library that
 72your application uses.  To do that you'll put all your *installed*
 73libraries in another repository.  You can do that like::
 74
 75    $ cd $VIRTUAL_ENV/lib
 76    $ rm -r python
 77    $ hg init python
 78
 79or use ``git init``, or create a repository and clone/check it out.
 80This repository will be separate from your main application.
 81
 82Note that everything gets installed into ``lib/python/``, not into
 83``lib/python2.6/site-packages/`` (which exists, but won't be added
 84to).
 85
 86Installing Stuff
 87----------------
 88
 89Now you have some files in place, but nothing is really "installed".
 90
 91If you have a ``setup.py`` file, then run::
 92
 93    $ cd $VIRTUAL_ENV
 94    $ pip install -e src/mything/
 95
 96This will make the package importable and install any requirements
 97you've specified.
 98
 99If you *have not* written a ``setup.py`` file (common for Django
100applications) then you'll have to make sure the appropriate directory
101is on the path in a more manual fashion.  Let's say you want
102``src/mything/`` directly on the path, then you'll do::
103
104    $ cd $VIRTUAL_ENV/lib/python/
105    $ echo ../../src/mything/ > mything.pth
106
107If you need to install some additional things, go ahead now::
108
109    $ pip install SomeLibrary
110
111If you are developing a library concurrently with your application
112then you should also check that library out into ``src/`` and use
113``pip install -e``.
114
115You should use **pip** specifically and not easy_install, as pip
116cleans up after itself, uninstalling libraries and old versions of
117libraries.
118
119Non-Python Libraries
120--------------------
121
122If you have any libraries that you need that aren't pure-Python, you
123should install them system-wide.  Ideally you should use your
124operating system facilities to install these libraries (e.g.,
125``apt-get install python-lxml``).
126
127Make note of these libraries.  Database connection libraries will be
128installed automatically, but any other libraries will have to be
129explicitly added (more on that later).
130
131Describe your application with ``app.ini``
132------------------------------------------
133
134Now you have to tell Silver Lining how to start up your application,
135and possibly some other details.  This is done through a configuration
136file ``app.ini`` in the root of your app.
137
138There will be an example file in place.  You might just want to edit
139it, making note of these settings::
140
141    [production]
142    app_name = mything
143    runner = src/mything/silver-runner.py
144
145Those are really the most important settings.  Also if you are using a
146database (likely!) then find the appropriate line and uncomment it.
147In our example we'll imagine you are using PostgreSQL::
148
149    service.postgresql =
150
151Note that you don't need any value there.  (Maybe someday there will
152be a service that isn't just "enabled" but is actually configured, at
153which point it will take some value.)
154
155The most important thing you'll note is that now you have a "runner"
156defined in ``src/mything/silver-runner.py``.  You better write that!
157
158The specific code you'll use depends on your web framework.  This file
159will basically look like a mod_wsgi ``.wsgi`` file: it's some Python
160code that creates an object ``application``.
161
162You shouldn't need to set up your path in this file.  In fact, you
163shouldn't need to set up any of your environment, you just find the
164application object.  You can also use a `Paste Deploy
165<http://pythonpaste.org/deploy/>`_ ini file if you want (but even if
166you are using a framework such as Pylons, you can if you want import
167your ``make_app`` function directly and call it).
168
169Here's an example for Django::
170
171    import django.core.handlers.wsgi
172    application = django.core.handlers.wsgi.WSGIHandler()
173
174Setting Up Your Environment
175---------------------------
176
177One nice thing about Silver Lining is that your environment can
178*always* be setup.  That means, everything importable all the time,
179everything configurable all the time, all data available.
180
181To do this there is a specific file for you to customize (well, a file
182for you to create): ``lib/python/silvercustomize.py`` (similar to
183``sitecustomize.py``).
184
185If you are using Django, you should do at least this::
186
187    import os
188    os.environ['DJANGO_SETTINGS_MODULE'] = 'mything.settings'
189
190On other systems you might import or configure other things.  It is
191preferable to put things here rather than in your runner, as this file
192is always loaded, so it will be available in the interactive
193interpreter, in tests, in scripts, etc.
194
195Configuration
196-------------
197
198Silver Lining uses a different model of configuration than is
199typically used.  You can, if you want, ignore configuration entirely
200-- but this is about *porting* an application, so you certainly
201haven't ignored configuration before.  So you need to adapt that
202configuration.
203
204Silver Lining tells the application about the environment through
205`environmental variables <envvariables.html>`_ (``os.environ``).
206These variables are *always* set.  So if you use a PostgreSQL database
207you would look at these:
208
209``os.environ['CONFIG_PG_DBNAME']``: the name of the database you
210should connect to.
211
212``os.environ['CONFIG_PG_HOST']``: the host of the database (empty
213string means localhost).
214
215``os.environ['CONFIG_PG_PORT']``: the port of the database (empty
216string means default port).
217
218``os.environ['CONFIG_PG_USER']``: the user to connect as.
219
220``os.environ['CONFIG_PG_PASSWORD']``: the password to use (empty string
221means no password).
222
223``os.environ['CONFIG_PG_SQLALCHEMY']``: creating the SQLAlchemy
224connection string from all these pieces is somewhat annoying, so this
225does it for you.
226
227These variables will be set both during local development and when
228deployed, so you can always rely on them -- you don't need any special
229conditionals.
230
231``bin/``
232--------
233
234Yet to be written (it's kind of a pain currently).
235
236Setting Up Your Database
237------------------------
238
239Now you have something that will *run*, but with a blank database.
240That's probably not what you want.
241
242You can tell Silver Lining to fetch a URL or call a script every time
243an application is updated.  It is up to this script to do the right
244thing -- to alter tables, to notice tables that already exists, etc.
245All Silver Lining handles is fetching this program.
246
247To do this, add a setting to ``app.ini``::
248
249    [production]
250    ...
251    update_fetch = /update-database
252
253That gets a URL, to call a script::
254
255    update_fetch = script:bin/django-admin.py syncdb
256
257You can have multiple entries, one per line (indent subsequent lines).
258
259If you have to poke at a database remotely there's also a way to do
260that, with ``silver run``.
261
262These URLs or scripts will also be called everytime you start up the
263application locally using ``silver serve``.
264
265Static Files
266------------
267
268If you have static files in your application, they go in ``static/``.
269They can (and should) be symlinks.  Note that ``static`` doesn't
270appear in the URL; so if for example you have a convention that all
271your static files go in ``http://example.com/static/`` then you
272actually have to get the files into ``static/static/``.
273
274So do something like::
275
276    $ cd $VIRTUAL_ENV/static
277    $ ln -s ../src/mything/mything/media media
278
279For Django you might also symlink things from the admin media into a
280location here, like::
281
282    $ ln -s ../lib/python/django/contrib/admin/media admin-media
283
284and in ``settings.py``::
285
286    ADMIN_MEDIA_PREFIX = '/admin-media/'
287
288Non-Python Libraries
289--------------------
290
291Any non-Python libraries have to be installed in production as deb
292packages.  For instance if you need lxml you'll need the
293``python-lxml`` package installed.  You can get this to happen with
294this addition to app.ini::
295
296    packages =
297        python-lxml
298
299You can have multiple packages, one on each line.  This doesn't
300include databases though!  (Well, SQLite is fine, as it runs
301in-process.)
302
303Testing It Out
304--------------
305
306You can run this application locally now, using::
307
308    $ silver serve ~/src/mything-app/
309
310This will run any URLs or scripts in ``update_fetch``, and serve up
311the application at ``http://localhost:8080``.  If you edit any files
312the server will restart to get the refreshed files.
313
314Note that when running locally you have to do things like create
315databases on your own.  You can also `customize the local
316configuration <services.html#local-development-configuration>`_ (this
317is done *outside* the application).
318
319To test an actual deployment you need a server to deploy to.  Silver
320Lining can deploy to any dedicated Ubuntu Lucid machine that has been
321configured by Silver Lining (using ``silver setup-node``), but the
322cloud makes getting a testing server very easy and quite cheap (when
323testing, you can allocate a server just for a few hours for testing
324before getting rid of it), so you might consider opening an account.
325
326
327Problems
328--------
329
330Here are some problems you might encounter, with ideas for solutions:
331
332I can't see errors
333~~~~~~~~~~~~~~~~~~
334
335Silver Lining doesn't do anything very useful with exceptions on its
336own.  You should use whatever facilities your web framework has.
337Projects like `weberror <http://bitbucket.org/bbangert/weberror/>`_
338and `flickzeug <http://dev.pocoo.org/projects/flickzeug/>`_ are a
339generic way of wrapping your application, and could be applied in the
340runner.
341
342To detect if you are in a production environment, you can use::
343
344    from silversupport.env import is_production
345
346    application = normal instantiation
347
348    if not is_production():
349        from flickzeug.debug import DebuggedApplication
350        application = DebuggedApplication(application, evalex=True)
351
352I need custom database setup
353~~~~~~~~~~~~~~~~~~~~~~~~~~~~
354
355If you want to, you can do things more manually than just using
356``update_fetch``.  One way is to use ``silver run``.  For instance,
357instead of using ``script:bin/django-admin.py syncdb`` you can invoke
358this manually on a server like::
359
360    $ silver run mything-host.com django-admin.py syncdb
361
362This command can be interactive.  There isn't good access directly to
363commands like ``psql`` though.
364
365I need a service that isn't supported
366~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
367
368Then write the code!  You can fork `the project
369<http://bitbucket.org/ianb/silverlining>`_ and add code in
370``silversupport/services/``.  It's not very complicated, or at least
371not more complicated than using a database properly anyway.