Installation d'un module puppet à partir d'un script manifeste
J'utilise puppet pour fournir une machine virtuelle vagrant (basée sur ubuntu). Dans mon script, je dois:
sudo apt-get build-dep python-lxml
Je sais que je peux installer le apt
Module marionnette donc je peux utiliser:
apt::builddep { 'python-lxml': }
Mais je ne trouve aucune référence sur l'installation d'un module à partir du script et comment l'inclure/l'exiger. Il me semble que les documents puppet se réfèrent uniquement à l'installation à partir de l'outil puppet en ligne de commande
J'ai aussi essayé de faire quelque chose comme:
define build_dep($pkgname){
exec {
"builddepend_$pkgname":
commmand => "sudo apt-get build-dep $pkgname";
}
}
build_dep{
"python-imaging":
pkgname => "python-imaging";
"python-lxml":
pkgname => "python-lxml";
}
Mais marionnette terminé avec une erreur à ce sujet. Et aussi:
exec{"install apt module":
command => "puppet module install puppetlabs/apt"
}
class { 'apt':
require => Exec["install apt module"]}
include apt
apt::builddep { 'python-imaging':
}
Mais obtenu could not find declared class apt at..
Des idées? les directions? Je sais que je manque quelque chose d'évident, mais je ne peux pas comprendre cela.
EDIT: Si je pré-installe (avec puppet module install
de la ligne de commande) le apt:builddep
fonctionne bien. mais j'ai besoin de puppet pour gérer le téléchargement et l'installation du module . Certains des autres travaux fonctionnent également pour le cas d'utilisation de base, mais ne répondront pas à ma question principale.
8 réponses
J'ai également rencontré ce problème. L'astuce consiste à télécharger les modules à l'aide d'une commande shell vagrant avant que le provisionneur puppet ne s'exécute.
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
L'ordre est important ici, et puisque le provisionneur puppet n'a pas exécuté le dossier/etc/puppet / modules n'existe pas encore.
La raison pour laquelle j'ai décidé, comme alonisser, d'installer les modules à l'aide de l'outil puppet module au lieu d'utiliser un dossier de module avec le provisioner puppet vagrant était parce que je ne voulais pas avoir à télécharger toutes les dépendances des modules que j'allais utiliser et stocker tous ces modules dans mon contrôle de source. L'exécution de ces deux commandes entraîne 5 dépendances qui, autrement, se situeraient dans mon référentiel git prenant de la place.
Voici ce que j'ai fait pour que la commande puppet module install
s'exécute au plus une fois:
$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
J'utilise une approche similaire à @brain_bacon - la complication supplémentaire que j'ai eue est qu'en plus des modules pré-emballés comme puppetlabs/nodejs j'avais besoin de modules locaux par rapport à mon Vagrantfile. Je ne voulais pas vérifier les modules pré-emballés dans le cadre de mon référentiel, ni utiliser les sous-modules git à cause des problèmes signalés par @Igor Popov.
Enfin, la solution que j'ai choisie était d'utiliser un script shell pour télécharger les modules, mais en forçant leur chemin dans le répertoire partagé entre la VM Vagrant et l'hôte, et en utilisant .gitignore pour éviter que ce chemin soit sous le contrôle de la source.
Pour être clair, avec cet arbre:
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
Sur .gitignore
, j'ai ajouté
/puppet/modules/mysql
Sur 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
Vous pouvez installer des modules puppet sur la machine hôte dans votre vagrantdir
:
puppet module --modulepath=./puppet/modules/ install puppetlabs/mysql
Vagrant prend soin de monter ce répertoire au bon endroit. Il n'est donc pas nécessaire d'exécuter des scripts autres que puppet lui-même sur le nœud.
Inspiré par wtanaka.com la réponse, j'ai implémenté une solution comme ci-dessous qui, je pense, est beaucoup plus lisible.
1) Créez un nouveau fichier ruby appelé ' puppet_deps.rb ' sous le même dossier que Vagrantfile avec le code comme ci-dessous:
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) dans votre fichier Vagrantfile, vous pouvez charger ce fichier ruby et l'utiliser pour spécifier la dépendance puppet:
# 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')
Vous pouvez créer un répertoire pour les modules et ajouter le module apt
que vous avez téléchargé depuis la forge. Donc ce sera modules/apt/*
. Ensuite, vous pouvez spécifier ce répertoire de module dans Vagrantfile
(module_path
est relatif à Vagrantfile
):
Vagrant.configure("2") do |config|
config.vm.provision :puppet do |puppet|
puppet.module_path = "modules"
end
end
La stratégie de@brain_bacon a fonctionné presque parfaitement pour moi, avec une petite mise en garde - si le module existe déjà, alors le script d'approvisionnement échoue, arrêtant le processus d'approvisionnement. L'ajustement suivant a corrigé ceci:
config.vm.provision :shell, :run => "always" do |shell|
shell.inline = %{
mkdir -p /etc/puppet/modules;
function install_module {
folder=`echo $1 | sed s/.*-//`
if [ ! -d /etc/puppet/modules/$folder ]; then
puppet module install $1
fi
}
install_module stdlib
install_module apt
install_module ruby
}
end
En utilisant les réponses de cette question, j'ai créé ce script:
#!/bin/bash
function install_module {
IFS=':' read module version <<< "$1"
if (puppet module list | grep $module ) >/dev/null; then
echo "Module $module is already installed"
else
if [ -z "$version" ]; then
puppet module install $module
else
puppet module install -v $version $module
fi
fi
}
if dpkg --compare-versions `puppet --version` "lt" 3.8.7; then
sudo apt-get remove --purge -y puppet
sudo apt-get -y autoremove
fi
if which puppet >/dev/null; then
echo "Puppet is already installed"
else
echo "Installing puppet"
wget https://apt.puppetlabs.com/puppetlabs-release-trusty.deb
sudo dpkg -i puppetlabs-release-trusty.deb
sudo apt-get update
sudo apt-get install -y puppet=3.8.7*
mkdir -p /etc/puppet/modules
fi
for var in "$@"
do
install_module "$var"
done
, Alors vous pouvez utiliser à partir de votre Vagrantfile
comme ceci:
puppet_modules = [
'puppetlabs-stdlib:4.16.0',
'puppetlabs-apt:2.3.0',
'puppet-nodejs:2.3.0'
]
config.vm.provision "shell", path: "puppet/scripts/puppet.sh", args: puppet_modules.join(" ")
Il supprime puppet de la machine virtuelle si la version est inférieure à 3.8.7
, puis installe puppet 3.8.7
, puis installe tous les modules.
Cela ne fonctionnerait probablement que sur les boîtes debian/ubuntu.