Implement check for already active machine.

This commit re-instates the behavior of auto-updating the
/etc/hosts file on each active machine. If machine is already
active, no update will occur.
This commit is contained in:
Shawn Dahlen 2013-04-08 13:20:22 -04:00
parent 39c197d7cc
commit 33c391cfe0
11 changed files with 53 additions and 117 deletions

View File

@ -21,24 +21,21 @@ Install the plugin following the typical Vagrant 1.1 procedure:
Usage Usage
----- -----
To update the `/etc/hosts` file on each active machine, run the following The plugin hooks into the `vagrant up` and `vagrant destroy` commands
command: automatically. When a machine is created or destroyed, all active
machines with the same provider will have their `/etc/hosts` file updated
accordingly. Auto update may be disabled by setting the
`config.hostmanager.auto_update` attribute to false in the Vagrantfile.
To update the `/etc/hosts` file on each active machine manually, run the
following command:
$ vagrant hostmanager $ vagrant hostmanager
The plugin may hook into the `vagrant up` and `vagrant destroy` commands
automatically to update the `/etc/hosts` file on each active machine that
is using the same provider. To enable this, add the following configuration
to your Vagrant file:
```ruby
Vagrant.configure('2') do |config|
config.hostmanager.auto_update = true
end
```
A machine's IP address is defined by either the static IP for a private A machine's IP address is defined by either the static IP for a private
network configuration or by the SSH host configuration. network configuration or by the SSH host configuration. To disable
using the private network IP address, set `config.hostmanger.ignore_private_ip`
to true.
A machine's host name is defined by `config.vm.hostname`. If this is not A machine's host name is defined by `config.vm.hostname`. If this is not
set, it falls back to the symbol defining the machine in the Vagrantfile. set, it falls back to the symbol defining the machine in the Vagrantfile.

View File

@ -1,4 +1,3 @@
require 'vagrant'
require 'vagrant-hostmanager/plugin' require 'vagrant-hostmanager/plugin'
require 'vagrant-hostmanager/version' require 'vagrant-hostmanager/version'
require 'vagrant-hostmanager/errors' require 'vagrant-hostmanager/errors'
@ -8,5 +7,8 @@ module VagrantPlugins
def self.source_root def self.source_root
@source_root ||= Pathname.new(File.expand_path('../../', __FILE__)) @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
end end
I18n.load_path << File.expand_path('locales/en.yml', source_root)
I18n.reload!
end end
end end

View File

@ -9,22 +9,23 @@ module VagrantPlugins
def initialize(app, env) def initialize(app, env)
@app = app @app = app
@machine = env[:machine] @machine = env[:machine]
@translator = Helpers::Translator.new('action.update_hosts_file') @logger = Log4r::Logger.new('vagrant::hostmanager::update_hosts_file')
@logger =
Log4r::Logger.new('vagrant_hostmanager::action::update')
end end
def call(env) def call(env)
# check config to see if the hosts file should updated automatically # check if machine is already active
if @machine.config.hostmanager.auto_update return @app.call(env) if @machine.id
# generate temporary hosts file
machines = generate(@machine.env, @machine.provider_name)
# update /etc/hosts file on each active machine # check config to see if the hosts file should be update automatically
machines.each { |machine| update(machine) } return @app.call(env) if !@machine.config.hostmanager.auto_update
end @logger.info 'Updating /etc/hosts file automatically'
# continue the action stack so the machine will be created
@app.call(env) @app.call(env)
# update /etc/hosts file on each active machine
machines = generate(@machine.env, @machine.provider_name)
machines.each { |machine| update(machine) }
end end
end end
end end

View File

@ -2,18 +2,16 @@ module VagrantPlugins
module HostManager module HostManager
class Config < Vagrant.plugin('2', :config) class Config < Vagrant.plugin('2', :config)
attr_accessor :auto_update attr_accessor :auto_update
attr_accessor :ignore_private_ip
def initialize def initialize
@auto_update = false @auto_update = UNSET_VALUE
@ignore_private_ip = UNSET_VALUE
end end
def validate(machine) def finalize!
errors = [] @auto_update = true if @auto_update == UNSET_VALUE
if !(!!@auto_update == @auto_update) @ignore_private_ip = false if @ignore_private_ip == UNSET_VALUE
errors << 'auto_update must be a boolean'
end
{ 'hostmanager' => errors }
end end
end end
end end

View File

@ -1,20 +0,0 @@
module VagrantPlugins
module HostManager
module Helpers
class Translator
def self.plugin_namespace=(val)
@@plugin_namespace = val
end
def initialize(namespace)
@namespace = namespace
end
def t(keys, opts = {})
value = I18n.t("#{@@plugin_namespace}.#{@namespace}.#{keys}", opts)
opts[:progress] == false ? value : value + "..."
end
end
end
end
end

View File

@ -10,10 +10,12 @@ module VagrantPlugins
# define a lambda for looking up a machine's ip address # define a lambda for looking up a machine's ip address
get_ip_address = lambda do |machine| get_ip_address = lambda do |machine|
ip = nil ip = nil
machine.config.vm.networks.each do |network| unless machine.config.hostmanager.ignore_private_ip
key, options = network[0], network[1] machine.config.vm.networks.each do |network|
ip = options[:ip] if key == :private_network key, options = network[0], network[1]
next if ip ip = options[:ip] if key == :private_network
next if ip
end
end end
ip || machine.ssh_info[:host] ip || machine.ssh_info[:host]
end end
@ -43,15 +45,13 @@ module VagrantPlugins
def update(machine) def update(machine)
path = machine.env.tmp_path.join('hosts') path = machine.env.tmp_path.join('hosts')
if machine.communicate.ready? if machine.communicate.ready?
machine.env.ui.info translator.t('update', { :name => machine.name }) machine.env.ui.info I18n.t('vagrant_hostmanager.action.update', {
:name => machine.name
})
machine.communicate.upload(path, '/tmp/hosts') machine.communicate.upload(path, '/tmp/hosts')
machine.communicate.sudo("mv /tmp/hosts /etc/hosts") machine.communicate.sudo("mv /tmp/hosts /etc/hosts")
end end
end end
def translator
Helpers::Translator.new('hosts_file')
end
end end
end end
end end

View File

@ -1,4 +1,3 @@
require 'vagrant-hostmanager/helpers/translator'
require 'vagrant-hostmanager/action/update_hosts_file' require 'vagrant-hostmanager/action/update_hosts_file'
module VagrantPlugins module VagrantPlugins
@ -6,66 +5,27 @@ module VagrantPlugins
class Plugin < Vagrant.plugin('2') class Plugin < Vagrant.plugin('2')
name 'HostManager' name 'HostManager'
description <<-DESC description <<-DESC
This plugin manages the /etc/hosts file for guest machines. A entry is This plugin manages the /etc/hosts file for guest machines. An entry is
created for each active machine using the hostname attribute. created for each active machine using the hostname attribute.
DESC DESC
def self.update(hook)
setup_i18n
setup_logging
hook.append(Action::UpdateHostsFile)
end
config(:hostmanager) do config(:hostmanager) do
require_relative 'config' require_relative 'config'
Config Config
end end
action_hook(:hostmanager_up, :machine_action_up, &method(:update)) action_hook(:hostmanager, :machine_action_up) do |hook|
action_hook(:hostmanger_destroy, :machine_action_destroy, &method(:update)) hook.prepend(Action::UpdateHostsFile)
end
action_hook(:hostmanager, :machine_action_destroy) do |hook|
hook.append(Action::UpdateHostsFile)
end
# TODO remove duplication of i18n and logging setup
command(:hostmanager) do command(:hostmanager) do
setup_i18n
setup_logging
require_relative 'command' require_relative 'command'
Command Command
end end
def self.setup_i18n
I18n.load_path << File.expand_path(
'locales/en.yml',
HostManager.source_root)
I18n.reload!
Helpers::Translator.plugin_namespace = 'vagrant_hostmanager'
end
def self.setup_logging
level = nil
begin
level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
rescue NameError
# This means that the logging constant wasn't found,
# which is fine. We just keep `level` as `nil`. But
# we tell the user.
level = nil
end
# Some constants, such as "true" resolve to booleans, so the
# above error checking doesn't catch it. This will check to make
# sure that the log level is an integer, as Log4r requires.
level = nil if !level.is_a?(Integer)
# Set the logging level on all "vagrant" namespaced
# logs as long as we have a valid level.
if level
logger = Log4r::Logger.new("vagrant_hostmanager")
logger.outputters = Log4r::Outputter.stderr
logger.level = level
logger = nil
end
end
end end
end end
end end

View File

@ -1,5 +1,5 @@
module VagrantPlugins module VagrantPlugins
module HostManager module HostManager
VERSION = '0.0.4' VERSION = '0.1.0'
end end
end end

View File

@ -1,4 +1,4 @@
en: en:
vagrant_hostmanager: vagrant_hostmanager:
hosts_file: action:
update: "[%{name}] Updating /etc/hosts file" update: "[%{name}] Updating /etc/hosts file"

2
test/Vagrantfile vendored
View File

@ -7,6 +7,8 @@ Vagrant.configure('2') do |config|
config.vm.box = 'precise64-chef11.2' config.vm.box = 'precise64-chef11.2'
config.vm.box_url = 'https://opscode-vm.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_chef-11.2.0.box' config.vm.box_url = 'https://opscode-vm.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_chef-11.2.0.box'
config.hostmanager.auto_update = false
config.vm.define :server1 do |server| config.vm.define :server1 do |server|
server.vm.hostname = 'fry' server.vm.hostname = 'fry'
server.vm.network :private_network, :ip => '10.0.5.2' server.vm.network :private_network, :ip => '10.0.5.2'

View File

@ -1,10 +1,6 @@
cd test cd test
vagrant up vagrant up
echo "[server1] /etc/hosts file:"
vagrant ssh server1 -c 'cat /etc/hosts'
echo "[server2] /etc/hosts file:"
vagrant ssh server2 -c 'cat /etc/hosts'
vagrant hostmanager vagrant hostmanager