2. You mission, should you choose to accept it:
Make your application run with 1 click,
everywhere it counts, every time.
Make your application run exactly the same way,
everywhere it counts, every time.
Prove that the above are true.
Reproducibility
3. Reproducible Infrastructure
Reproducible Systems
Reproducible [Django] Applications
Dependencies
Configuration
Data
Deployment
Steps to Reproducibility
5. A Stable Foundation
Stable Operating System
Reproducible Installation
Kickstart Install
Base Image
Configuration Management
Puppet, Chef
Packaging
Systems
6. What Python?
How will you install packages?
How will you make it reproducible?
Database?
Backup / Restore
Failover
Performance
Caching?
HTTP
Objects
Queuing?
SSL?
Application Environment
7. It’s just code, right?
Probably Not
Application
8. Just use pip! lib/pypi-cache:
Django-1.4.3.tar.gz
Not so fast.
Lots of external requirements.txt:
dependencies Django==1.4.3
Eliminate them
with a local Type this:
pip install --no-index --find-links
cache
file://$(PWD)/lib/pypi-cache -r
Don’t’ forget requirements.txt
virtualenv!
Dependencies
9. settings.py settings.py:
No logic allowed! from urlparse import urljoin
‚unknown‛ from os import environ
import times import dj_database_url #courtesy of Heroku
Critical
Local_settings.py DATABASES =
More of the same dj_database.config(default=‚xxx‛)
BASE_URL = environ*‘DJANGO_BASE_URL’+
Consider pushing STATIC_URL = urljoin(BASE_URL, ‘static’)
configuration in MEDIA_URL = urljoin(BASE_URL, ‘media’)
externally via
environ, Run this:
configparser, etc DJANGO_BASE_URL=http://cdn.com/base/
django-admin.py runserver
Configuration
10. Fixtures. Consider fixtures/polls.py:
writing them in from ..models import Poll, Choice
def apply():
Python! p = Poll.objects.get_or_create(q=‘test q’,
Testable defaults=dict(pub_date=‘1980-01-01))
c1 = Choices.objects.get_or_create(poll=p,
More resilient to
choice_text=‘option 1’)
change
Less pk pain fixtures/tests/test_poll.py:
Class PollFixtureTestCase(TestCase):
def test_fixture_applied():
Migrations! self.assertEquals(Poll.objects.get(q=‘test q’)
Test them
Application: Database
11. management/__init__.py:
from django.db.models.signals import post_syncdb
from south.signals import post_migrate
from .. import models, fixtures
def update_poll_fixtures(verbose=True):
fixtures.poll.apply()
if verbose:
print "Updating dynamic fixtures for profile”
def update_fixtures_post_syncdb(sender, **kwargs):
update_poll_fixtures()
def update_fixtures_post_migrate(app, **kwargs):
if app == ’polls':
update_poll_fixtures()
post_syncdb.connect(fixtures_post_syncdb, sender=models)
post_migrate.connect(fixtures_post_migrate)
12. Interwebs
Back Up Everything!
Move files to Green
Fabric?
RPM?
Tar?
Git?
Rsync?
App App Deploy / Test
Update Stuff
syncdb
apply fixtures
Test Green!
Flip/Flop Blue/Green Data
(Roll back to Blue)
Deployment: Blue/Green
13. Erik LaBianca, WiserTogether, Inc.
erik.labianca@gmail.com
@easel
https://linkedin.com/in/eriklabianca/
https://slideshare.net/easel1/
https://github.com/easel/
https://github.com/WiserTogether/
Questions?
Editor's Notes
----- Meeting Notes (2/12/13 12:10) -----json fixtures: primary key problems, skips model.save, fixtures get of date when model changes