ruby 本地覆盖 Vagrant 配置设置(每个开发者)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13065576/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Override Vagrant configuration settings locally (per-dev)
提问by netmikey
I'd like the question to be answered in general, but to illustrate it, here's a use case:
我希望这个问题得到一般性的回答,但为了说明这一点,这里有一个用例:
I'm using Vagrant for a simple LMAP project. I use standalone Puppet for provisioning. Now, there might be some developers who sit behind a proxy and they would need some additional configuration to be made to the VM. I have things working on the Puppet side: I can pass the proxy IP (if any) as a fact to puppet in the Vagrantfileand Puppet reacts accordingly if it's set.
我正在将 Vagrant 用于一个简单的 LMAP 项目。我使用独立的 Puppet 进行配置。现在,可能有一些开发人员坐在代理后面,他们需要对 VM 进行一些额外的配置。我在 Puppet 方面有一些工作:我可以将代理 IP(如果有)作为一个事实传递给 puppet 中的 puppet,Vagrantfile如果它被设置,Puppet 会做出相应的反应。
The only issue I have is: how can developers specify/override this setting for their development environment without having to change the Vagrantfile(which is under version control and must remain dev-environment-neutral)?
我唯一的问题是:开发人员如何为他们的开发环境指定/覆盖此设置而不必更改Vagrantfile(受版本控制并且必须保持开发环境中立)?
If would be awesome if people could override some Vagrant settings in a file called e.g. Vagrantfile.local, which I would exclude via .gitignore.
如果人们可以覆盖名为 eg 的文件中的某些 Vagrant 设置,那将会很棒Vagrantfile.local,我将通过.gitignore.
Since a Vagrantfile is just Ruby, I tried the following:
由于 Vagrantfile 只是 Ruby,我尝试了以下操作:
# Also load per-dev custom vagrant config
custom_vagrantfile = 'Vagrantfile.local'
load custom_vagrantfile if File.exist?(custom_vagrantfile)
The file inclusion basically works, but it looks like in the included file, I'm not in the same Vagrant context anymore...
文件包含基本上有效,但看起来在包含的文件中,我不再处于同一个 Vagrant 上下文中......
Vagrant::Config.run do |config|
config.vm.provision :puppet do |puppet|
puppet.facter = { "proxy" => "proxy.host:80" }
end
end
... also "resets" all other puppet config values I made in the main Vagrantfile, which makes me think I'm heading in the wrong direction here. I should note that I'm a total noob at Ruby ;)
...还“重置”了我在 mainVagrantfile中创建的所有其他 puppet 配置值,这让我觉得我在这里走错了方向。我应该注意,我对 Ruby 完全是个菜鸟 ;)
Can anyone give me a hint or even a working solution for how per-dev customization could be done here in general?
任何人都可以给我一个提示,甚至是一个可行的解决方案,说明如何在这里完成每个开发者的定制?
采纳答案by Philip Durbin
I would suggest using environment variables to dynamically change the behavior of the Vagrantfilewithout editing the file itself.
我建议使用环境变量来动态更改 的行为,而Vagrantfile无需编辑文件本身。
To give a real world example, here's how you could use an Ubuntu base box by default but have an environment variable define an alternative Linux distribution:
举一个真实世界的例子,这里是你如何在默认情况下使用 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
This example comes from https://github.com/puppetlabs/puppetlabs-openstack_dev_env
这个例子来自https://github.com/puppetlabs/puppetlabs-openstack_dev_env
回答by
The Vagrantfileis just Ruby, so YAML is another option.
这Vagrantfile只是 Ruby,所以 YAML 是另一种选择。
For example, in the VagrantfileI do this:
例如,在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
Then I have a vagrant.ymlfile (I just made up the name; you can use whatever name you like) for the developer-specific configuration:
然后我有一个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
回答by Courtney Miles
If you are prepared to define settings that are applied to all your vagrant boxes it's worth noting that, "Vagrant actually loads a series of Vagrantfiles, merging the settings as it goes." (ref https://docs.vagrantup.com/v2/vagrantfile/)
如果您准备定义应用于所有 vagrant 框的设置,值得注意的是,“Vagrant 实际上加载了一系列 Vagrantfiles,并在运行时合并设置。” (参考https://docs.vagrantup.com/v2/vagrantfile/)
So I have the following defined in ~/.vagrant.d/Vagrantfileto increase the amount of RAM for my Vagrant boxes:
所以我定义了以下内容~/.vagrant.d/Vagrantfile来增加我的 Vagrant 盒子的 RAM 量:
Vagrant.configure(2) do |config|
config.vm.provider "virtualbox" do |vb|
vb.memory = 2048
end
end
回答by Sergio Tulentsev
Here's an idea. It may be "ugly" and "wrong", but, at least, it works :)
这是一个想法。它可能是“丑陋的”和“错误的”,但至少,它有效:)
# 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'
Let's run that
让我们运行
$ ruby file1.rb
first
included external file which uses outer var: bar
second
Adapting to your example, file2.rb would contain only usage of configwithout defining it (configwill be provided from outer context)
适应你的例子,file2.rb 将只包含使用config而不定义它(config将从外部上下文提供)
config.vm.provision :puppet do |puppet|
puppet.facter = { "proxy" => "proxy.host:80" }
end
And your Vagrant file may look like this:
您的 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
Update (another, "data-driven" approach)
更新(另一种“数据驱动”方法)
# 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
回答by Amr Mostafa
I believe that's the exact use case that Nugrant pluginwas created to solve. It allows each of your devs to have a .vagrantuser(which is a .gitignore-ed file) in YAML specifying custom configuration values then reference these values with ease in Vagrantfile.
我相信这正是Nugrant 插件旨在解决的用例。它允许您的每个开发人员.vagrantuser在 YAML 中有一个(这是一个 .gitignore-ed 文件),指定自定义配置值,然后在 .gitignore 中轻松引用这些值Vagrantfile。
In your case, a proxied developer would have their .vagrantuserfile looking like this:
在您的情况下,代理开发人员的.vagrantuser文件将如下所示:
proxy: 'proxy.host:80'
And your Vagrantfilewould look like this (pseudo code, I don't really know ruby):
你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
You should bundle a sample/reference vagrantuser (i.e. vagrantuser.example) file for your devs to copy and adjust to their environment.
您应该捆绑一个示例/参考 vagrantuser(即vagrantuser.example)文件,供您的开发人员复制并适应他们的环境。
回答by Tomas
To extend on @Willie Wheeler 's answer. My setup is:
扩展@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
默认值.yml
vb:
memory: 1024
env.yml
环境.yml
vb:
memory: 204
This will merge whatever defaults you have with your per-dev config. Also it is clear to developers what values they can actually change
这会将您拥有的任何默认值与您的每个开发配置合并。开发人员也很清楚他们可以实际更改哪些值
回答by Rafa? K?ys
Consider using vagrant-proxyconfplugin. It allows to set proxy for all Vagrant VMs globally.
考虑使用vagrant-proxyconf插件。它允许全局设置所有 Vagrant VM 的代理。
Another solution is to run external shell script during provisioning. I use separate config.vm.provisionsection at the beginning of Vagrantfileto do it:
另一种解决方案是在配置期间运行外部 shell 脚本。我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
Then just put a Vagrantfile-settings.shfile next to Vagrantfile, add it to .gitignore(or whatever) and put any script inside, for example to set proxy for interactive terminal, all daemons and docker containers:
然后只需在Vagrantfile-settings.sh旁边放置一个文件Vagrantfile,将其添加到.gitignore(或其他)并将任何脚本放入其中,例如为交互式终端、所有守护进程和 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
回答by kenorb
You can load the settings from YAML file. This is demonstrated in Drupal VMas below:
您可以从 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")
So then you can create config.ymllike:
那么你可以config.yml像这样创建:
vagrant_box: geerlingguy/ubuntu1404
vagrant_user: vagrant
vagrant_ip: 192.168.88.88
and in Vagrantfileyou can use variables as:
并且Vagrantfile您可以将变量用作:
config.vm.box = vconfig['vagrant_box']
config.vm.network "private_network", ip: vconfig['vagrant_ip']

