diff --git a/lib/vagrant/actions/vm/boot.rb b/lib/vagrant/actions/vm/boot.rb index 4832660d4..d7f035bb3 100644 --- a/lib/vagrant/actions/vm/boot.rb +++ b/lib/vagrant/actions/vm/boot.rb @@ -30,7 +30,7 @@ module Vagrant @runner.env.config.ssh.max_tries.to_i.times do |i| logger.info "Trying to connect (attempt ##{i+1} of #{@runner.env.config[:ssh][:max_tries]})..." - if @runner.env.ssh.up? + if @runner.ssh.up? logger.info "VM booted and ready for use!" return true end diff --git a/lib/vagrant/provisioners/base.rb b/lib/vagrant/provisioners/base.rb index 063322e55..79b675576 100644 --- a/lib/vagrant/provisioners/base.rb +++ b/lib/vagrant/provisioners/base.rb @@ -7,11 +7,19 @@ module Vagrant class Base include Vagrant::Util - # The environment which this is being provisioned in - attr_reader :env + # The VM which this is being provisioned for + attr_reader :vm - def initialize(env) - @env = env + def initialize(vm) + @vm = vm + end + + # This method returns the environment which the provisioner is working + # on. This is also the environment of the VM. This method is provided + # as a simple helper since the environment is often used throughout the + # provisioner. + def env + @vm.env end # This is the method called to "prepare" the provisioner. This is called diff --git a/lib/vagrant/provisioners/chef.rb b/lib/vagrant/provisioners/chef.rb index 35ba58d43..2be95980b 100644 --- a/lib/vagrant/provisioners/chef.rb +++ b/lib/vagrant/provisioners/chef.rb @@ -77,7 +77,7 @@ module Vagrant def chown_provisioning_folder logger.info "Setting permissions on chef provisioning folder..." - env.ssh.execute do |ssh| + vm.ssh.execute do |ssh| ssh.exec!("sudo mkdir -p #{env.config.chef.provisioning_path}") ssh.exec!("sudo chown #{env.config.ssh.username} #{env.config.chef.provisioning_path}") end @@ -89,7 +89,7 @@ module Vagrant }.merge(template_vars)) logger.info "Uploading chef configuration script..." - env.ssh.upload!(StringIO.new(config_file), File.join(env.config.chef.provisioning_path, filename)) + vm.ssh.upload!(StringIO.new(config_file), File.join(env.config.chef.provisioning_path, filename)) end def setup_json @@ -110,7 +110,7 @@ module Vagrant json = data.to_json - env.ssh.upload!(StringIO.new(json), File.join(env.config.chef.provisioning_path, "dna.json")) + vm.ssh.upload!(StringIO.new(json), File.join(env.config.chef.provisioning_path, "dna.json")) end end end diff --git a/lib/vagrant/provisioners/chef_server.rb b/lib/vagrant/provisioners/chef_server.rb index 6ae70b221..f69cf9547 100644 --- a/lib/vagrant/provisioners/chef_server.rb +++ b/lib/vagrant/provisioners/chef_server.rb @@ -64,7 +64,7 @@ module Vagrant end def guest_validation_key_path - File.join(@env.config.chef.provisioning_path, "validation.pem") + File.join(env.config.chef.provisioning_path, "validation.pem") end end end diff --git a/lib/vagrant/systems/linux.rb b/lib/vagrant/systems/linux.rb index 563ee7d4f..cf6fdc46c 100644 --- a/lib/vagrant/systems/linux.rb +++ b/lib/vagrant/systems/linux.rb @@ -30,7 +30,7 @@ module Vagrant #------------------------------------------------------------------- def halt logger.info "Attempting graceful shutdown of linux..." - vm.env.ssh.execute do |ssh| + vm.ssh.execute do |ssh| ssh.exec!("sudo halt") end diff --git a/lib/vagrant/vm.rb b/lib/vagrant/vm.rb index 175bd19c5..0183b776c 100644 --- a/lib/vagrant/vm.rb +++ b/lib/vagrant/vm.rb @@ -20,9 +20,14 @@ module Vagrant @env = env @vm = vm - load_system! unless @env.nil? + load_system! if !@env.nil? end + # Loads the system associated with the VM. The system class is + # responsible for OS-specific functionality. More information + # can be found by reading the documentation on {Vagrant::Systems::Base}. + # + # **This method should never be called manually.** def load_system! system = env.config.vm.system @@ -31,9 +36,7 @@ module Vagrant error_and_exit(:system_invalid_class, :system => system.to_s) unless @system.is_a?(Systems::Base) elsif system.is_a?(Symbol) # Hard-coded internal systems - mapping = { - :linux => Systems::Linux - } + mapping = { :linux => Systems::Linux } if !mapping.has_key?(system) error_and_exit(:system_unknown_type, :system => system.to_s) @@ -46,6 +49,13 @@ module Vagrant end end + # Access the {Vagrant::SSH} object associated with this VM. + # On the initial call, this will initialize the object. On + # subsequent calls it will reuse the existing object. + def ssh + @ssh ||= SSH.new(env) + end + def uuid vm ? vm.uuid : nil end diff --git a/test/test_helper.rb b/test/test_helper.rb index 6f5eebd3c..6464a660d 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -73,6 +73,14 @@ class Test::Unit::TestCase environment end + # Sets up the mocks for a VM + def mock_vm + vm = Vagrant::VM.new(nil, nil) + vm.stubs(:env).returns(mock_environment) + vm.stubs(:ssh).returns(Vagrant::SSH.new(vm.env)) + vm + end + # Sets up the mocks and instantiates an action for testing def mock_action(action_klass, *args) vm = mock("vboxvm") @@ -87,6 +95,11 @@ class Test::Unit::TestCase mock_vm.stubs(:actions).returns([action]) mock_vm.stubs(:env).returns(mock_environment) + mock_ssh = Vagrant::SSH.new(mock_vm.env) + mock_ssh.stubs(:execute) + + mock_vm.stubs(:ssh).returns(mock_ssh) + vm.stubs(:env).returns(mock_vm.env) [mock_vm, vm, action] diff --git a/test/vagrant/actions/vm/boot_test.rb b/test/vagrant/actions/vm/boot_test.rb index f98dabcd5..82034acb3 100644 --- a/test/vagrant/actions/vm/boot_test.rb +++ b/test/vagrant/actions/vm/boot_test.rb @@ -43,13 +43,13 @@ class BootActionTest < Test::Unit::TestCase context "waiting for boot" do should "repeatedly ping the SSH port and return false with no response" do seq = sequence('pings') - @runner.env.ssh.expects(:up?).times(@runner.env.config.ssh.max_tries.to_i - 1).returns(false).in_sequence(seq) - @runner.env.ssh.expects(:up?).once.returns(true).in_sequence(seq) + @runner.ssh.expects(:up?).times(@runner.env.config.ssh.max_tries.to_i - 1).returns(false).in_sequence(seq) + @runner.ssh.expects(:up?).once.returns(true).in_sequence(seq) assert @action.wait_for_boot(0) end should "ping the max number of times then just return" do - @runner.env.ssh.expects(:up?).times(@runner.env.config.ssh.max_tries.to_i).returns(false) + @runner.ssh.expects(:up?).times(@runner.env.config.ssh.max_tries.to_i).returns(false) assert !@action.wait_for_boot(0) end end diff --git a/test/vagrant/provisioners/base_test.rb b/test/vagrant/provisioners/base_test.rb index 316d93cca..1820bfa46 100644 --- a/test/vagrant/provisioners/base_test.rb +++ b/test/vagrant/provisioners/base_test.rb @@ -7,13 +7,13 @@ class BaseProvisionerTest < Test::Unit::TestCase context "base instance" do setup do - @env = mock_environment - @base = Vagrant::Provisioners::Base.new(@env) + @vm = mock("vm") + @base = Vagrant::Provisioners::Base.new(@vm) end should "set the environment" do - base = Vagrant::Provisioners::Base.new(@env) - assert_equal @env, base.env + base = Vagrant::Provisioners::Base.new(@vm) + assert_equal @vm, base.vm end should "implement provision! which does nothing" do diff --git a/test/vagrant/provisioners/chef_server_test.rb b/test/vagrant/provisioners/chef_server_test.rb index 348a47366..fae97a331 100644 --- a/test/vagrant/provisioners/chef_server_test.rb +++ b/test/vagrant/provisioners/chef_server_test.rb @@ -2,8 +2,9 @@ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper') class ChefServerProvisionerTest < Test::Unit::TestCase setup do - @env = mock_environment - @action = Vagrant::Provisioners::ChefServer.new(@env) + @vm = mock_vm + @env = @vm.env + @action = Vagrant::Provisioners::ChefServer.new(@vm) end context "provisioning" do diff --git a/test/vagrant/provisioners/chef_solo_test.rb b/test/vagrant/provisioners/chef_solo_test.rb index 83b495eb8..91d3d6ca5 100644 --- a/test/vagrant/provisioners/chef_solo_test.rb +++ b/test/vagrant/provisioners/chef_solo_test.rb @@ -2,8 +2,9 @@ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper') class ChefSoloProvisionerTest < Test::Unit::TestCase setup do - @env = mock_environment - @action = Vagrant::Provisioners::ChefSolo.new(@env) + @vm = mock_vm + @env = @vm.env + @action = Vagrant::Provisioners::ChefSolo.new(@vm) end context "preparing" do diff --git a/test/vagrant/provisioners/chef_test.rb b/test/vagrant/provisioners/chef_test.rb index 1eda93676..d21fcd486 100644 --- a/test/vagrant/provisioners/chef_test.rb +++ b/test/vagrant/provisioners/chef_test.rb @@ -2,8 +2,9 @@ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper') class ChefProvisionerTest < Test::Unit::TestCase setup do - @env = mock_environment - @action = Vagrant::Provisioners::Chef.new(@env) + @vm = mock_vm + @env = @vm.env + @action = Vagrant::Provisioners::Chef.new(@vm) end context "preparing" do @@ -67,14 +68,14 @@ class ChefProvisionerTest < Test::Unit::TestCase ssh = mock("ssh") ssh.expects(:exec!).with("sudo mkdir -p #{@env.config.chef.provisioning_path}").once.in_sequence(ssh_seq) ssh.expects(:exec!).with("sudo chown #{@env.config.ssh.username} #{@env.config.chef.provisioning_path}").once.in_sequence(ssh_seq) - @env.ssh.expects(:execute).yields(ssh) + @vm.ssh.expects(:execute).yields(ssh) @action.chown_provisioning_folder end end context "generating and uploading chef configuration file" do setup do - @env.ssh.stubs(:upload!) + @vm.ssh.stubs(:upload!) @template = "template" @filename = "foo.rb" @@ -88,7 +89,7 @@ class ChefProvisionerTest < Test::Unit::TestCase Vagrant::Util::TemplateRenderer.expects(:render).with(@template, anything).returns(template_data) StringIO.expects(:new).with(template_data).returns(string_io) File.expects(:join).with(@env.config.chef.provisioning_path, @filename).once.returns("bar") - @env.ssh.expects(:upload!).with(string_io, "bar") + @vm.ssh.expects(:upload!).with(string_io, "bar") @action.setup_config(@template, @filename, {}) end @@ -124,7 +125,7 @@ class ChefProvisionerTest < Test::Unit::TestCase context "generating and uploading json" do def assert_json - @env.ssh.expects(:upload!).with do |json, path| + @vm.ssh.expects(:upload!).with do |json, path| data = JSON.parse(json.read) yield data true @@ -155,7 +156,7 @@ class ChefProvisionerTest < Test::Unit::TestCase should "upload a StringIO to dna.json" do StringIO.expects(:new).with(anything).returns("bar") File.expects(:join).with(@env.config.chef.provisioning_path, "dna.json").once.returns("baz") - @env.ssh.expects(:upload!).with("bar", "baz").once + @vm.ssh.expects(:upload!).with("bar", "baz").once @action.setup_json end end diff --git a/test/vagrant/systems/linux_test.rb b/test/vagrant/systems/linux_test.rb index 6c654944f..f66b0499b 100644 --- a/test/vagrant/systems/linux_test.rb +++ b/test/vagrant/systems/linux_test.rb @@ -4,8 +4,7 @@ class LinuxSystemTest < Test::Unit::TestCase setup do @klass = Vagrant::Systems::Linux - @vm = mock("vm") - @vm.stubs(:env).returns(mock_environment) + @vm = mock_vm @instance = @klass.new(@vm) end @@ -14,7 +13,7 @@ class LinuxSystemTest < Test::Unit::TestCase @ssh_session = mock("ssh_session") @ssh = mock("ssh") @ssh.stubs(:execute).yields(@ssh_session) - @vm.env.stubs(:ssh).returns(@ssh) + @vm.stubs(:ssh).returns(@ssh) @real_vm = mock("real_vm") @real_vm.stubs(:state).returns(:powered_off) diff --git a/test/vagrant/vm_test.rb b/test/vagrant/vm_test.rb index 4791318e0..1a4b902b6 100644 --- a/test/vagrant/vm_test.rb +++ b/test/vagrant/vm_test.rb @@ -39,6 +39,28 @@ class VMTest < Test::Unit::TestCase @mock_vm.stubs(:uuid).returns("foo") end + context "accessing the SSH object" do + setup do + # Reset this to nil to force the reload + @vm.instance_variable_set(:@ssh, nil) + + @ssh = mock("ssh") + Vagrant::SSH.stubs(:new).returns(@ssh) + end + + should "load it the first time" do + Vagrant::SSH.expects(:new).with(@env).once.returns(@ssh) + @vm.ssh + @vm.ssh + @vm.ssh + end + + should "use the same value once its loaded" do + result = @vm.ssh + assert_equal result, @vm.ssh + end + end + context "loading associated system" do should "error and exit if system is not specified" do @vm.env.config.vm.system = nil