diff --git a/lib/vagrant.rb b/lib/vagrant.rb index e96bad3bd..2e48f1161 100644 --- a/lib/vagrant.rb +++ b/lib/vagrant.rb @@ -114,16 +114,6 @@ module Vagrant def self.commands @commands ||= Registry.new end - - # Global registry of available host classes and shortcut symbols - # associated with them. - # - # This registry is used to look up the shorcuts for `config.vagrant.host`, - # or to query all hosts for automatically detecting the host system. - # The registry is global to all of Vagrant. - def self.hosts - @hosts ||= Registry.new - end end # # Default I18n to load the en locale @@ -157,13 +147,3 @@ Vagrant.commands.register(:"ssh-config") { Vagrant::Command::SSHConfig } Vagrant.commands.register(:status) { Vagrant::Command::Status } Vagrant.commands.register(:suspend) { Vagrant::Command::Suspend } Vagrant.commands.register(:up) { Vagrant::Command::Up } - -# Register the built-in hosts -Vagrant.hosts.register(:arch) { Vagrant::Hosts::Arch } -Vagrant.hosts.register(:bsd) { Vagrant::Hosts::BSD } -Vagrant.hosts.register(:fedora) { Vagrant::Hosts::Fedora } -Vagrant.hosts.register(:opensuse) { Vagrant::Hosts::OpenSUSE } -Vagrant.hosts.register(:freebsd) { Vagrant::Hosts::FreeBSD } -Vagrant.hosts.register(:gentoo) { Vagrant::Hosts::Gentoo } -Vagrant.hosts.register(:linux) { Vagrant::Hosts::Linux } -Vagrant.hosts.register(:windows) { Vagrant::Hosts::Windows } diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index f4ff7b38c..b4d057725 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -178,7 +178,15 @@ module Vagrant # check is done after the detect check because the symbol check # will return nil, and we don't want to trigger a detect load. host_klass = config.global.vagrant.host - host_klass = Hosts.detect(Vagrant.hosts) if host_klass.nil? || host_klass == :detect + if host_klass.nil? || host_klass == :detect + hosts = {} + Vagrant.plugin("1").registered.each do |plugin| + hosts = hosts.merge(plugin.host.to_hash) + end + + # Get the flattened list of available hosts + host_klass = Hosts.detect(hosts) + end host_klass = Vagrant.hosts.get(host_klass) if host_klass.is_a?(Symbol) # If no host class is detected, we use the base class. diff --git a/lib/vagrant/hosts.rb b/lib/vagrant/hosts.rb index 019c91d95..46cde3e65 100644 --- a/lib/vagrant/hosts.rb +++ b/lib/vagrant/hosts.rb @@ -14,12 +14,13 @@ module Vagrant # This method detects the correct host based on the `match?` methods # implemented in the registered hosts. + # + # @param [Hash] registry Hash mapping key to host class def self.detect(registry) logger = Log4r::Logger.new("vagrant::hosts") # Sort the hosts by their precedence - host_klasses = registry.to_hash.values - host_klasses = host_klasses.sort_by { |a| a.precedence }.reverse + host_klasses = registry.values.sort_by { |a| a.precedence }.reverse logger.debug("Host path search classes: #{host_klasses.inspect}") # Test for matches and return the host class that matches diff --git a/lib/vagrant/plugin/v1.rb b/lib/vagrant/plugin/v1.rb index 179425208..25225cdda 100644 --- a/lib/vagrant/plugin/v1.rb +++ b/lib/vagrant/plugin/v1.rb @@ -72,6 +72,20 @@ module Vagrant data[:guests] end + # Defines an additionally available host implementation with + # the given key. + # + # @param [String] name Name of the host. + def self.host(name=UNSET_VALUE, &block) + data[:hosts] ||= Registry.new + + # Register a new host class only if a name was given + data[:hosts].register(name.to_sym, &block) if name != UNSET_VALUE + + # Return the registry + data[:hosts] + end + # Registers additional provisioners to be available. # # @param [String] name Name of the provisioner. diff --git a/lib/vagrant/hosts/arch.rb b/plugins/host_arch/host.rb similarity index 92% rename from lib/vagrant/hosts/arch.rb rename to plugins/host_arch/host.rb index da52effeb..66034e5a0 100644 --- a/lib/vagrant/hosts/arch.rb +++ b/plugins/host_arch/host.rb @@ -1,6 +1,6 @@ -module Vagrant - module Hosts - class Arch < Linux +module VagrantPlugins + module HostArch + class Host < VagrantPlugins::HostLinux::Host def self.match? File.exist?("/etc/rc.conf") && File.exist?("/etc/pacman.conf") end diff --git a/plugins/host_arch/plugin.rb b/plugins/host_arch/plugin.rb new file mode 100644 index 000000000..204d89929 --- /dev/null +++ b/plugins/host_arch/plugin.rb @@ -0,0 +1,14 @@ +require "vagrant" + +module VagrantPlugins + module HostArch + autoload :Host, File.expand_path("../host", __FILE__) + + class Plugin < Vagrant.plugin("1") + name "Arch host" + description "Arch host support." + + host("arch") { Host } + end + end +end diff --git a/lib/vagrant/hosts/bsd.rb b/plugins/host_bsd/host.rb similarity index 92% rename from lib/vagrant/hosts/bsd.rb rename to plugins/host_bsd/host.rb index 6d7163d45..91b0a208b 100644 --- a/lib/vagrant/hosts/bsd.rb +++ b/plugins/host_bsd/host.rb @@ -2,15 +2,15 @@ require 'log4r' require 'vagrant/util/platform' -module Vagrant - module Hosts +module VagrantPlugins + module HostBSD # Represents a BSD host, such as FreeBSD and Darwin (Mac OS X). - class BSD < Base - include Util - include Util::Retryable + class Host < Vagrant::Hosts::Base + include Vagrant::Util + include Vagrant::Util::Retryable def self.match? - Util::Platform.darwin? || Util::Platform.bsd? + Vagrant::Util::Platform.darwin? || Vagrant::Util::Platform.bsd? end def self.precedence diff --git a/plugins/host_bsd/plugin.rb b/plugins/host_bsd/plugin.rb new file mode 100644 index 000000000..4ba7a0ec9 --- /dev/null +++ b/plugins/host_bsd/plugin.rb @@ -0,0 +1,14 @@ +require "vagrant" + +module VagrantPlugins + module HostBSD + autoload :Host, File.expand_path("../host", __FILE__) + + class Plugin < Vagrant.plugin("1") + name "BSD host" + description "BSD host support." + + host("bsd") { Host } + end + end +end diff --git a/lib/vagrant/hosts/fedora.rb b/plugins/host_fedora/host.rb similarity index 80% rename from lib/vagrant/hosts/fedora.rb rename to plugins/host_fedora/host.rb index 1d2f17756..9929b87e1 100644 --- a/lib/vagrant/hosts/fedora.rb +++ b/plugins/host_fedora/host.rb @@ -1,8 +1,8 @@ -require 'pathname' +require "pathname" -module Vagrant - module Hosts - class Fedora < Linux +module VagrantPlugins + module HostFedora + class Host < VagrantPlugins::HostLinux::Host def self.match? release_file = Pathname.new("/etc/redhat-release") diff --git a/plugins/host_fedora/plugin.rb b/plugins/host_fedora/plugin.rb new file mode 100644 index 000000000..7ac2c2a42 --- /dev/null +++ b/plugins/host_fedora/plugin.rb @@ -0,0 +1,14 @@ +require "vagrant" + +module VagrantPlugins + module HostFedora + autoload :Host, File.expand_path("../host", __FILE__) + + class Plugin < Vagrant.plugin("1") + name "Fedora host" + description "Fedora host support." + + host("fedora") { Host } + end + end +end diff --git a/lib/vagrant/hosts/freebsd.rb b/plugins/host_freebsd/host.rb similarity index 71% rename from lib/vagrant/hosts/freebsd.rb rename to plugins/host_freebsd/host.rb index 52abbe252..0753b9121 100644 --- a/lib/vagrant/hosts/freebsd.rb +++ b/plugins/host_freebsd/host.rb @@ -1,18 +1,17 @@ require 'vagrant/util/platform' -module Vagrant - module Hosts - # Represents a FreeBSD host - class FreeBSD < BSD - class FreeBSDHostError < Errors::VagrantError +module VagrantPlugins + module HostFreeBSD + class Host < VagrantPlugins::HostBSD::Host + class FreeBSDHostError < Vagrant::Errors::VagrantError error_namespace("vagrant.hosts.freebsd") end - include Util - include Util::Retryable + include Vagrant::Util + include Vagrant::Util::Retryable def self.match? - Util::Platform.freebsd? + Vagrant::Util::Platform.freebsd? end # Normal, mid-range precedence. diff --git a/plugins/host_freebsd/plugin.rb b/plugins/host_freebsd/plugin.rb new file mode 100644 index 000000000..bbb501723 --- /dev/null +++ b/plugins/host_freebsd/plugin.rb @@ -0,0 +1,14 @@ +require "vagrant" + +module VagrantPlugins + module HostFreeBSD + autoload :Host, File.expand_path("../host", __FILE__) + + class Plugin < Vagrant.plugin("1") + name "FreeBSD host" + description "FreeBSD host support." + + host("freebsd") { Host } + end + end +end diff --git a/lib/vagrant/hosts/gentoo.rb b/plugins/host_gentoo/host.rb similarity index 75% rename from lib/vagrant/hosts/gentoo.rb rename to plugins/host_gentoo/host.rb index d91b211bb..d5c994c64 100644 --- a/lib/vagrant/hosts/gentoo.rb +++ b/plugins/host_gentoo/host.rb @@ -1,6 +1,6 @@ -module Vagrant - module Hosts - class Gentoo < Linux +module VagrantPlugins + module HostGentoo + class Host < VagrantPlugins::HostLinux::Host def self.match? return File.exists?("/etc/gentoo-release") end diff --git a/plugins/host_gentoo/plugin.rb b/plugins/host_gentoo/plugin.rb new file mode 100644 index 000000000..efdf5b29f --- /dev/null +++ b/plugins/host_gentoo/plugin.rb @@ -0,0 +1,14 @@ +require "vagrant" + +module VagrantPlugins + module HostGentoo + autoload :Host, File.expand_path("../host", __FILE__) + + class Plugin < Vagrant.plugin("1") + name "Gentoo host" + description "Gentoo host support." + + host("gentoo") { Host } + end + end +end diff --git a/lib/vagrant/hosts/linux.rb b/plugins/host_linux/host.rb similarity index 93% rename from lib/vagrant/hosts/linux.rb rename to plugins/host_linux/host.rb index 105e654ae..210cced34 100644 --- a/lib/vagrant/hosts/linux.rb +++ b/plugins/host_linux/host.rb @@ -2,15 +2,15 @@ require 'log4r' require 'vagrant/util/platform' -module Vagrant - module Hosts +module VagrantPlugins + module HostLinux # Represents a Linux based host, such as Ubuntu. - class Linux < Base - include Util - include Util::Retryable + class Host < Vagrant::Hosts::Base + include Vagrant::Util + include Vagrant::Util::Retryable def self.match? - Util::Platform.linux? + Vagrant::Util::Platform.linux? end def self.precedence diff --git a/plugins/host_linux/plugin.rb b/plugins/host_linux/plugin.rb new file mode 100644 index 000000000..7e1029831 --- /dev/null +++ b/plugins/host_linux/plugin.rb @@ -0,0 +1,14 @@ +require "vagrant" + +module VagrantPlugins + module HostLinux + autoload :Host, File.expand_path("../host", __FILE__) + + class Plugin < Vagrant.plugin("1") + name "Linux host" + description "Linux host support." + + host("linux") { Host } + end + end +end diff --git a/lib/vagrant/hosts/opensuse.rb b/plugins/host_opensuse/host.rb similarity index 80% rename from lib/vagrant/hosts/opensuse.rb rename to plugins/host_opensuse/host.rb index 27ab73eac..59dddc165 100644 --- a/lib/vagrant/hosts/opensuse.rb +++ b/plugins/host_opensuse/host.rb @@ -1,8 +1,8 @@ -require 'pathname' +require "pathname" -module Vagrant - module Hosts - class OpenSUSE < Linux +module VagrantPlugins + module HostOpenSUSE + class Host < VagrantPlugins::HostLinux::Host def self.match? release_file = Pathname.new("/etc/SuSE-release") diff --git a/plugins/host_opensuse/plugin.rb b/plugins/host_opensuse/plugin.rb new file mode 100644 index 000000000..2e49a5f79 --- /dev/null +++ b/plugins/host_opensuse/plugin.rb @@ -0,0 +1,14 @@ +require "vagrant" + +module VagrantPlugins + module HostOpenSUSE + autoload :Host, File.expand_path("../host", __FILE__) + + class Plugin < Vagrant.plugin("1") + name "OpenSUSE host" + description "OpenSUSE host support." + + host("opensuse") { Host } + end + end +end diff --git a/lib/vagrant/hosts/windows.rb b/plugins/host_windows/host.rb similarity index 56% rename from lib/vagrant/hosts/windows.rb rename to plugins/host_windows/host.rb index 3f2afffef..e65a11d1e 100644 --- a/lib/vagrant/hosts/windows.rb +++ b/plugins/host_windows/host.rb @@ -1,10 +1,10 @@ require 'vagrant/util/platform' -module Vagrant - module Hosts - class Windows < Base +module VagrantPlugins + module HostWindows + class Host < Vagrant::Hosts::Base def self.match? - Util::Platform.windows? + Vagrant::Util::Platform.windows? end # Windows does not support NFS diff --git a/plugins/host_windows/plugin.rb b/plugins/host_windows/plugin.rb new file mode 100644 index 000000000..4c338e988 --- /dev/null +++ b/plugins/host_windows/plugin.rb @@ -0,0 +1,14 @@ +require "vagrant" + +module VagrantPlugins + module HostWindows + autoload :Host, File.expand_path("../host", __FILE__) + + class Plugin < Vagrant.plugin("1") + name "Windows host" + description "Windows host support." + + host("windows") { Host } + end + end +end diff --git a/test/unit/vagrant/hosts_test.rb b/test/unit/vagrant/hosts_test.rb index 60fe6ff68..c046b37e3 100644 --- a/test/unit/vagrant/hosts_test.rb +++ b/test/unit/vagrant/hosts_test.rb @@ -1,7 +1,7 @@ require File.expand_path("../../base", __FILE__) describe Vagrant::Hosts do - let(:registry) { Vagrant::Registry.new } + let(:registry) { Hash.new } it "detects the host that matches true" do foo_klass = Class.new(Vagrant::Hosts::Base) do @@ -12,8 +12,8 @@ describe Vagrant::Hosts do def self.match?; true; end end - registry.register(:foo, foo_klass) - registry.register(:bar, bar_klass) + registry[:foo] = foo_klass + registry[:bar] = bar_klass described_class.detect(registry).should == bar_klass end @@ -28,8 +28,8 @@ describe Vagrant::Hosts do def self.precedence; 9; end end - registry.register(:foo, foo_klass) - registry.register(:bar, bar_klass) + registry[:foo] = foo_klass + registry[:bar] = bar_klass described_class.detect(registry).should == bar_klass end diff --git a/test/unit/vagrant/plugin/v1_test.rb b/test/unit/vagrant/plugin/v1_test.rb index ab513f030..4e0671305 100644 --- a/test/unit/vagrant/plugin/v1_test.rb +++ b/test/unit/vagrant/plugin/v1_test.rb @@ -60,8 +60,8 @@ describe Vagrant::Plugin::V1 do plugin.guest[:foo].should == "bar" end - it "should lazily register configuration classes" do - # Below would raise an error if the value of the config class was + it "should lazily register guest classes" do + # Below would raise an error if the value of the guest class was # evaluated immediately. By asserting that this does not raise an # error, we verify that the value is actually lazily loaded plugin = nil @@ -71,7 +71,7 @@ describe Vagrant::Plugin::V1 do end }.to_not raise_error - # Now verify when we actually get the configuration key that + # Now verify when we actually get the guest key that # a proper error is raised. expect { plugin.guest[:foo] @@ -79,6 +79,34 @@ describe Vagrant::Plugin::V1 do end end + describe "hosts" do + it "should register host classes" do + plugin = Class.new(described_class) do + host("foo") { "bar" } + end + + plugin.host[:foo].should == "bar" + end + + it "should lazily register host classes" do + # Below would raise an error if the value of the host class was + # evaluated immediately. By asserting that this does not raise an + # error, we verify that the value is actually lazily loaded + plugin = nil + expect { + plugin = Class.new(described_class) do + host("foo") { raise StandardError, "FAIL!" } + end + }.to_not raise_error + + # Now verify when we actually get the host key that + # a proper error is raised. + expect { + plugin.host[:foo] + }.to raise_error(StandardError) + end + end + describe "provisioners" do it "should register provisioner classes" do plugin = Class.new(described_class) do diff --git a/test/unit/vagrant_test.rb b/test/unit/vagrant_test.rb index a1116498e..8363a3505 100644 --- a/test/unit/vagrant_test.rb +++ b/test/unit/vagrant_test.rb @@ -9,10 +9,6 @@ describe Vagrant do described_class.commands.should be_a(Vagrant::Registry) end - it "has a registry for hosts" do - described_class.hosts.should be_a(Vagrant::Registry) - end - describe "plugin superclass" do it "returns the proper class for version 1" do described_class.plugin("1").should == Vagrant::Plugin::V1