SlideShare a Scribd company logo
Buildout How to maintain big app stacks without losing your mind Dylan Jay Sypy.org
History Made by Jim Fulton. 2006
“It should be possible to check-in a buildout specification and reproduce the same software”
What problem does it solve?
Isolating Python Libraries Like virtualenv
Managing depencies/versions Bit like pip requires.txt
Compiling/Building stuff Bit like Make or Ant
Installing/Configuring/Deploying Bit like Chef or Puppet
Checkout Development Code Bit like svn externals
Simplifying Config Templates  Bit like Paster Script
But wait there's more! We'll do all that in one .cfg file
So what is buildout? Gaffer tape is like the force. It has a light side, a dark  side, and it holds the universe together.
App Stacks Nginix, Varinish, HAProxy, Zope, Plone, MySQL
Perl, Munin
Pyramid, Gevent, pyramid_socketio, Redis
Django, customapp1, customapp2, customapp3
Etc etc
Anatomy of a Buildout buildout.cfg: [buildout] parts = MyPart [MyPart] recipe = recipepackage arg1 = value1
Initialising $ easy_install zc.buildout … Finished processing dependencies for zc.buildout $ buildout init Creating directory '/Users/dylanjay/Projects/sandpit/buildout/bin'. Creating directory '/Users/dylanjay/Projects/sandpit/buildout/parts'. Creating directory '/Users/dylanjay/Projects/sandpit/buildout/develop-eggs'. Generated script '/Users/dylanjay/Projects/sandpit/buildout/bin/buildout'. $ bin/buildout
“What goes on in buildout, stays in buildout”
Hello World [buildout] parts = helloworld chmod [helloworld] recipe = collective.recipe.template output = ${buildout:bin-directory}/hello input = inline: echo 'hello world' [chmod] recipe = plone.recipe.command command = chmod +x ${helloworld:output}
Dependencies and Substitutions [ buildout] parts = chmod [ helloworld] recipe = collective.recipe.template output = ${buildout:bin-directory}/hello input = inline: echo 'hello world' [ chmod] recipe = plone.recipe.command command = chmod +x ${helloworld:output}
Installing Packages (easy_install) [buildout] parts = helloworld [helloworld] recipe = zc.recipe.egg eggs = Fabulous Pillow Interpreter = python $ bin/python -m fabulous.text hello world
Installing Scripts [ buildout] parts = helloworld [ helloworld] recipe = zc.recipe.egg eggs = fabulous Pillow #  if package has its own entry-point, you don't need the stuff below initialization = from fabulous import text; print text.Text("Hello World", shadow=True) go = lambda: True scripts = hello entry-points = hello=__main__:go
Inside bin/script (not rocket science) #!/Users/dylanjay/Projects/virtual/buildout/bin/python import sys sys.path[0:0] = [ '/../download-cache/eggs/elementtree-1.2.7_20070827_preview-py2.4.egg', '/../download-cache/eggs/archetypes.kss-1.4.3-py2.4.egg', … ] import plone.recipe.zope2instance.ctl if __name__ == '__main__': plone.recipe.zope2instance.ctl.main( ["-C", '/Users/dylanjay/Projects/gcio/parts/instance/etc/zope.conf'] + sys.argv[1:])
Inside Recipes class HelloRecipe(object): def __init__(self, buildout, name, options): self.input = options.get('input','world') self.output = options['output'] = 'hello %s' % self.input self.location = options['location'] = self.buildout['buildout']['bin-directory']+'hello' def install(self): # Return files that were created by the recipe. The buildout # will remove all returned files upon reinstall. f = open(self.location).write(self.output) ; f.close() return [self.location] def update(self): pass
mr.developer [buildout] parts = helloworld extensions = mr.developer auto-checkout= helloworld [sources] helloworld = git git://github.com/topher200/genetic-hello-world-python.git [ helloworld] recipe=zc.recipe.egg eggs = genetic-hello-world-python # WARNING: this example doesn't work
zc.recipe.cmmi [buildout] parts = instance varnish [instance] recipe = plone.recipe.zope2instance eggs = Plone HelloWorldPlone Http-address = 127.0.0.1:8080 [varnish-build] recipe = zc.recipe.cmmi url = http://downloads.sourceforge.net/varnish/varnish-2.1.3.tar.gz [varnish] recipe = plone.recipe.varnish daemon = ${varnish-build:location}/sbin/varnishd bind = 127.0.0.1:8080 backends = ${instance:http-address}
Versions [ buildout] parts = instance varnish [ instance] recipe = plone.recipe.zope2instance eggs =  Plone >= 4.1
Versions Pinning [ buildout] parts = instance [ instance] recipe = plone.recipe.zope2instance eggs = Plone [ versions] Plone= 4.1
Versions KGS [ buildout] extends =  http://dist.plone.org/release/4.1/versions.cfg parts = instance varnish [ instance] recipe = plone.recipe.zope2instance eggs = Plone
Version Conflicts Installing. Getting section zeoserver. Initializing part zeoserver. Error: There is a version conflict. We already have: zope.component 3.8.0 but five.localsitemanager 1.1 requires 'zope.component<3.6dev'. Conflicts are caused by buildout having no way to know depenency specs until its too late.
Version Conflict Prevention $  bin/buildout -N (prevent auto upgrading packages) $  bin/buidout -v  (discover where conflict arose) Or Pinning versions
dumppickedversions [buildout] extensions = buildout.dumppickedversions $ bin/buildout Getting distribution for 'buildout.dumppickedversions'. ... *************** PICKED VERSIONS **************** [versions] myegg = 1.1 setuptools = 2.1 zc.buildout = 1.5.3 zc.recipe.egg = 1.5.2 <BLANKLINE> *************** /PICKED VERSIONS ***************
Saving versions [ buildout] extensions = buildout.dumppickedversions dump-picked-versions-file = picked.cfg
Macros [ buildout] parts = instance varnish [ instance] recipe = plone.recipe.zope2instance eggs = Plone HelloWorldPlone http-address =  127.0.0.1:8080 [instance2] <=instance1 http-address = 127.0.0.1:8081 [ instance2] <= instance1 http-address = 127.0.0.1:8081 [ varnish-build] recipe = zc.recipe.cmmi url = http://downloads.sourceforge.net/varnish/varnish-2.1.3.tar.gz [ varnish] recipe = plone.recipe.varnish daemon = ${varnish-build:location}/sbin/varnishd bind = 127.0.0.1:80 backends =  ${ instance:http-address} ${ instance1:http-address} ${ instance2:http-address}
mr.scripty [ ports_base] Instance1 = 80 Instance2 = 81 Instance3 = 83 [ ports] recipe=mr.scripty OFFSET = 1000 init= ...  for key,value in self.buildout['ports_base'].items(): ...  self.options[key] = str(int(value)+int(self.OFFSET))
mr.scripty [ buildout] parts = instance varnish [ instance] recipe = plone.recipe.zope2instance eggs = Plone HelloWorldPlone http-address = ${ports:instance1} [ instance2] <= instance1 http-address = ${ports:instance2} [ instance2] <= instance1 http-address = ${ports:instance3}

More Related Content

KEY
Write php deploy everywhere
KEY
Plack - LPW 2009
PPTX
Take Command of WordPress With WP-CLI at WordCamp Long Beach
PDF
Bfg Ploneconf Oct2008
KEY
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
PDF
Datagrids with Symfony 2, Backbone and Backgrid
PDF
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史
PDF
はじめてのSymfony2
Write php deploy everywhere
Plack - LPW 2009
Take Command of WordPress With WP-CLI at WordCamp Long Beach
Bfg Ploneconf Oct2008
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Datagrids with Symfony 2, Backbone and Backgrid
[PHP 也有 Day] 垃圾留言守城記 - 用 Laravel 阻擋 SPAM 留言的奮鬥史
はじめてのSymfony2

What's hot (20)

PDF
Plone 5 and machine learning
PPTX
2012 coscup - Build your PHP application on Heroku
PPTX
Take Command of WordPress With WP-CLI
PPTX
Bower - A package manager for the web
PDF
Microservice Teststrategie mit Symfony2
PDF
WordPress mit Composer und Git verwalten
PPT
Composer - Package Management for PHP. Silver Bullet?
PDF
PuppetCamp SEA 1 - Version Control with Puppet
PDF
Die .htaccess richtig nutzen
PDF
HTTPS + Let's Encrypt
KEY
PSGI/Plack OSDC.TW
ODP
Vagrant move over, here is Docker
PPT
How to host an app for $20 in 20min using buildout and hostout
PDF
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
PDF
How containers helped a SaaS startup be developed and go live
KEY
Zend Framework Study@Tokyo #2
PDF
Asynchronous PHP and Real-time Messaging
PPTX
Socket programming with php
PDF
Create Development and Production Environments with Vagrant
PDF
Quick and Dirty Python Deployments with Heroku
Plone 5 and machine learning
2012 coscup - Build your PHP application on Heroku
Take Command of WordPress With WP-CLI
Bower - A package manager for the web
Microservice Teststrategie mit Symfony2
WordPress mit Composer und Git verwalten
Composer - Package Management for PHP. Silver Bullet?
PuppetCamp SEA 1 - Version Control with Puppet
Die .htaccess richtig nutzen
HTTPS + Let's Encrypt
PSGI/Plack OSDC.TW
Vagrant move over, here is Docker
How to host an app for $20 in 20min using buildout and hostout
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
How containers helped a SaaS startup be developed and go live
Zend Framework Study@Tokyo #2
Asynchronous PHP and Real-time Messaging
Socket programming with php
Create Development and Production Environments with Vagrant
Quick and Dirty Python Deployments with Heroku
Ad

Similar to Buildout: How to maintain big app stacks without losing your mind (20)

ODP
Buildout: creating and deploying repeatable applications in python
ODP
ZopeSkel & Buildout packages
PDF
Using Buildout to Develop and Deploy Python Projects
PDF
Introduction to zc.buildout
ZIP
Zenoss: Buildout
PDF
Buildout: Fostering Repeatability
PDF
Buildout and Plone
ODP
PyGrunn - Buildout presentation
PDF
Plone 3 2: What's New
PDF
Oops, where's my site?
KEY
Practical introduction to dev ops with chef
PDF
Martin Aspeli Extending And Customising Plone 3
ODP
Opps I deployed it again-ploneconf2010
ODP
Managing Plone Projects with Perl and Subversion
PPT
Adventures in infrastructure as code
PDF
Leonid Vasilyev "Building, deploying and running production code at Dropbox"
PDF
Django & Buildout (en)
PDF
Stupid Buildout Tricks
KEY
Linecook - A Chef Alternative
PDF
Buildout future
Buildout: creating and deploying repeatable applications in python
ZopeSkel & Buildout packages
Using Buildout to Develop and Deploy Python Projects
Introduction to zc.buildout
Zenoss: Buildout
Buildout: Fostering Repeatability
Buildout and Plone
PyGrunn - Buildout presentation
Plone 3 2: What's New
Oops, where's my site?
Practical introduction to dev ops with chef
Martin Aspeli Extending And Customising Plone 3
Opps I deployed it again-ploneconf2010
Managing Plone Projects with Perl and Subversion
Adventures in infrastructure as code
Leonid Vasilyev "Building, deploying and running production code at Dropbox"
Django & Buildout (en)
Stupid Buildout Tricks
Linecook - A Chef Alternative
Buildout future
Ad

More from Dylan Jay (12)

PPTX
5 things STILL! TOO! HARD! in Plone 5
PDF
The eggless Plone manifesto (or Plone the open source cms-as-a-service platf...
PDF
The goodies of zope, pyramid, and plone (2)
ODP
Surviving an earthquake's worth of traffic
ODP
TTW FTW: Plone as the new wordpress
ODP
Plone pwns
ODP
Pyramid Lighter/Faster/Better web apps
PPTX
Plone: The CMS that hits above it's weight
PPT
Funnelweb ploneconf2010
ODP
Opps i deployed it again
ODP
Plone for python programmers
ODP
TestBrowser Driven Development: How to get bulletproof code from lazy developers
5 things STILL! TOO! HARD! in Plone 5
The eggless Plone manifesto (or Plone the open source cms-as-a-service platf...
The goodies of zope, pyramid, and plone (2)
Surviving an earthquake's worth of traffic
TTW FTW: Plone as the new wordpress
Plone pwns
Pyramid Lighter/Faster/Better web apps
Plone: The CMS that hits above it's weight
Funnelweb ploneconf2010
Opps i deployed it again
Plone for python programmers
TestBrowser Driven Development: How to get bulletproof code from lazy developers

Recently uploaded (20)

PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PPTX
SOPHOS-XG Firewall Administrator PPT.pptx
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
Getting Started with Data Integration: FME Form 101
PPTX
Tartificialntelligence_presentation.pptx
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Heart disease approach using modified random forest and particle swarm optimi...
PPTX
Machine Learning_overview_presentation.pptx
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
Group 1 Presentation -Planning and Decision Making .pptx
PDF
A comparative study of natural language inference in Swahili using monolingua...
PPTX
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
A comparative analysis of optical character recognition models for extracting...
Advanced methodologies resolving dimensionality complications for autism neur...
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Mobile App Security Testing_ A Comprehensive Guide.pdf
Building Integrated photovoltaic BIPV_UPV.pdf
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
SOPHOS-XG Firewall Administrator PPT.pptx
NewMind AI Weekly Chronicles - August'25-Week II
Getting Started with Data Integration: FME Form 101
Tartificialntelligence_presentation.pptx
Spectral efficient network and resource selection model in 5G networks
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Heart disease approach using modified random forest and particle swarm optimi...
Machine Learning_overview_presentation.pptx
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Group 1 Presentation -Planning and Decision Making .pptx
A comparative study of natural language inference in Swahili using monolingua...
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
Accuracy of neural networks in brain wave diagnosis of schizophrenia
Network Security Unit 5.pdf for BCA BBA.
A comparative analysis of optical character recognition models for extracting...

Buildout: How to maintain big app stacks without losing your mind

  • 1. Buildout How to maintain big app stacks without losing your mind Dylan Jay Sypy.org
  • 2. History Made by Jim Fulton. 2006
  • 3. “It should be possible to check-in a buildout specification and reproduce the same software”
  • 4. What problem does it solve?
  • 5. Isolating Python Libraries Like virtualenv
  • 6. Managing depencies/versions Bit like pip requires.txt
  • 7. Compiling/Building stuff Bit like Make or Ant
  • 9. Checkout Development Code Bit like svn externals
  • 10. Simplifying Config Templates Bit like Paster Script
  • 11. But wait there's more! We'll do all that in one .cfg file
  • 12. So what is buildout? Gaffer tape is like the force. It has a light side, a dark side, and it holds the universe together.
  • 13. App Stacks Nginix, Varinish, HAProxy, Zope, Plone, MySQL
  • 18. Anatomy of a Buildout buildout.cfg: [buildout] parts = MyPart [MyPart] recipe = recipepackage arg1 = value1
  • 19. Initialising $ easy_install zc.buildout … Finished processing dependencies for zc.buildout $ buildout init Creating directory '/Users/dylanjay/Projects/sandpit/buildout/bin'. Creating directory '/Users/dylanjay/Projects/sandpit/buildout/parts'. Creating directory '/Users/dylanjay/Projects/sandpit/buildout/develop-eggs'. Generated script '/Users/dylanjay/Projects/sandpit/buildout/bin/buildout'. $ bin/buildout
  • 20. “What goes on in buildout, stays in buildout”
  • 21. Hello World [buildout] parts = helloworld chmod [helloworld] recipe = collective.recipe.template output = ${buildout:bin-directory}/hello input = inline: echo 'hello world' [chmod] recipe = plone.recipe.command command = chmod +x ${helloworld:output}
  • 22. Dependencies and Substitutions [ buildout] parts = chmod [ helloworld] recipe = collective.recipe.template output = ${buildout:bin-directory}/hello input = inline: echo 'hello world' [ chmod] recipe = plone.recipe.command command = chmod +x ${helloworld:output}
  • 23. Installing Packages (easy_install) [buildout] parts = helloworld [helloworld] recipe = zc.recipe.egg eggs = Fabulous Pillow Interpreter = python $ bin/python -m fabulous.text hello world
  • 24. Installing Scripts [ buildout] parts = helloworld [ helloworld] recipe = zc.recipe.egg eggs = fabulous Pillow # if package has its own entry-point, you don't need the stuff below initialization = from fabulous import text; print text.Text(&quot;Hello World&quot;, shadow=True) go = lambda: True scripts = hello entry-points = hello=__main__:go
  • 25. Inside bin/script (not rocket science) #!/Users/dylanjay/Projects/virtual/buildout/bin/python import sys sys.path[0:0] = [ '/../download-cache/eggs/elementtree-1.2.7_20070827_preview-py2.4.egg', '/../download-cache/eggs/archetypes.kss-1.4.3-py2.4.egg', … ] import plone.recipe.zope2instance.ctl if __name__ == '__main__': plone.recipe.zope2instance.ctl.main( [&quot;-C&quot;, '/Users/dylanjay/Projects/gcio/parts/instance/etc/zope.conf'] + sys.argv[1:])
  • 26. Inside Recipes class HelloRecipe(object): def __init__(self, buildout, name, options): self.input = options.get('input','world') self.output = options['output'] = 'hello %s' % self.input self.location = options['location'] = self.buildout['buildout']['bin-directory']+'hello' def install(self): # Return files that were created by the recipe. The buildout # will remove all returned files upon reinstall. f = open(self.location).write(self.output) ; f.close() return [self.location] def update(self): pass
  • 27. mr.developer [buildout] parts = helloworld extensions = mr.developer auto-checkout= helloworld [sources] helloworld = git git://github.com/topher200/genetic-hello-world-python.git [ helloworld] recipe=zc.recipe.egg eggs = genetic-hello-world-python # WARNING: this example doesn't work
  • 28. zc.recipe.cmmi [buildout] parts = instance varnish [instance] recipe = plone.recipe.zope2instance eggs = Plone HelloWorldPlone Http-address = 127.0.0.1:8080 [varnish-build] recipe = zc.recipe.cmmi url = http://downloads.sourceforge.net/varnish/varnish-2.1.3.tar.gz [varnish] recipe = plone.recipe.varnish daemon = ${varnish-build:location}/sbin/varnishd bind = 127.0.0.1:8080 backends = ${instance:http-address}
  • 29. Versions [ buildout] parts = instance varnish [ instance] recipe = plone.recipe.zope2instance eggs = Plone >= 4.1
  • 30. Versions Pinning [ buildout] parts = instance [ instance] recipe = plone.recipe.zope2instance eggs = Plone [ versions] Plone= 4.1
  • 31. Versions KGS [ buildout] extends = http://dist.plone.org/release/4.1/versions.cfg parts = instance varnish [ instance] recipe = plone.recipe.zope2instance eggs = Plone
  • 32. Version Conflicts Installing. Getting section zeoserver. Initializing part zeoserver. Error: There is a version conflict. We already have: zope.component 3.8.0 but five.localsitemanager 1.1 requires 'zope.component<3.6dev'. Conflicts are caused by buildout having no way to know depenency specs until its too late.
  • 33. Version Conflict Prevention $ bin/buildout -N (prevent auto upgrading packages) $ bin/buidout -v (discover where conflict arose) Or Pinning versions
  • 34. dumppickedversions [buildout] extensions = buildout.dumppickedversions $ bin/buildout Getting distribution for 'buildout.dumppickedversions'. ... *************** PICKED VERSIONS **************** [versions] myegg = 1.1 setuptools = 2.1 zc.buildout = 1.5.3 zc.recipe.egg = 1.5.2 <BLANKLINE> *************** /PICKED VERSIONS ***************
  • 35. Saving versions [ buildout] extensions = buildout.dumppickedversions dump-picked-versions-file = picked.cfg
  • 36. Macros [ buildout] parts = instance varnish [ instance] recipe = plone.recipe.zope2instance eggs = Plone HelloWorldPlone http-address = 127.0.0.1:8080 [instance2] <=instance1 http-address = 127.0.0.1:8081 [ instance2] <= instance1 http-address = 127.0.0.1:8081 [ varnish-build] recipe = zc.recipe.cmmi url = http://downloads.sourceforge.net/varnish/varnish-2.1.3.tar.gz [ varnish] recipe = plone.recipe.varnish daemon = ${varnish-build:location}/sbin/varnishd bind = 127.0.0.1:80 backends = ${ instance:http-address} ${ instance1:http-address} ${ instance2:http-address}
  • 37. mr.scripty [ ports_base] Instance1 = 80 Instance2 = 81 Instance3 = 83 [ ports] recipe=mr.scripty OFFSET = 1000 init= ... for key,value in self.buildout['ports_base'].items(): ... self.options[key] = str(int(value)+int(self.OFFSET))
  • 38. mr.scripty [ buildout] parts = instance varnish [ instance] recipe = plone.recipe.zope2instance eggs = Plone HelloWorldPlone http-address = ${ports:instance1} [ instance2] <= instance1 http-address = ${ports:instance2} [ instance2] <= instance1 http-address = ${ports:instance3}
  • 39. Extending #staging.cfg [buildout] extends = buildout.cfg [ports] OFFSET=8000
  • 40. Annotation mode $ bin/buildout annotate Annotated sections ================== [bfg] dependent-scripts= true /Users/dylanjay/Projects/sandpit/mobme/buildout.cfg eggs= repoze.bfg mobme /Users/dylanjay/Projects/sandpit/mobme/buildout.cfg index= http://dist.repoze.org/bfg/current/simple /Users/dylanjay/Projects/sandpit/mobme/buildout.cfg recipe= zc.recipe.egg /Users/dylanjay/Projects/sandpit/mobme/buildout.cfg [buildout] accept-buildout-test-releases= false DEFAULT_VALUE
  • 42. collective.hostout Deploys a buildout to a new location (host)
  • 43. Uses Fabric under the hood