diff --git a/README.md b/README.md index 62f487f..0f11188 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,10 @@ to true. 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. +When using include_offline set to true, only boxes that are up or have a +private ip configured will be added to the hosts file. You will receive a +warning on skipped boxes. + In addition, the `hostmanager.aliases` configuration attribute can be used to provide aliases for your host names. @@ -49,6 +53,7 @@ Example configuration: Vagrant.configure("2") do |config| config.hostmanager.enabled = true config.hostmanager.ignore_private_ip = false + config.hostmanager.include_offline = true config.vm.define "example-box" do |node| node.vm.hostname = "example-box-hostname" node.vm.network :private_network, ip: "192.168.42.42" @@ -57,6 +62,17 @@ Vagrant.configure("2") do |config| end ``` +As a last option, you can also choose hostmanager as a provisioner. +This allows you to use the provisioning order to ensure that hostmanager +runs before or after provisioning. The provisioner will collect hosts from +boxes with the same provider as the running box. + +Use: + +```ruby +config.vm.provision :hostmanager +``` + Contribute ---------- Contributions are welcome. diff --git a/lib/vagrant-hostmanager/command.rb b/lib/vagrant-hostmanager/command.rb index 7b886fb..52a0078 100644 --- a/lib/vagrant-hostmanager/command.rb +++ b/lib/vagrant-hostmanager/command.rb @@ -8,6 +8,8 @@ module VagrantPlugins opts = OptionParser.new do |o| o.banner = 'Usage: vagrant hostmanager [vm-name]' o.separator '' + o.version = VagrantPlugins::HostManager::VERSION + o.program_name = 'vagrant hostmanager' o.on('--provider provider', String, 'Update machines with the specific provider.') do |provider| @@ -16,6 +18,8 @@ module VagrantPlugins end argv = parse_options(opts) + return if !argv + options[:provider] ||= @env.default_provider with_target_vms(argv, options) do |machine| diff --git a/lib/vagrant-hostmanager/config.rb b/lib/vagrant-hostmanager/config.rb index cb5aace..e537d06 100644 --- a/lib/vagrant-hostmanager/config.rb +++ b/lib/vagrant-hostmanager/config.rb @@ -5,46 +5,68 @@ module VagrantPlugins attr_accessor :manage_local attr_accessor :ignore_private_ip attr_accessor :aliases + attr_accessor :include_offline alias_method :enabled?, :enabled + alias_method :include_offline?, :include_offline def initialize @enabled = false @manage_local = true @ignore_private_ip = UNSET_VALUE @aliases = Array.new + @include_offline = false end def finalize! @ignore_private_ip = false if @ignore_private_ip == UNSET_VALUE + @aliases = [ @aliases ].flatten end def validate(machine) errors = Array.new # check if enabled option is either true or false - if ![TrueClass, FalseClass].include?(enabled.class) - errors << "A value for hostmanager.enabled can be true or false." - end + errors << validate_bool('hostmanager.enabled', enabled) + + # check if include_offline is either true or false + errors << validate_bool('hostmanager.include_offline', include_offline) # check if manage_local option is either true or false if ![TrueClass, FalseClass].include?(manage_local.class) errors << "A value for hostmanager.manage_local can be true or false." end - # check if ignore_private_ip option is either true or false - if ![TrueClass, FalseClass].include?(ignore_private_ip.class) && - @ignore_private_ip != UNSET_VALUE - errors << "A value for hostmanager.ignore_private_ip can be true or false." + # check if ignore_private_ip option is either true or false (or UNSET_VALUE) + if @ignore_private_ip != UNSET_VALUE + errors << validate_bool('hostmanager.ignore_private_ip', ignore_private_ip) end # check if aliases option is an Array - if !machine.config.hostmanager.aliases.kind_of?(Array) - errors << "A value for hostmanager.aliases must be an Array." + if !machine.config.hostmanager.aliases.kind_of?(Array) and + !machine.config.hostmanager.aliases.kind_of?(String) + errors << I18n.t('vagrant_hostmanager.config.not_an_array_or_string', { + :config_key => 'hostmanager.aliases', + :is_class => aliases.class.to_s, + }) end + errors.compact! { "HostManager configuration" => errors } end + + private + def validate_bool(key, value) + if ![TrueClass, FalseClass].include?(value.class) + I18n.t('vagrant_hostmanager.config.not_a_bool', { + :config_key => key, + :value => value.class.to_s, + }) + else + nil + end + end + end end end diff --git a/lib/vagrant-hostmanager/hosts_file.rb b/lib/vagrant-hostmanager/hosts_file.rb index 6330de8..508ff82 100644 --- a/lib/vagrant-hostmanager/hosts_file.rb +++ b/lib/vagrant-hostmanager/hosts_file.rb @@ -69,7 +69,7 @@ module VagrantPlugins next if ip end end - ip || machine.ssh_info[:host] + ip || (machine.ssh_info ? machine.ssh_info[:host] : nil) end def update_entry(machine,file_name,sudo=false) @@ -147,6 +147,30 @@ module VagrantPlugins machine.communicate.sudo("mv /tmp/hosts /etc/hosts") end end + + private + # Either use the active machines, or loop over all available machines and + # get those with the same provider (aka, ignore boxes that throw MachineNotFound errors). + # + # Returns an array with the same structure as env.active_machines: + # [ [:machine, :virtualbox], [:foo, :virtualbox] ] + def get_machines(env, provider) + if env.config_global.hostmanager.include_offline? + machines = [] + env.machine_names.each do |name| + begin + m = env.machine(name, provider) + machines << [name, provider] + rescue Vagrant::Errors::MachineNotFound => ex + # ignore this box. + end + end + machines + else + env.active_machines + end + end + end end end diff --git a/lib/vagrant-hostmanager/plugin.rb b/lib/vagrant-hostmanager/plugin.rb index f0af8d7..7323544 100644 --- a/lib/vagrant-hostmanager/plugin.rb +++ b/lib/vagrant-hostmanager/plugin.rb @@ -10,6 +10,8 @@ module VagrantPlugins description <<-DESC This plugin manages the /etc/hosts file for guest machines. An entry is created for each active machine using the hostname attribute. + + You can also use the hostmanager provisioner to update the hosts file. DESC config(:hostmanager) do @@ -31,6 +33,11 @@ module VagrantPlugins hook.append(Action::DeleteGuests) end + provisioner(:hostmanager) do + require_relative 'provisioner' + Provisioner + end + command(:hostmanager) do require_relative 'command' Command diff --git a/lib/vagrant-hostmanager/provisioner.rb b/lib/vagrant-hostmanager/provisioner.rb new file mode 100644 index 0000000..65d43db --- /dev/null +++ b/lib/vagrant-hostmanager/provisioner.rb @@ -0,0 +1,12 @@ +module VagrantPlugins + module HostManager + class Provisioner < Vagrant.plugin('2', :provisioner) + include HostsFile + + def provision + generate(@machine.env, @machine.box.provider.to_sym) + update(@machine) + end + end + end +end diff --git a/lib/vagrant-hostmanager/version.rb b/lib/vagrant-hostmanager/version.rb index dc96dc4..bf8a05a 100644 --- a/lib/vagrant-hostmanager/version.rb +++ b/lib/vagrant-hostmanager/version.rb @@ -1,5 +1,5 @@ module VagrantPlugins module HostManager - VERSION = '0.2.0' + VERSION = '0.4.0' end end diff --git a/locales/en.yml b/locales/en.yml index 7bcb324..e27083b 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -4,3 +4,9 @@ en: update_guest: "[%{name}] Updating /etc/hosts file" update_host: "Updating local /etc/hosts file" run_sudo: "Running sudo to modify host machine's /etc/hosts file" + add_host: "Adding /etc/hosts entry: %{ip} %{host} %{aliases}" + host_no_ip: "Could not determine ip for machine '%{name}': no private ip configured or machine not up." + update: "[%{name}] Updating /etc/hosts file" + config: + not_a_bool: "A value for %{config_key} can only be true or false, not type '%{value}'" + not_an_array_or_string: "A value for %{config_key} must be an Array or String, not type '%{is_class}'"