12. Buildout - Parte I

Buildout compone su aplicación por usted, de acuerdo a sus reglas.

Para componer su aplicación es necesario definir los paquetes eggs que usted necesita, ¿qué versión?, ¿qué archivos de configuración Buildout tiene que generar para usted?, para descargar y compilar, así sucesivamente. Buildout descarga los paquetes eggs requeridos y resuelve todas las dependencias. Es posible que necesite cinco paquetes eggs diferentes, pero al final, Buildout tiene que instalar 300 paquetes eggs, todos con la versión correcta.

Buildout hace esto sin tocar el sistema Python o afectar a ningún otro paquete. Los comando creados por buildout traer todos los paquetes requeridos en el entorno Python. Cada comando crea mis diferentes bibliotecas o incluso diferentes versiones de la misma biblioteca.

Plone necesita carpetas para los archivos de registro, bases de datos y archivos de configuración. Buildout ensambla todo esto para usted.

Usted necesitará una gran cantidad de funcionalidades que Buildout no proporciona fuera de la caja, así usted necesitará varias extensiones. Algunas extensiones proporcionan una funcionalidad totalmente nueva, como mr.developer, la mejor manera de manejar sus repositorios de código fuente.

Sintaxis

La sintaxis de los archivos de configuración de despliegue es similar a los archivos clásicos ini. Usted escribe un nombre de parámetro, un signo igual y el valor. Si introduce otro valor en la siguiente línea y indentada, Buildout entiende que ambos valores pertenecen al nombre del parámetro y el parámetro almacena todos los valores en forma de lista.

Un Buildout consta de múltiples secciones. Las secciones comienzan con el nombre de la sección entre corchetes. Cada sección declara una parte diferente de su aplicación. Como analogía aproximada, su archivo Buildout es un libro de cocina con múltiples recetas.

Hay una sección especial, llamada [buildout]. En esta sección se puede cambiar el comportamiento de la propia Buildout. Las variables parts define, cuál de las secciones existentes deben ser efectivamente utilizadas.

Recetas

Buildout por si mismo no tiene idea de como instalar Zope. Buildout es un sistema basado en plugin, este viene con un pequeño conjunto de plugins para crear archivos de configuración y descargar paquetes eggs con sus dependencias y su versión apropiada. Para instalar un sitio Zope, necesitas un plugin de terceros. El plugin provee nuevas recetas que tu tienes que declarar y configurar en una sección.

Un ejemplo es esta sección.

[instance]
recipe = plone.recipe.zope2instance
user = admin:admin

Esto usa el paquete de python plone.recipe.zope2instance para crear y configurar la instancia Zope 2 la cual usamos para ejecutar Plone. Todas las lineas después de recipe = xyz son la configuración de la receta usada.

Referencias

Buildout le permite usar referencias en la configuración. Una declaración de variable no sólo puede mantener el valor de variable, pero también una referencia al lugar donde buscar el valor de la variable.

Si usted tiene una gran instalación con muchos sitios Plone con pequeños cambios entre cada configuración, se puede generar una plantilla de configuración, y cada sitio hace referencia a todo, desde la plantilla y sobrescribe justo en lo que necesita ser cambiado.

Incluso en los buildouts más pequeños esta es una característica útil. Estamos utilizando collective.recipe.omelette. Una receta muy práctica, la cual crea un directorio virtual para facilitar la navegación al código fuente de cada paquete egg.

La receta omelette tiene que saber cuales son los paquetes eggs para hacer referencia. Queremos los mismos paquetes eggs usados por nuestra instancia Zope, por lo que nos referimos a los paquetes eggs de la instancia en lugar de repetir toda la lista.

Otro ejemplo: Digamos usted crea archivos de configuración para un servidor Web como Nginx, puede definir el puerto de destino para el Proxy inverso al mirar hacia arriba a partir de la receta zope2instance.

La configuración de sistemas complejos siempre implica una gran cantidad de duplicación de la información. El uso de referencias en la configuración buildout le permite minimizar estas duplicaciones.

Un ejemplo de la vida real

Examinemos el archivo buildout.cfg para el entrenamiento y miremos algunas de las variables más importantes:

[buildout]
extends =
    http://dist.plone.org/release/4.3.10/versions.cfg

# We add our own versions
    versions.cfg

versions = versions

extensions = mr.developer
# Tell mr.developer to ask before updating a checkout.
always-checkout = true
show-picked-versions = true
sources = sources

# Put checkouts in src-mrd. We keep our own package in src
sources-dir = src-mrd

# The directory this buildout is in. Modified when using vagrant.
buildout_dir = ${buildout:directory}

# We want to checkouts these eggs directly from github
auto-checkout =
#    ploneconf.site_sneak
#    starzel.votable_behavior
#    ploneconf.site

parts =
    checkversions
    codeintel
    instance
    mrbob
    packages
#    robot
    test
    zopepy
#    zopeskel

eggs =
    Plone
    Pillow

# development tools
    z3c.jbot
    plone.api
    plone.reload
    Products.PDBDebugMode
    plone.app.debugtoolbar
    Products.PrintingMailHost

# 3rd party addons
    Products.PloneFormGen
    collective.plonetruegallery
    collective.js.datatables
    eea.facetednavigation
    collective.behavior.banner

# dexterity default types
    plone.app.contenttypes

# The addon we develop in the training
#    ploneconf.site

# Voting on content
#    starzel.votable_behavior

zcml =

test-eggs +=
#    ploneconf.site [test]

[instance]
recipe = plone.recipe.zope2instance
user = admin:admin
http-address = 8080
debug-mode = on
verbose-security = on
deprecation-warnings = on
eggs = ${buildout:eggs}
zcml = ${buildout:zcml}
file-storage = ${buildout:buildout_dir}/var/filestorage/Data.fs
blob-storage = ${buildout:buildout_dir}/var/blobstorage

[test]
recipe = zc.recipe.testrunner
eggs = ${buildout:test-eggs}
defaults = ['--exit-with-status', '--auto-color', '--auto-progress']

[packages]
recipe = collective.recipe.omelette
eggs = ${buildout:eggs}
location = ${buildout:buildout_dir}/packages

[codeintel]
recipe = corneti.recipes.codeintel
eggs = ${buildout:eggs}

[checkversions]
recipe = zc.recipe.egg
eggs = z3c.checkversions [buildout]

[zopepy]
recipe = zc.recipe.egg
eggs = ${buildout:eggs}
interpreter = zopepy
scripts = zopepy

[zopeskel]
recipe = zc.recipe.egg
eggs =
    ZopeSkel
    Paste
    PasteDeploy
    PasteScript
    zopeskel.diazotheme
    zopeskel.dexterity
    zest.releaser
    ${buildout:eggs}

[mrbob]
recipe = zc.recipe.egg
eggs =
    mr.bob
    bobtemplates.plone

[sources]
# ploneconf.site = fs ploneconf.site full-path=${buildout:directory}/src/ploneconf.site
starzel.votable_behavior = git https://github.com/collective/starzel.votable_behavior.git pushurl=git@github.com:collective/starzel.votable_behavior.git

Cuando usted ejecuta el comando ./bin/buildout sin argumentos, Buildout buscara por este archivo.

Echemos un vistazo más de cerca a algunas variables.

extends =
    http://dist.plone.org/release/4.3.10/versions.cfg
    versions.cfg

Esta línea le dice al Buildout lea más archivos de configuración. Puede hacer referencia a los archivos de configuración locales en el equipo o los archivos de configuración en Internet, accesible a través de protocolo HTTP. Puede utilizar varios archivos de configuración para compartir entre múltiples configuraciones Buildouts, o para separar los diferentes aspectos de su configuración en archivos diferentes. Ejemplos típicos son especificaciones de la versión o la configuración que difieren entre los diferentes entornos de instalación como desarrollo, calidad, producción.

eggs =
    Plone
    Pillow
    z3c.jbot
    plone.api
    plone.reload
    Products.PDBDebugMode
    plone.app.debugtoolbar
    Paste
    Products.PloneFormGen
    collective.plonetruegallery
    collective.js.datatables
    eea.facetednavigation
    collective.behavior.banner
    plone.app.contenttypes
#    ploneconf.site
#    starzel.votable_behavior

Esta es la lista de los paquetes eggs que nosotros configuramos para estar disponible para Zope. Estos paquetes eggs se ponen en el PYTHONPATH del script bin/instance con el cual se iniciara y detendrá con Plone.

El paquete egg Plone es una envoltura sin código fuente. Entre sus dependencias esta Products.CMFPlone que es el paquete egg en el cual esta propiamente de Plone.

El resto son complementos que ya hemos usado o usará más tarde. Los últimos paquetes eggs están comentadas por lo que no se instalarán por Buildout.

El archivo versions.cfg se incluye por la declaración extends = ... contiene las versiones que definimos:

[versions]
# dev tools
z3c.jbot = 0.7.2
plone.api = 1.1.0
plone.app.debugtoolbar = 1.0a3
...

Esta es otra sección especial. Se ha convertido en una sección especial de declaración. En nuestra sección [buildout] establecemos una variable versions = versions. Esto le dice a buildout, existe una sección denominada versions, conteniendo información de las versiones a usar. Cuando Buildout instala paquetes eggs se utilizará la versión definida en esta sección.

¡Hola mr.developer!

Hay muchas cosas más importantes que debe saber, y no podemos pasar por ellos en todos los detalles, pero quiero centrarme en una característica específica: mr.developer

Con mr.developer puede declarar los paquetes que desee comprobar desde o hacia un sistema de control de versiones y de cual dirección URL del repositorio. Usted puede comprobar código fuente desde diversos CVS como git, subversion, bzr, hg y quizá más. También, se puede indicar a Buildout algún código fuente se encuentran en el sistema de archivos local sin aplicar control de versiones.

mr.developer viene con un comando, ./bin/develop. Se puede utilizar para actualizar su código fuente, para comprobar los nuevos cambios y así sucesivamente. Usted puede activar y desactivar sus checkouts de sus código fuente. Si usted desarrolla sus extensiones en los paquetes eggs con checkouts separadas, lo cual es una buena práctica, usted puede planear publicaciones por tener todas los checkouts desactivados, y sólo activarlos, al escribir los cambios que requieren una nueva versión. Usted puede activar y desactivar los paquetes eggs a través del comando develop o vía la configuración Buildout. Siempre debe usar la forma Buildout. Su commit sirve como documentación.

Extensible

Usted puede haber notado que la mayoría, si no toda la funcionalidad sólo está disponible a través de plugins. Una de las cosas que sobresale en Buildout sin ningún plugin, es la resolución de dependencias. Usted puede ayudar a Plone en la resolución de dependencias, al declarar exactamente cual versión de un paquete egg usted desea. Esto es sólo un caso de uso. Otra es mucho más importante: Si usted quiere tener un Buildout repetible, el cual funcione de dos meses a partir de ahora también, se debe declarar todas sus versiones de paquete egg. De otro modo Buildout podría instalar las nuevas versiones.

Sea un McGuyver

Como puede ver, usted puede construir sistemas muy complejos con Buildout. Es hora de algunas advertencias. Sea selectivo en sus recetas. Supervisor es un programa para gestionar servidores en ejecución, es bastante bueno. No hay una receta para ello.

¡La configuración para esta receta es más complicada que la propia configuración del Supervisor en si! Mediante el uso de esta receta, se fuerza a los demás a comprender la sintaxis de configuración específica recetas y la sintaxis Supervisor. Para tales casos, collective.recipe.template presenta una mejor coincidencia.

Otro problema es el manejo de errores. ¿Buildout intenta instalar una rara dependencia que en realidad no quiere? Buildout no le dirá, lo que está viniendo.

Si hay un problema, siempre se puede ejecutar Buildout con la opción -v, para obtener una salida más detallada, a veces ayuda.

$ ./bin/buildout -v

Si se solicitan las versiones de paquetes eggs extraños, verifique la declaración de las dependencias de los paquetes eggs y su versión definida.

Algunas partes de Buildout interpretan nombres de paquete egg entre mayúsculas y minúsculas, otros no. Esto puede dar lugar a problemas de divertidos.

Verifique siempre el orden de su configuraciones extendidas, utilice siempre el comando annotate de Buildout para ver si se interpreta la configuración diferente a la que usted definió. Restringirse a los archivos de despliegue simples. Puede hacer referencia a variables de otras secciones, incluso se puede utilizar toda una sección como plantilla. Hemos aprendido que esto no funciona bien con jerarquías complejas y se tuvo que abandonar esa característica.

En el capítulo Buildout - Parte II: Cómo prepararse para el despliegue veremos una configuración de despliegue lista para entornos de producción de Plone que tiene muchas características útiles.