I\'m using puppet to provision a vagrant (ubuntu based) virtual machine. In my script I need to:
sudo apt-get build-dep python-lxml
I know
Inspired by wtanaka.com's answer, I implemented a solution like below which I think is much more readable.
1) create a new ruby file called 'puppet_deps.rb' under the same folder as Vagrantfile with code like below:
def install_dep(name, version, install_dir = nil)
install_dir ||= '/etc/puppet/modules'
"mkdir -p #{install_dir} && (puppet module list | grep #{name}) || puppet module install -v #{version} #{name}"
end
2) In your Vagrantfile, you can load this ruby file and use it to specify the puppet dependency:
# on top of your Vagrantfile
require './puppet_deps'
...
...
# in your vm definition, use a shell provisioning this:
config.vm.provision :shell, :inline => install_dep('puppetlabs-firewall', '1.1.3')
config.vm.provision :shell, :inline => install_dep('puppetlabs-stdlib', '4.3.2')
You can install puppet modules on the host machine within your vagrantdir
:
puppet module --modulepath=./puppet/modules/ install puppetlabs/mysql
Vagrant takes care to mount this directory to the right place. So there is no need to run scripts other than puppet itself on the node.
I ran into this problem as well. The trick is to download the modules using a vagrant shell command before the puppet provisioner runs.
config.vm.provision :shell do |shell|
shell.inline = "mkdir -p /etc/puppet/modules;
puppet module install puppetlabs/nodejs;
puppet module install puppetlabs/apache"
end
config.vm.provision :puppet do |puppet|
puppet.manifests_path = "puppet/manifests"
puppet.manifest_file = "site.pp"
end
Order is important here, and since the puppet provisioner hasn't run the folder /etc/puppet/modules does not exist yet.
The reason I decided, like alonisser, to install the modules using the puppet module tool instead of using a module folder with the vagrant puppet provisioner was because I didn't want to have to download all of the dependencies of the modules I was going to use and store all of those modules in my source control. Running these two commands results in 5 dependencies that would otherwise sit in my git repository taking up space.
Here's what I did to make the puppet module install
command run at most once:
$script = <<EOF
mkdir -p /etc/puppet/modules
(puppet module list | grep puppetlabs-mysql) ||
puppet module install -v 2.1.0 puppetlabs/mysql
EOF
Vagrant::Config.run do |config|
config.vm.provision :shell, :inline => $script
I use an approach similar to @brain_bacon - the additional complication I had is that in addition of pre-packaged modules like puppetlabs/nodejs I needed local modules relative to my Vagrantfile. I didn't want to check in the pre-packaged modules as part of my repository, nor use git submodules because of the problems pointed out by @Igor Popov.
Finally the solution I chose was to use a shell script to download the modules, but forcing their path into the shared directory between the Vagrant VM and the host, and using .gitignore to avoid that path being under source control.
To be clear, with this tree:
jcmendez$ tree
.
├── README.md
├── Vagrantfile
├── files
├── puppet
│ ├── manifests
│ │ └── init.pp
│ └── modules
│ ├── misc
│ │ └── manifests
│ │ └── init.pp
│ ├── mysql
...
│ └── wordpress
│ ├── files
│ │ ├── wordpress-db.sql
│ │ ├── wp-config.php
│ │ └── wp-tests-config.php
│ └── manifests
│ └── init.pp
└── wordpress
On .gitignore
I added
/puppet/modules/mysql
On Vagrantfile
config.vm.provision :shell do |shell|
shell.inline = "puppet module install puppetlabs/mysql --force --modulepath '/vagrant/puppet/modules'"
end
config.vm.provision :puppet do |puppet|
puppet.manifests_path = 'puppet/manifests'
puppet.module_path = 'puppet/modules'
puppet.manifest_file = "init.pp"
puppet.options="--verbose --debug"
end
You can create a directory for modules and add the apt
module that you downloaded from the forge. So it will be modules/apt/*
. Then you can specify this module directory in Vagrantfile
(module_path
is relative to Vagrantfile
):
Vagrant.configure("2") do |config|
config.vm.provision :puppet do |puppet|
puppet.module_path = "modules"
end
end
For more information see the documentation.