SlideShare a Scribd company logo
1 of 21
Download to read offline
Stupid Buildout Tricks
                              Ricardo Newbery




Wednesday, November 9, 2011
First, a basic buildout
                      [buildout]
                      parts =
                          pyramid
                          myapp

                      [pyramid]
                      recipe = zc.recipe.egg
                      dependent-scripts = true
                      eggs = pyramid
                      interpreter = py

                      [myapp]
                      recipe = collective.recipe.template
                      input = templates/myapp.ini.in
                      output = ${buildout:directory}/etc/myapp.ini
                      key_a = value_a
                      key_b = value_b




Wednesday, November 9, 2011
The problem
                      Multiple environments (dev, qa, staging, production) requiring
                      different buildout configurations.
                      $ bin/buildout -c dev.cfg

                      $ bin/buildout -c qa1.cfg

                      $ bin/buildout -c qa2.cfg


                      ad nauseum ...


                      The non-dev builds are performed by release engineers who
                      have better things to do than to read complicated release
                      notes to figure out the right buildout incantation for the
                      current environment.


Wednesday, November 9, 2011
The solution


                      Add environment variables into each non-dev environment
                      and have buildout figure out which config is the right one.




Wednesday, November 9, 2011
First try...
                      Used a buildout extension to munge the buildout config
                      dynamically. Similar to the way collective.recipe.python works.
                      Two issues:
                      1) The variant configs are hard to read.

                      2) Doesn't play well with mr.developer since "bin/develop"
                      turns off extensions when reading the config.


                      This was painful so I redid this w/o the buildout extensions...




Wednesday, November 9, 2011
Nothing fancy...
                      $       bin/buildout 
                                   -c config/variant-staging.cfg 
                                   buildout:directory=<<PATH TO BUILDOUT ROOT>>


                      The "buildout:directory" value fixes the problem where
                      buildout assumes the build context is the directory where the
                      main config resides.
                      Now, I just need a script to generate this call to buildout...

                      $       bin/environ


                      Let's make this script...




Wednesday, November 9, 2011
import   os
                      import   sys
                      import   logging
                      import   subprocess


                      logger = logging.getLogger('buildout.variants')
                      logger.setLevel(logging.INFO)
                      handler = logging.StreamHandler()
                      handler.setFormatter(logging.Formatter('%(message)s'))
                      logger.propagate = False
                      logger.addHandler(handler)
                      log = logger.info


                      # Is config file specified on command line?
                      config_file = False
                      args_in = sys.argv[1:]
                      while args_in:
                          op = args_in.pop(0)
                          if op[:2] == '-c':
                              config_file = True
                              log("buildout.variants: Disabled.")


                      # If config file not specified, check for one matching the environment
                      args = ['bin/buildout']
                      if not config_file:
                          environ = os.environ.get('BUILDOUT_ENVIRON')
                          if environ:
                              log("buildout.variants: Detected environment '%s'" %environ)
                              config_file = 'config/variant-%s.cfg' %environ
                              if not os.path.exists(config_file):
                                  log("buildout.variants: Not found '%s'" %config_file)
                                  config_file = False
                          if config_file:
                              args.append('-c%s' %config_file)
                              args.append('buildout:directory=%s' %os.getcwd())
                              log("buildout.variants: Applying variant '%s'" %config_file)
                          else:
                              log("buildout.variants: No variants found.")


                      # Run buildout
                      args = args + sys.argv[1:]
                      subprocess.call(args)



Wednesday, November 9, 2011
# Is config file specified on command line?



                      config_file = False
                      args_in = sys.argv[1:]
                      while args_in:
                          op = args_in.pop(0)
                          if op[:2] == '-c':
                              config_file = True
                              log("buildout.variants: Disabled.")




Wednesday, November 9, 2011
# Check the environment

                      args = ['bin/buildout']

                      if not config_file:
                          environ = os.environ.get('BUILDOUT_ENVIRON')
                          if environ:
                              log("buildout.variants: Detected '%s'" %environ)
                              config_file = 'config/variant-%s.cfg' %environ
                              if not os.path.exists(config_file):
                                  log("buildout.variants: Not found '%s'" %config_file)
                                  config_file = False
                          if config_file:
                              args.append('-c%s' %config_file)
                              args.append('buildout:directory=%s' %os.getcwd())
                              log("buildout.variants: Applying variant '%s'" %config_file)
                          else:
                              log("buildout.variants: No variants found.")




Wednesday, November 9, 2011
# Run buildout script

                      args = args + sys.argv[1:]
                      subprocess.call(args)




Wednesday, November 9, 2011
release engineers = :-)
                      Only need to know one command to update a buildout
                      $       bin/environ




                      Environment buildouts can always be overridden.
                      $       bin/environ -c local.cfg


                      or
                      $ BUILDOUT_ENVIRON=staging         bin/environ




Wednesday, November 9, 2011
Extra credit
                      All the documentation says to run buildout with...
                      $       bin/buildout


                      Let's not confuse the release engineers with yet another way
                      to run a buildout so I just created a custom buildout script
                      (generated by the bootstrap.py) that folds this environment
                      hook into bin/buildout itself.
                      [customizing buildout script left as an exercise for the reader]
                      So no more 'bin/environ'. Just 'bin/buildout' again.
                      Release engineers even happier :-)




Wednesday, November 9, 2011
An alternative
                      Another way to get environment-aware buildout configurations
                      is with mr.scripty,

                      http://pypi.python.org/pypi/mr.scripty

                      Allows defining values in a buildout part with regular python
                      expressions. This is possibly a more general solution although
                      the configs may be a little harder to read. You also can't adjust
                      a buildout config "extends" value with this method.




Wednesday, November 9, 2011
Another problem
                      Staging environment sucks.
                      Occasionally, stuff in python site packages in staging borks the
                      buildout. I could work on fixing the staging environment but
                      I've got better things to do.
                      So let's isolate the buildout from site packages.
                      Some possible solutions...

                      1) virtualenv

                      2) zc.buildout, version 1.5.x

                      Let's show the virtualenv method...


Wednesday, November 9, 2011
Release notes 2.0

                      Using virtualenv...


                      $       hg clone <path-to-repo>   MyBuildout

                      $       virtualenv --no-site-packages   MyBuildout

                      $       cd MyBuildout

                      $       bin/python bootstrap.py

                      $       bin/buildout




Wednesday, November 9, 2011
A virtualenv bootstrap
                      Virtualenv must be installed, or we need to create a bootstrap.

                      $       virtualenv.create_bootstrap_script(extra_text)


                      The extra_text is just some python script to hook in extra
                      behavior during a bootstrap.
                                extend_parser(optparse_parser):
                                    Add or remove options from the parser here.

                                adjust_options(options, args):
                                    Change options or args here.

                                after_install(options, home_dir):
                                    After everything is installed, this function is called.


                      See the virtualenv docs for details.



Wednesday, November 9, 2011
(cont.)
                      >>>     extra_text = """
                      >>>     def adjust_options(options, args):
                      >>>
                      >>>           # Create virtualenv in current dir
                      >>>           args = ['.']
                      >>>
                      >>>           # Isolate from system python site-packages
                      >>>           options.no_site_packages = True
                      >>>
                      >>>           # Use distribute instead of setuptools
                      >>>           options.use_distribute = True
                      >>>     """
                      >>>
                      >>>     import virtualenv
                      >>>     out = virtualenv.create_bootstrap_script(extra_text)
                      >>>     open('virtualenv.py', 'w').write(out)




Wednesday, November 9, 2011
Release notes 3.0
                      Virtualenv not installed in system python...

                      $       hg clone <path-to-repo>   MyBuildout

                      $       cd MyBuildout

                      $       python2.6 virtualenv.py

                      $       bin/python bootstrap.py

                      $       bin/buildout




Wednesday, November 9, 2011
But wait, there's more

                      Add the following to the virtualenv bootstrap script,

                      def after_install(options, home_dir):
                          if os.path.exists('bootstrap.py'):
                              logger.notify('Running bootstrap.py')
                              subprocess.call([os.path.join(home_dir, 'bin', 'python'),   
                                                     'bootstrap.py'])




                      Now bootstrapping virtualenv also bootstraps buildout.




Wednesday, November 9, 2011
Release notes 4.0

                      $       hg clone <path-to-repo>   MyBuildout

                      $       cd MyBuildout

                      $       python2.6 virtualenv.py

                      $       bin/buildout




Wednesday, November 9, 2011
Conclusion


                       * Much simpler release process... happy release engineers.

                       * Much simpler release notes... happy developers

                       * Joy all around.




Wednesday, November 9, 2011

More Related Content

What's hot

Роман Лютиков "Web Apps Performance & JavaScript Compilers"
Роман Лютиков "Web Apps Performance & JavaScript Compilers"Роман Лютиков "Web Apps Performance & JavaScript Compilers"
Роман Лютиков "Web Apps Performance & JavaScript Compilers"
Fwdays
 
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
Jeongkyu Shin
 

What's hot (20)

Grooscript greach 2015
Grooscript greach 2015Grooscript greach 2015
Grooscript greach 2015
 
Webinar - Setup MySQL with Puppet
Webinar - Setup MySQL with PuppetWebinar - Setup MySQL with Puppet
Webinar - Setup MySQL with Puppet
 
Grooscript gr8conf 2015
Grooscript gr8conf 2015Grooscript gr8conf 2015
Grooscript gr8conf 2015
 
Webinar - PuppetDB
Webinar - PuppetDBWebinar - PuppetDB
Webinar - PuppetDB
 
Docker and plone
Docker and ploneDocker and plone
Docker and plone
 
Get Grulping with JavaScript Task Runners
Get Grulping with JavaScript Task RunnersGet Grulping with JavaScript Task Runners
Get Grulping with JavaScript Task Runners
 
Grooscript greach
Grooscript greachGrooscript greach
Grooscript greach
 
History & Practices for UniRx(EN)
History & Practices for UniRx(EN)History & Practices for UniRx(EN)
History & Practices for UniRx(EN)
 
Using Buildout to Develop and Deploy Python Projects
Using Buildout to Develop and Deploy Python ProjectsUsing Buildout to Develop and Deploy Python Projects
Using Buildout to Develop and Deploy Python Projects
 
Webinar - Windows Application Management with Puppet
Webinar - Windows Application Management with PuppetWebinar - Windows Application Management with Puppet
Webinar - Windows Application Management with Puppet
 
Роман Лютиков "Web Apps Performance & JavaScript Compilers"
Роман Лютиков "Web Apps Performance & JavaScript Compilers"Роман Лютиков "Web Apps Performance & JavaScript Compilers"
Роман Лютиков "Web Apps Performance & JavaScript Compilers"
 
Die .htaccess richtig nutzen
Die .htaccess richtig nutzenDie .htaccess richtig nutzen
Die .htaccess richtig nutzen
 
Grooscript and Grails 3
Grooscript and Grails 3Grooscript and Grails 3
Grooscript and Grails 3
 
HTTPS + Let's Encrypt
HTTPS + Let's EncryptHTTPS + Let's Encrypt
HTTPS + Let's Encrypt
 
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other ToolsCool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
 
Javascript is your (Auto)mate
Javascript is your (Auto)mateJavascript is your (Auto)mate
Javascript is your (Auto)mate
 
HTML5 tutorial: canvas, offfline & sockets
HTML5 tutorial: canvas, offfline & socketsHTML5 tutorial: canvas, offfline & sockets
HTML5 tutorial: canvas, offfline & sockets
 
Devoxx France: Développement JAVA avec un IDE dans le Cloud: Yes we can !
Devoxx France: Développement JAVA avec un IDE dans le Cloud: Yes we can !Devoxx France: Développement JAVA avec un IDE dans le Cloud: Yes we can !
Devoxx France: Développement JAVA avec un IDE dans le Cloud: Yes we can !
 
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
연구자 및 교육자를 위한 계산 및 분석 플랫폼 설계 - PyCon KR 2015
 
はじめてのSymfony2
はじめてのSymfony2はじめてのSymfony2
はじめてのSymfony2
 

Viewers also liked

I pad user group nov
I pad user group novI pad user group nov
I pad user group nov
Josh Allen
 
3.2 My Works About Visual Design
3.2 My Works About Visual Design3.2 My Works About Visual Design
3.2 My Works About Visual Design
Ruby Kuo
 
My works About UT Report 2004 (draft)
My works About UT Report 2004 (draft)My works About UT Report 2004 (draft)
My works About UT Report 2004 (draft)
Ruby Kuo
 

Viewers also liked (20)

State of Plone Caching
State of Plone CachingState of Plone Caching
State of Plone Caching
 
(Broken... use the other upload, same title) State of Plone Caching
(Broken... use the other upload, same title)  State of Plone Caching(Broken... use the other upload, same title)  State of Plone Caching
(Broken... use the other upload, same title) State of Plone Caching
 
Presentation
PresentationPresentation
Presentation
 
FLOW3-Workshop F3X12
FLOW3-Workshop F3X12FLOW3-Workshop F3X12
FLOW3-Workshop F3X12
 
Filosofia da educação uma abordagem sobre fundamentos da educação no brasil
Filosofia da educação   uma abordagem sobre fundamentos da educação no brasilFilosofia da educação   uma abordagem sobre fundamentos da educação no brasil
Filosofia da educação uma abordagem sobre fundamentos da educação no brasil
 
Comic strip i
Comic strip iComic strip i
Comic strip i
 
Kazan 31.10.12
Kazan 31.10.12Kazan 31.10.12
Kazan 31.10.12
 
I pad user group nov
I pad user group novI pad user group nov
I pad user group nov
 
الجلسة التشاركية النهائية للبرنامج السنوي الإستثماري 2017 ‎
الجلسة التشاركية النهائية للبرنامج السنوي الإستثماري 2017 ‎الجلسة التشاركية النهائية للبرنامج السنوي الإستثماري 2017 ‎
الجلسة التشاركية النهائية للبرنامج السنوي الإستثماري 2017 ‎
 
Giftoman - система онлайн мотивации линейного персонала в ритейле
Giftoman -  система онлайн мотивации линейного персонала в ритейлеGiftoman -  система онлайн мотивации линейного персонала в ритейле
Giftoman - система онлайн мотивации линейного персонала в ритейле
 
3.2 My Works About Visual Design
3.2 My Works About Visual Design3.2 My Works About Visual Design
3.2 My Works About Visual Design
 
Relarn 2013
Relarn 2013Relarn 2013
Relarn 2013
 
International Conference on Renewable Energy Development & Applications for a...
International Conference on Renewable Energy Development & Applications for a...International Conference on Renewable Energy Development & Applications for a...
International Conference on Renewable Energy Development & Applications for a...
 
Easter cards
Easter cardsEaster cards
Easter cards
 
Do italia sas samolet
Do italia sas samoletDo italia sas samolet
Do italia sas samolet
 
London
LondonLondon
London
 
Water and blue color
Water and blue colorWater and blue color
Water and blue color
 
Aaa
AaaAaa
Aaa
 
My works About UT Report 2004 (draft)
My works About UT Report 2004 (draft)My works About UT Report 2004 (draft)
My works About UT Report 2004 (draft)
 
Mesi 2012
Mesi 2012Mesi 2012
Mesi 2012
 

Similar to Stupid Buildout Tricks

ZopeSkel & Buildout packages
ZopeSkel & Buildout packagesZopeSkel & Buildout packages
ZopeSkel & Buildout packages
Quintagroup
 
Complet vector.dep.inc# This code depends on make tool being .docx
Complet vector.dep.inc# This code depends on make tool being .docxComplet vector.dep.inc# This code depends on make tool being .docx
Complet vector.dep.inc# This code depends on make tool being .docx
ardhowp
 
WebLogic Administration und Deployment mit WLST
WebLogic Administration und Deployment mit WLSTWebLogic Administration und Deployment mit WLST
WebLogic Administration und Deployment mit WLST
enpit GmbH & Co. KG
 
From Dev to DevOps - Codemotion ES 2012
From Dev to DevOps - Codemotion ES 2012From Dev to DevOps - Codemotion ES 2012
From Dev to DevOps - Codemotion ES 2012
Carlos Sanchez
 
Head First Zend Framework - Part 1 Project & Application
Head First Zend Framework - Part 1 Project & ApplicationHead First Zend Framework - Part 1 Project & Application
Head First Zend Framework - Part 1 Project & Application
Jace Ju
 

Similar to Stupid Buildout Tricks (20)

Bangpypers april-meetup-2012
Bangpypers april-meetup-2012Bangpypers april-meetup-2012
Bangpypers april-meetup-2012
 
Automation with Ansible and Containers
Automation with Ansible and ContainersAutomation with Ansible and Containers
Automation with Ansible and Containers
 
ZopeSkel & Buildout packages
ZopeSkel & Buildout packagesZopeSkel & Buildout packages
ZopeSkel & Buildout packages
 
OpenWRT guide and memo
OpenWRT guide and memoOpenWRT guide and memo
OpenWRT guide and memo
 
Complet vector.dep.inc# This code depends on make tool being .docx
Complet vector.dep.inc# This code depends on make tool being .docxComplet vector.dep.inc# This code depends on make tool being .docx
Complet vector.dep.inc# This code depends on make tool being .docx
 
XPDDS18: A dive into kbuild - Cao jin, Fujitsu
XPDDS18: A dive into kbuild - Cao jin, FujitsuXPDDS18: A dive into kbuild - Cao jin, Fujitsu
XPDDS18: A dive into kbuild - Cao jin, Fujitsu
 
Lean Php Presentation
Lean Php PresentationLean Php Presentation
Lean Php Presentation
 
WebLogic Administration und Deployment mit WLST
WebLogic Administration und Deployment mit WLSTWebLogic Administration und Deployment mit WLST
WebLogic Administration und Deployment mit WLST
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnApp
 
Puppet Deployment at OnApp
Puppet Deployment at OnApp Puppet Deployment at OnApp
Puppet Deployment at OnApp
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnApp
 
Configuration Management with Cfengine
Configuration Management with CfengineConfiguration Management with Cfengine
Configuration Management with Cfengine
 
Lets make better scripts
Lets make better scriptsLets make better scripts
Lets make better scripts
 
From Dev to DevOps - Codemotion ES 2012
From Dev to DevOps - Codemotion ES 2012From Dev to DevOps - Codemotion ES 2012
From Dev to DevOps - Codemotion ES 2012
 
Buildr In Action @devoxx france 2012
Buildr In Action @devoxx france 2012Buildr In Action @devoxx france 2012
Buildr In Action @devoxx france 2012
 
Head First Zend Framework - Part 1 Project & Application
Head First Zend Framework - Part 1 Project & ApplicationHead First Zend Framework - Part 1 Project & Application
Head First Zend Framework - Part 1 Project & Application
 
Crafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in RubyCrafting Beautiful CLI Applications in Ruby
Crafting Beautiful CLI Applications in Ruby
 
Autoconf&Automake
Autoconf&AutomakeAutoconf&Automake
Autoconf&Automake
 
Isolated development in python
Isolated development in pythonIsolated development in python
Isolated development in python
 
DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)
 

Recently uploaded

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Recently uploaded (20)

Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 

Stupid Buildout Tricks

  • 1. Stupid Buildout Tricks Ricardo Newbery Wednesday, November 9, 2011
  • 2. First, a basic buildout [buildout] parts = pyramid myapp [pyramid] recipe = zc.recipe.egg dependent-scripts = true eggs = pyramid interpreter = py [myapp] recipe = collective.recipe.template input = templates/myapp.ini.in output = ${buildout:directory}/etc/myapp.ini key_a = value_a key_b = value_b Wednesday, November 9, 2011
  • 3. The problem Multiple environments (dev, qa, staging, production) requiring different buildout configurations. $ bin/buildout -c dev.cfg $ bin/buildout -c qa1.cfg $ bin/buildout -c qa2.cfg ad nauseum ... The non-dev builds are performed by release engineers who have better things to do than to read complicated release notes to figure out the right buildout incantation for the current environment. Wednesday, November 9, 2011
  • 4. The solution Add environment variables into each non-dev environment and have buildout figure out which config is the right one. Wednesday, November 9, 2011
  • 5. First try... Used a buildout extension to munge the buildout config dynamically. Similar to the way collective.recipe.python works. Two issues: 1) The variant configs are hard to read. 2) Doesn't play well with mr.developer since "bin/develop" turns off extensions when reading the config. This was painful so I redid this w/o the buildout extensions... Wednesday, November 9, 2011
  • 6. Nothing fancy... $ bin/buildout -c config/variant-staging.cfg buildout:directory=<<PATH TO BUILDOUT ROOT>> The "buildout:directory" value fixes the problem where buildout assumes the build context is the directory where the main config resides. Now, I just need a script to generate this call to buildout... $ bin/environ Let's make this script... Wednesday, November 9, 2011
  • 7. import os import sys import logging import subprocess logger = logging.getLogger('buildout.variants') logger.setLevel(logging.INFO) handler = logging.StreamHandler() handler.setFormatter(logging.Formatter('%(message)s')) logger.propagate = False logger.addHandler(handler) log = logger.info # Is config file specified on command line? config_file = False args_in = sys.argv[1:] while args_in: op = args_in.pop(0) if op[:2] == '-c': config_file = True log("buildout.variants: Disabled.") # If config file not specified, check for one matching the environment args = ['bin/buildout'] if not config_file: environ = os.environ.get('BUILDOUT_ENVIRON') if environ: log("buildout.variants: Detected environment '%s'" %environ) config_file = 'config/variant-%s.cfg' %environ if not os.path.exists(config_file): log("buildout.variants: Not found '%s'" %config_file) config_file = False if config_file: args.append('-c%s' %config_file) args.append('buildout:directory=%s' %os.getcwd()) log("buildout.variants: Applying variant '%s'" %config_file) else: log("buildout.variants: No variants found.") # Run buildout args = args + sys.argv[1:] subprocess.call(args) Wednesday, November 9, 2011
  • 8. # Is config file specified on command line? config_file = False args_in = sys.argv[1:] while args_in: op = args_in.pop(0) if op[:2] == '-c': config_file = True log("buildout.variants: Disabled.") Wednesday, November 9, 2011
  • 9. # Check the environment args = ['bin/buildout'] if not config_file: environ = os.environ.get('BUILDOUT_ENVIRON') if environ: log("buildout.variants: Detected '%s'" %environ) config_file = 'config/variant-%s.cfg' %environ if not os.path.exists(config_file): log("buildout.variants: Not found '%s'" %config_file) config_file = False if config_file: args.append('-c%s' %config_file) args.append('buildout:directory=%s' %os.getcwd()) log("buildout.variants: Applying variant '%s'" %config_file) else: log("buildout.variants: No variants found.") Wednesday, November 9, 2011
  • 10. # Run buildout script args = args + sys.argv[1:] subprocess.call(args) Wednesday, November 9, 2011
  • 11. release engineers = :-) Only need to know one command to update a buildout $ bin/environ Environment buildouts can always be overridden. $ bin/environ -c local.cfg or $ BUILDOUT_ENVIRON=staging bin/environ Wednesday, November 9, 2011
  • 12. Extra credit All the documentation says to run buildout with... $ bin/buildout Let's not confuse the release engineers with yet another way to run a buildout so I just created a custom buildout script (generated by the bootstrap.py) that folds this environment hook into bin/buildout itself. [customizing buildout script left as an exercise for the reader] So no more 'bin/environ'. Just 'bin/buildout' again. Release engineers even happier :-) Wednesday, November 9, 2011
  • 13. An alternative Another way to get environment-aware buildout configurations is with mr.scripty, http://pypi.python.org/pypi/mr.scripty Allows defining values in a buildout part with regular python expressions. This is possibly a more general solution although the configs may be a little harder to read. You also can't adjust a buildout config "extends" value with this method. Wednesday, November 9, 2011
  • 14. Another problem Staging environment sucks. Occasionally, stuff in python site packages in staging borks the buildout. I could work on fixing the staging environment but I've got better things to do. So let's isolate the buildout from site packages. Some possible solutions... 1) virtualenv 2) zc.buildout, version 1.5.x Let's show the virtualenv method... Wednesday, November 9, 2011
  • 15. Release notes 2.0 Using virtualenv... $ hg clone <path-to-repo> MyBuildout $ virtualenv --no-site-packages MyBuildout $ cd MyBuildout $ bin/python bootstrap.py $ bin/buildout Wednesday, November 9, 2011
  • 16. A virtualenv bootstrap Virtualenv must be installed, or we need to create a bootstrap. $ virtualenv.create_bootstrap_script(extra_text) The extra_text is just some python script to hook in extra behavior during a bootstrap. extend_parser(optparse_parser): Add or remove options from the parser here. adjust_options(options, args): Change options or args here. after_install(options, home_dir): After everything is installed, this function is called. See the virtualenv docs for details. Wednesday, November 9, 2011
  • 17. (cont.) >>> extra_text = """ >>> def adjust_options(options, args): >>> >>> # Create virtualenv in current dir >>> args = ['.'] >>> >>> # Isolate from system python site-packages >>> options.no_site_packages = True >>> >>> # Use distribute instead of setuptools >>> options.use_distribute = True >>> """ >>> >>> import virtualenv >>> out = virtualenv.create_bootstrap_script(extra_text) >>> open('virtualenv.py', 'w').write(out) Wednesday, November 9, 2011
  • 18. Release notes 3.0 Virtualenv not installed in system python... $ hg clone <path-to-repo> MyBuildout $ cd MyBuildout $ python2.6 virtualenv.py $ bin/python bootstrap.py $ bin/buildout Wednesday, November 9, 2011
  • 19. But wait, there's more Add the following to the virtualenv bootstrap script, def after_install(options, home_dir): if os.path.exists('bootstrap.py'): logger.notify('Running bootstrap.py') subprocess.call([os.path.join(home_dir, 'bin', 'python'), 'bootstrap.py']) Now bootstrapping virtualenv also bootstraps buildout. Wednesday, November 9, 2011
  • 20. Release notes 4.0 $ hg clone <path-to-repo> MyBuildout $ cd MyBuildout $ python2.6 virtualenv.py $ bin/buildout Wednesday, November 9, 2011
  • 21. Conclusion * Much simpler release process... happy release engineers. * Much simpler release notes... happy developers * Joy all around. Wednesday, November 9, 2011