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.

Reply via email to