diff --git a/Gemfile b/Gemfile index 1022da98f..13ca85e13 100644 --- a/Gemfile +++ b/Gemfile @@ -5,6 +5,7 @@ gem "vagrant", :path => '.' # Use the following gems straight from git, since Vagrant dev # typically coincides with it gem "virtualbox", :git => "git://github.com/mitchellh/virtualbox.git" +gem "net-ssh-shell", :git => "git://github.com/mitchellh/net-ssh-shell.git" # Gems required for testing only. To install run # gem bundle test diff --git a/lib/vagrant/provisioners/chef.rb b/lib/vagrant/provisioners/chef.rb index 8cf5f7cf4..81728dfaf 100644 --- a/lib/vagrant/provisioners/chef.rb +++ b/lib/vagrant/provisioners/chef.rb @@ -10,9 +10,11 @@ module Vagrant def verify_binary(binary) vm.ssh.execute do |ssh| - # Checks for the existence of chef binary and error if it - # doesn't exist. - ssh.exec!("which #{binary}", :error_class => ChefError, :_key => :chef_not_detected, :binary => binary) + ssh.shell do |sh| + # Checks for the existence of chef binary and error if it + # doesn't exist. + sh.execute("which #{binary}", :error_class => ChefError, :_key => :chef_not_detected, :binary => binary) + end end end diff --git a/lib/vagrant/ssh.rb b/lib/vagrant/ssh.rb index a53d248f5..f7f7cc61e 100644 --- a/lib/vagrant/ssh.rb +++ b/lib/vagrant/ssh.rb @@ -1,5 +1,6 @@ require 'timeout' require 'net/ssh' +require 'net/ssh/shell' require 'net/scp' require 'mario' diff --git a/lib/vagrant/ssh/session.rb b/lib/vagrant/ssh/session.rb index f4d97b67b..d5a138de8 100644 --- a/lib/vagrant/ssh/session.rb +++ b/lib/vagrant/ssh/session.rb @@ -12,6 +12,29 @@ module Vagrant @session = session end + # Opens a shell with this SSH session, which forces things like the + # `/etc/profile` script to load, and for state to exist between commands, + # and so on. The overhead on this is much higher than simply calling + # {#exec!} and should really only be called when settings for the terminal + # may be needed (for things such as a PATH modifications and so on). + def shell + session.shell do |sh| + sh.on_process_run do |sh, process| + process.on_finish do |p| + # By default when a process finishes we want to check the exit + # status so we can properly raise an exception + self.check_exit_status(p.exit_status, p.command, p.properties) + end + end + + yield sh + + # Exit and wait. We don't run shell commands in the background. + sh.execute "exit" + sh.wait! + end + end + # Executes a given command and simply returns true/false if the # command succeeded or not. def test?(command) diff --git a/test/vagrant/provisioners/chef_test.rb b/test/vagrant/provisioners/chef_test.rb index 41fb9b8f8..5c8f68da7 100644 --- a/test/vagrant/provisioners/chef_test.rb +++ b/test/vagrant/provisioners/chef_test.rb @@ -111,12 +111,14 @@ class ChefProvisionerTest < Test::Unit::TestCase context "verifying binary" do setup do @ssh = mock("ssh") + @shell = mock("shell") + @ssh.stubs(:shell).yields(@shell) @vm.ssh.stubs(:execute).yields(@ssh) end should "verify binary exists" do binary = "foo" - @ssh.expects(:exec!).with("which #{binary}", anything) + @shell.expects(:execute).with("which #{binary}", anything) @action.verify_binary(binary) end end diff --git a/vagrant.gemspec b/vagrant.gemspec index 9d2187706..a64dd1e45 100644 --- a/vagrant.gemspec +++ b/vagrant.gemspec @@ -19,6 +19,7 @@ Gem::Specification.new do |s| s.add_dependency "json", "~> 1.4.6" s.add_dependency "mario", "~> 0.0.6" s.add_dependency "net-ssh", "~> 2.0.23" + s.add_dependency "net-ssh-shell", "~> 0.2.0" s.add_dependency "net-scp", "~> 1.0.4" s.add_dependency "i18n", "~> 0.5.0" s.add_dependency "thor", "~> 0.14.6"