Source

silverlining / docs / todo.txt

Full commit
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
Things Silver Lining Should Do
==============================

This document lists out things that I think Silver Lining should do,
but does not yet do.  It's also kind of a notepad for design ideas.
It should not surprise you if I forget to remove something from this
document after implementing it.

Far-future expiration of static content
---------------------------------------

It's nice to present static content with far-future expiration dates.
Do do this while still allowing this static content to be updated, it
is conventional to use a timestamp of some sort in the URL itself.  An
example might be::

    /static/20100127_1/media/style.css

Then if the application is updated this URL will change.  You could
use the modification date of the file itself, but a sweeping
invalidation of all content is less error-prone and requires very
little framework support.

I think Silver Lining should add a new location (like in the example)
where content in the ``static/`` directory is served with this
caching, and an environmental variable ``$STATIC_URL`` which you use
to prefix all your media files.  Probably the current pattern will be
preserved, as it can be handy when retrofitting an application.  The
datestamp_version used in the application directories is apppriately
unique.

Then in the future there should also be support for uploading these
static files to a CDN, at which point the variable will point to the
CDN.

Groups of servers, replication
------------------------------

There are notes on this in ``multiserver design notes
<multiserver.html>`_.

Backups
-------

Backup and restore is implemented in a basic fashion.  It would be
very nice if backup files were portable.  Then, for instance, you
could download the backups to replicate live data on your site for
your development.  (PostGIS is a case where portable backups can be a
bit tricky at times.)

It would be even more neat if backup files were somewhat version
control friendly.  E.g., well-ordered SQL dumps.  This might make the
backup process do double duty as a test fixture process, and a process
to setup data in new instances.

Site-to-site backups should be supported (which would essentially
clone the data from one server to another).

Logs
----

Log files should also be handled gracefully, tracked, and possibly
some frontend (`frontend in progress
<http://bitbucket.org/ianb/silverlog>`_).  Though I feel like some
kind of management programming interface is better, and then a
"deployed" app would use that interface.  Actually, "interface" is
probably saying too much; it should be sufficient to simply have a
documented and conscious server layout that an application can be
written to inspect.

There should be a way to get a list of all log files for a host/app.
Maybe there should be a standard way to effect the Python standard
logging module output, and then put it in a normal location (I think
``/var/log/silverlining/apps/NAME/*``).  There are some more notes
down in Debugging_.

Monitoring
----------

Basically a way is needed to answer the question "do I need to rent
bigger (or smaller) nodes?" Basic metrics like load, RAM, swap and
requets per second should be monitored and graphed. Munin seems to be a
popular choice for that.  Probably a Nagios setup makes sense here.
`This post
<http://agiletesting.blogspot.com/2010/02/web-site-monitoring-techniques-and.html>`_
also has some additional ideas.

Also similar to ``update_fetch`` etc, there should be an optional
defined "ping" URL for an application.  This would be some location
that could be safely fetched, wouldn't be time-intensive, and would
report general errors.  An application could do self-testing here.
Monitoring infrastructure would then be setup to ping this URL.
Unlike ``update_fetch`` and other management URLs, this would be
fetched in-process in the live server (management URLs get fetched
with an analogous but non-mod_wsgi request).  Probably there should be
some indication of how often the pinging should happen (i.e., if the
ping is cheap do it often, if it's expensive be more reserved).

CloudKick
~~~~~~~~~

CloudKick has started doing a bunch of monitoring things, and has an
API.  A quick way of doing monitoring might simply be via CloudKick
(or maybe just an option).

Security
--------

We should have a good quality rotating random value.  (Like
``silversupport.secret.get_secret``).  Google has a library for this.

We should have a way to do security logging.  E.g., log attempted
attacks.  There should be a whitelist, so that internal people can do
bad things (e.g., when testing).

Translation
-----------

I'd like to integrate Pontoon into applications, so that Silver Lining
can be a general way to setup applications for localization.  This
might primarily be a second deployed application that modifies files
in the other application (somewhere in ``$CONFIG_FiLES``).

Create Virtual Machine Images
-----------------------------

Local development can for some people be quite hard.  This is
especially true of Windows users (for which silverlining doesn't have
any support, and no support is planned).

It would be nice to be able to run something like:

    silver setup-develop-image . some-image-filename

and have it get a bare Ubuntu image (for VMWare, VirtualBox, or
whatever) and run some adaptation of setup-node, and setup a file
server to make editing files easy, and then upload the application
into the machine (version control files and everything).

To make it more awesome, a built-in web app for managing the image;
checking in files, restarting, tooling, etc.  Maybe the image could be
run headless then?  This is more ambitious, but it could in some way
be an introduction to good open source development practices.

This is an aside, but probably the generalized "DEST" idea of ``silver
backup`` would be useful here and elsewhere: anywhere you write
something (like an image file) allow remote locations.  Of course
silver backup is done on the remote server and uploaded from there,
while this is done locally, so the advantage is smaller.

The core of this is probably two variations:

* ``setup-node``, except setting up a "development" node.  This would
  be a node with git/hg/svn installed, somewhat different mod_wsgi
  configuration, and other such details.

* ``update``, except again a "development" version, one that copies
  over VCS metadata (``.hg/`` etc).  Also it wouldn't create
  versioned/dated directories, but instead support only one version of
  an application (the version you are developing).

Test-Before-Activate
--------------------

There should be a kind of "check functions are go" URL or command,
similar to how ``update_fetch`` works.  This would be fetched on
update, but before the update was really made live (the internal
request mechanism can be run on any instance, even one that is not
live yet).  If this returned a non-2xx result, then the update would
be aborted (or if it's a test script, exit with an error code).

Backup/Restore/Revert on update
-------------------------------

Each update is a point when a persistence checkpoint should happen.
This is most easily done with a local backup.

There should also be a "run all database updates" URL (also similar to
``update_fetch``).  This might fail, in which case the backup should
be restored and the update aborted.

I think this should be run before test-before-activate, but if
test-before-activate fails then the databases should also be reverted.

There are fancy ways of doing really fast checkpoints, like backups
without actually backing things up.  These should be accessible even
in a VPS, but they require some fancy sysadmin knowledge that I don't
have.

Debugging
---------

I'm fairly conflicted about what Silver Lining should do with respect
to debugging.  I am inclined to say that applications should be
instrumented with debugging tools natively, e.g., using Django's
built-in tools or weberror, etc.

On the other hand, without this kind of wrapping you get something
that really sucks -- normal Apache error logs.  Maybe at least
``environ['wsgi.errors']`` should be fixed (along with stderr) to
point to something better/reasonable.  (And maybe warnings
specifically should be handled, so only unique warnings are logged,
and they are reset between updates.)

Setting up the ``logging`` module is somewhat similar, it could be
done manually by applications.  (Sometimes you want to turn up
logging, *in production* temporarily to see what is going on in a live
server: this is something not in the current workflow.)

Also there should be centralized configuration of things like, e.g.,
where error messages are sent.  Then tools could be configured in a
more transportable way (e.g., ``DEBUG_EMAIL =
os.environ['SILVER_DEBUG_EMAIL']``).  This might fit into how
configuration is generally handled.

Error reporting for non-requests (like a cron script) is harder.  Most
of these are done synchronously, so you can just show the user what is
happening, but at least for cron and perhaps tasks this is not the
case.  Unifying environment setup might resolve this particular
issue...

Cron and Tasks
--------------

App Engine style cronjobs and tasks are definitely planned.  (I also
just found some code called PyPeriodic that I think I wrote a long
time ago and forgot.)

Cron jobs are based on requests run periodically.  Though I guess they
could also be commands.  One advantage of keeping to requests is to
have some kind of monitoring for failed or rejected requests (though
the internal request mechanism is not as robust currently as the
external request system, which is managed by mod_wsgi).

Tasks are things to be done in the future, asynchronously with any
request.  These are queued, get retried in cases of failure (non-2xx
response); maybe given multiple servers they could be run on different
servers.

Cron is a higher priority.

For persistence of the jobs, Redis seems quite possible (small enough
that I don't feel bad having it always installed, seems relatively
robust and easy to use).

API Keys
--------

This is the obvious kind of non-portable configuration.  There is some
support for this already, but it is poorly exposed.

This is something that might be good to manage organization-wide.
Which just makes the workflow slightly different.

In some ways this is just global configuration (as opposed to
application-specific configuration).  This same configuration could
potentially be used for things like admin email addresses, logging
information, etc.  Applications would have to pull it in, but it would
be updated on a machine basis, not a per-application basis (though
possibly you could have per-application overrides?)

Inter-application communication
-------------------------------

This will only happen with a strong use case to motivate it; I can
certainly *imagine* such use cases, but I need something more concrete
than my imagination.

In that case, an application could receive configuration information
for other applications.  Communication would have to be through some
service (e.g., a database) or HTTP.  Accessing applications on other
servers would probably not be supported (though potentially it could
be), but given per-path applications it is reasonable to consider
cases where this would be useful.  Auth is an obvious case.

The Silver Lining secret is currently per-server (and will probably be
per-group in the future), so some things like reading cookies could be
done across applications already (given the appropriate code).

Testing and Test Fixture Setup
------------------------------

It would be nice to have a nice setup for getting test data setup.  I
think some degree of testing support would be nice, though simply
installing and using a standard test runner seems mostly fine.  A
recipe for integration testing would be nice.  A recipe for full-stack
testing (e.g., with Windmill or Selenium) would be nice.  These are
probably more recipes than core Silver Lining things.

It's possible that Silver Lining could setup a second set of "testing"
services.  So if you ran development off a database named ``myapp``,
maybe in "testing" mode it would use ``test_myapp`` (and the database
would be cleared on every run).

Full-stack development environment
----------------------------------

I can imagine a through-the-browser development environment, based on
Bespin.  This could be cool.  It could be really VM-friendly as well.
Circumstances may determine if I really try this out.

To do this, Bespin would be installed and running, and configured to
point at the application location.  Version control can be managed
through Bespin.

Additionally Hudson could be installed, enabling a kind of built-in
test suite.  I'm not sure how else Hudson could be enabled (except
perhaps to list a test script in ``app.ini`` and go from there), but
specifically for this case it seems like it would be nice.  By
including a test suite configuration it might generally be possible to
do a very simple and easy Hudson setup.

Another interface would control Silver Lining itself, allowing you to
configure production providers and deploy to them.  It could be very
simple.

Hudson is available as a `third-party Debian package
<http://hudson-ci.org/debian/>`_.  Bespin would probably be deployed
as a Silver Lining application itself.  I imagine you might define a
base domain (e.g., ``mydevel``) and then you'd have:

* ``www.mydevel``: the application itself, running
* ``dev.mydevel``: Bespin
* ``test.mydevel``: Hudson
* ``deploy.mydevel``: Silver Lining interface

One could imagine a load tester somewhere in here too.  And maybe
a rig for Selenium or other through-the-web tester?

With all these, heck, maybe I'd develop through a virtual machine even
though I'm on Linux already.

Bespin would not preclude file sharing so that you could do editing
(even version control) as though it was local.  It would simply be
another alternative.

Application Packs
-----------------

Right now this system emphasizes development.  It would be nice to
also support ready-to-go applications.  This might be simply a zip
file created from an application, that can be easily uploaded.  It
might not be something at all fancy.  But thinking it out would be
nice.

Trac would be an ideal candidate for sometihng like this.  It also has
enough customization that I can imagine some interesting use cases;
how do you select the plugins you want and the templates you want to
override?  If you aren't "developing" the application then this isn't
as clear.

Maybe on application upload you could have two directories; one the
"code" and another the "customizations".  The code would have a script
to check and merge in the customizations before upload.  One can
imagine other useful things the code could do with the customizations
(for instance, support plugin installation through knowledge of the
app's plugin index and techniques).

Maybe it would look like::

    silver update someapp.zip --customize=mycustomizations/

That's the easy way.  Plugin installation?

::

    silver manage-app someapp.zip --customize=mycustomizations/ \
           --list-commands
    silver manage-app someapp.zip --customize=mycustomizations/ \
           install-plugin Akismet

It feels a bit crude.  Maybe another command besides ``silver`` for
pre-packaged apps?  Or another set of subcommands.

Middleware Packs
----------------

Sometimes you want to apply middleware in a deployment-specific
fashion (not application-specific).  Some examples:

* Site disabling
* Error catching
* Password protecting a site before it is public
* Ad hoc authorization

I'd like the ability to apply a piece of middleware to an
application.  This wouldn't *just* be WSGI middleware, it would
probably include some extra information (description, etc).  Also a
PHP equivalent version ("fat" middleware) would be nice to include.
Using PHP's output buffer operations you can simulate middleware.

I'm not sure what the command would look like.  Maybe just::

  silver apply-middleware path/to/middleware LOCATION

There's also be ``show-middleware`` and ``remove-middleware``
operations, I suppose.  Like applications, there's a missing notion of
versions here.  Also middleware would have to be compatible with the
libraries of the hosted application, as they would run in the same
process.  Probably middleware libraries would be added after the path,
and the middleware should be written to be as library-version-agnostic
as possible.  There should be a fairly finite number of middleware
packs.

Configuration should apply to middleware, though maybe a second set of
configuration to avoid overlap.

Configuration Management
------------------------

Now that there's a ``--config`` option you can have
deployment-specific configuration of your application, but it's only
exposed through ``silver update``.  It should be exposed as a separate
operation, to view, edit, backup, etc. the configuration, you
shouldn't have to deploy just to change the configuration.  A complete
set of commands might be:

Show the configuration (all past revisions)::

  silver config-query LOCATION
  # To show info about files:
  silver config-query LOCATION --files
  # To download config:
  silver config-query LOCATION --dump=path/

Then operations to actually modify the configuration::

  # Upload new configuration:
  silver config LOCATION path/to/config
  # Revert configuration to some previous version ("PREV" literal, or
  # some revision number as shown by config-query):
  silver config LOCATION --revert VERSION
  # Remove configuration:
  silver config LOCATION --delete
  # Copy configuration from another site:
  silver config LOCATION --copy=SOURCE_LOCATION

Doing version control on the configuration would be nice.  Also
supporting an app that did generic through-the-web application
configuration (needs a DevAuth-style thing again).  Such configuration
would just do through-the-web-editing of the source files, and
probably call the validation function if available.  It might also
allow for operations like reverting, seeing logs, etc.

Application Versions
--------------------

It's hard to figure out exactly what "version" of an application is
installed somewhere.  There's no particular line, and no one thing is
the only important version number.

It'd be nice to look around the files for VCS data and get a version
snapshot for all pieces.

Another option is to have a deploy-application-registry, which would
hold all the files that were deployed.  This would be a parallel
version control system unrelated to any developer version control, and
would be used only for auditing.

Local/CDN Javascript
--------------------

I've done some applications that are mostly static pages on the
frontend with Javascript.  I like to use Google's hosted versions of
these libraries.  But then offline I lose access to the app :(

It would be nice to have a local cache of these files in Silver
Lining.  Except I can't figure out how you'd write a static HTML file
that could select the local or remote file.  Maybe one option is to
use Google's loader, but kind of mock it out for local use.  But even
that is tricky.  It would be possible to do a small amount of
rewriting of HTML pages, replacing those links (maybe literally) with
local versions.  During development static files are served fairly
naively, so it wouldn't be hard to do this substitution.  Also
minimized files could be replaced with unminimized files.  Because the
actual HTML would be production-ready there's no compromise, only in
development are they reverted.

Silver Lining could ship these libraries, or maybe there could be an
``app.ini`` setting like::

    [development]
    local_html_replacements =
        http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js /_devel/jquery.js

Then you'd put that file in ``static/_devel/jquery.js``.  I can't even
get that on a single line...  maybe these replacements should be put
in a separate file, and maybe that should be a set of regular
expressions.  On the other hand, if this is really restricted to URLs
and local files, you could "sync" these files automatically.  But in
this case, as an example, you actually want a different file during
development (the non-minimized ``jquery.js``).

Also while this is otherwise kind of unresolvable for static files, it
would be nice if this also worked for dynamic files.  There would then
have to be some API.  Maybe each of these resources would be "named",
in a file like::

    [jquery]
    production = http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js
    devel = /_devel/jquery.js

And then an API like::

    <script src="${silversupport.href['jquery']}"></script>

Using ``__getitem__`` would make this more Django-template friendly I
believe (though a more traditional ``silversupport.href('jquery')`` could
also be supported).

This could also be the basis for the CDN setup, and it's possible that
minimization could happen using this.  Maybe like::

    [js]
    jquery.json file = static/js/jquery.json.js
    app.js file = static/js/app.js
    all_js combine = jquery.json app.js

Then in production ``silversupport.href('all_js')`` would return a URL
pointing to the minimized and combined version of all those files, and
``silversupport.href('jquery.json')`` and ``silversupport.href('app.js')``
would both return None.  In development the inverse would be true.

Using ``silver serve`` there should be an option to do
minimization, so the minimized versions could be tested.  The same
ideas apply to CSS.  Something like this might make sense for images,
but no minimization would occur.  You might not want to enumerate
images, so you might do:

    [images]
    images directory = static/images/

And then use ``${silversupport.href('images')}/folder.png``

Start Up Local Service
----------------------

There should be a way (probably via ``~/.silverlining.conf``) to
indicate how to start local services.  Then, for example, you would
not need to run PostgreSQL or Couch all the time, but could make it
available as needed.  Maybe it would look like::

    [service.couchdb]
    start = sudo /etc/init.d/couchdb start
    stop = sudo /etc/init.d/couchdb stop

Of course starting and stopping all the time is annoying, but it
wouldn't have to happen if the reloader did the restart.  Also perhaps
Silver Lining could lazily stop the service by daemonizing a
stop-script on exit.  (Maybe only if there's an additional
``lazy_stop`` setting.)

Keep setup-node Version
-----------------------

It would be good to auto-detect when setup-node has to be rerun.  I
imagine either simply using a hash of all files that are part of
setup-node, or using the latest timestamp.  The timestamp would change
from computer to computer though, giving false positives.

I imagine if you run ``silver update`` that it would do something
like::

    $ silver update --node=foo
    Warning: the node foo is not up to date; setup-node should be run
    Continue anyway (y)es/(n)o/(u)pdate?

Yes (which would work with ``--yes``) would just keep going, No
aborts, Update would run setup-node immediately and then continue.

Serve general files
-------------------

You can use `mod_negotiation
<http://httpd.apache.org/docs/2.2/mod/mod_negotiation.html>`_ to serve
static files without extensions.  These are files that include headers
(that indicate things like Content-Type) as well as the body.
Probably they'd have a different extension.

Security Headers
----------------

`Content Security Policy
<https://wiki.mozilla.org/Security/CSP/Specification>`_ seems like you
*might* want to enable it globally (not as part of the application).
Specifically for static file headers.

Maybe a middleware pack would handle this case.

Short-term list
---------------

Here's what I want to do right away:

* Write a VirtualBox libcloud driver (for testing)
  - Will use VBoxManage
* Backup/restore (backup done, restore mostly done)
  - Consider how this interacts with testing
  - Specifically the Django ``test_*`` databases
* Setup up deployment for Weave Sync 2.0 API implementation
  - Set up multi-server deployments
* Set up DevAuth for admin access
* Get https working in some fashion.  (Ad hoc https seems to only get
  harder over time though)
* Look into the Varnish logs (Apache logs aren't that complete,
  really)
* Make the instantiated app available in the interactive shell
* Move towards a general schema for commands (mostly these are
  arguments with known names):
  * destination location
  * app dir
  * provider
  * node
  Then some general conventions could be done for default_app, maybe
  default_provider and some other stuff, as well as info in
  ``~/.silverlining.conf``
* There's some nice features in the `Mozilla AMO Hudson instace
  <https://hudson.mozilla.org/job/addons.mozilla.org/>`_ that I would
  like here (checking coding conventions and other details).