I'm working on a module to handle creating and populating Python virtualenvs. Without going into too much detail, basically these are nicely-encapsulated environments into which python packages can be installed and run. It's not uncommon to have several virtualenvs on a system, potentially with the same packages installed (maybe different versions).
Puppet's defines are here to help with stuff that can be installed multiple times on a particular system, but this particular situation is two-layered: I want to install the same version of Twisted into two different virtualenvs. Here's the code: define python::virtualenv($python, $ensure="present", $packages) { include python::package_dir $virtualenv = $title case $ensure { present: { file { # create the virtualenv directory "$virtualenv": ensure => directory; } $touchfile = "$virtualenv/.ve-setup" exec { "virtualenv $virtualenv": logoutput => on_failure, name => "$python $package_dir/virtualenv.py \ --python=$python --distribute $virtualenv \ && touch '$touchfile'", require => [ File[$package_dir], ], creates => $touchfile; } python::package { $packages: virtualenv => $virtualenv; } } absent: { # absent? that's easy - blow away the directory file { "$virtualenv": ensure => absent, backup => false, force => true; } } } } class python::package_dir { file { "$package_dir": source => "puppet:///python/package_dir", recurse => true, purge => true, backup => false; } } define python::package($virtualenv) { include python::package_dir $pkg = $title # the tarball to install from $tarball = "$package_dir/$pkg.tar.gz" # pip options to make sure no internet access occurs $pip_options = "--upgrade --no-deps --no-index --find-links/nosuchdir" exec { "virtualenv-package-$virtualenv-$pkg": logoutput => on_failure, name => "$virtualenv/bin/pip install $pip_options $tarball", unless => "/usr/bin/test -d '$virtualenv/lib/python'*'/site-packages/$pkg'*'.egg-info'", require => [ File[$package_dir], Exec["virtualenv $virtualenv"] ]; } } # site.pp: import "python" node default { python::virtualenv { "/tools/virtualenv-1": python => "/usr/bin/python", packages => [ 'mock-0.6.0' ]; "/tools/virtualenv-2": python => "/usr/bin/python2.4", packages => [ 'mock-0.6.0' ]; } } The trained eye can probably see immediately why this doesn't work - it tries to instantiate two copies of Python::Package[mock-0.6.0], each with different $virtualenv parameters. I think I could make this particular process work if I could qualify the Python::Package resource names, and then un-qualify them to figure out what package to install and what virtualenv to install it in. Then I would have Python::Package[/tools/virtualenv-1|mock-0.6.0] Python::Package[/tools/virtualenv-2|mock-0.6.0] In the python::package define, I could split $title into $virtualenv and $pkg easily enough with regsubst(). However, how can I take an array of bare package names and prepend the virtualenv name and "|" to each one? Another thought is that I could use Exec directly, since it is not impeded by duplicate resource names. That would mean replacing the python::package resource instantiation with something like exec { $packages: name => "$virtualenv/bin/pip install $title"; } but the $title there won't be qualified with each element of the $packages array -- it will be the value of $title from the enclosing scope (define python::virtualenv) So, is there a better way to approach this problem? I'm worried that if I can't get something this simple figured out, I'm not going to be able to get Puppet to do the more complex things I'd like.. Dustin -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.