Переопределение параметров конфигурации Vagrant локально (для каждого разработчика)


Я бы хотел, чтобы на этот вопрос был дан ответ в целом, но чтобы проиллюстрировать его, вот пример использования:

Я использую Vagrant для простого проекта LMAP. Я использую автономную марионетку для подготовки. Теперь могут быть некоторые разработчики, которые сидят за прокси, и им потребуется дополнительная конфигурация для виртуальной машины. У меня есть вещи, работающие на стороне марионетки: я могу передать IP-адрес прокси (если таковой имеется) как факт марионетке в Vagrantfile и кукла реагирует соответственно, если это набор.

единственная проблема у меня есть: как разработчики могут указать / переопределить этот параметр для своей среды разработки без необходимости изменять Vagrantfile (который находится под контролем версий и должен оставаться dev-environment-neutral)?

было бы здорово, если бы люди могли переопределить некоторые настройки Бродяги в файле под названием, например,Vagrantfile.local, который я бы исключил через .gitignore.

так как Vagrantfile - это просто Ruby, я попробовал следующее:

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

включение файла в основном работает, но похоже, что в включенном файле я больше не в том же бродячем контексте...

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

... также "сбрасывает" все остальные значения конфигурации марионетки, которые я сделал в основном Vagrantfile, что заставляет меня думать, что я иду в неправильном направлении здесь. Я должен отметить, что я полный нуб в Рубин ;)

может ли кто-нибудь дать мне подсказку или даже рабочее решение для того, как настройка per-dev может быть выполнена здесь генерал?

7 54

7 ответов:

Я бы предложил использовать переменные среды для динамического изменения поведения Vagrantfile без редактирования самого файла.

чтобы дать пример реального мира, вот как вы можете использовать базовую коробку Ubuntu по умолчанию, но иметь переменную среды, определяющую альтернативный дистрибутив Linux:

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

этот пример исходит из https://github.com/puppetlabs/puppetlabs-openstack_dev_env

The Vagrantfile это просто Рубин, поэтому YAML-это еще один вариант.

например,Vagrantfile Я делаю так:

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

тогда у меня есть (Я только что придумал ему имя, вы можете использовать любое имя, которое вам нравится) для разработчика конфигурации:

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

Если вы готовы определить настройки, которые применяются ко всем вашим коробкам vagrant, стоит отметить, что "Vagrant фактически загружает серию Vagrantfiles, объединяя настройки по мере их поступления."(ref https://docs.vagrantup.com/v2/vagrantfile/)

поэтому у меня есть следующее определение в ~/.vagrant.d/Vagrantfile чтобы увеличить объем оперативной памяти для моих бродячих ящиков:

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

вот идея. Это может быть "некрасиво" и "неправильно", но, по крайней мере, это работает :)

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

играем

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

адаптация к вашему примеру, file2.РБ будет содержать только использование config без определения его (config будет предоставлено из внешнего контекста)

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

и ваш бродячий файл может выглядеть так:

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

Я считаю, что это точный случай использования, что плагин Nugrant был создан, чтобы решить. Это позволяет каждому из ваших разработчиков иметь .vagrantuser (что является a .gitignore-ed file) в YAML, указывая пользовательские значения конфигурации, затем легко ссылаться на эти значения в Vagrantfile.

в вашем случае, проксированный разработчик будет иметь их .vagrantuser файл выглядит так:

proxy: 'proxy.host:80'

и свой Vagrantfile будет выглядеть так (псевдокод, я не знаю Рубин):

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

вы должны связать образец / ссылку vagrantuser (т. е. vagrantuser.example) файл для ваших разработчиков, чтобы скопировать и настроить их среду.

чтобы продлить ответ @Willie Wheeler. Моя настройка:

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"]

по умолчанию.в формате YML

vb:
  memory: 1024

env.в формате YML

vb:
  memory: 204

это объединит все значения по умолчанию, которые у вас есть с вашей конфигурацией per-dev. Также разработчикам понятно, какие значения они могут реально изменить

вы можете загрузить настройки из файла YAML. Это показано в Drupal VM как показано ниже:

# 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")

так что вы можете создать config.yml как:

vagrant_box: geerlingguy/ubuntu1404
vagrant_user: vagrant
vagrant_ip: 192.168.88.88

и Vagrantfile вы можете использовать переменные как:

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