在本地覆盖Vagrant配置设置(每个开发人员)

时间:2012-10-25 09:30:33

标签: ruby vagrant

我希望这个问题能够得到一般性的回答,但为了说明一下,这是一个用例:

我正在使用Vagrant进行简单的LMAP项目。我使用独立的Puppet进行配置。现在,可能有一些开发人员坐在代理后面,他们需要对VM进行一些额外的配置。我有事情在Puppet方面工作:我可以将代理IP(如果有的话)作为事实传递给Vagrantfile中的木偶,如果它被设置,Puppet会做出相应的反应。

我唯一的问题是:开发人员如何为他们的开发环境指定/覆盖此设置,而不必更改Vagrantfile(在版本控制下并且必须保持dev-environment-neutral)?

如果人们可以覆盖名为例如文件中的某些Vagrant设置,那将会很棒。 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上下文中......

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

...还“重置”我在主Vagrantfile中创建的所有其他木偶配置值,这让我觉得我在这里朝着错误的方向前进。我应该注意到我在Ruby上是一个完全的菜鸟;)

任何人都可以给我一个提示,甚至是一个有效的解决方案,了解如何在这里完成per-dev定制?

8 个答案:

答案 0 :(得分:87)

Vagrantfile只是Ruby,所以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

然后我有一个vagrant.yml文件(我只是编写了名称;你可以使用你喜欢的任何名称)来进行特定于开发人员的配置:

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

答案 1 :(得分:26)

我建议使用环境变量动态更改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

答案 2 :(得分:12)

如果您准备定义适用于所有流浪盒的设置,值得注意的是,“Vagrant实际上会加载一系列Vagrantfiles,并将设置合并到一起。” (参考https://docs.vagrantup.com/v2/vagrantfile/

所以我在~/.vagrant.d/Vagrantfile中定义了以下内容来增加我的Vagrant框的RAM数量:

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

答案 3 :(得分:6)

这是一个想法。它可能是“丑陋的”和“错误的”,但至少它有效:)

# 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.rb将仅包含config的使用而不定义它(config将从外部上下文提供)

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

您的Vagrant文​​件可能如下所示:

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

答案 4 :(得分:5)

我认为这是Nugrant plugin创建解决的确切用例。它允许每个开发人员在YAML中使用.vagrantuser(这是一个.gitignore-ed文件)指定自定义配置值,然后在Vagrantfile中轻松引用这些值。

在您的情况下,代理开发人员的.vagrantuser文件将如下所示:

proxy: 'proxy.host:80'

你的Vagrantfile看起来像这样(伪代码,我真的不知道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

您应该为您的开发人员捆绑样本/参考vagrantuser(即vagrantuser.example)文件,以便复制并调整其环境。

答案 5 :(得分:4)

延伸@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"]

<强> defaults.yml

vb:
  memory: 1024

<强> env.yml

vb:
  memory: 204

这将合并你的per-dev配置的默认值。开发人员也清楚他们可以实际改变哪些值

答案 6 :(得分:0)

考虑使用vagrant-proxyconf插件。它允许为全球所有Vagrant VM设置代理。

另一个解决方案是在置备期间运行外部Shell脚本。我在HashSet的开头使用了单独的isProfane = false; for(String word: phrase.toLowerCase().split("\\s+")) { if(blacklistPhraseSet.contains(word)) { isProfane = true; break; } } 部分:

config.vm.provision

然后将Vagrantfile文件放在# 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 旁边,将其添加到Vagrantfile-settings.sh(或其他任何文件)中,然后放置任何脚本,例如为交互式终端,所有守护程序设置代理和docker容器:

Vagrantfile

答案 7 :(得分:-2)

您可以从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']