Anular localmente los ajustes de configuración de Vagrant (por dev)

Me gustaría que la pregunta fuera respondida en general, pero para ilustrarla, aquí hay un caso de uso:

Estoy usando Vagrant para un proyecto LMAP simple. Yo uso Puppet independiente para aprovisionamiento. Ahora, podría haber algunos desarrolladores que se sientan detrás de un proxy y necesitarían una configuración adicional para la VM. Tengo cosas trabajando en el lado de Puppet: puedo pasar la IP del proxy (si existe) como un hecho a Puppet en el Vagrantfile y Puppet reactjs en consecuencia si está configurado.

El único problema que tengo es: ¿cómo pueden los desarrolladores especificar / anular esta configuración para su entorno de desarrollo sin tener que cambiar el Vagrantfile (que está bajo el control de la versión y debe permanecer sin cambios en el entorno)?

Sería increíble si las personas pudieran anular algunas configuraciones de Vagrant en un archivo llamado, por ejemplo, Vagrantfile.local , que excluiría a través de .gitignore .

Como un Vagrantfile es solo Ruby, probé lo siguiente:

 # Also load per-dev custom vagrant config custom_vagrantfile = 'Vagrantfile.local' load custom_vagrantfile if File.exist?(custom_vagrantfile) 

La inclusión de archivos básicamente funciona, pero parece que en el archivo incluido, ya no estoy en el mismo contexto Vagrant …

 Vagrant::Config.run do |config| config.vm.provision :puppet do |puppet| puppet.facter = { "proxy" => "proxy.host:80" } end end 

… también “restablece” todos los demás valores de configuración de títeres que hice en el Vagrantfile principal, lo que me hace pensar que me estoy dirigiendo en la dirección equivocada aquí. Debo señalar que soy un noob total en Ruby;)

¿Alguien puede darme una sugerencia o incluso una solución de trabajo sobre cómo se puede hacer la personalización per-dev aquí en general?

Yo sugeriría usar variables de entorno para cambiar dinámicamente el comportamiento de Vagrantfile sin editar el archivo en sí.

Para dar un ejemplo del mundo real, aquí le explicamos cómo podría usar un cuadro base de Ubuntu de manera predeterminada pero tener una variable de entorno que defina una distribución de Linux alternativa:

 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 

Este ejemplo proviene de https://github.com/puppetlabs/puppetlabs-openstack_dev_env

El Vagrantfile es solo Ruby, así que YAML es otra opción.

Por ejemplo, en el Vagrantfile hago esto:

 # -*- 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 

Luego tengo un archivo vagrant.yml (acabo de crear el nombre; puedes usar el nombre que quieras) para la configuración específica del desarrollador:

 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 está preparado para definir la configuración que se aplica a todos sus cuadros errantes, vale la pena señalar que “Vagrant en realidad carga una serie de archivos Vagrant, fusionando la configuración a medida que avanza”. (ref https://docs.vagrantup.com/v2/vagrantfile/ )

Así que tengo lo siguiente definido en ~/.vagrant.d/Vagrantfile para boost la cantidad de RAM para mis cajas de Vagrant:

 Vagrant.configure(2) do |config| config.vm.provider "virtualbox" do |vb| vb.memory = 2048 end end 

Aquí hay una idea. Puede ser “feo” y “incorrecto”, pero, al menos, funciona 🙂

 # 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' 

Vamos a correr eso

 $ ruby file1.rb first included external file which uses outer var: bar second 

Adaptándose a su ejemplo, file2.rb contendría solo el uso de config sin definirlo (la config se proporcionará desde el contexto externo)

  config.vm.provision :puppet do |puppet| puppet.facter = { "proxy" => "proxy.host:80" } end 

Y tu archivo Vagrant puede verse así:

 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 

Actualización (otro, enfoque “basado en datos”)

 # 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 

Creo que ese es el caso de uso exacto que el complemento Nugrant fue creado para resolver. Permite que cada uno de sus desarrolladores tenga un .vagrantuser (que es un archivo .gitignore-ed) en YAML que especifica valores de configuración personalizados y luego hace referencia a estos valores con facilidad en Vagrantfile .

En su caso, un desarrollador proxy tendría su archivo .vagrantuser el siguiente aspecto:

 proxy: 'proxy.host:80' 

Y tu Vagrantfile se vería así (pseudo código, realmente no sé 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 

Debes agrupar un archivo vagrantuser de muestra / referencia (es decir, vagrantuser.example ) para que tus desarrolladores los copien y ajusten a su entorno.

Para ampliar en la respuesta de @Willie Wheeler. Mi configuración es:

 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 

Esto fusionará los valores predeterminados que tenga con su configuración por-dev. También está claro para los desarrolladores qué valores pueden cambiar realmente

Puede cargar la configuración desde el archivo YAML. Esto se demuestra en Drupal VM de la siguiente manera:

 # Use config.yml for basic VM configuration. require 'yaml' dir = File.dirname(File.expand_path(__FILE__)) if !File.exist?("#{dir}/config.yml") raise 'Configuration file not found! Please copy example.config.yml to config.yml and try again.' end vconfig = YAML::load_file("#{dir}/config.yml") 

Entonces puedes crear config.yml como:

 vagrant_box: geerlingguy/ubuntu1404 vagrant_user: vagrant vagrant_ip: 192.168.88.88 

y en Vagrantfile puedes usar variables como:

 config.vm.box = vconfig['vagrant_box'] config.vm.network "private_network", ip: vconfig['vagrant_ip']