diff --git a/lib/vagrant/action.rb b/lib/vagrant/action.rb index d13b6d105..627be5ab2 100644 --- a/lib/vagrant/action.rb +++ b/lib/vagrant/action.rb @@ -16,6 +16,7 @@ module Vagrant autoload :DestroyConfirm, "vagrant/action/builtin/destroy_confirm" autoload :EnvSet, "vagrant/action/builtin/env_set" autoload :GracefulHalt, "vagrant/action/builtin/graceful_halt" + autoload :HandleBox, "vagrant/action/builtin/handle_box" autoload :HandleBoxUrl, "vagrant/action/builtin/handle_box_url" autoload :HandleForwardedPortCollisions, "vagrant/action/builtin/handle_forwarded_port_collisions" autoload :Lock, "vagrant/action/builtin/lock" diff --git a/lib/vagrant/action/builtin/handle_box.rb b/lib/vagrant/action/builtin/handle_box.rb new file mode 100644 index 000000000..932125798 --- /dev/null +++ b/lib/vagrant/action/builtin/handle_box.rb @@ -0,0 +1,131 @@ +require "thread" + +require "log4r" + +module Vagrant + module Action + module Builtin + # This built-in middleware handles the `box` setting by verifying + # the box is already installed, dowloading the box if it isn't, + # updating the box if it is requested, etc. + class HandleBox + @@big_lock = Mutex.new + @@small_locks = Hash.new { |h,k| h[k] = Mutex.new } + + def initialize(app, env) + @app = app + @logger = Log4r::Logger.new("vagrant::action::builtin::handle_box") + end + + def call(env) + machine = env[:machine] + + if !machine.config.vm.box + @logger.info("Skipping HandleBox because no box is set") + return @app.call(env) + end + + # Acquire a lock for this box to handle multi-threaded + # environments. + lock = nil + @@big_lock.synchronize do + lock = @@small_locks[machine.config.vm.box] + end + + lock.synchronize do + if !machine.config.vm.box_url + handle_metadata_box(env) + else + handle_direct_box(env) + end + end + + @app.call(env) + end + + def handle_direct_box(env) + end + + def handle_metadata_box(env) + end + +=begin + def call(env) + if !env[:machine].config.vm.box || !env[:machine].config.vm.box_url + @logger.info("Skipping HandleBoxUrl because box or box_url not set.") + @app.call(env) + return + end + + if env[:machine].box + @logger.info("Skipping HandleBoxUrl because box is already available") + @app.call(env) + return + end + + # Get a "big lock" to make sure that our more fine grained + # lock access is thread safe. + lock = nil + @@big_lock.synchronize do + lock = @@handle_box_url_locks[env[:machine].config.vm.box] + end + + box_name = env[:machine].config.vm.box + box_url = env[:machine].config.vm.box_url + box_download_ca_cert = env[:machine].config.vm.box_download_ca_cert + box_download_checksum = env[:machine].config.vm.box_download_checksum + box_download_checksum_type = env[:machine].config.vm.box_download_checksum_type + box_download_client_cert = env[:machine].config.vm.box_download_client_cert + box_download_insecure = env[:machine].config.vm.box_download_insecure + + # Expand the CA cert file relative to the Vagrantfile path, if + # there is one. + if box_download_ca_cert + box_download_ca_cert = File.expand_path( + box_download_ca_cert, env[:machine].env.root_path) + end + + lock.synchronize do + # Check that we don't already have the box, which can happen + # if we're slow to acquire the lock because of another thread + box_formats = env[:machine].provider_options[:box_format] || + env[:machine].provider_name + if env[:box_collection].find(box_name, box_formats) + break + end + + # Add the box then reload the box collection so that it becomes + # aware of it. + env[:ui].info I18n.t( + "vagrant.actions.vm.check_box.not_found", + :name => box_name, + :provider => env[:machine].provider_name) + + begin + env[:action_runner].run(Vagrant::Action.action_box_add, { + :box_checksum => box_download_checksum, + :box_checksum_type => box_download_checksum_type, + :box_client_cert => box_download_client_cert, + :box_download_ca_cert => box_download_ca_cert, + :box_download_insecure => box_download_insecure, + :box_name => box_name, + :box_provider => box_formats, + :box_url => box_url, + }) + rescue Errors::BoxAlreadyExists + # Just ignore this, since it means the next part will succeed! + # This can happen in a multi-threaded environment. + end + end + + # Reload the environment and set the VM to be the new loaded VM. + env[:machine] = env[:machine].env.machine( + env[:machine].name, env[:machine].provider_name, true) + + @app.call(env) + end +=end + end + end + end +end diff --git a/lib/vagrant/box_collection.rb b/lib/vagrant/box_collection.rb index a108d84d3..c299ab162 100644 --- a/lib/vagrant/box_collection.rb +++ b/lib/vagrant/box_collection.rb @@ -245,18 +245,24 @@ module Vagrant return nil end - box_directory.children(true).each do |versiondir| + versions = box_directory.children(true).map do |versiondir| version = versiondir.basename.to_s - if !requirements.all? { |r| r.satisfied_by?(Gem::Version.new(version)) } + Gem::Version.new(version) + end + + # Traverse through versions with the latest version first + versions.sort.reverse.each do |v| + if !requirements.all? { |r| r.satisfied_by?(v) } # Unsatisfied version requirements next end + versiondir = box_directory.join(v.to_s) providers.each do |provider| provider_dir = versiondir.join(provider.to_s) next if !provider_dir.directory? @logger.info("Box found: #{name} (#{provider})") - return Box.new(name, provider, version, provider_dir) + return Box.new(name, provider, v.to_s, provider_dir) end end end diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index dff913c39..db0d79812 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -349,8 +349,7 @@ module Vagrant box = nil if config.vm.box begin - # TODO: support real version constraints - box = boxes.find(config.vm.box, box_formats, ">= 0") + box = boxes.find(config.vm.box, box_formats, config.vm.box_version) rescue Errors::BoxUpgradeRequired # Upgrade the box if we must @logger.info("Upgrading box during config load: #{config.vm.box}") diff --git a/plugins/kernel_v2/config/vm.rb b/plugins/kernel_v2/config/vm.rb index 1e92f68f3..55d8dc752 100644 --- a/plugins/kernel_v2/config/vm.rb +++ b/plugins/kernel_v2/config/vm.rb @@ -18,6 +18,7 @@ module VagrantPlugins attr_accessor :boot_timeout attr_accessor :box attr_accessor :box_url + attr_accessor :box_version attr_accessor :box_download_ca_cert attr_accessor :box_download_checksum attr_accessor :box_download_checksum_type @@ -38,6 +39,7 @@ module VagrantPlugins @box_download_client_cert = UNSET_VALUE @box_download_insecure = UNSET_VALUE @box_url = UNSET_VALUE + @box_version = UNSET_VALUE @graceful_halt_timeout = UNSET_VALUE @guest = UNSET_VALUE @hostname = UNSET_VALUE @@ -309,6 +311,7 @@ module VagrantPlugins @box_download_client_cert = nil if @box_download_client_cert == UNSET_VALUE @box_download_insecure = false if @box_download_insecure == UNSET_VALUE @box_url = nil if @box_url == UNSET_VALUE + @box_version = ">= 0" if @box_version == UNSET_VALUE @graceful_halt_timeout = 60 if @graceful_halt_timeout == UNSET_VALUE @guest = nil if @guest == UNSET_VALUE @hostname = nil if @hostname == UNSET_VALUE @@ -449,11 +452,20 @@ module VagrantPlugins def validate(machine) errors = _detected_errors errors << I18n.t("vagrant.config.vm.box_missing") if !box - errors << I18n.t("vagrant.config.vm.box_not_found", :name => box) if \ - box && !box_url && !machine.box errors << I18n.t("vagrant.config.vm.hostname_invalid_characters") if \ @hostname && @hostname !~ /^[a-z0-9][-.a-z0-9]+$/i + if @box_version + @box_version.split(",").each do |v| + begin + Gem::Requirement.new(v.strip) + rescue Gem::Requirement::BadRequirementError + errors << I18n.t( + "vagrant.config.vm.bad_version", version: v) + end + end + end + if box_download_ca_cert path = Pathname.new(box_download_ca_cert). expand_path(machine.env.root_path) diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 4ec7ade1f..044c649ff 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -950,6 +950,8 @@ en: ssh: private_key_missing: "`private_key_path` file must exist: %{path}" vm: + bad_version: |- + Invalid box version constraints: %{version} box_download_ca_cert_not_found: |- "box_download_ca_cert" file not found: %{path} box_download_checksum_blank: |- @@ -957,7 +959,6 @@ en: box_download_checksum_notblank: |- Checksum specified but must also specify "box_download_checksum_type" box_missing: "A box must be specified." - box_not_found: "The box '%{name}' could not be found." hostname_invalid_characters: |- The hostname set for the VM should only contain letters, numbers, hyphens or dots. It cannot start with a hyphen or dot. diff --git a/test/unit/plugins/kernel_v2/config/vm_test.rb b/test/unit/plugins/kernel_v2/config/vm_test.rb index 99afefdab..9eaf0473c 100644 --- a/test/unit/plugins/kernel_v2/config/vm_test.rb +++ b/test/unit/plugins/kernel_v2/config/vm_test.rb @@ -5,6 +5,26 @@ require Vagrant.source_root.join("plugins/kernel_v2/config/vm") describe VagrantPlugins::Kernel_V2::VMConfig do subject { described_class.new } + let(:machine) { double("machine") } + + def assert_valid + errors = subject.validate(machine) + if !errors.values.all? { |v| v.empty? } + raise "Errors: #{errors.inspect}" + end + end + + before do + machine.stub(provider_config: nil) + + subject.box = "foo" + end + + it "is valid with test defaults" do + subject.finalize! + assert_valid + end + describe "#base_mac" do it "defaults properly" do subject.finalize! @@ -19,6 +39,28 @@ describe VagrantPlugins::Kernel_V2::VMConfig do end end + context "#box_version" do + it "defaults to >= 0" do + subject.finalize! + + expect(subject.box_version).to eq(">= 0") + end + + it "errors if invalid version" do + subject.box_version = "nope" + subject.finalize! + + expect { assert_valid }.to raise_error(RuntimeError) + end + + it "can have complex constraints" do + subject.box_version = ">= 0, ~> 1.0" + subject.finalize! + + assert_valid + end + end + describe "#network(s)" do it "defaults to forwarding SSH" do subject.finalize! diff --git a/test/unit/vagrant/action/builtin/handle_box_test.rb b/test/unit/vagrant/action/builtin/handle_box_test.rb new file mode 100644 index 000000000..510ab0368 --- /dev/null +++ b/test/unit/vagrant/action/builtin/handle_box_test.rb @@ -0,0 +1,31 @@ +require File.expand_path("../../../../base", __FILE__) + +describe Vagrant::Action::Builtin::HandleBox do + include_context "unit" + + let(:app) { lambda { |env| } } + let(:env) { { + machine: machine, + ui: Vagrant::UI::Silent.new, + } } + + subject { described_class.new(app, env) } + + let(:iso_env) do + # We have to create a Vagrantfile so there is a root path + env = isolated_environment + env.vagrantfile("") + env.create_vagrant_env + end + + let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) } + + it "works if there is no box set" do + machine.config.vm.box = nil + machine.config.vm.box_url = nil + + app.should_receive(:call).with(env) + + subject.call(env) + end +end diff --git a/test/unit/vagrant/box_collection_test.rb b/test/unit/vagrant/box_collection_test.rb index 6a83f847d..d2ac1dac1 100644 --- a/test/unit/vagrant/box_collection_test.rb +++ b/test/unit/vagrant/box_collection_test.rb @@ -58,6 +58,19 @@ describe Vagrant::BoxCollection do expect(result.name).to eq("foo") end + it "returns latest version matching constraint" do + # Create the "box" + environment.box3("foo", "1.0", :virtualbox) + environment.box3("foo", "1.5", :virtualbox) + + # Actual test + result = subject.find("foo", :virtualbox, ">= 0") + expect(result).to_not be_nil + expect(result).to be_kind_of(box_class) + expect(result.name).to eq("foo") + expect(result.version).to eq("1.5") + end + it "can satisfy complex constraints" do # Create the "box" environment.box3("foo", "0.1", :virtualbox) diff --git a/test/unit/vagrant/environment_test.rb b/test/unit/vagrant/environment_test.rb index 5dadef024..2e7758dcd 100644 --- a/test/unit/vagrant/environment_test.rb +++ b/test/unit/vagrant/environment_test.rb @@ -194,6 +194,334 @@ describe Vagrant::Environment do end end + describe "#machine" do + # A helper to register a provider for use in tests. + def register_provider(name, config_class=nil, options=nil) + provider_cls = Class.new(Vagrant.plugin("2", :provider)) + + register_plugin("2") do |p| + p.provider(name, options) { provider_cls } + + if config_class + p.config(name, :provider) { config_class } + end + end + + provider_cls + end + + it "should return a machine object with the correct provider" do + # Create a provider + foo_provider = register_provider("foo") + + # Create the configuration + isolated_env = isolated_environment do |e| + e.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "base" + config.vm.define "foo" +end +VF + + e.box3("base", "1.0", :foo) + end + + # Verify that we can get the machine + env = isolated_env.create_vagrant_env + machine = env.machine(:foo, :foo) + machine.should be_kind_of(Vagrant::Machine) + machine.name.should == :foo + machine.provider.should be_kind_of(foo_provider) + machine.provider_config.should be_nil + end + + it "should return a machine object with the machine configuration" do + # Create a provider + foo_config = Class.new(Vagrant.plugin("2", :config)) do + attr_accessor :value + end + + foo_provider = register_provider("foo", foo_config) + + # Create the configuration + isolated_env = isolated_environment do |e| + e.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "base" + config.vm.define "foo" + + config.vm.provider :foo do |fooconfig| + fooconfig.value = 100 + end +end +VF + + e.box3("base", "1.0", :foo) + end + + # Verify that we can get the machine + env = isolated_env.create_vagrant_env + machine = env.machine(:foo, :foo) + machine.should be_kind_of(Vagrant::Machine) + machine.name.should == :foo + machine.provider.should be_kind_of(foo_provider) + machine.provider_config.value.should == 100 + end + + it "should cache the machine objects by name and provider" do + # Create a provider + foo_provider = register_provider("foo") + bar_provider = register_provider("bar") + + # Create the configuration + isolated_env = isolated_environment do |e| + e.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "base" + config.vm.define "vm1" + config.vm.define "vm2" +end +VF + + e.box3("base", "1.0", :foo) + e.box3("base", "1.0", :bar) + end + + env = isolated_env.create_vagrant_env + vm1_foo = env.machine(:vm1, :foo) + vm1_bar = env.machine(:vm1, :bar) + vm2_foo = env.machine(:vm2, :foo) + + vm1_foo.should eql(env.machine(:vm1, :foo)) + vm1_bar.should eql(env.machine(:vm1, :bar)) + vm1_foo.should_not eql(vm1_bar) + vm2_foo.should eql(env.machine(:vm2, :foo)) + end + + it "should load a machine without a box" do + register_provider("foo") + + environment = isolated_environment do |env| + env.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "i-dont-exist" +end +VF + end + + env = environment.create_vagrant_env + machine = env.machine(:default, :foo) + machine.box.should be_nil + end + + it "should load the machine configuration" do + register_provider("foo") + + environment = isolated_environment do |env| + env.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.ssh.port = 1 + config.vm.box = "base" + + config.vm.define "vm1" do |inner| + inner.ssh.port = 100 + end +end +VF + + env.box3("base", "1.0", :foo) + end + + env = environment.create_vagrant_env + machine = env.machine(:vm1, :foo) + machine.config.ssh.port.should == 100 + machine.config.vm.box.should == "base" + end + + it "should load the box configuration for a box" do + register_provider("foo") + + environment = isolated_environment do |env| + env.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "base" +end +VF + + env.box3("base", "1.0", :foo, :vagrantfile => <<-VF) +Vagrant.configure("2") do |config| + config.ssh.port = 100 +end +VF + end + + env = environment.create_vagrant_env + machine = env.machine(:default, :foo) + machine.config.ssh.port.should == 100 + end + + it "should load the box configuration for a box and custom Vagrantfile name" do + register_provider("foo") + + environment = isolated_environment do |env| + env.file("some_other_name", <<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "base" +end +VF + + env.box3("base", "1.0", :foo, :vagrantfile => <<-VF) +Vagrant.configure("2") do |config| + config.ssh.port = 100 +end +VF + end + + env = with_temp_env("VAGRANT_VAGRANTFILE" => "some_other_name") do + environment.create_vagrant_env + end + + machine = env.machine(:default, :foo) + machine.config.ssh.port.should == 100 + end + + it "should load the box configuration for other formats for a box" do + register_provider("foo", nil, box_format: "bar") + + environment = isolated_environment do |env| + env.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "base" +end +VF + + env.box3("base", "1.0", :bar, :vagrantfile => <<-VF) +Vagrant.configure("2") do |config| + config.ssh.port = 100 +end +VF + end + + env = environment.create_vagrant_env + machine = env.machine(:default, :foo) + machine.config.ssh.port.should == 100 + end + + it "prefer sooner formats when multiple box formats are available" do + register_provider("foo", nil, box_format: ["fA", "fB"]) + + environment = isolated_environment do |env| + env.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "base" +end +VF + + env.box3("base", "1.0", :fA, :vagrantfile => <<-VF) +Vagrant.configure("2") do |config| + config.ssh.port = 100 +end +VF + + env.box3("base", "1.0", :fB, :vagrantfile => <<-VF) +Vagrant.configure("2") do |config| + config.ssh.port = 200 +end +VF + end + + env = environment.create_vagrant_env + machine = env.machine(:default, :foo) + machine.config.ssh.port.should == 100 + end + + it "should load the proper version of a box" do + register_provider("foo") + + environment = isolated_environment do |env| + env.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "base" + config.vm.box_version = "~> 1.2" +end +VF + + env.box3("base", "1.0", :foo, :vagrantfile => <<-VF) +Vagrant.configure("2") do |config| + config.ssh.port = 100 +end +VF + + env.box3("base", "1.5", :foo, :vagrantfile => <<-VF) +Vagrant.configure("2") do |config| + config.ssh.port = 200 +end +VF + end + + env = environment.create_vagrant_env + machine = env.machine(:default, :foo) + machine.config.ssh.port.should == 200 + end + + it "should load the provider override if set" do + register_provider("bar") + register_provider("foo") + + isolated_env = isolated_environment do |e| + e.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "foo" + + config.vm.provider :foo do |_, c| + c.vm.box = "bar" + end +end +VF + end + + env = isolated_env.create_vagrant_env + foo_vm = env.machine(:default, :foo) + bar_vm = env.machine(:default, :bar) + foo_vm.config.vm.box.should == "bar" + bar_vm.config.vm.box.should == "foo" + end + + it "should reload the cache if refresh is set" do + # Create a provider + foo_provider = register_provider("foo") + + # Create the configuration + isolated_env = isolated_environment do |e| + e.vagrantfile(<<-VF) +Vagrant.configure("2") do |config| + config.vm.box = "base" +end +VF + + e.box3("base", "1.0", :foo) + end + + env = isolated_env.create_vagrant_env + vm1 = env.machine(:default, :foo) + vm2 = env.machine(:default, :foo, true) + vm3 = env.machine(:default, :foo) + + vm1.should_not eql(vm2) + vm2.should eql(vm3) + end + + it "should raise an error if the VM is not found" do + expect { instance.machine("i-definitely-dont-exist", :virtualbox) }. + to raise_error(Vagrant::Errors::MachineNotFound) + end + + it "should raise an error if the provider is not found" do + expect { instance.machine(:default, :lol_no) }. + to raise_error(Vagrant::Errors::ProviderNotFound) + end + end + describe "active machines" do it "should be empty if the machines folder doesn't exist" do folder = instance.local_data_path.join("machines") @@ -559,305 +887,6 @@ VF end end - describe "getting a machine" do - # A helper to register a provider for use in tests. - def register_provider(name, config_class=nil, options=nil) - provider_cls = Class.new(Vagrant.plugin("2", :provider)) - - register_plugin("2") do |p| - p.provider(name, options) { provider_cls } - - if config_class - p.config(name, :provider) { config_class } - end - end - - provider_cls - end - - it "should return a machine object with the correct provider" do - # Create a provider - foo_provider = register_provider("foo") - - # Create the configuration - isolated_env = isolated_environment do |e| - e.vagrantfile(<<-VF) -Vagrant.configure("2") do |config| - config.vm.box = "base" - config.vm.define "foo" -end -VF - - e.box3("base", "1.0", :foo) - end - - # Verify that we can get the machine - env = isolated_env.create_vagrant_env - machine = env.machine(:foo, :foo) - machine.should be_kind_of(Vagrant::Machine) - machine.name.should == :foo - machine.provider.should be_kind_of(foo_provider) - machine.provider_config.should be_nil - end - - it "should return a machine object with the machine configuration" do - # Create a provider - foo_config = Class.new(Vagrant.plugin("2", :config)) do - attr_accessor :value - end - - foo_provider = register_provider("foo", foo_config) - - # Create the configuration - isolated_env = isolated_environment do |e| - e.vagrantfile(<<-VF) -Vagrant.configure("2") do |config| - config.vm.box = "base" - config.vm.define "foo" - - config.vm.provider :foo do |fooconfig| - fooconfig.value = 100 - end -end -VF - - e.box3("base", "1.0", :foo) - end - - # Verify that we can get the machine - env = isolated_env.create_vagrant_env - machine = env.machine(:foo, :foo) - machine.should be_kind_of(Vagrant::Machine) - machine.name.should == :foo - machine.provider.should be_kind_of(foo_provider) - machine.provider_config.value.should == 100 - end - - it "should cache the machine objects by name and provider" do - # Create a provider - foo_provider = register_provider("foo") - bar_provider = register_provider("bar") - - # Create the configuration - isolated_env = isolated_environment do |e| - e.vagrantfile(<<-VF) -Vagrant.configure("2") do |config| - config.vm.box = "base" - config.vm.define "vm1" - config.vm.define "vm2" -end -VF - - e.box3("base", "1.0", :foo) - e.box3("base", "1.0", :bar) - end - - env = isolated_env.create_vagrant_env - vm1_foo = env.machine(:vm1, :foo) - vm1_bar = env.machine(:vm1, :bar) - vm2_foo = env.machine(:vm2, :foo) - - vm1_foo.should eql(env.machine(:vm1, :foo)) - vm1_bar.should eql(env.machine(:vm1, :bar)) - vm1_foo.should_not eql(vm1_bar) - vm2_foo.should eql(env.machine(:vm2, :foo)) - end - - it "should load a machine without a box" do - register_provider("foo") - - environment = isolated_environment do |env| - env.vagrantfile(<<-VF) -Vagrant.configure("2") do |config| - config.vm.box = "i-dont-exist" -end -VF - end - - env = environment.create_vagrant_env - machine = env.machine(:default, :foo) - machine.box.should be_nil - end - - it "should load the machine configuration" do - register_provider("foo") - - environment = isolated_environment do |env| - env.vagrantfile(<<-VF) -Vagrant.configure("2") do |config| - config.ssh.port = 1 - config.vm.box = "base" - - config.vm.define "vm1" do |inner| - inner.ssh.port = 100 - end -end -VF - - env.box3("base", "1.0", :foo) - end - - env = environment.create_vagrant_env - machine = env.machine(:vm1, :foo) - machine.config.ssh.port.should == 100 - machine.config.vm.box.should == "base" - end - - it "should load the box configuration for a V2 box" do - register_provider("foo") - - environment = isolated_environment do |env| - env.vagrantfile(<<-VF) -Vagrant.configure("2") do |config| - config.vm.box = "base" -end -VF - - env.box3("base", "1.0", :foo, :vagrantfile => <<-VF) -Vagrant.configure("2") do |config| - config.ssh.port = 100 -end -VF - end - - env = environment.create_vagrant_env - machine = env.machine(:default, :foo) - machine.config.ssh.port.should == 100 - end - - it "should load the box configuration for a V2 box and custom Vagrantfile name" do - register_provider("foo") - - environment = isolated_environment do |env| - env.file("some_other_name", <<-VF) -Vagrant.configure("2") do |config| - config.vm.box = "base" -end -VF - - env.box3("base", "1.0", :foo, :vagrantfile => <<-VF) -Vagrant.configure("2") do |config| - config.ssh.port = 100 -end -VF - end - - env = with_temp_env("VAGRANT_VAGRANTFILE" => "some_other_name") do - environment.create_vagrant_env - end - - machine = env.machine(:default, :foo) - machine.config.ssh.port.should == 100 - end - - it "should load the box configuration for other formats for a V2 box" do - register_provider("foo", nil, box_format: "bar") - - environment = isolated_environment do |env| - env.vagrantfile(<<-VF) -Vagrant.configure("2") do |config| - config.vm.box = "base" -end -VF - - env.box3("base", "1.0", :bar, :vagrantfile => <<-VF) -Vagrant.configure("2") do |config| - config.ssh.port = 100 -end -VF - end - - env = environment.create_vagrant_env - machine = env.machine(:default, :foo) - machine.config.ssh.port.should == 100 - end - - it "prefer sooner formats when multiple box formats are available" do - register_provider("foo", nil, box_format: ["fA", "fB"]) - - environment = isolated_environment do |env| - env.vagrantfile(<<-VF) -Vagrant.configure("2") do |config| - config.vm.box = "base" -end -VF - - env.box3("base", "1.0", :fA, :vagrantfile => <<-VF) -Vagrant.configure("2") do |config| - config.ssh.port = 100 -end -VF - - env.box3("base", "1.0", :fB, :vagrantfile => <<-VF) -Vagrant.configure("2") do |config| - config.ssh.port = 200 -end -VF - end - - env = environment.create_vagrant_env - machine = env.machine(:default, :foo) - machine.config.ssh.port.should == 100 - end - - it "should load the provider override if set" do - register_provider("bar") - register_provider("foo") - - isolated_env = isolated_environment do |e| - e.vagrantfile(<<-VF) -Vagrant.configure("2") do |config| - config.vm.box = "foo" - - config.vm.provider :foo do |_, c| - c.vm.box = "bar" - end -end -VF - end - - env = isolated_env.create_vagrant_env - foo_vm = env.machine(:default, :foo) - bar_vm = env.machine(:default, :bar) - foo_vm.config.vm.box.should == "bar" - bar_vm.config.vm.box.should == "foo" - end - - it "should reload the cache if refresh is set" do - # Create a provider - foo_provider = register_provider("foo") - - # Create the configuration - isolated_env = isolated_environment do |e| - e.vagrantfile(<<-VF) -Vagrant.configure("2") do |config| - config.vm.box = "base" -end -VF - - e.box3("base", "1.0", :foo) - end - - env = isolated_env.create_vagrant_env - vm1 = env.machine(:default, :foo) - vm2 = env.machine(:default, :foo, true) - vm3 = env.machine(:default, :foo) - - vm1.should_not eql(vm2) - vm2.should eql(vm3) - end - - it "should raise an error if the VM is not found" do - expect { instance.machine("i-definitely-dont-exist", :virtualbox) }. - to raise_error(Vagrant::Errors::MachineNotFound) - end - - it "should raise an error if the provider is not found" do - expect { instance.machine(:default, :lol_no) }. - to raise_error(Vagrant::Errors::ProviderNotFound) - end - end - describe "getting machine names" do it "should return the default machine if no multi-VM is used" do # Create the config