web-dev-qa-db-fra.com

Remplacer les paramètres de configuration de Vagrant localement (par développeur)

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?

55
netmikey

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

26
Philip Durbin

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
87
Willie Wheeler

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
12
Courtney Miles

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

Mise à jour (une autre approche "axée sur les données")

# 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
6
Sergio Tulentsev

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.

5
Amr Mostafa

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

4
Tom

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
0
Rafał Kłys