vagrant 0.1.4 → 0.2.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. data/Gemfile +1 -1
  2. data/Rakefile +1 -1
  3. data/VERSION +1 -1
  4. data/bin/vagrant-box +1 -2
  5. data/bin/vagrant-down +1 -2
  6. data/bin/vagrant-halt +1 -2
  7. data/bin/vagrant-init +1 -2
  8. data/bin/vagrant-package +1 -2
  9. data/bin/vagrant-reload +1 -2
  10. data/bin/vagrant-resume +1 -2
  11. data/bin/vagrant-ssh +1 -2
  12. data/bin/vagrant-status +29 -0
  13. data/bin/vagrant-suspend +1 -2
  14. data/bin/vagrant-up +1 -2
  15. data/config/default.rb +5 -9
  16. data/keys/README.md +10 -0
  17. data/keys/vagrant +27 -0
  18. data/keys/vagrant.pub +1 -0
  19. data/lib/vagrant/actions/base.rb +14 -0
  20. data/lib/vagrant/actions/collection.rb +36 -0
  21. data/lib/vagrant/actions/runner.rb +4 -10
  22. data/lib/vagrant/actions/vm/boot.rb +4 -5
  23. data/lib/vagrant/actions/vm/customize.rb +17 -0
  24. data/lib/vagrant/actions/vm/destroy.rb +11 -2
  25. data/lib/vagrant/actions/vm/forward_ports.rb +24 -0
  26. data/lib/vagrant/actions/vm/import.rb +1 -0
  27. data/lib/vagrant/actions/vm/provision.rb +30 -52
  28. data/lib/vagrant/actions/vm/reload.rb +2 -2
  29. data/lib/vagrant/actions/vm/shared_folders.rb +37 -25
  30. data/lib/vagrant/actions/vm/up.rb +8 -4
  31. data/lib/vagrant/active_list.rb +66 -0
  32. data/lib/vagrant/commands.rb +44 -0
  33. data/lib/vagrant/config.rb +64 -47
  34. data/lib/vagrant/downloaders/file.rb +2 -12
  35. data/lib/vagrant/env.rb +48 -12
  36. data/lib/vagrant/provisioners/base.rb +22 -0
  37. data/lib/vagrant/provisioners/chef.rb +102 -0
  38. data/lib/vagrant/provisioners/chef_server.rb +96 -0
  39. data/lib/vagrant/provisioners/chef_solo.rb +67 -0
  40. data/lib/vagrant/ssh.rb +25 -6
  41. data/lib/vagrant/stacked_proc_runner.rb +33 -0
  42. data/lib/vagrant/vm.rb +8 -0
  43. data/lib/vagrant.rb +10 -5
  44. data/test/test_helper.rb +22 -6
  45. data/test/vagrant/actions/collection_test.rb +110 -0
  46. data/test/vagrant/actions/runner_test.rb +11 -7
  47. data/test/vagrant/actions/vm/boot_test.rb +7 -7
  48. data/test/vagrant/actions/vm/customize_test.rb +16 -0
  49. data/test/vagrant/actions/vm/destroy_test.rb +19 -6
  50. data/test/vagrant/actions/vm/forward_ports_test.rb +52 -0
  51. data/test/vagrant/actions/vm/import_test.rb +10 -3
  52. data/test/vagrant/actions/vm/provision_test.rb +75 -70
  53. data/test/vagrant/actions/vm/reload_test.rb +3 -2
  54. data/test/vagrant/actions/vm/shared_folders_test.rb +62 -9
  55. data/test/vagrant/actions/vm/up_test.rb +4 -4
  56. data/test/vagrant/active_list_test.rb +169 -0
  57. data/test/vagrant/config_test.rb +145 -29
  58. data/test/vagrant/downloaders/file_test.rb +4 -19
  59. data/test/vagrant/env_test.rb +96 -23
  60. data/test/vagrant/provisioners/base_test.rb +27 -0
  61. data/test/vagrant/provisioners/chef_server_test.rb +175 -0
  62. data/test/vagrant/provisioners/chef_solo_test.rb +142 -0
  63. data/test/vagrant/provisioners/chef_test.rb +116 -0
  64. data/test/vagrant/ssh_test.rb +29 -8
  65. data/test/vagrant/stacked_proc_runner_test.rb +43 -0
  66. data/test/vagrant/vm_test.rb +23 -0
  67. data/vagrant.gemspec +35 -8
  68. metadata +42 -11
  69. data/script/vagrant-ssh-expect.sh +0 -22
@@ -0,0 +1,67 @@
1
+ module Vagrant
2
+ module Provisioners
3
+ # This class implements provisioning via chef-solo.
4
+ class ChefSolo < Chef
5
+ def prepare
6
+ share_cookbook_folders
7
+ end
8
+
9
+ def provision!
10
+ chown_provisioning_folder
11
+ setup_json
12
+ setup_solo_config
13
+ run_chef_solo
14
+ end
15
+
16
+ def share_cookbook_folders
17
+ host_cookbook_paths.each_with_index do |cookbook, i|
18
+ Vagrant.config.vm.share_folder("vagrant-chef-solo-#{i}", cookbook_path(i), cookbook)
19
+ end
20
+ end
21
+
22
+ def setup_solo_config
23
+ solo_file = <<-solo
24
+ file_cache_path "#{Vagrant.config.chef.provisioning_path}"
25
+ cookbook_path #{cookbooks_path}
26
+ solo
27
+
28
+ logger.info "Uploading chef-solo configuration script..."
29
+ SSH.upload!(StringIO.new(solo_file), File.join(Vagrant.config.chef.provisioning_path, "solo.rb"))
30
+ end
31
+
32
+ def run_chef_solo
33
+ logger.info "Running chef-solo..."
34
+ SSH.execute do |ssh|
35
+ ssh.exec!("cd #{Vagrant.config.chef.provisioning_path} && sudo chef-solo -c solo.rb -j dna.json") do |channel, data, stream|
36
+ # TODO: Very verbose. It would be easier to save the data and only show it during
37
+ # an error, or when verbosity level is set high
38
+ logger.info("#{stream}: #{data}")
39
+ end
40
+ end
41
+ end
42
+
43
+ def host_cookbook_paths
44
+ cookbooks = Vagrant.config.chef.cookbooks_path
45
+ cookbooks = [cookbooks] unless cookbooks.is_a?(Array)
46
+ cookbooks.collect! { |cookbook| File.expand_path(cookbook, Env.root_path) }
47
+ return cookbooks
48
+ end
49
+
50
+ def cookbook_path(i)
51
+ File.join(Vagrant.config.chef.provisioning_path, "cookbooks-#{i}")
52
+ end
53
+
54
+ def cookbooks_path
55
+ result = []
56
+ host_cookbook_paths.each_with_index do |host_path, i|
57
+ result << cookbook_path(i)
58
+ end
59
+
60
+ # We're lucky that ruby's string and array syntax for strings is the
61
+ # same as JSON, so we can just convert to JSON here and use that
62
+ result = result.to_s if result.length == 1
63
+ result.to_json
64
+ end
65
+ end
66
+ end
67
+ end
data/lib/vagrant/ssh.rb CHANGED
@@ -1,19 +1,22 @@
1
1
  module Vagrant
2
2
  class SSH
3
- SCRIPT = File.join(File.dirname(__FILE__), '..', '..', 'script', 'vagrant-ssh-expect.sh')
3
+ include Vagrant::Util
4
4
 
5
5
  class << self
6
6
  def connect(opts={})
7
7
  options = {}
8
- [:host, :password, :username].each do |param|
8
+ [:host, :username, :private_key_path].each do |param|
9
9
  options[param] = opts[param] || Vagrant.config.ssh.send(param)
10
10
  end
11
11
 
12
- Kernel.exec "#{SCRIPT} #{options[:username]} #{options[:password]} #{options[:host]} #{port(opts)}".strip
12
+ Kernel.exec "ssh -p #{port(opts)} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i #{options[:private_key_path]} #{options[:username]}@#{options[:host]}".strip
13
13
  end
14
14
 
15
- def execute
16
- Net::SSH.start(Vagrant.config.ssh.host, Vagrant.config[:ssh][:username], :port => port, :password => Vagrant.config[:ssh][:password]) do |ssh|
15
+ def execute(opts={})
16
+ Net::SSH.start(Vagrant.config.ssh.host,
17
+ Vagrant.config[:ssh][:username],
18
+ opts.merge( :port => port,
19
+ :keys => [Vagrant.config.ssh.private_key_path])) do |ssh|
17
20
  yield ssh
18
21
  end
19
22
  end
@@ -29,7 +32,7 @@ module Vagrant
29
32
  check_thread = Thread.new do
30
33
  begin
31
34
  Thread.current[:result] = false
32
- Net::SSH.start(Vagrant.config.ssh.host, Vagrant.config.ssh.username, :port => port, :password => Vagrant.config.ssh.password, :timeout => Vagrant.config.ssh.timeout) do |ssh|
35
+ execute(:timeout => Vagrant.config.ssh.timeout) do |ssh|
33
36
  Thread.current[:result] = true
34
37
  end
35
38
  rescue Errno::ECONNREFUSED, Net::SSH::Disconnect
@@ -39,6 +42,22 @@ module Vagrant
39
42
 
40
43
  check_thread.join(Vagrant.config.ssh.timeout)
41
44
  return check_thread[:result]
45
+ rescue Net::SSH::AuthenticationFailed
46
+ error_and_exit(<<-msg)
47
+ SSH authentication failed! While this could be due to a variety of reasons,
48
+ the two most common are: private key path is incorrect or you're using a box
49
+ which was built for Vagrant 0.1.x.
50
+
51
+ Vagrant 0.2.x dropped support for password-based authentication. If you're
52
+ tring to `vagrant up` a box which does not support Vagrant's private/public
53
+ keypair, then this error will be raised. To resolve this, read the guide
54
+ on converting base boxes from password-based to keypairs here:
55
+
56
+ http://vagrantup.com/docs/converting_password_to_key_ssh.html
57
+
58
+ If the box was built for 0.2.x and contains a custom public key, perhaps
59
+ the path to the private key is incorrect. Check your `config.ssh.private_key_path`.
60
+ msg
42
61
  end
43
62
 
44
63
  def port(opts={})
@@ -0,0 +1,33 @@
1
+ module Vagrant
2
+ # Represents the "stacked proc runner" behavior which is used a
3
+ # couple places within Vagrant. This allows procs to "stack" on
4
+ # each other, then all execute in a single action. An example of
5
+ # its uses can be seen in the {Config} class.
6
+ module StackedProcRunner
7
+ # Returns the proc stack. This should always be called as the
8
+ # accessor of the stack. The instance variable itself should _never_
9
+ # be used.
10
+ #
11
+ # @return [Array<Proc>]
12
+ def proc_stack
13
+ @_proc_stack ||= []
14
+ end
15
+
16
+ # Adds (pushes) a proc to the stack. The actual proc added here is
17
+ # not executed, but merely stored.
18
+ #
19
+ # @param [Proc] block
20
+ def push_proc(&block)
21
+ proc_stack << block
22
+ end
23
+
24
+ # Executes all the procs on the stack, passing in the given arguments.
25
+ # The stack is not cleared afterwords. It is up to the user of this
26
+ # mixin to clear the stack by calling `proc_stack.clear`.
27
+ def run_procs!(*args)
28
+ proc_stack.each do |proc|
29
+ proc.call(*args)
30
+ end
31
+ end
32
+ end
33
+ end
data/lib/vagrant/vm.rb CHANGED
@@ -19,6 +19,14 @@ module Vagrant
19
19
  @vm = vm
20
20
  end
21
21
 
22
+ def uuid
23
+ vm ? vm.uuid : nil
24
+ end
25
+
26
+ def reload!
27
+ @vm = VirtualBox::VM.find(@vm.uuid)
28
+ end
29
+
22
30
  def package(out_path, include_files=[])
23
31
  add_action(Actions::VM::Export)
24
32
  add_action(Actions::VM::Package, out_path, include_files)
data/lib/vagrant.rb CHANGED
@@ -1,14 +1,19 @@
1
1
  libdir = File.dirname(__FILE__)
2
- $:.unshift(libdir)
3
2
  PROJECT_ROOT = File.join(libdir, '..') unless defined?(PROJECT_ROOT)
4
3
 
5
4
  # The libs which must be loaded prior to the rest
6
5
  %w{tempfile open-uri json pathname logger uri net/http virtualbox net/ssh archive/tar/minitar
7
- net/scp fileutils vagrant/util vagrant/actions/base vagrant/downloaders/base vagrant/actions/runner}.each do |f|
8
- require f
6
+ net/scp fileutils}.each do |lib|
7
+ require lib
8
+ end
9
+
10
+ # The vagrant specific files which must be loaded prior to the rest
11
+ %w{vagrant/util vagrant/stacked_proc_runner vagrant/actions/base vagrant/downloaders/base vagrant/actions/collection
12
+ vagrant/actions/runner vagrant/config vagrant/provisioners/base vagrant/provisioners/chef}.each do |f|
13
+ require File.expand_path(f, libdir)
9
14
  end
10
15
 
11
16
  # Glob require the rest
12
- Dir[File.join(PROJECT_ROOT, "lib", "vagrant", "**", "*.rb")].each do |f|
13
- require f
17
+ Dir[File.join(libdir, "vagrant", "**", "*.rb")].each do |f|
18
+ require File.expand_path(f)
14
19
  end
data/test/test_helper.rb CHANGED
@@ -20,11 +20,10 @@ require 'mocha'
20
20
  class Test::Unit::TestCase
21
21
  # Clears the previous config and sets up the new config
22
22
  def mock_config
23
- Vagrant::Config.instance_variable_set(:@config_runners, nil)
24
- Vagrant::Config.instance_variable_set(:@config, nil)
23
+ Vagrant::Config.reset!
25
24
 
26
25
  Vagrant::Config.run do |config|
27
- config.vagrant.dotfile_name = ".hobo"
26
+ config.vagrant.dotfile_name = ".vagrant"
28
27
 
29
28
  config.ssh.username = "foo"
30
29
  config.ssh.password = "bar"
@@ -32,21 +31,28 @@ class Test::Unit::TestCase
32
31
  config.ssh.forwarded_port_key = "ssh"
33
32
  config.ssh.max_tries = 10
34
33
  config.ssh.timeout = 10
34
+ config.ssh.private_key_path = '~/foo'
35
35
 
36
36
  config.vm.box = "foo"
37
37
  config.vm.box_ovf = "box.ovf"
38
38
  config.vm.base_mac = "42"
39
- config.vm.project_directory = "/hobo"
39
+ config.vm.project_directory = "/vagrant"
40
40
  config.vm.disk_image_format = 'VMDK'
41
41
  config.vm.forward_port("ssh", 22, 2222)
42
+ config.vm.shared_folder_uid = nil
43
+ config.vm.shared_folder_gid = nil
42
44
 
43
45
  config.package.name = 'vagrant'
44
46
  config.package.extension = '.box'
45
47
 
48
+ # Chef
49
+ config.chef.chef_server_url = "http://localhost:4000"
50
+ config.chef.validation_key_path = "validation.pem"
51
+ config.chef.client_key_path = "/zoo/foo/bar.pem"
46
52
  config.chef.cookbooks_path = "cookbooks"
47
- config.chef.provisioning_path = "/tmp/hobo-chef"
53
+ config.chef.provisioning_path = "/tmp/vagrant-chef"
48
54
  config.chef.json = {
49
- :recipes => ["hobo_main"]
55
+ :recipes => ["vagrant_main"]
50
56
  }
51
57
 
52
58
  config.vagrant.home = '~/.home'
@@ -72,6 +78,7 @@ class Test::Unit::TestCase
72
78
  vm = mock("vboxvm")
73
79
  mock_vm = mock("vm")
74
80
  action = action_klass.new(mock_vm, *args)
81
+ stub_default_action_dependecies(action)
75
82
 
76
83
  mock_vm.stubs(:vm).returns(vm)
77
84
  mock_vm.stubs(:vm=)
@@ -82,6 +89,11 @@ class Test::Unit::TestCase
82
89
  [mock_vm, vm, action]
83
90
  end
84
91
 
92
+ def stub_default_action_dependecies(mock, klass=MockAction)
93
+ mock.stubs(:precedes).returns([])
94
+ mock.stubs(:follows).returns([])
95
+ end
96
+
85
97
  # Sets up the mocks and stubs for a downloader
86
98
  def mock_downloader(downloader_klass)
87
99
  tempfile = mock("tempfile")
@@ -90,3 +102,7 @@ class Test::Unit::TestCase
90
102
  [downloader_klass.new, tempfile]
91
103
  end
92
104
  end
105
+
106
+ class MockAction; end
107
+ class MockActionOther; end
108
+
@@ -0,0 +1,110 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'test_helper')
2
+
3
+ class CollectionTest < Test::Unit::TestCase
4
+ context "checking uniqueness" do
5
+ setup do
6
+ @actions = Vagrant::Actions::Collection.new([1])
7
+ end
8
+
9
+ should "return true if there are duplicate classes in the collection" do
10
+ @actions << 1
11
+ assert @actions.duplicates?
12
+ end
13
+
14
+ should "return false it all the classes are unique" do
15
+ @actions << 1.0 << "foo"
16
+ assert !@actions.duplicates?
17
+ end
18
+
19
+ should "raise an exception when there are duplicates" do
20
+ @actions << 1
21
+ assert_raise Vagrant::Actions::DuplicateActionException do
22
+ @actions.duplicates!
23
+ end
24
+ end
25
+
26
+ should "not raise an exception when there are no duplicates" do
27
+ @actions << 1.0 << "foo"
28
+ assert_nothing_raised do
29
+ @actions.duplicates!
30
+ end
31
+ end
32
+ end
33
+
34
+ context "verifying dependencies" do
35
+ setup do
36
+ @mock_action = mock('action')
37
+ @mock_action.stubs(:class).returns(MockAction)
38
+
39
+ @mock_action2 = mock('action2')
40
+ @mock_action2.stubs(:class).returns(MockActionOther)
41
+ # see test_helper
42
+ stub_default_action_dependecies(@mock_action)
43
+ stub_default_action_dependecies(@mock_action2)
44
+ end
45
+
46
+ context "that come before an action" do
47
+ setup do
48
+ @mock_action.stubs(:follows).returns([MockActionOther])
49
+ end
50
+ should "raise an exception if they are not met" do
51
+ assert_raise Vagrant::Actions::DependencyNotSatisfiedException do
52
+ collection.new([@mock_action]).dependencies!
53
+ end
54
+ end
55
+
56
+ should "not raise an exception if they are met" do
57
+ assert_nothing_raised do
58
+ collection.new([@mock_action2, @mock_action]).dependencies!
59
+ end
60
+ end
61
+ end
62
+
63
+ context "that follow an an action" do
64
+ setup do
65
+ @mock_action.stubs(:precedes).returns([MockActionOther])
66
+ end
67
+
68
+ should "raise an exception if they are not met" do
69
+ assert_raise Vagrant::Actions::DependencyNotSatisfiedException do
70
+ collection.new([@mock_action]).dependencies!
71
+ end
72
+ end
73
+
74
+ should "not raise an exception if they are met" do
75
+ assert_nothing_raised do
76
+ collection.new([@mock_action, @mock_action2]).dependencies!
77
+ end
78
+ end
79
+ end
80
+
81
+ context "that are before and after an action" do
82
+ setup do
83
+ @mock_action.stubs(:precedes).returns([MockActionOther])
84
+ @mock_action.stubs(:follows).returns([MockActionOther])
85
+ end
86
+
87
+ should "raise an exception if they are met" do
88
+ assert_raise Vagrant::Actions::DependencyNotSatisfiedException do
89
+ collection.new([@mock_action2, @mock_action]).dependencies!
90
+ end
91
+ end
92
+
93
+ should "not raise and exception if they are met" do
94
+ assert_nothing_raised do
95
+ collection.new([@mock_action2, @mock_action, @mock_action2]).dependencies!
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ context "klasses" do
102
+ should "return a list of the collection element's classes" do
103
+ @action = mock('action')
104
+ assert_equal collection.new([@action]).klasses, [@action.class]
105
+ assert_equal collection.new([@action, 1.0, "foo"]).klasses, [@action.class, Float, String]
106
+ end
107
+ end
108
+
109
+ def collection; Vagrant::Actions::Collection end
110
+ end
@@ -6,6 +6,7 @@ class ActionRunnerTest < Test::Unit::TestCase
6
6
  action.stubs(:prepare)
7
7
  action.stubs(:execute!)
8
8
  action.stubs(:cleanup)
9
+ stub_default_action_dependecies(action)
9
10
  action
10
11
  end
11
12
 
@@ -135,6 +136,7 @@ class ActionRunnerTest < Test::Unit::TestCase
135
136
  should "clear the actions and run a single action if given to execute!" do
136
137
  action = mock("action")
137
138
  run_action = mock("action_run")
139
+ stub_default_action_dependecies(run_action)
138
140
  run_class = mock("run_class")
139
141
  run_class.expects(:new).once.returns(run_action)
140
142
  @runner.actions << action
@@ -148,7 +150,6 @@ class ActionRunnerTest < Test::Unit::TestCase
148
150
  end
149
151
 
150
152
  should "clear actions after running execute!" do
151
- @runner.actions << mock_fake_action
152
153
  @runner.actions << mock_fake_action
153
154
  assert !@runner.actions.empty? # sanity
154
155
  @runner.execute!
@@ -158,9 +159,10 @@ class ActionRunnerTest < Test::Unit::TestCase
158
159
  should "run #prepare on all actions, then #execute!" do
159
160
  action_seq = sequence("action_seq")
160
161
  actions = []
161
- 5.times do |i|
162
+ [MockAction, MockActionOther].each_with_index do |klass, i|
162
163
  action = mock("action#{i}")
163
-
164
+ action.expects(:class).returns(klass)
165
+ stub_default_action_dependecies(action, klass)
164
166
  @runner.actions << action
165
167
  actions << action
166
168
  end
@@ -176,10 +178,12 @@ class ActionRunnerTest < Test::Unit::TestCase
176
178
 
177
179
  context "exceptions" do
178
180
  setup do
179
- @actions = [mock_fake_action, mock_fake_action]
180
- @actions.each do |a|
181
- a.stubs(:rescue)
182
- @runner.actions << a
181
+ @actions = [MockAction, MockActionOther].map do |klass|
182
+ action = mock_fake_action
183
+ action.expects(:class).returns(klass)
184
+ action.stubs(:rescue)
185
+ @runner.actions << action
186
+ action
183
187
  end
184
188
 
185
189
  @exception = Exception.new
@@ -7,6 +7,13 @@ class BootActionTest < Test::Unit::TestCase
7
7
  mock_config
8
8
  end
9
9
 
10
+ context "preparing" do
11
+ should "add the root shared folder" do
12
+ Vagrant.config.vm.expects(:share_folder).with("vagrant-root", Vagrant.config.vm.project_directory, Vagrant::Env.root_path).once
13
+ @action.prepare
14
+ end
15
+ end
16
+
10
17
  context "execution" do
11
18
  should "invoke the 'boot' around callback" do
12
19
  boot_seq = sequence("boot_seq")
@@ -45,11 +52,4 @@ class BootActionTest < Test::Unit::TestCase
45
52
  assert !@action.wait_for_boot(0)
46
53
  end
47
54
  end
48
-
49
- context "callbacks" do
50
- should "setup the root directory shared folder" do
51
- expected = ["vagrant-root", Vagrant::Env.root_path, Vagrant.config.vm.project_directory]
52
- assert_equal expected, @action.collect_shared_folders
53
- end
54
- end
55
55
  end
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
+
3
+ class CustomizeActionTest < Test::Unit::TestCase
4
+ setup do
5
+ @runner, @vm, @action = mock_action(Vagrant::Actions::VM::Customize)
6
+ mock_config
7
+ end
8
+
9
+ context "executing" do
10
+ should "run the VM customization procs then save the VM" do
11
+ Vagrant.config.vm.expects(:run_procs!).with(@vm)
12
+ @vm.expects(:save).with(true).once
13
+ @action.execute!
14
+ end
15
+ end
16
+ end
@@ -2,23 +2,36 @@ require File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper')
2
2
 
3
3
  class DestroyActionTest < Test::Unit::TestCase
4
4
  setup do
5
- @mock_vm, @vm, @action = mock_action(Vagrant::Actions::VM::Destroy)
5
+ @runner, @vm, @action = mock_action(Vagrant::Actions::VM::Destroy)
6
6
  mock_config
7
7
  end
8
8
 
9
9
  context "executing" do
10
- setup do
11
- @vm.stubs(:destroy)
10
+ should "invoke an around callback around the destroy" do
11
+ @runner.expects(:invoke_around_callback).with(:destroy).once
12
+ @action.execute!
12
13
  end
13
14
 
14
- should "invoke an around callback around the destroy" do
15
- @mock_vm.expects(:invoke_around_callback).with(:destroy).once
15
+ should "destroy VM and clear persist" do
16
+ @runner.stubs(:invoke_around_callback).yields
17
+ clear_seq = sequence("clear")
18
+ @action.expects(:destroy_vm).in_sequence(clear_seq)
19
+ @action.expects(:depersist).in_sequence(clear_seq)
16
20
  @action.execute!
17
21
  end
22
+ end
18
23
 
24
+ context "destroying the VM" do
19
25
  should "destroy VM and attached images" do
20
26
  @vm.expects(:destroy).with(:destroy_image => true).once
21
- @action.execute!
27
+ @action.destroy_vm
28
+ end
29
+ end
30
+
31
+ context "depersisting" do
32
+ should "call depersist_vm on Env" do
33
+ Vagrant::Env.expects(:depersist_vm).with(@runner).once
34
+ @action.depersist
22
35
  end
23
36
  end
24
37
  end
@@ -6,6 +6,58 @@ class ForwardPortsActionTest < Test::Unit::TestCase
6
6
  mock_config
7
7
  end
8
8
 
9
+ context "checking for colliding ports" do
10
+ setup do
11
+ @forwarded_port = mock("forwarded_port")
12
+ @forwarded_port.stubs(:hostport)
13
+ @forwarded_ports = [@forwarded_port]
14
+
15
+ @vm = mock("vm")
16
+ @vm.stubs(:forwarded_ports).returns(@forwarded_ports)
17
+ @vm.stubs(:running?).returns(true)
18
+ @vm.stubs(:uuid).returns("foo")
19
+ @mock_vm.stubs(:uuid).returns("bar")
20
+ vms = [@vm]
21
+ VirtualBox::VM.stubs(:all).returns(vms)
22
+
23
+ mock_config do |config|
24
+ config.vm.forwarded_ports.clear
25
+ config.vm.forward_port("ssh", 22, 2222)
26
+ end
27
+ end
28
+
29
+ should "ignore vms which aren't running" do
30
+ @vm.expects(:running?).returns(false)
31
+ @vm.expects(:forwarded_ports).never
32
+ @action.prepare
33
+ end
34
+
35
+ should "ignore vms which are equivalent to ours" do
36
+ @mock_vm.expects(:uuid).returns(@vm.uuid)
37
+ @vm.expects(:forwarded_ports).never
38
+ @action.prepare
39
+ end
40
+
41
+ should "not raise any errors if no forwarded ports collide" do
42
+ @forwarded_port.expects(:hostport).returns(80)
43
+ assert_nothing_raised { @action.prepare }
44
+ end
45
+
46
+ should "raise an ActionException if a port collides" do
47
+ @forwarded_port.expects(:hostport).returns(2222)
48
+ assert_raises(Vagrant::Actions::ActionException) {
49
+ @action.prepare
50
+ }
51
+ end
52
+
53
+ should "convert ports to strings prior to checking" do
54
+ @forwarded_port.expects(:hostport).returns("2222")
55
+ assert_raises(Vagrant::Actions::ActionException) {
56
+ @action.prepare
57
+ }
58
+ end
59
+ end
60
+
9
61
  context "execution" do
10
62
  should "clear all previous ports and forward new ports" do
11
63
  exec_seq = sequence("exec_seq")
@@ -23,14 +23,21 @@ class ImportActionTest < Test::Unit::TestCase
23
23
  end
24
24
 
25
25
  should "call import on VirtualBox::VM with the proper base" do
26
- VirtualBox::VM.expects(:import).once.with(@ovf_file)
27
- @import.execute!
26
+ VirtualBox::VM.expects(:import).once.with(@ovf_file).returns("foo")
27
+ assert_nothing_raised { @import.execute! }
28
+ end
29
+
30
+ should "raise an exception if import is nil" do
31
+ @mock_vm.expects(:vm).returns(nil)
32
+ assert_raises(Vagrant::Actions::ActionException) {
33
+ @import.execute!
34
+ }
28
35
  end
29
36
 
30
37
  should "set the resulting VM as the VM of the Vagrant VM object" do
31
38
  new_vm = mock("new_vm")
32
39
  @mock_vm.expects(:vm=).with(new_vm).once
33
- VirtualBox::VM.expects(:import).returns(new_vm)
40
+ VirtualBox::VM.expects(:import).returns(new_vm).returns("foo")
34
41
  @import.execute!
35
42
  end
36
43
  end