本地覆盖Vagrantconfiguration设置(per-dev)
我希望这个问题得到普遍的回答,但为了说明这个问题,这里有一个用例:
我正在使用Vagrant进行简单的LMAP项目。 我使用独立的Puppet进行configuration。 现在,可能会有一些开发人员坐在代理之后,他们需要对虚拟机进行一些额外的configuration。 我在Puppet方面有一些工作:我可以将代理IP(如果有的话)作为一个事实传递给Vagrantfile
木偶,如果设置了,Puppet会作出相应的反应。
我唯一的问题是:开发人员如何在开发环境中指定/覆盖此设置,而无需更改Vagrantfile
(版本控制下,并且必须保持dev-environment-neutral)?
如果人们可以重写一个叫做Vagrantfile.local
的文件中的一些Vagrant设置,那么我会通过.gitignore
排除。
由于Vagrantfile只是Ruby,我尝试了以下内容:
# Also load per-dev custom vagrant config custom_vagrantfile = 'Vagrantfile.local' load custom_vagrantfile if File.exist?(custom_vagrantfile)
文件包含基本上工作,但它看起来像在包含的文件,我不在同一个stream浪上下文了…
Vagrant::Config.run do |config| config.vm.provision :puppet do |puppet| puppet.facter = { "proxy" => "proxy.host:80" } end end
…也会“重置”我在主Vagrantfile
所做的所有其他木偶configuration值,这让我觉得我正在朝着错误的方向前进。 我应该注意到,我是Ruby的总noob;)
任何人都可以给我一个提示,甚至一个工作的解决scheme,如何在每个开发定制可以在这里做一般?
我会build议使用环境variables来dynamic改变Vagrantfile
的行为而不用编辑文件本身。
为了给出一个真实世界的例子,默认情况下,你可以如何使用Ubuntu的基本框,但是有一个环境variables定义了一个可选的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
Vagrantfile
只是Ruby,所以YAML是另一种select。
例如,在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
文件(我刚刚vagrant.yml
了这个名称;你可以使用任何你喜欢的名字)进行开发者特定的configuration:
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
如果你准备定义应用于所有stream浪者箱子的设置,值得注意的是,“stream浪者实际上加载了一系列的stream浪文件,并将设置合并。” (参考https://docs.vagrantup.com/v2/vagrantfile/ )
所以我在~/.vagrant.d/Vagrantfile
定义了以下~/.vagrant.d/Vagrantfile
来增加我的stream浪者箱子的RAM数量:
Vagrant.configure(2) do |config| config.vm.provider "virtualbox" do |vb| vb.memory = 2048 end end
这是一个想法。 这可能是“丑陋”和“错误”,但至less它工作:)
# 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
我相信这就是Nugrant插件被创build来解决的确切用例。 它允许你的每个开发者在YAML中有一个.vagrantuser
(这是一个.gitignore-ed文件)指定自定义configuration值,然后在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
)文件来复制和调整其环境。
延长@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
这将合并你的每个开发configuration的默认值。 开发人员也清楚他们实际上可以改变什么价值
您可以从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")
那么你可以像创buildconfig.yml
一样:
vagrant_box: geerlingguy/ubuntu1404 vagrant_user: vagrant vagrant_ip: 192.168.88.88
在Vagrantfile
你可以使用如下的variables:
config.vm.box = vconfig['vagrant_box'] config.vm.network "private_network", ip: vconfig['vagrant_ip']