J'aimerais que l'on réponde à la question en général, mais pour l'illustrer, voici un cas d'utilisation:
J'utilise Vagrant pour un projet LMAP simple. J'utilise Puppet autonome pour l'approvisionnement. Maintenant, certains développeurs peuvent être assis derrière un proxy et ils auraient besoin d'une configuration supplémentaire pour être effectuée sur la machine virtuelle. J'ai des choses qui fonctionnent du côté Puppet: je peux passer l'IP proxy (le cas échéant) comme un fait à puppet dans le Vagrantfile
et Puppet réagit en conséquence s'il est défini.
Le seul problème que j'ai est: comment les développeurs peuvent-ils spécifier/remplacer ce paramètre pour leur environnement de développement sans avoir à modifier le Vagrantfile
(qui est sous contrôle de version et doit rester neutre pour l'environnement de développement)?
Ce serait génial si les gens pouvaient remplacer certains paramètres Vagrant dans un fichier appelé par exemple Vagrantfile.local
, que j'exclurais via .gitignore
.
Puisqu'un Vagrantfile est juste Ruby, j'ai essayé ce qui suit:
# Also load per-dev custom vagrant config
custom_vagrantfile = 'Vagrantfile.local'
load custom_vagrantfile if File.exist?(custom_vagrantfile)
L'inclusion de fichiers fonctionne fondamentalement, mais il ressemble au fichier inclus, je ne suis plus dans le même contexte Vagrant ...
Vagrant::Config.run do |config|
config.vm.provision :puppet do |puppet|
puppet.facter = { "proxy" => "proxy.Host:80" }
end
end
... "réinitialise" également toutes les autres valeurs de configuration de marionnettes que j'ai faites dans le Vagrantfile
principal, ce qui me fait penser que je vais dans la mauvaise direction ici. Je dois noter que je suis un noob total à Ruby;)
Quelqu'un peut-il me donner un indice ou même une solution de travail sur la façon dont la personnalisation par développeur pourrait être effectuée ici en général?
Je suggérerais d'utiliser des variables d'environnement pour changer dynamiquement le comportement du Vagrantfile
sans éditer le fichier lui-même.
Pour donner un exemple réel, voici comment vous pouvez utiliser une boîte de base Ubuntu par défaut mais avoir une variable d'environnement définir une distribution Linux alternative:
if ENV['OPERATINGSYSTEM']
if ENV['OPERATINGSYSTEM'].downcase == 'redhat'
os_name = 'centos'
config.vm.box = 'centos'
config.vm.box_url = 'https://dl.dropbox.com/u/7225008/Vagrant/CentOS-6.3-x86_64-minimal.box'
else
raise(Exception, "undefined operatingsystem: #{ENV['OPERATINGSYSTEM']}")
end
else
os_name = 'precise64'
config.vm.box = 'precise64'
config.vm.box_url = 'http://files.vagrantup.com/precise64.box'
end
Cet exemple provient de https://github.com/puppetlabs/puppetlabs-openstack_dev_env
Le Vagrantfile
est juste Ruby, donc YAML est une autre option.
Par exemple, dans le Vagrantfile
je fais ceci:
# -*- mode: Ruby -*-
# vi: set ft=Ruby :
require 'yaml'
settings = YAML.load_file 'vagrant.yml'
db_ip_address = settings['db']['ip_address']
api_ip_address = settings['api']['ip_address']
Vagrant.configure("2") do |config|
config.vm.box = "ffuenf/ubuntu-13.10-server-AMD64"
config.vm.box_url = "https://vagrantcloud.com/ffuenf/ubuntu-13.10-server-AMD64/version/4/provider/virtualbox.box"
config.vm.define "db" do |db|
db.vm.synced_folder settings['db']['artifacts_dir']['Host'], settings['db']['artifacts_dir']['guest']
db.vm.network "private_network", ip: db_ip_address
... other stuff ...
end
config.vm.define "api" do |api|
api.vm.synced_folder settings['api']['artifacts_dir']['Host'], settings['api']['artifacts_dir']['guest']
api.vm.network "private_network", ip: api_ip_address
api.vm.network "forwarded_port", guest: settings['api']['forwarded_port']['guest'], Host: settings['api']['forwarded_port']['Host']
end
end
Ensuite, j'ai un vagrant.yml
fichier (je viens de composer le nom; vous pouvez utiliser le nom que vous voulez) pour la configuration spécifique au développeur:
db:
ip_address: 192.168.4.14
artifacts_dir:
Host: /Users/willie/myapp/db-scripts
guest: /opt/myapp/db
api:
ip_address: 192.168.4.15
forwarded_port:
Host: 9080
guest: 8080
artifacts_dir:
Host: /Users/willie/myapp/artifacts
guest: /opt/myapp/api
Si vous êtes prêt à définir des paramètres qui s'appliquent à toutes vos boîtes vagabondes, il convient de noter que "Vagrant charge en fait une série de fichiers Vagrant, fusionnant les paramètres au fur et à mesure". (réf https://docs.vagrantup.com/v2/vagrantfile/ )
J'ai donc ce qui suit défini dans ~/.vagrant.d/Vagrantfile
pour augmenter la quantité de RAM pour mes boîtes Vagrant:
Vagrant.configure(2) do |config|
config.vm.provider "virtualbox" do |vb|
vb.memory = 2048
end
end
Voici une idée. Ça peut être "moche" et "faux", mais au moins ça marche :)
# file2.rb, this is your per-dev configuration file
puts "included external file which uses outer var: #{foo}"
# file1.rb, this would be your Vagrantfile
puts 'first'
foo = 'bar'
external = File.read 'file2.rb'
eval external
puts 'second'
Lançons cela
$ Ruby file1.rb
first
included external file which uses outer var: bar
second
En s'adaptant à votre exemple, file2.rb ne contiendrait que l'utilisation de config
sans le définir (config
sera fourni à partir du contexte externe)
config.vm.provision :puppet do |puppet|
puppet.facter = { "proxy" => "proxy.Host:80" }
end
Et votre fichier Vagrant peut ressembler à ceci:
Vagrant::Config.run do |config|
external = File.read 'Vagrantfile.local'
eval external
# proceed with general settings here
config.vm.provision :puppet do |puppet|
puppet.facter = { "proxy" => "proxy.Host:80" }
end
end
# Vagranfile.local
config_values[:puppet][:facter][:proxy] = 'proxy.Host:80'
# Vargantfile
Vagrant::Config.run do |config|
config_values = {
puppet: {
facter: {
proxy: nil
},
manifests_file: 'my_manifest.pp'
}
}
external = File.read 'Vagrantfile.local'
eval external # this should overwrite proxy config
# proceed with general settings here
config.vm.provision :puppet do |puppet|
if config_values[:puppet][:facter][:proxy]
puppet.facter = { "proxy" => config_values[:puppet][:facter][:proxy] }
end
puppet.manifests_file = config_values[:puppet][:manifests_file]
end
end
Je crois que c'est le cas d'utilisation exact que plugin Nugrant a été créé pour résoudre. Il permet à chacun de vos développeurs d'avoir un .vagrantuser
(qui est un fichier .gitignore-ed) dans YAML spécifiant des valeurs de configuration personnalisées, puis référencez facilement ces valeurs dans Vagrantfile
.
Dans votre cas, un développeur mandataire aurait son .vagrantuser
fichier ressemblant à ceci:
proxy: 'proxy.Host:80'
Et votre Vagrantfile
ressemblerait à ceci (pseudo-code, je ne connais pas vraiment Ruby):
Vagrant::Config.run do |config|
config.vm.provision :puppet do |puppet|
if config.user.has_key?('proxy')
puppet.facter = { "proxy" => config.user.proxy }
end
end
end
Vous devez regrouper un échantillon/utilisateur vagabond de référence (c'est-à-dire vagrantuser.example
) pour que vos développeurs les copient et les adaptent à leur environnement.
Pour prolonger la réponse de @Willie Wheeler. Ma configuration est:
Root
|-- defaults.yml
|-- env.yml
|-- Vagrantfile
Vagrantfile
# Load local env config
require 'yaml'
dir = File.dirname(File.expand_path(__FILE__))
# defaults
settings = YAML::load_file("#{dir}/defaults.yml")
if File.exist?("#{dir}/env.yml")
env_settings = YAML::load_file("#{dir}/env.yml")
settings.merge!(env_settings)
end
...
# Customize the amount of memory on the VM:
vb.memory = settings["vb"]["memory"]
defaults.yml
vb:
memory: 1024
env.yml
vb:
memory: 204
Cela fusionnera toutes les valeurs par défaut que vous avez avec votre configuration par développeur. Il est également clair pour les développeurs quelles valeurs ils peuvent réellement changer
Pensez à utiliser le plugin vagrant-proxyconf . Il permet de définir un proxy pour toutes les machines virtuelles Vagrant dans le monde.
Une autre solution consiste à exécuter un script Shell externe pendant l'approvisionnement. J'utilise des config.vm.provision
section au début de Vagrantfile
pour le faire:
# reset: true below is needed to reset the connection to the VM so that new
# environment variables set in /etc/environment will be picked up in next
# provisioning steps
config.vm.provision "Shell", reset: true, inline: <<-Shell
if [ -f /vagrant/Vagrantfile-settings.sh ]
then
/vagrant/Vagrantfile-settings.sh
fi
Shell
Ensuite, mettez simplement un Vagrantfile-settings.sh
fichier à côté de Vagrantfile
, ajoutez-le à .gitignore
(ou autre) et mettez n'importe quel script à l'intérieur, par exemple pour définir un proxy pour le terminal interactif, tous les démons et les conteneurs de docker:
# Proxy for interactive terminals
echo "http_proxy=http://PROXY_ADDRESS:PROXY_PORT" >> /etc/environment
echo "https_proxy=http://PROXY_ADDRESS:PROXY_PORT" >> /etc/environment
echo "no_proxy=127.0.0.1,localhost" >> /etc/environment
# Proxy for daemons (e.g. Docker deamon - used to pull images, apt - run from default daily cron job)
mkdir /etc/systemd/system.conf.d
echo [Manager] > /etc/systemd/system.conf.d/01-http-proxy.conf
echo "DefaultEnvironment=\"http_proxy=PROXY_ADDRESS:PROXY_PORT\"" >> /etc/systemd/system.conf.d/01-http-proxy.conf
echo "DefaultEnvironment=\"https_proxy=PROXY_ADDRESS:PROXY_PORT\"" >> /etc/systemd/system.conf.d/01-http-proxy.conf
echo "DefaultEnvironment=\"no_proxy=127.0.0.1,localhost\"" >> /etc/systemd/system.conf.d/01-http-proxy.conf
echo "# Docker requires upper-case http proxy environment variables..." >> /etc/systemd/system.conf.d/01-http-proxy.conf
echo "DefaultEnvironment=\"HTTP_PROXY=http://PROXY_ADDRESS:PROXY_PORT2\"" >> /etc/systemd/system.conf.d/01-http-proxy.conf
echo "DefaultEnvironment=\"HTTPS_PROXY=http://PROXY_ADDRESS:PROXY_PORT\"" >> /etc/systemd/system.conf.d/01-http-proxy.conf
echo "DefaultEnvironment=\"NO_PROXY=127.0.0.1,localhost\"" >> /etc/systemd/system.conf.d/01-http-proxy.conf
# Proxy for docker containers started with `docker run`
mkdir /home/vagrant/.docker
cat <<EOF > /home/vagrant/.docker/config.json
{
"proxies": {
"default": {
"httpProxy": "http:/PROXY_ADDRESS:PROXY_PORT",
"httpsProxy": "http://PROXY_ADDRESS:PROXY_PORT",
"noProxy": "127.0.0.1,localhost"
}
}
}
EOF
chown -R vagrant:vagrant /home/vagrant/.docker